You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/01/20 18:29:02 UTC

[1/3] juneau git commit: Refactor RestInfoProvider.

Repository: juneau
Updated Branches:
  refs/heads/master 3c498b4b9 -> 62b041abd


http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/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 bf84613..c5ec797 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
@@ -86,7 +86,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	private String charset;
 	private RequestHeaders headers;
 	private ConfigFile cf;
-	private Swagger swagger, fileSwagger;
+	private Swagger swagger;
 
 	/**
 	 * Constructor.
@@ -156,8 +156,8 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		this.properties = properties;
 		this.beanSession = rjm.beanContext.createSession();
 		this.pathParams
-			.setParser(rjm.partParser)
-			.setBeanSession(beanSession);
+			.parser(rjm.partParser)
+			.beanSession(beanSession);
 		this.queryParams
 			.addDefault(rjm.defaultQuery)
 			.setParser(rjm.partParser)
@@ -288,7 +288,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * 
 	 * @return The set of media types registered in the serializer group of this request.
 	 */
-	public List<MediaType> getSupportedAcceptTypes() {
+	public List<MediaType> getProduces() {
 		return restJavaMethod.supportedAcceptTypes;
 	}
 
@@ -297,7 +297,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * 
 	 * @return The set of media types registered in the parser group of this request.
 	 */
-	public List<MediaType> getSupportedContentTypes() {
+	public List<MediaType> getConsumes() {
 		return restJavaMethod.supportedContentTypes;
 	}
 
@@ -630,7 +630,13 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * @return The localized servlet label.
 	 */
 	public String getSiteName() {
-		return context.getInfoProvider().getSiteName(this);
+		try {
+			return context.getInfoProvider().getSiteName(this);
+		} catch (RestException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+		}
 	}
 
 	/**
@@ -642,7 +648,13 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * @return The localized servlet label.
 	 */
 	public String getServletTitle() {
-		return context.getInfoProvider().getTitle(this);
+		try {
+			return context.getInfoProvider().getTitle(this);
+		} catch (RestException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+		}
 	}
 
 	/**
@@ -654,31 +666,49 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * @return The localized servlet description.
 	 */
 	public String getServletDescription() {
-		return context.getInfoProvider().getDescription(this);
+		try {
+			return context.getInfoProvider().getDescription(this);
+		} catch (RestException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+		}
 	}
 
 	/**
 	 * Returns the localized method summary.
 	 * 
 	 * <p>
-	 * Equivalent to calling {@link RestInfoProvider#getMethodSummary(String, RestRequest)} with this object.
+	 * Equivalent to calling {@link RestInfoProvider#getMethodSummary(Method, RestRequest)} with this object.
 	 * 
 	 * @return The localized method description.
 	 */
 	public String getMethodSummary() {
-		return context.getInfoProvider().getMethodSummary(javaMethod.getName(), this);
+		try {
+			return context.getInfoProvider().getMethodSummary(javaMethod, this);
+		} catch (RestException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+		}
 	}
 
 	/**
 	 * Returns the localized method description.
 	 * 
 	 * <p>
-	 * Equivalent to calling {@link RestInfoProvider#getMethodDescription(String, RestRequest)} with this object.
+	 * Equivalent to calling {@link RestInfoProvider#getMethodDescription(Method, RestRequest)} with this object.
 	 * 
 	 * @return The localized method description.
 	 */
 	public String getMethodDescription() {
-		return context.getInfoProvider().getMethodDescription(javaMethod.getName(), this);
+		try {
+			return context.getInfoProvider().getMethodDescription(javaMethod, this);
+		} catch (RestException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+		}
 	}
 
 	//--------------------------------------------------------------------------------
@@ -690,7 +720,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * 
 	 * @return The serializers associated with this request.
 	 */
-	public SerializerGroup getSerializerGroup() {
+	public SerializerGroup getSerializers() {
 		return restJavaMethod.serializers;
 	}
 
@@ -699,7 +729,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * 
 	 * @return The parsers associated with this request.
 	 */
-	public ParserGroup getParserGroup() {
+	public ParserGroup getParsers() {
 		return restJavaMethod.parsers;
 	}
 
@@ -920,9 +950,15 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * 	Never <jk>null</jk>.
 	 */
 	public Swagger getSwagger() {
-		if (swagger == null)
-			swagger = context.getInfoProvider().getSwagger(this);
-		return swagger;
+		try {
+			if (swagger == null)
+				swagger = context.getInfoProvider().getSwagger(this);
+			return swagger;
+		} catch (RestException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+		}
 	}
 
 	/**
@@ -936,26 +972,6 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		return restJavaMethod.widgets;
 	}
 
-	/**
-	 * 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 = context.getInfoProvider().getSwaggerFromFile(this);
-		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");

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletGroupDefault.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletGroupDefault.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletGroupDefault.java
index b0d7fda..8f4e639 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletGroupDefault.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletGroupDefault.java
@@ -36,9 +36,10 @@ public abstract class RestServletGroupDefault extends RestServletDefault {
 	 * 
 	 * @param req The HTTP request.
 	 * @return The bean containing links to the child resources.
+	 * @throws Exception 
 	 */
 	@RestMethod(name=GET, path="/", description="Child resources")
-	public ChildResourceDescriptions getChildren(RestRequest req) {
+	public ChildResourceDescriptions getChildren(RestRequest req) throws Exception {
 		return new ChildResourceDescriptions(getContext(), req);
 	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java
index e495760..1512cb0 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/MethodSwagger.java
@@ -12,7 +12,9 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.annotation;
 
-import org.apache.juneau.rest.*;
+import org.apache.juneau.ini.*;
+import org.apache.juneau.rest.vars.*;
+import org.apache.juneau.svl.vars.*;
 
 /**
  * Extended annotation for {@link RestMethod#swagger() RestMethod.swagger()}.
@@ -40,8 +42,27 @@ public @interface MethodSwagger {
 	 * </p>
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/paths/{path}/{method}/deprecated</code>.
@@ -79,8 +100,27 @@ public @interface MethodSwagger {
 	 * </p>
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/paths/{path}/{method}/externalDocs</code>.
@@ -126,8 +166,27 @@ public @interface MethodSwagger {
 	 * English), and use resource bundles if you need to support localization.
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/paths/{path}/{method}/parameters</code>.
@@ -174,8 +233,27 @@ public @interface MethodSwagger {
 	 * English), and use resource bundles if you need to support localization.
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 */
 	Response[] responses() default {};
 
@@ -204,8 +282,27 @@ public @interface MethodSwagger {
 	 * </p>
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/paths/{path}/{method}/tags</code>.

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
index 0709af4..058a4b2 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/ResourceSwagger.java
@@ -12,7 +12,10 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.annotation;
 
+import org.apache.juneau.ini.*;
 import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.vars.*;
+import org.apache.juneau.svl.vars.*;
 
 /**
  * Extended annotation for {@link RestResource#swagger() @RestResource.swagger()}.
@@ -50,8 +53,27 @@ public @interface ResourceSwagger {
 	 * </p>
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/info/contact</code>.
@@ -91,8 +113,27 @@ public @interface ResourceSwagger {
 	 * </p>
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/tags</code>.
@@ -133,8 +174,27 @@ public @interface ResourceSwagger {
 	 * </p>
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/info/license</code>.
@@ -180,8 +240,27 @@ public @interface ResourceSwagger {
 	 * </p>
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/tags</code>.
@@ -202,8 +281,27 @@ public @interface ResourceSwagger {
 	 * (e.g. <js>"termsOfService = foo"</js> or <js>"MyServlet.termsOfService = foo"</js>).
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/info/termsOfService</code>.
@@ -225,8 +323,27 @@ public @interface ResourceSwagger {
 	 * (e.g. <js>"version = 2.0"</js> or <js>"MyServlet.version = 2.0"</js>).
 	 * 
 	 * <p>
-	 * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>).
-	 * <br>See {@link RestContext#getVarResolver()} for the list of supported variables.
+	 * Value can contain any of the following variables:  
+	 * {@link ConfigFileVar $C} 
+	 * {@link CoalesceVar $CO}
+	 * {@link CoalesceAndRecurseVar $CR}
+	 * {@link EnvVariablesVar $E} 
+	 * {@link FileVar $F} 
+	 * {@link ServletInitParamVar $I},
+	 * {@link IfVar $IF}
+	 * {@link LocalizationVar $L}
+	 * {@link RequestAttributeVar $RA} 
+	 * {@link RequestFormDataVar $RF} 
+	 * {@link RequestHeaderVar $RH} 
+	 * {@link RequestPathVar $RP} 
+	 * {@link RequestQueryVar $RQ} 
+	 * {@link RequestVar $R} 
+	 * {@link SystemPropertiesVar $S}
+	 * {@link SerializedRequestAttrVar $SA}
+	 * {@link SwitchVar $SW}
+	 * {@link UrlVar $U}
+	 * {@link UrlEncodeVar $UE}
+	 * {@link WidgetVar $W}
 	 * 
 	 * <p>
 	 * Corresponds to the swagger field <code>/info/version</code>.

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/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 a1acbbb..6b79b84 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
@@ -754,10 +754,10 @@ public @interface RestMethod {
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link RestContext#REST_supportedAcceptTypes}
+	 * 	<li class='jf'>{@link RestContext#REST_produces}
 	 * </ul>
 	 */
-	String[] supportedAcceptTypes() default {};
+	String[] produces() default {};
 	
 	/**
 	 * Supported content media types.
@@ -777,10 +777,10 @@ public @interface RestMethod {
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link RestContext#REST_supportedContentTypes}
+	 * 	<li class='jf'>{@link RestContext#REST_consumes}
 	 * </ul>
 	 */
-	String[] supportedContentTypes() default {};
+	String[] consumes() default {};
 
 	/**
 	 * Provides swagger-specific metadata on this method.

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
index 4f74b47..774a2d1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
@@ -886,10 +886,10 @@ public @interface RestResource {
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link RestContext#REST_supportedAcceptTypes}
+	 * 	<li class='jf'>{@link RestContext#REST_produces}
 	 * </ul>
 	 */
-	String[] supportedAcceptTypes() default {};
+	String[] produces() default {};
 	
 	/**
 	 * Supported content media types.
@@ -909,10 +909,10 @@ public @interface RestResource {
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link RestContext#REST_supportedContentTypes}
+	 * 	<li class='jf'>{@link RestContext#REST_consumes}
 	 * </ul>
 	 */
-	String[] supportedContentTypes() default {};
+	String[] consumes() default {};
 	
 	/**
 	 * Provides swagger-specific metadata on this resource.

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java
index c857c66..228e570 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java
@@ -31,8 +31,9 @@ public class ChildResourceDescriptions extends LinkedList<ResourceDescription> {
 	 * 
 	 * @param context The servlet context that this bean describes.
 	 * @param req The HTTP servlet request.
+	 * @throws Exception 
 	 */
-	public ChildResourceDescriptions(RestContext context, RestRequest req) {
+	public ChildResourceDescriptions(RestContext context, RestRequest req) throws Exception {
 		this(context, req, false);
 	}
 
@@ -44,8 +45,9 @@ public class ChildResourceDescriptions extends LinkedList<ResourceDescription> {
 	 * @param sort
 	 * 	If <jk>true</jk>, list will be ordered by name alphabetically.
 	 * 	Default is to maintain the order as specified in the annotation.
+	 * @throws Exception 
 	 */
-	public ChildResourceDescriptions(RestContext context, RestRequest req, boolean sort) {
+	public ChildResourceDescriptions(RestContext context, RestRequest req, boolean sort) throws Exception {
 		for (Map.Entry<String,RestContext> e : context.getChildResources().entrySet())
 			add(new ResourceDescription(e.getKey(), e.getValue().getInfoProvider().getTitle(req)));
 		if (sort)

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
index deff1fd..0ead7a0 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
@@ -2375,8 +2375,8 @@
 						<li><ck>$RI{description}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getDescription(RestRequest)}.
 						<li><ck>$RI{externalDocs}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getExternalDocs(RestRequest)}.
 						<li><ck>$RI{license}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getLicense(RestRequest)}.
-						<li><ck>$RI{methodDescription}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getMethodDescription(RestRequest)}.
-						<li><ck>$RI{methodSummary}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getMethodSummary(RestRequest)}.
+						<li><ck>$RI{methodDescription}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getMethodDescription(Method,RestRequest)}.
+						<li><ck>$RI{methodSummary}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getMethodSummary(Method,RestRequest)}.
 						<li><ck>$RI{siteName}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getSiteName(RestRequest)}.
 						<li><ck>$RI{tags}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getTags(RestRequest)}.
 						<li><ck>$RI{termsOfService}</ck> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getTermsOfService(RestRequest)}.

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RestInfoVar.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RestInfoVar.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RestInfoVar.java
index a5f427e..89b65a8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RestInfoVar.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RestInfoVar.java
@@ -12,8 +12,11 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.vars;
 
+import java.lang.reflect.*;
 import java.util.*;
 
+import javax.servlet.http.*;
+
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
@@ -38,8 +41,8 @@ import org.apache.juneau.svl.*;
  * 	<li><js>"description"</js> - Value returned by {@link RestInfoProvider#getDescription(RestRequest)}
  * 	<li><js>"externalDocs"</js> - Value returned by {@link RestInfoProvider#getExternalDocs(RestRequest)}
  * 	<li><js>"license"</js> - Value returned by {@link RestInfoProvider#getLicense(RestRequest)}
- * 	<li><js>"methodDescription"</js> - Value returned by {@link RestInfoProvider#getMethodDescription(RestRequest)}
- * 	<li><js>"methodSummary"</js> - Value returned by {@link RestInfoProvider#getMethodSummary(RestRequest)}
+ * 	<li><js>"methodDescription"</js> - Value returned by {@link RestInfoProvider#getMethodDescription(Method,RestRequest)}
+ * 	<li><js>"methodSummary"</js> - Value returned by {@link RestInfoProvider#getMethodSummary(Method,RestRequest)}
  * 	<li><js>"siteName"</js> - Value returned by {@link RestInfoProvider#getSiteName(RestRequest)}
  * 	<li><js>"tags"</js> - Value returned by {@link RestInfoProvider#getTags(RestRequest)}
  * 	<li><js>"termsOfService"</js> - Value returned by {@link RestInfoProvider#getTermsOfService(RestRequest)}
@@ -96,49 +99,55 @@ public class RestInfoVar extends MultipartResolvingVar {
 
 	@Override /* Parameter */
 	public String resolve(VarResolverSession session, String key) {
-		RestRequest req = session.getSessionObject(RestRequest.class, SESSION_req);
-		RestInfoProvider rip = req.getInfoProvider();
-		WriterSerializer s = JsonSerializer.DEFAULT_LAX;
-		char c = StringUtils.charAt(key, 0);
-		if (c == 'c') {
-			if ("contact".equals(key)) {
-				Contact x = rip.getContact(req);
-				return x == null ? null : s.toString(x);
-			}
-		} else if (c == 'd') {
-			if ("description".equals(key)) 
-				return rip.getDescription(req);
-		} else if (c == 'e') {
-			if ("externalDocs".equals(key)) {
-				ExternalDocumentation x = rip.getExternalDocs(req);
-				return x == null ? null : s.toString(x);
-			}
-		} else if (c == 'l') {
-			if ("license".equals(key)) {
-				License x = rip.getLicense(req);
-				return x == null ? null : s.toString(x);
-			}
-		} else if (c == 'm') {
-			if ("methodDescription".equals(key)) 
-				return rip.getMethodDescription(req);
-			if ("methodSummary".equals(key)) 
-				return rip.getMethodSummary(req);
-		} else if (c == 's') {
-			if ("siteName".equals(key)) 
-				return rip.getSiteName(req);
-		} else if (c == 't') {
-			if ("tags".equals(key)) {
-				List<Tag> x = rip.getTags(req);
-				return x == null ? null : s.toString(x);
-			} else if ("termsOfService".equals(key)) {
-				return rip.getTermsOfService(req);
-			} else if ("title".equals(key)) {
-				return rip.getTitle(req);
+		try {
+			RestRequest req = session.getSessionObject(RestRequest.class, SESSION_req);
+			RestInfoProvider rip = req.getInfoProvider();
+			WriterSerializer s = JsonSerializer.DEFAULT_LAX;
+			char c = StringUtils.charAt(key, 0);
+			if (c == 'c') {
+				if ("contact".equals(key)) {
+					Contact x = rip.getContact(req);
+					return x == null ? null : s.toString(x);
+				}
+			} else if (c == 'd') {
+				if ("description".equals(key)) 
+					return rip.getDescription(req);
+			} else if (c == 'e') {
+				if ("externalDocs".equals(key)) {
+					ExternalDocumentation x = rip.getExternalDocs(req);
+					return x == null ? null : s.toString(x);
+				}
+			} else if (c == 'l') {
+				if ("license".equals(key)) {
+					License x = rip.getLicense(req);
+					return x == null ? null : s.toString(x);
+				}
+			} else if (c == 'm') {
+				if ("methodDescription".equals(key)) 
+					return rip.getMethodDescription(req.getJavaMethod(), req);
+				if ("methodSummary".equals(key)) 
+					return rip.getMethodSummary(req.getJavaMethod(), req);
+			} else if (c == 's') {
+				if ("siteName".equals(key)) 
+					return rip.getSiteName(req);
+			} else if (c == 't') {
+				if ("tags".equals(key)) {
+					List<Tag> x = rip.getTags(req);
+					return x == null ? null : s.toString(x);
+				} else if ("termsOfService".equals(key)) {
+					return rip.getTermsOfService(req);
+				} else if ("title".equals(key)) {
+					return rip.getTitle(req);
+				}
+			} else if (c == 'v') {
+				if ("version".equals(key)) 
+					return rip.getVersion(req);
 			}
-		} else if (c == 'v') {
-			if ("version".equals(key)) 
-				return rip.getVersion(req);
+			return null;
+		} catch (RestException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
 		}
-		return null;
 	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/SerializedRequestAttrVar.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/SerializedRequestAttrVar.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/SerializedRequestAttrVar.java
index de5e1d6..4b5e9e8 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/SerializedRequestAttrVar.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/SerializedRequestAttrVar.java
@@ -59,7 +59,7 @@ public class SerializedRequestAttrVar extends StreamedVar {
 			Object o = req.getAttribute(key);
 			if (o == null)
 				o = key;
-			Serializer s = req.getSerializerGroup().getSerializer(s2[0]);
+			Serializer s = req.getSerializers().getSerializer(s2[0]);
 			if (s != null)
 				s.serialize(w, o);
 		}

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/ContentTypeMenuItem.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/ContentTypeMenuItem.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/ContentTypeMenuItem.java
index 005557a..74ae47f 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/ContentTypeMenuItem.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/ContentTypeMenuItem.java
@@ -68,7 +68,7 @@ public class ContentTypeMenuItem extends MenuItemWidget {
 	public Div getContent(RestRequest req) {
 		Div div = div();
 		Set<MediaType> l = new TreeSet<>();
-		for (Serializer s : req.getSerializerGroup().getSerializers())
+		for (Serializer s : req.getSerializers().getSerializers())
 			l.add(s.getMediaTypes()[0]);
 		for (MediaType mt : l) {
 			URI uri = req.getUri(true, new AMap<String,String>().append("plainText","true").append("Accept",mt.toString()));


[3/3] juneau git commit: Refactor RestInfoProvider.

Posted by ja...@apache.org.
Refactor RestInfoProvider.

Project: http://git-wip-us.apache.org/repos/asf/juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/juneau/commit/62b041ab
Tree: http://git-wip-us.apache.org/repos/asf/juneau/tree/62b041ab
Diff: http://git-wip-us.apache.org/repos/asf/juneau/diff/62b041ab

Branch: refs/heads/master
Commit: 62b041abd97ac04d0cb4628ee4dec0bac54d445a
Parents: 3c498b4
Author: JamesBognar <ja...@apache.org>
Authored: Sat Jan 20 13:28:51 2018 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Sat Jan 20 13:28:51 2018 -0500

----------------------------------------------------------------------
 .../juneau/dto/swagger/ParameterInfo.java       |   60 +
 .../apache/juneau/dto/swagger/ResponseInfo.java |   22 +
 .../juneau/internal/BeanPropertyUtils.java      |   22 +-
 .../org/apache/juneau/internal/StringUtils.java |   28 +
 juneau-doc/src/main/javadoc/overview.html       |   22 +-
 .../juneau/rest/test/InheritanceResource.java   |    6 +-
 .../java/org/apache/juneau/rest/test/Root.java  |    2 +-
 .../juneau/rest/test/NlsResource.properties     |   89 +-
 .../org/apache/juneau/rest/RequestBody.java     |    2 +-
 .../apache/juneau/rest/RequestPathMatch.java    |   22 +-
 .../org/apache/juneau/rest/RestContext.java     |  244 ++--
 .../apache/juneau/rest/RestContextBuilder.java  |   36 +-
 .../apache/juneau/rest/RestInfoProvider.java    |  248 +++-
 .../juneau/rest/RestInfoProviderDefault.java    | 1258 +++++++++++++++---
 .../org/apache/juneau/rest/RestJavaMethod.java  |  359 +----
 .../org/apache/juneau/rest/RestRequest.java     |   90 +-
 .../juneau/rest/RestServletGroupDefault.java    |    3 +-
 .../juneau/rest/annotation/MethodSwagger.java   |  119 +-
 .../juneau/rest/annotation/ResourceSwagger.java |  141 +-
 .../juneau/rest/annotation/RestMethod.java      |    8 +-
 .../juneau/rest/annotation/RestResource.java    |    8 +-
 .../rest/labels/ChildResourceDescriptions.java  |    6 +-
 .../java/org/apache/juneau/rest/package.html    |    4 +-
 .../apache/juneau/rest/vars/RestInfoVar.java    |   97 +-
 .../rest/vars/SerializedRequestAttrVar.java     |    2 +-
 .../juneau/rest/widget/ContentTypeMenuItem.java |    2 +-
 26 files changed, 1991 insertions(+), 909 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
index 3129f8d..cc3965e 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
@@ -130,6 +130,66 @@ public class ParameterInfo extends SwaggerElement {
 	}
 
 	/**
+	 * Copies any non-null fields from the specified object to this object.
+	 * 
+	 * @param p 
+	 * 	The object to copy fields from.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public ParameterInfo copyFrom(ParameterInfo p) {
+		if (p != null) {
+			if (p.name != null)
+				name = p.name;
+			if (p.in != null)
+				in = p.in;
+			if (p.description != null)
+				description = p.description;
+			if (p.type != null)
+				type = p.type;
+			if (p.format != null)
+				format = p.format;
+			if (p.pattern != null)
+				pattern = p.pattern;
+			if (p.collectionFormat != null)
+				collectionFormat = p.collectionFormat;
+			if (p.maximum != null)
+				maximum = p.maximum;
+			if (p.minimum != null)
+				minimum = p.minimum;
+			if (p.multipleOf != null)
+				multipleOf = p.multipleOf;
+			if (p.maxLength != null)
+				maxLength = p.maxLength;
+			if (p.minLength != null)
+				minLength = p.minLength;
+			if (p.maxItems != null)
+				maxItems = p.maxItems;
+			if (p.minItems != null)
+				minItems = p.minItems;
+			if (p.required != null)
+				required = p.required;
+			if (p.allowEmptyValue != null)
+				allowEmptyValue = p.allowEmptyValue;
+			if (p.exclusiveMaximum != null)
+				exclusiveMaximum = p.exclusiveMaximum;
+			if (p.exclusiveMinimum != null)
+				exclusiveMinimum = p.exclusiveMinimum;
+			if (p.uniqueItems != null)
+				uniqueItems = p.uniqueItems;
+			if (p.schema != null)
+				schema = p.schema;
+			if (p.items != null)
+				items = p.items;
+			if (p._default != null)
+				_default = p._default;
+			if (p._enum != null)
+				_enum = p._enum;
+		}
+		return this;
+	}
+	
+	/**
 	 * Bean property getter:  <property>name</property>.
 	 * 
 	 * <p>

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
index ead018d..6a7f9d5 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
@@ -66,6 +66,28 @@ public class ResponseInfo extends SwaggerElement {
 	private Map<String,Object> examples;
 
 	/**
+	 * Copies any non-null fields from the specified object to this object.
+	 * 
+	 * @param r 
+	 * 	The object to copy fields from.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public ResponseInfo copyFrom(ResponseInfo r) {
+		if (r != null) {
+			if (r.description != null)
+				description = r.description;
+			if (r.schema != null)
+				schema = r.schema;
+			if (r.headers != null)
+				headers = r.headers;
+			if (r.examples != null)
+				examples = r.examples;
+		}
+		return this;
+	}
+	
+	/**
 	 * Bean property getter:  <property>description</property>.
 	 * 
 	 * <p>

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java
index 8a01323..63b481c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java
@@ -12,6 +12,8 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.internal;
 
+import static org.apache.juneau.internal.StringUtils.*;
+
 import java.lang.reflect.*;
 import java.util.*;
 
@@ -105,7 +107,7 @@ public final class BeanPropertyUtils {
 					}
 				}
 			}
-			return l;
+			return l.isEmpty() ? null : l;
 		} catch (ParseException e) {
 			throw new RuntimeException(e);
 		}
@@ -142,28 +144,12 @@ public final class BeanPropertyUtils {
 					}
 				}
 			}
-			return m;
+			return m.isEmpty() ? null : m;
 		} catch (ParseException e) {
 			throw new RuntimeException(e);
 		}
 	}
 	
-	private static boolean isObjectList(Object o) {
-		if (o instanceof CharSequence) {
-			String s = o.toString();
-			return (s.startsWith("[") && s.endsWith("]") && BeanContext.DEFAULT != null);
-		}
-		return false;
-	}
-
-	private static boolean isObjectMap(Object o) {
-		if (o instanceof CharSequence) {
-			String s = o.toString();
-			return (s.startsWith("{") && s.endsWith("}") && BeanContext.DEFAULT != null);
-		}
-		return false;
-	}
-
 	/**
 	 * Converts an object to the specified type.
 	 * 

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
index e5b2b45..3dea15d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -1893,4 +1893,32 @@ public final class StringUtils {
 	public static boolean contains(String value, CharSequence substring) {
 		return value == null ? false : value.contains(substring);
 	}
+	
+	/**
+	 * Returns <jk>true</jk> if the specified string appears to be an JSON array.
+	 * 
+	 * @param o The object to test.
+	 * @return <jk>true</jk> if the specified string appears to be a JSON array.
+	 */
+	public static boolean isObjectList(Object o) {
+		if (o instanceof CharSequence) {
+			String s = o.toString();
+			return (s.startsWith("[") && s.endsWith("]") && BeanContext.DEFAULT != null);
+		}
+		return false;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified string appears to be a JSON object.
+	 * 
+	 * @param o The object to test.
+	 * @return <jk>true</jk> if the specified string appears to be a JSON object.
+	 */
+	public static boolean isObjectMap(Object o) {
+		if (o instanceof CharSequence) {
+			String s = o.toString();
+			return (s.startsWith("{") && s.endsWith("}") && BeanContext.DEFAULT != null);
+		}
+		return false;
+	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-doc/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 797c40b..39a4410 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -9211,8 +9211,8 @@
 							<li><js>"description"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getDescription(RestRequest)}
 							<li><js>"externalDocs"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getExternalDocs(RestRequest)}
 							<li><js>"license"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getLicense(RestRequest)}
-							<li><js>"methodDescription"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getMethodDescription(RestRequest)}
-							<li><js>"methodSummary"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getMethodSummary(RestRequest)}
+							<li><js>"methodDescription"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getMethodDescription(Method,RestRequest)}
+							<li><js>"methodSummary"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getMethodSummary(Method,RestRequest)}
 							<li><js>"siteName"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getSiteName(RestRequest)}
 							<li><js>"tags"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getTags(RestRequest)}
 							<li><js>"termsOfService"</js> - Value returned by {@link org.apache.juneau.rest.RestInfoProvider#getTermsOfService(RestRequest)}
@@ -9257,8 +9257,8 @@
 					<li>{@link org.apache.juneau.rest.RestContext#REST_responseHandlers REST_responseHandlers}
 					<li>{@link org.apache.juneau.rest.RestContext#REST_defaultRequestHeaders REST_defaultRequestHeaders}
 					<li>{@link org.apache.juneau.rest.RestContext#REST_defaultResponseHeaders REST_defaultResponseHeaders}
-					<li>{@link org.apache.juneau.rest.RestContext#REST_supportedAcceptTypes REST_supportedAcceptTypes}
-					<li>{@link org.apache.juneau.rest.RestContext#REST_supportedContentTypes REST_supportedContentTypes}
+					<li>{@link org.apache.juneau.rest.RestContext#REST_produces REST_produces}
+					<li>{@link org.apache.juneau.rest.RestContext#REST_consumes REST_consumes}
 					<li>{@link org.apache.juneau.rest.RestContext#REST_clientVersionHeader REST_clientVersionHeader}
 					<li>{@link org.apache.juneau.rest.RestContext#REST_resourceResolver REST_resourceResolver}
 					<li>{@link org.apache.juneau.rest.RestContext#REST_logger REST_logger}
@@ -9330,8 +9330,8 @@
 				Changes to {@link org.apache.juneau.rest.RestRequest}:
 				<ul>	
 					<li><code>getSupportedMediaTypes()</code> replaced with
-						{@link org.apache.juneau.rest.RestRequest#getSupportedAcceptTypes() getSupportedAcceptTypes()} and
-						{@link org.apache.juneau.rest.RestRequest#getSupportedContentTypes() getSupportedContentTypes()}.
+						{@link org.apache.juneau.rest.RestRequest#getConsumes() getConsumes()} and
+						{@link org.apache.juneau.rest.RestRequest#getProduces() getProduces()}.
 					<li><code>getReaderResource(String,boolean,MediaType)</code> renamed to 
 						{@link org.apache.juneau.rest.RestRequest#getClasspathReaderResource(String,boolean,MediaType) getClasspathReaderResource(String,boolean,MediaType)}
 					<li><code>getReaderResource(String,boolean)</code> renamed to 
@@ -9347,8 +9347,8 @@
 			<li>
 				Changes to {@link org.apache.juneau.rest.annotation.RestMethod @RestMethod}:
 				<ul>
-					<li>New {@link org.apache.juneau.rest.annotation.RestMethod#supportedAcceptTypes() supportedAcceptTypes()} and
-						{@link org.apache.juneau.rest.annotation.RestMethod#supportedContentTypes() supportedContentTypes()}
+					<li>New {@link org.apache.juneau.rest.annotation.RestMethod#consumes() consumes()} and
+						{@link org.apache.juneau.rest.annotation.RestMethod#produces() produces()}
 						for overriding the supported media types inferred from the serializers and parsers.
 				</ul>
 			<li>
@@ -9374,6 +9374,8 @@
 				annotations.
 				<br>These aren't needed anymore since you can just pass in <code>MessageBundle</code> and
 				<code>RestRequestProperties</code> as unannotated parameters.
+			<li>
+				Revamped the {@link org.apache.juneau.rest.RestInfoProvider} class.
 		</ul>
 
 		<h6 class='topic'>juneau-rest-client</h6>
@@ -11404,8 +11406,8 @@
 							<li><code><del>@RestResource.version()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getVersion(RestRequest)}
 							<li><code><del>@RestResource.tags()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getTags(RestRequest)}
 							<li><code><del>@RestResource.externalDocs()</del></code> / {@link org.apache.juneau.rest.RestInfoProvider#getExternalDocs(RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestMethod#summary() @RestMethod.summary()} / {@link org.apache.juneau.rest.RestInfoProvider#getMethodSummary(String,RestRequest)}
-							<li>{@link org.apache.juneau.rest.annotation.RestMethod#description() @RestMethod.description()} / {@link org.apache.juneau.rest.RestInfoProvider#getMethodDescription(String,RestRequest)}
+							<li>{@link org.apache.juneau.rest.annotation.RestMethod#summary() @RestMethod.summary()} / <code><del>RestInfoProvider.getMethodSummary(String,RestRequest)</del></code>
+							<li>{@link org.apache.juneau.rest.annotation.RestMethod#description() @RestMethod.description()} /<code><del>RestInfoProvider.getMethodDescription(String,RestRequest)</del></code>
 							<li><code><del>@RestMethod.externalDocs()</del></code>
 							<li><code><del>@RestMethod.tags()</del></code>
 							<li><code><del>@RestMethod.deprecated()</del></code> 

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java
index 863c7cb..2ba85e5 100644
--- a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java
+++ b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java
@@ -102,7 +102,7 @@ public class InheritanceResource extends RestServlet {
 			path="/test1"
 		)
 		public Reader test1(RestRequest req) {
-			return new StringReader(new ObjectList(req.getSupportedContentTypes()).toString());
+			return new StringReader(new ObjectList(req.getConsumes()).toString());
 		}
 
 		// Should show ['text/p5']
@@ -112,7 +112,7 @@ public class InheritanceResource extends RestServlet {
 			parsers=P5.class
 		)
 		public Reader test2(RestRequest req) {
-			return new StringReader(new ObjectList(req.getSupportedContentTypes()).toString());
+			return new StringReader(new ObjectList(req.getConsumes()).toString());
 		}
 
 		// Should show ['text/p5','text/p3','text/p4','text/p1','text/p2']
@@ -123,7 +123,7 @@ public class InheritanceResource extends RestServlet {
 			inherit="PARSERS"
 		)
 		public Reader test3(RestRequest req) {
-			return new StringReader(new ObjectList(req.getSupportedContentTypes()).toString());
+			return new StringReader(new ObjectList(req.getConsumes()).toString());
 		}
 	}
 

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
index 43c1181..6acd2e8 100644
--- a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
+++ b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
@@ -82,7 +82,7 @@ public class Root extends RestServletDefault {
 	private static final long serialVersionUID = 1L;
 
 	@RestMethod(name=GET, path="/")
-	public ChildResourceDescriptions doGet(RestRequest req) {
+	public ChildResourceDescriptions doGet(RestRequest req) throws Exception {
 		return new ChildResourceDescriptions(getContext(), req);
 	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/NlsResource.properties
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/NlsResource.properties b/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/NlsResource.properties
index d461923..1c820fd 100644
--- a/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/NlsResource.properties
+++ b/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/NlsResource.properties
@@ -15,41 +15,52 @@
 title = Test2.a
 description = Test2.b
 test2.summary = Test2.c
-test2.req.path.a.description = Test2.d
-test2.req.query.b.description = Test2.e
-test2.req.body.description = Test2.f
-test2.req.header.D.description = Test2.g
-test2.req.path.a2.description = Test2.h
-test2.req.query.b2.description = Test2.i
-test2.req.header.D2.description = Test2.j
-test2.res.200.description = OK2
-test2.res.201.description = Test2.l
+test2.parameters = [\
+		{in:"path",name:"a",description:"Test2.d"},\
+		{in:"query",name:"b",description:"Test2.e"},\
+		{in:"body",description:"Test2.f"},\
+		{in:"header",name:"D",description:"Test2.g"},\
+		{in:"path",name:"a2",description:"Test2.h"},\
+		{in:"query",name:"b2",description:"Test2.i"},\
+		{in:"header",name:"D2",description:"Test2.j"}\
+	]
+test2.responses = {\
+		200:{description:"OK2"},\
+		201:{description:"Test2.l"}\
+	}
 
 Test3.title = Test3.a
 Test3.description = Test3.b
 Test3.test3.summary = Test3.c
-Test3.test3.req.path.a.description = Test3.d
-Test3.test3.req.query.b.description = Test3.e
-Test3.test3.req.body.description = Test3.f
-Test3.test3.req.header.D.description = Test3.g
-Test3.test3.req.path.a2.description = Test3.h
-Test3.test3.req.query.b2.description = Test3.i
-Test3.test3.req.header.D2.description = Test3.j
-Test3.test3.res.200.description = OK3
-Test3.test3.res.201.description = Test3.l
+test3.parameters = [\
+		{in:"path",name:"a",description:"Test3.d"},\
+		{in:"query",name:"b",description:"Test3.e"},\
+		{in:"body",description:"Test3.f"},\
+		{in:"header",name:"D",description:"Test3.g"},\
+		{in:"path",name:"a2",description:"Test3.h"},\
+		{in:"query",name:"b2",description:"Test3.i"},\
+		{in:"header",name:"D2",description:"Test3.j"}\
+	]
+test3.responses = {\
+		200:{description:"OK3"},\
+		201:{description:"Test3.l"}\
+	}
 
 Test4.title = $L{foo}
 Test4.description = $L{foo}
-Test4.test4.summary = $L{foo}
-Test4.test4.req.path.a.description = $L{foo}
-Test4.test4.req.query.b.description = $L{foo}
-Test4.test4.req.body.description = $L{foo}
-Test4.test4.req.header.D.description = $L{foo}
-Test4.test4.req.path.a2.description = $L{foo}
-Test4.test4.req.query.b2.description = $L{foo}
-Test4.test4.req.header.D2.description = $L{foo}
-Test4.test4.res.200.description = foo$L{foo}foo$L{foo}foo
-Test4.test4.res.201.description = $L{foo}
+test4.parameters = [\
+		{in:"path",name:"a",description:"$L{foo}"},\
+		{in:"query",name:"b",description:"$L{foo}"},\
+		{in:"body",description:"$L{foo}"},\
+		{in:"header",name:"D",description:"$L{foo}"},\
+		{in:"path",name:"a2",description:"$L{foo}"},\
+		{in:"query",name:"b2",description:"$L{foo}"},\
+		{in:"header",name:"D2",description:"$L{foo}"}\
+	]
+test4.responses = {\
+		200:{description:"foo$L{foo}foo$L{foo}foo"},\
+		201:{description:"$L{foo}"}\
+	}
 
 foo = $L{bar}
 bar = baz
@@ -57,15 +68,19 @@ bar = baz
 Test5.title = $L{foo2}
 Test5.description = $R{servletTitle}
 Test5.test5.summary = $R{servletTitle}
-Test5.test5.req.path.a.description = $R{servletTitle}
-Test5.test5.req.query.b.description = $R{servletTitle}
-Test5.test5.req.body.description = $R{servletTitle}
-Test5.test5.req.header.D.description = $R{servletTitle}
-Test5.test5.req.path.a2.description = $R{servletTitle}
-Test5.test5.req.query.b2.description = $R{servletTitle}
-Test5.test5.req.header.D2.description = $R{servletTitle}
-Test5.test5.res.200.description = foo$R{servletTitle}foo$R{servletTitle}foo
-Test5.test5.res.201.description = $R{servletTitle}
+test5.parameters = [\
+		{in:"path",name:"a",description:"$R{servletTitle}"},\
+		{in:"query",name:"b",description:"$R{servletTitle}"},\
+		{in:"body",description:"$R{servletTitle}"},\
+		{in:"header",name:"D",description:"$R{servletTitle}"},\
+		{in:"path",name:"a2",description:"$R{servletTitle}"},\
+		{in:"query",name:"b2",description:"$R{servletTitle}"},\
+		{in:"header",name:"D2",description:"$R{servletTitle}"}\
+	]
+test5.responses = {\
+		200:{description:"foo$R{servletTitle}foo$R{servletTitle}foo"},\
+		201:{description:"$R{servletTitle}"}\
+	}
 Test5.foo2 = $L{bar2}
 Test5.bar2 = baz2
 

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
index 51117b0..b804e75 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
@@ -374,7 +374,7 @@ public class RequestBody {
 
 			throw new RestException(SC_UNSUPPORTED_MEDIA_TYPE,
 				"Unsupported media-type in request header ''Content-Type'': ''{0}''\n\tSupported media-types: {1}",
-				headers.getContentType(), req.getParserGroup().getSupportedMediaTypes()
+				headers.getContentType(), req.getParsers().getSupportedMediaTypes()
 			);
 
 		} catch (IOException e) {

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathMatch.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathMatch.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathMatch.java
index ea30efa..49e4eda 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathMatch.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathMatch.java
@@ -33,27 +33,32 @@ public class RequestPathMatch extends TreeMap<String,String> {
 
 	private HttpPartParser parser;
 	private BeanSession beanSession;
-	private String remainder;
+	private String remainder, pattern;
 
 	RequestPathMatch() {
 		super(String.CASE_INSENSITIVE_ORDER);
 	}
 
-	RequestPathMatch setParser(HttpPartParser parser) {
+	RequestPathMatch parser(HttpPartParser parser) {
 		this.parser = parser;
 		return this;
 	}
 
-	RequestPathMatch setBeanSession(BeanSession beanSession) {
+	RequestPathMatch beanSession(BeanSession beanSession) {
 		this.beanSession = beanSession;
 		return this;
 	}
 
-	RequestPathMatch setRemainder(String remainder) {
+	RequestPathMatch remainder(String remainder) {
 		this.remainder = remainder;
 		return this;
 	}
 
+	RequestPathMatch pattern(String pattern) {
+		this.pattern = pattern;
+		return this;
+	}
+
 	/**
 	 * Sets a request query parameter value.
 	 * 
@@ -219,4 +224,13 @@ public class RequestPathMatch extends TreeMap<String,String> {
 	public String getRemainderUndecoded() {
 		return remainder;
 	}
+	
+	/**
+	 * Returns the path pattern that matched this request.
+	 * 
+	 * @return The path pattern that matched this request.
+	 */
+	public String getPattern() {
+		return pattern;
+	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 7230156..eedf655 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -339,6 +339,17 @@ public final class RestContext extends BeanContext {
 	 * 		}
 	 * 	}
 	 * </p>
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(RestContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
+	 * </ul>
 	 */
 	public static final String REST_callHandler = PREFIX + "callHandler.o";
 
@@ -406,17 +417,6 @@ public final class RestContext extends BeanContext {
 	 * 	</dd>
 	 * </dl>
 	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>When defined as classes, instances are resolved using the registered {@link #REST_resourceResolver} which
-	 * 		by default is {@link RestResourceResolverDefault} which requires the class have one of the following
-	 * 		constructors:
-	 * 		<ul>
-	 * 			<li><code><jk>public</jk> T(RestContextBuilder)</code>
-	 * 			<li><code><jk>public</jk> T()</code>
-	 * 		</ul>
-	 * </ul>
-	 * 
 	 * <h5 class='section'>Example:</h5>
 	 * <p class='bcode'>
 	 * 	<jc>// Our child resource.</jc>
@@ -450,6 +450,17 @@ public final class RestContext extends BeanContext {
 	 * 		}
 	 * 	}
 	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>When defined as classes, instances are resolved using the registered {@link #REST_resourceResolver} which
+	 * 		by default is {@link RestResourceResolverDefault} which requires the class have one of the following
+	 * 		constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(RestContextBuilder)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * </ul>
+	 * 
 	 * <h5 class='section'>Documentation:</h5>
 	 * <ul>
 	 * 	<li><a class="doclink" href="package-summary.html#RestResources.Children">org.apache.juneau.rest &gt; Children</a>
@@ -550,6 +561,13 @@ public final class RestContext extends BeanContext {
 	 * 		<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.
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(RestContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
+	 * </ul>
 	 * </ul>
 	 */
 	public static final String REST_classpathResourceFinder = PREFIX + "classpathResourceFinder.o";
@@ -779,6 +797,17 @@ public final class RestContext extends BeanContext {
 	 * <ul>
 	 * 	<li><a class="doclink" href="package-summary.html#RestResources.Converters">org.apache.juneau.rest &gt; Converters</a>
 	 * </ul>
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(BeanContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
+	 * </ul>
 	 */
 	public static final String REST_converters = PREFIX + "converters.lo";
 
@@ -1000,16 +1029,6 @@ public final class RestContext extends BeanContext {
 	 * <p>
 	 * These can be used to enable various kinds of compression (e.g. <js>"gzip"</js>) on requests and responses.
 	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>When defined as classes, the class must provide one of the following constructors:
-	 * 		<ul>
-	 * 			<li><code><jk>public</jk> T(PropertyStore)</code>
-	 * 			<li><code><jk>public</jk> T()</code>
-	 * 		</ul>
-	 * 	<li>Instance class can be defined as an inner class of the REST resource class.
-	 * </ul>
-	 * 
 	 * <h5 class='section'>Example:</h5>
 	 * <p class='bcode'>
 	 * 	<jc>// Registered via annotation.</jc>
@@ -1042,6 +1061,17 @@ public final class RestContext extends BeanContext {
 	 * 	}
 	 * </p>
 	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(BeanContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
+	 * </ul>
+	 * 
 	 * <h5 class='section'>Documentation:</h5>
 	 * <ul>
 	 * 	<li><a class="doclink" href="package-summary.html#RestResources.Encoders">org.apache.juneau.rest &gt; Encoders</a>
@@ -1076,19 +1106,8 @@ public final class RestContext extends BeanContext {
 	 * <br>These guards get called immediately before execution of any REST method in this class.
 	 * 
 	 * <p>
-	 * Typically, guards will be used for permissions checking on the user making the request, but it can also be used
-	 * for other purposes like pre-call validation of a request.
-	 * 
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>When defined as classes, the class must provide one of the following constructors:
-	 * 		<ul>
-	 * 			<li><code><jk>public</jk> T(PropertyStore)</code>
-	 * 			<li><code><jk>public</jk> T()</code>
-	 * 		</ul>
-	 * 	<li>Instance class can be defined as an inner class of the REST resource class.
-	 * 	<li>If multiple guards are specified, <b>ALL</b> guards must pass.
-	 * </ul>
+	 * If multiple guards are specified, <b>ALL</b> guards must pass.
+	 * <br>Note that this is different than matchers were only ONE matcher needs to pass.
 	 * 
 	 * <h5 class='section'>Example:</h5>
 	 * <p class='bcode'>
@@ -1130,6 +1149,17 @@ public final class RestContext extends BeanContext {
 	 * 	}
 	 * </p>
 	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(BeanContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
+	 * </ul>
+	 * 
 	 * <h5 class='section'>Documentation:</h5>
 	 * <ul>
 	 * 	<li><a class="doclink" href="package-summary.html#RestResources.Guards">org.apache.juneau.rest &gt; Guards</a>
@@ -1213,6 +1243,17 @@ public final class RestContext extends BeanContext {
 	 * 		}
 	 * 	}
 	 * </p>
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(BeanContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
+	 * </ul>
 	 */
 	public static final String REST_infoProvider = PREFIX + "infoProvider.o";
 	
@@ -1361,6 +1402,17 @@ public final class RestContext extends BeanContext {
 	 * 		}
 	 * 	}
 	 * </p>
+	 * 
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(BeanContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
+	 * </ul>
 	 */
 	public static final String REST_maxInput = PREFIX + "maxInput.s";
 	
@@ -1527,7 +1579,13 @@ public final class RestContext extends BeanContext {
 	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>{@link RestParam} classes must have either a no-arg or {@link PropertyStore} argument constructors.
+	 * 	<li>
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(BeanContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
 	 * </ul>
 	 */
 	public static final String REST_paramResolvers = PREFIX + "paramResolvers.lo";
@@ -1729,10 +1787,15 @@ public final class RestContext extends BeanContext {
 	 * <p>
 	 * Can be used to provide customized resolution of REST resource class instances (e.g. resources retrieve from Spring).
 	 * 
-	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
 	 * 	<li>Unless overridden, resource resolvers are inherited from parent resources.
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(BeanContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
 	 * </ul>
 	 */
 	public static final String REST_resourceResolver = PREFIX + "resourceResolver.o";
@@ -1772,11 +1835,16 @@ public final class RestContext extends BeanContext {
 	 * 	<li>{@link RedirectHandler}
 	 * 	<li>{@link DefaultHandler}
 	 * </ul>
-
-	 * <p>
+	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>{@link ResponseHandler} classes must have either a no-arg or {@link PropertyStore} argument constructors.
+	 * 	<li>Unless overridden, resource resolvers are inherited from parent resources.
+	 * 	<li>When defined as a class, the implementation must have one of the following constructors:
+	 * 		<ul>
+	 * 			<li><code><jk>public</jk> T(BeanContext)</code>
+	 * 			<li><code><jk>public</jk> T()</code>
+	 * 		</ul>
+	 * 	<li>Inner classes of the REST resource class are allowed.
 	 * </ul>
 	 */
 	public static final String REST_responseHandlers = PREFIX + "responseHandlers.lo";
@@ -1917,19 +1985,19 @@ public final class RestContext extends BeanContext {
 	 * 
 	 * <h5 class='section'>Property:</h5>
 	 * <ul>
-	 * 	<li><b>Name:</b>  <js>"RestContext.supportedAcceptTypes.ls"</js>
+	 * 	<li><b>Name:</b>  <js>"RestContext.produces.ls"</js>
 	 * 	<li><b>Data type:</b>  <code>List&lt;String&gt;</code>
 	 * 	<li><b>Default:</b>  empty list
 	 * 	<li><b>Session-overridable:</b>  <jk>false</jk>
 	 * 	<li><b>Annotations:</b>
 	 * 		<ul>
-	 * 			<li class='ja'>{@link RestResource#supportedAcceptTypes()}
-	 * 			<li class='ja'>{@link RestMethod#supportedAcceptTypes()}
+	 * 			<li class='ja'>{@link RestResource#produces()}
+	 * 			<li class='ja'>{@link RestMethod#produces()}
 	 * 		</ul> 
 	 * 	<li><b>Methods:</b>  
 	 * 		<ul>
-	 * 			<li class='jm'>{@link RestContextBuilder#supportedAcceptTypes(boolean,String...)}
-	 * 			<li class='jm'>{@link RestContextBuilder#supportedAcceptTypes(boolean,MediaType...)}
+	 * 			<li class='jm'>{@link RestContextBuilder#produces(boolean,String...)}
+	 * 			<li class='jm'>{@link RestContextBuilder#produces(boolean,MediaType...)}
 	 * 		</ul>
 	 * </ul>
 	 * 
@@ -1938,29 +2006,29 @@ public final class RestContext extends BeanContext {
 	 * 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
+	 * This affects the values returned by {@link RestRequest#getProduces()} and the supported accept
 	 * types shown in {@link RestInfoProvider#getSwagger(RestRequest)}.
 	 */
-	public static final String REST_supportedAcceptTypes = PREFIX + "supportedAcceptTypes.ls";
+	public static final String REST_produces = PREFIX + "produces.ls";
 
 	/**
 	 * Configuration property:  Supported content media types.
 	 * 
 	 * <h5 class='section'>Property:</h5>
 	 * <ul>
-	 * 	<li><b>Name:</b>  <js>"RestContext.supportedContentTypes.ls"</js>
+	 * 	<li><b>Name:</b>  <js>"RestContext.consumes.ls"</js>
 	 * 	<li><b>Data type:</b>  <code>List&lt;String&gt;</code>
 	 * 	<li><b>Default:</b>  empty list
 	 * 	<li><b>Session-overridable:</b>  <jk>false</jk>
 	 * 	<li><b>Annotations:</b>
 	 * 		<ul>
-	 * 			<li class='ja'>{@link RestResource#supportedContentTypes()}
-	 * 			<li class='ja'>{@link RestMethod#supportedContentTypes()}
+	 * 			<li class='ja'>{@link RestResource#consumes()}
+	 * 			<li class='ja'>{@link RestMethod#consumes()}
 	 * 		</ul> 
 	 * 	<li><b>Methods:</b>  
 	 * 		<ul>
-	 * 			<li class='jm'>{@link RestContextBuilder#supportedContentTypes(boolean,String...)}
-	 * 			<li class='jm'>{@link RestContextBuilder#supportedContentTypes(boolean,MediaType...)}
+	 * 			<li class='jm'>{@link RestContextBuilder#consumes(boolean,String...)}
+	 * 			<li class='jm'>{@link RestContextBuilder#consumes(boolean,MediaType...)}
 	 * 		</ul>
 	 * </ul>
 	 * 
@@ -1969,10 +2037,10 @@ public final class RestContext extends BeanContext {
 	 * 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
+	 * This affects the values returned by {@link RestRequest#getConsumes()} and the supported content
 	 * types shown in {@link RestInfoProvider#getSwagger(RestRequest)}.
 	 */
-	public static final String REST_supportedContentTypes = PREFIX + "supportedContentTypes.ls";
+	public static final String REST_consumes = PREFIX + "consumes.ls";
 	
 	/**
 	 * Configuration property:  Use classpath resource caching. 
@@ -2123,8 +2191,8 @@ public final class RestContext extends BeanContext {
 	private final HttpPartParser partParser;
 	private final EncoderGroup encoders;
 	private final List<MediaType>
-		supportedContentTypes,
-		supportedAcceptTypes;
+		consumes,
+		produces;
 	private final Map<String,Object> 
 		defaultRequestHeaders,
 		defaultResponseHeaders,
@@ -2206,12 +2274,12 @@ public final class RestContext extends BeanContext {
 			maxInput = getProperty(REST_maxInput, long.class, 100_000_000l);
 			clientVersionHeader = getProperty(REST_clientVersionHeader, String.class, "X-Client-Version");
 
-			converters = getInstanceArrayProperty(REST_converters, resource, RestConverter.class, new RestConverter[0], true, ps);
-			guards = getInstanceArrayProperty(REST_guards, resource, RestGuard.class, new RestGuard[0], true, ps);
-			responseHandlers = getInstanceArrayProperty(REST_responseHandlers, resource, ResponseHandler.class, new ResponseHandler[0], true, ps);
+			converters = getInstanceArrayProperty(REST_converters, resource, RestConverter.class, new RestConverter[0], true, this);
+			guards = getInstanceArrayProperty(REST_guards, resource, RestGuard.class, new RestGuard[0], true, this);
+			responseHandlers = getInstanceArrayProperty(REST_responseHandlers, resource, ResponseHandler.class, new ResponseHandler[0], true, this);
 
 			Map<Class<?>,RestParam> _paramResolvers = new HashMap<>();
-			for (RestParam rp : getInstanceArrayProperty(REST_paramResolvers, RestParam.class, new RestParam[0], true, ps)) 
+			for (RestParam rp : getInstanceArrayProperty(REST_paramResolvers, RestParam.class, new RestParam[0], true, this)) 
 				_paramResolvers.put(rp.forClass(), rp);
 			paramResolvers = Collections.unmodifiableMap(_paramResolvers);
 			
@@ -2222,7 +2290,7 @@ public final class RestContext extends BeanContext {
 			defaultResponseHeaders = getMapProperty(REST_defaultResponseHeaders, Object.class);
 			staticFileResponseHeaders = getMapProperty(REST_staticFileResponseHeaders, Object.class);	
 			
-			logger = getInstanceProperty(REST_logger, resource, RestLogger.class, RestLoggerNoOp.class, true, ps);
+			logger = getInstanceProperty(REST_logger, resource, RestLogger.class, RestLoggerNoOp.class, true, this);
 
 			varResolver = builder.varResolverBuilder
 				.vars(
@@ -2258,12 +2326,12 @@ public final class RestContext extends BeanContext {
 			for (String mimeType : getArrayProperty(REST_mimeTypes, String.class))
 				mimetypesFileTypeMap.addMimeTypes(mimeType);
 			
-			ClasspathResourceFinder rf = getInstanceProperty(REST_classpathResourceFinder, ClasspathResourceFinder.class, ClasspathResourceFinderBasic.class);
+			ClasspathResourceFinder rf = getInstanceProperty(REST_classpathResourceFinder, ClasspathResourceFinder.class, ClasspathResourceFinderBasic.class, true, this);
 			boolean useClasspathResourceCaching = getProperty(REST_useClasspathResourceCaching, boolean.class, true);
 			staticResourceManager = new ClasspathResourceManager(resourceClass, rf, useClasspathResourceCaching);
 
-			supportedContentTypes = getListProperty(REST_supportedContentTypes, MediaType.class, serializers.getSupportedMediaTypes());
-			supportedAcceptTypes = getListProperty(REST_supportedAcceptTypes, MediaType.class, parsers.getSupportedMediaTypes());
+			consumes = getListProperty(REST_consumes, MediaType.class, parsers.getSupportedMediaTypes());
+			produces = getListProperty(REST_produces, MediaType.class, serializers.getSupportedMediaTypes());
 			
 			staticFiles = ArrayUtils.reverse(getArrayProperty(REST_staticFiles, StaticFileMapping.class));
 			Set<String> s = new TreeSet<>();
@@ -2480,7 +2548,7 @@ public final class RestContext extends BeanContext {
 			this.callRouters = Collections.unmodifiableMap(_callRouters);
 
 			// Initialize our child resources.
-			resourceResolver = getInstanceProperty(REST_resourceResolver, resource, RestResourceResolver.class, parentContext == null ? RestResourceResolverDefault.class : parentContext.resourceResolver, true, this, ps);
+			resourceResolver = getInstanceProperty(REST_resourceResolver, resource, RestResourceResolver.class, parentContext == null ? RestResourceResolverDefault.class : parentContext.resourceResolver, true, this);
 			for (Object o : getArrayProperty(REST_children, Object.class)) {
 				String path = null;
 				Object r = null;
@@ -2520,8 +2588,8 @@ public final class RestContext extends BeanContext {
 				childResources.put(path, rc2);
 			}
 
-			callHandler = getInstanceProperty(REST_callHandler, resource, RestCallHandler.class, RestCallHandlerDefault.class, true, this, ps);
-			infoProvider = getInstanceProperty(REST_infoProvider, resource, RestInfoProvider.class, RestInfoProviderDefault.class, true, this, ps);
+			callHandler = getInstanceProperty(REST_callHandler, resource, RestCallHandler.class, RestCallHandlerDefault.class, true, this);
+			infoProvider = getInstanceProperty(REST_infoProvider, resource, RestInfoProvider.class, RestInfoProviderDefault.class, true, this);
 
 		} catch (RestException e) {
 			_initException = e;
@@ -3484,13 +3552,20 @@ public final class RestContext extends BeanContext {
 	 * 
 	 * <p>
 	 * By default, this is simply the list of accept types supported by the registered parsers, but
-	 * can be overridden via the {@link RestContextBuilder#supportedAcceptTypes(boolean,MediaType...)}/{@link RestContextBuilder#supportedAcceptTypes(boolean,String...)}
-	 * methods.
+	 * can be overridden via the following:
+	 * <ul>
+	 * 	<li class='jf'>{@link RestContext#REST_produces}
+	 * 	<li class='ja'>{@link RestResource#produces()}
+	 * 	<li class='jm'>{@link RestContextBuilder#produces(boolean,MediaType...)}
+	 * 	<li class='jm'>{@link RestContextBuilder#produces(boolean,String...)}
+	 * </ul>
 	 * 
-	 * @return The supported <code>Accept</code> header values for this resource.  Never <jk>null</jk>.
+	 * @return 
+	 * 	The supported <code>Accept</code> header values for this resource.  
+	 * 	<br>Never <jk>null</jk>.
 	 */
-	protected List<MediaType> getSupportedAcceptTypes() {
-		return supportedAcceptTypes;
+	protected List<MediaType> getProduces() {
+		return produces;
 	}
 
 	/**
@@ -3498,13 +3573,20 @@ public final class RestContext extends BeanContext {
 	 * 
 	 * <p>
 	 * By default, this is simply the list of content types supported by the registered serializers, but can be
-	 * overridden via the {@link RestContextBuilder#supportedContentTypes(boolean,MediaType...)}/{@link RestContextBuilder#supportedContentTypes(boolean,String...)}
-	 * methods.
+	 * overridden via the following:
+	 * <ul>
+	 * 	<li class='jf'>{@link RestContext#REST_consumes}
+	 * 	<li class='ja'>{@link RestResource#consumes()}
+	 * 	<li class='jm'>{@link RestContextBuilder#consumes(boolean,MediaType...)}
+	 * 	<li class='jm'>{@link RestContextBuilder#consumes(boolean,String...)}
+	 * </ul>
 	 * 
-	 * @return The supported <code>Content-Type</code> header values for this resource.  Never <jk>null</jk>.
+	 * @return 
+	 * 	The supported <code>Content-Type</code> header values for this resource.  
+	 * 	<br>Never <jk>null</jk>.
 	 */
-	protected List<MediaType> getSupportedContentTypes() {
-		return supportedContentTypes;
+	protected List<MediaType> getConsumes() {
+		return consumes;
 	}
 
 	/**
@@ -3701,6 +3783,16 @@ public final class RestContext extends BeanContext {
 		return null;
 	}
 
+	/**
+	 * TODO
+	 * 
+	 * @param method
+	 * @return TODO
+	 */
+	protected RestParam[] getRestParams(Method method) {
+		return callMethods.get(method.getName()).params;
+	}
+
 	@Override /* BeanContextBuilder */
 	public BeanSession createSession(BeanSessionArgs args) {
 		throw new NoSuchMethodError();

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/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 85bbf26..7c24de3 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
@@ -189,10 +189,10 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 				serializers(r.serializers());
 				parsers(r.parsers());
 				encoders(r.encoders());
-				if (r.supportedAcceptTypes().length > 0)
-					supportedAcceptTypes(false, resolveVars(vr, r.supportedAcceptTypes()));
-				if (r.supportedContentTypes().length > 0)
-					supportedContentTypes(false, resolveVars(vr, r.supportedContentTypes()));
+				if (r.produces().length > 0)
+					produces(false, resolveVars(vr, r.produces()));
+				if (r.consumes().length > 0)
+					consumes(false, resolveVars(vr, r.consumes()));
 				defaultRequestHeaders(resolveVars(vr, r.defaultRequestHeaders()));
 				defaultResponseHeaders(resolveVars(vr, r.defaultResponseHeaders()));
 				responseHandlers(r.responseHandlers());
@@ -1766,7 +1766,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link RestContext#REST_supportedAcceptTypes}
+	 * 	<li class='jf'>{@link RestContext#REST_produces}
 	 * </ul>
 	 * 
 	 * @param append
@@ -1774,19 +1774,19 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * @param values The values to add to this setting.
 	 * @return This object (for method chaining).
 	 */
-	public RestContextBuilder supportedAcceptTypes(boolean append, String...values) {
-		return set(append, REST_supportedAcceptTypes, values);
+	public RestContextBuilder produces(boolean append, String...values) {
+		return set(append, REST_produces, values);
 	}
 
 	/**
 	 * Configuration property:  Supported accept media types.
 	 * 
 	 * <p>
-	 * Same as {@link #supportedAcceptTypes(boolean, String...)} except input is {@link MediaType} instances.
+	 * Same as {@link #produces(boolean, String...)} except input is {@link MediaType} instances.
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link RestContext#REST_supportedAcceptTypes}
+	 * 	<li class='jf'>{@link RestContext#REST_produces}
 	 * </ul>
 	 * 
 	 * @param append
@@ -1794,8 +1794,8 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * @param values The values to add to this setting.
 	 * @return This object (for method chaining).
 	 */
-	public RestContextBuilder supportedAcceptTypes(boolean append, MediaType...values) {
-		return set(append, REST_supportedAcceptTypes, values);
+	public RestContextBuilder produces(boolean append, MediaType...values) {
+		return set(append, REST_produces, values);
 	}
 
 	/**
@@ -1806,7 +1806,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link RestContext#REST_supportedContentTypes}
+	 * 	<li class='jf'>{@link RestContext#REST_consumes}
 	 * </ul>
 	 * 
 	 * @param append
@@ -1814,19 +1814,19 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * @param values The values to add to this setting.
 	 * @return This object (for method chaining).
 	 */
-	public RestContextBuilder supportedContentTypes(boolean append, String...values) {
-		return set(append, REST_supportedContentTypes, values);
+	public RestContextBuilder consumes(boolean append, String...values) {
+		return set(append, REST_consumes, values);
 	}
 
 	/**
 	 * Configuration property:  Supported content media types.
 	 * 
 	 * <p>
-	 * Same as {@link #supportedContentTypes(boolean, String...)} except input is {@link MediaType} instances.
+	 * Same as {@link #consumes(boolean, String...)} except input is {@link MediaType} instances.
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link RestContext#REST_supportedContentTypes}
+	 * 	<li class='jf'>{@link RestContext#REST_consumes}
 	 * </ul>
 	 * 
 	 * @param append
@@ -1834,8 +1834,8 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * @param values The values to add to this setting.
 	 * @return This object (for method chaining).
 	 */
-	public RestContextBuilder supportedContentTypes(boolean append, MediaType...values) {
-		return set(append, REST_supportedContentTypes, values);
+	public RestContextBuilder consumes(boolean append, MediaType...values) {
+		return set(append, REST_consumes, values);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/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 b817fb4..188540e 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
@@ -12,13 +12,18 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest;
 
+import java.lang.reflect.Method;
 import java.util.*;
 
 import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.rest.annotation.*;
 
 /**
- * Class that provides documentation and other related information about a REST resource.
+ * REST resource information provider.
  * 
+ * <p>
+ * Provides localized Swagger documentation and other related information about a REST resource.
  * 
  * <h5 class='topic'>Additional Information</h5>
  * <ul>
@@ -41,136 +46,277 @@ public interface RestInfoProvider {
 	 * 
 	 * @param req The incoming HTTP request.
 	 * @return 
-	 * 	The contents of the parsed swagger file.
-	 * 	Returns <jk>null</jk> if a swagger file could not be found.
-	 * @throws RestException
+	 * 	The contents of the parsed swagger file, or <jk>null</jk> if a swagger file could not be found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public Swagger getSwaggerFromFile(RestRequest req) throws RestException;
+	public Swagger getSwaggerFromFile(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized swagger for this REST resource.
+	 * Returns the localized swagger for the REST resource.
 	 * 
 	 * <p>
 	 * If {@link #getSwaggerFromFile(RestRequest)} returns a non-<jk>null</jk> value, then 
 	 * that swagger is returned by this method.
-	 * <br>Otherwise, a new swagger object is return with information gathered via various means.
+	 * <br>Otherwise, a new swagger object is return with information gathered via the other methods defined on this class.
 	 * 
 	 * @param req The incoming HTTP request.
-	 * @return A new Swagger instance.
-	 * @throws RestException
+	 * @return 
+	 * 	A new {@link Swagger} instance.
+	 * 	<br>Never <jk>null</jk>.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public Swagger getSwagger(RestRequest req) throws RestException;
-
+	public Swagger getSwagger(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized summary of the specified java method on this servlet.
+	 * Returns the localized operation ID of the specified java method.
 	 * 
-	 * @param javaMethodName The name of the Java method whose description we're retrieving.
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
 	 * @param req The current request.
-	 * @return The localized summary of the method, or a blank string if no summary was found.
+	 * @return The localized operation ID of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getMethodSummary(String javaMethodName, RestRequest req);
+	public String getMethodOperationId(Method method, RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized summary of the java method invoked on the specified request.
+	 * Returns the localized summary of the specified java method.
 	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
 	 * @param req The current request.
-	 * @return The localized summary of the method, or a blank string if no summary was found.
+	 * @return The localized summary of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getMethodSummary(RestRequest req);
+	public String getMethodSummary(Method method, RestRequest req) throws Exception;
 
 	/**
 	 * Returns the localized description of the specified java method on this servlet.
 	 * 
-	 * @param javaMethodName The name of the Java method whose description we're retrieving.
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The localized description of the method, or <jk>null</jk> if none was was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
+	 */
+	public String getMethodDescription(Method method, RestRequest req) throws Exception;
+
+	/**
+	 * Returns the localized tags of the specified java method on this servlet.
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The localized tags of the method, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
+	 */
+	public List<String> getMethodTags(Method method, RestRequest req) throws Exception;
+	
+	/**
+	 * Returns the localized external documentation of the specified java method on this servlet.
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The localized external documentation of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
+	 */
+	public ExternalDocumentation getMethodExternalDocs(Method method, RestRequest req) throws Exception;
+	
+	/**
+	 * Returns the localized parameter info for the specified java method.
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The localized parameter info of the method, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
+	 */
+	public List<ParameterInfo> getMethodParameters(Method method, RestRequest req) throws Exception;
+
+	/**
+	 * Returns the localized Swagger response information about the specified Java method.
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
 	 * @param req The current request.
-	 * @return The localized description of the method, or a blank string if no description was found.
+	 * @return The localized response information of the method, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getMethodDescription(String javaMethodName, RestRequest req);
+	public Map<Integer,ResponseInfo> getMethodResponses(Method method, RestRequest req) throws Exception;
+	
+	/**
+	 * Returns the supported <code>Accept</code> types the specified Java method.
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The supported <code>Accept</code> types of the method, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
+	 */
+	public List<MediaType> getMethodProduces(Method method, RestRequest req) throws Exception;
+	
+	/**
+	 * Returns the supported <code>Content-Type</code> types the specified Java method.
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The supported <code>Content-Type</code> types of the method, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
+	 */
+	public List<MediaType> getMethodConsumes(Method method, RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized description of the invoked java method on the specified request.
+	 * Returns whether the specified method is deprecated
 	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
 	 * @param req The current request.
-	 * @return The localized description of the method, or a blank string if no description was found.
+	 * @return <jk>true</jk> if the method is deprecated.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getMethodDescription(RestRequest req);
+	public boolean isDeprecated(Method method, RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized site name of this REST resource.
+	 * Returns the localized site name of the REST resource.
 	 * 
 	 * @param req The current request.
-	 * @return The localized description of this REST resource, or <jk>null</jk> if no resource description was found.
+	 * @return The localized site name of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getSiteName(RestRequest req);
+	public String getSiteName(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized title of this REST resource.
+	 * Returns the localized title of the REST resource.
 	 * 
 	 * @param req The current request.
-	 * @return The localized description of this REST resource, or <jk>null</jk> if no resource description was found.
+	 * @return The localized title of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getTitle(RestRequest req);
+	public String getTitle(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized description of this REST resource.
+	 * Returns the localized description of the REST resource.
 	 * 
 	 * @param req The current request.
-	 * @return The localized description of this REST resource, or <jk>null</jk> if no resource description was found.
+	 * @return The localized description of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getDescription(RestRequest req);
+	public String getDescription(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized contact information of this REST resource.
+	 * Returns the localized contact information of the REST resource.
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized contact information of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public Contact getContact(RestRequest req) ;
+	public Contact getContact(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the localized license information of this REST resource.
+	 * Returns the localized license information of the REST resource.
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized license information of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public License getLicense(RestRequest req);
+	public License getLicense(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the terms-of-service information of this REST resource.
+	 * Returns the terms-of-service iof the REST resource.
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized terms-of-service of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getTermsOfService(RestRequest req);
+	public String getTermsOfService(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the version information of this REST resource.
+	 * Returns the localized version of the REST resource.
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized version of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public String getVersion(RestRequest req);
+	public String getVersion(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the version information of this REST resource.
+	 * Returns the supported <code>Content-Type</code> request headers for the REST resource.
+	 * 
+	 * @param req The current request.
+	 * @return
+	 * 	The supported <code>Content-Type</code> request headers of the REST resource, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
+	 */
+	public List<MediaType> getConsumes(RestRequest req) throws Exception;
+	
+	/**
+	 * Returns the supported <code>Accept</code> request headers for the REST resource.
+	 * 
+	 * @param req The current request.
+	 * @return
+	 * 	The supported <code>Accept</code> request headers of the REST resource, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
+	 */
+	public List<MediaType> getProduces(RestRequest req) throws Exception;
+	
+	/**
+	 * Returns the localized tags of the REST resource.
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized tags of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public List<Tag> getTags(RestRequest req);
+	public List<Tag> getTags(RestRequest req) throws Exception;
 
 	/**
-	 * Returns the external documentation of this REST resource.
+	 * Returns the external documentation of the REST resource.
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized external documentation of the REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 * 	Throw a {@link RestException} with a specific HTTP error status or any other exception 
+	 * 	to cause a <jsf>SC_INTERNAL_SERVER_ERROR</jsf>.
 	 */
-	public ExternalDocumentation getExternalDocs(RestRequest req);
+	public ExternalDocumentation getExternalDocs(RestRequest req) throws Exception;
 }


[2/3] juneau git commit: Refactor RestInfoProvider.

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProviderDefault.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProviderDefault.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProviderDefault.java
index 11cad76..983856a 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProviderDefault.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProviderDefault.java
@@ -16,11 +16,13 @@ import static javax.servlet.http.HttpServletResponse.*;
 import static org.apache.juneau.dto.swagger.SwaggerBuilder.*;
 import static org.apache.juneau.internal.ReflectionUtils.*;
 
+import java.lang.reflect.Method;
 import java.util.*;
 import java.util.concurrent.*;
 
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
@@ -31,8 +33,6 @@ import org.apache.juneau.svl.*;
  * 
  * <p>
  * Subclasses can override these methods to tailor how HTTP REST resources are documented.
- * Subclasses MUST implement a public constructor that takes in a {@link RestContext} object.
- * 
  * 
  * <h5 class='topic'>Additional Information</h5>
  * <ul>
@@ -125,20 +125,17 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Returned objects are cached for later quick-lookup.
 	 * 
 	 * @param req The incoming HTTP request.
-	 * @return The parsed swagger object, or <jk>null</jk> if the swagger file could not be found.
-	 * @throws RestException
+	 * @return The parsed swagger object, or <jk>null</jk> if none could be found.
+	 * @throws Exception 
+	 * 	If swagger file was not valid JSON.
 	 */
 	@Override /* RestInfoProvider */
-	public Swagger getSwaggerFromFile(RestRequest req) throws RestException {
+	public Swagger getSwaggerFromFile(RestRequest req) throws Exception {
 		Locale locale = req.getLocale();
 		Swagger s = swaggers.get(locale);
 		if (s == null) {
-			try {
-				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);
-			}
+			s = context.getClasspathResource(Swagger.class, MediaType.JSON, getClass().getSimpleName() + ".json", locale);
+			swaggers.putIfAbsent(locale, s == null ? Swagger.NULL : s);
 		}
 		return s == Swagger.NULL ? null : s;
 	}
@@ -146,98 +143,137 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	/**
 	 * Returns the localized swagger for this REST resource.
 	 * 
+	 * <p>
+	 * Subclasses can override this method to customize the Swagger.
+	 * 
 	 * @param req The incoming HTTP request.
-	 * @return A new Swagger instance.
-	 * @throws RestException
+	 * @return 
+	 * 	A new Swagger instance.
+	 * 	<br>Never <jk>null</jk>.
+	 * @throws Exception
 	 */
 	@Override /* RestInfoProvider */
-	public Swagger getSwagger(RestRequest req) throws RestException {
-		try {
-			// If a file is defined, use that.
-			Swagger s = req.getSwaggerFromFile();
-			if (s != null)
-				return s;
-
-			s = swagger(
-				info(getTitle(req), getVersion(req))
-					.contact(getContact(req))
-					.license(getLicense(req))
-					.description(getDescription(req))
-					.termsOfService(getTermsOfService(req))
-				)
-				.consumes(req.getSupportedAcceptTypes())
-				.produces(req.getSupportedContentTypes())
-				.tags(getTags(req))
-				.externalDocs(getExternalDocs(req));
-
-			for (RestJavaMethod sm : context.getCallMethods().values()) {
-				if (sm.isRequestAllowed(req)) {
-					Operation o = sm.getSwaggerOperation(req);
-					s.path(
-						sm.getPathPattern(),
-						sm.getHttpMethod().toLowerCase(),
-						o
-					);
-				}
-			}
+	public Swagger getSwagger(RestRequest req) throws Exception {
+		
+		// If a file is defined, use that.
+		Swagger s = getSwaggerFromFile(req);
+		if (s != null)
 			return s;
-		} catch (RestException e) {
-			throw e;
-		} catch (Exception e) {
-			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+
+		s = swagger(
+			info(getTitle(req), getVersion(req))
+				.contact(getContact(req))
+				.license(getLicense(req))
+				.description(getDescription(req))
+				.termsOfService(getTermsOfService(req))
+			)
+			.consumes(getConsumes(req))
+			.produces(getProduces(req))
+			.tags(getTags(req))
+			.externalDocs(getExternalDocs(req));
+
+		for (RestJavaMethod sm : context.getCallMethods().values()) {
+			if (sm.isRequestAllowed(req)) {
+				Method m = sm.method;
+				Operation o = operation()
+					.operationId(getMethodOperationId(m, req))
+					.description(getMethodDescription(m, req))
+					.tags(getMethodTags(m, req))
+					.summary(getMethodSummary(m, req))
+					.externalDocs(getMethodExternalDocs(m, req))
+					.parameters(getMethodParameters(m, req))
+					.responses(getMethodResponses(m, req));
+
+				if (isDeprecated(m, req))
+					o.deprecated(true);
+				
+				o.consumes(getMethodConsumes(m, req));
+				o.produces(getMethodProduces(m, req));
+
+				s.path(
+					sm.getPathPattern(),
+					sm.getHttpMethod().toLowerCase(),
+					o
+				);
+			}
 		}
+		
+		return s;
 	}
 
 	/**
-	 * Returns the localized summary of the specified java method on this servlet.
+	 * Returns the localized operation ID of the specified java method.
 	 * 
 	 * <p>
-	 * Subclasses can override this method to provide their own summary.
+	 * Subclasses can override this method to provide their own operation ID.
 	 * 
 	 * <p>
-	 * The default implementation returns the summary from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link RestMethod#summary() @RestMethod.summary()} annotation on the method.
-	 * 	<li><ck>[ClassName].[javaMethodName].summary</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>[javaMethodName].summary</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * </ol>
+	 * The default implementation simply returns the Java method name.
 	 * 
-	 * @param javaMethodName The name of the Java method whose description we're retrieving.
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
 	 * @param req The current request.
-	 * @return The localized summary of the method, or a blank string if no summary was found.
+	 * @return The localized operation ID of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getMethodSummary(String javaMethodName, RestRequest req) {
-		RestJavaMethod m = context.getCallMethods().get(javaMethodName);
-		if (m != null)
-			return m.getSummary(req);
-		return "";
+	public String getMethodOperationId(Method method, RestRequest req) throws Exception {
+		return method.getName();
 	}
 
 	/**
-	 * Returns the localized summary of the java method invoked on the specified request.
+	 * Returns the localized summary of the specified java method on this servlet.
 	 * 
 	 * <p>
 	 * Subclasses can override this method to provide their own summary.
 	 * 
 	 * <p>
-	 * The default implementation returns the summary from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link RestMethod#summary() @RestMethod.summary()} annotation on the method.
-	 * 	<li><ck>[ClassName].[javaMethodName].summary</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>[javaMethodName].summary</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link RestMethod#summary() @RestMethod.summary()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ja>@RestMethod</ja>(summary=<js>"Summary of my method"</js>)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ja>@RestMethod</ja>(summary=<js>"$L{myLocalizedSummary}"</js>)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * 	<li>Localized string from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].[javaMethodName].summary</ck>
+	 * 			<li><ck>[javaMethodName].summary</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link RestMethod#summary() @RestMethod.summary()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.myMethod.summary</ck> = <cv>Summary of my method.</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.myMethod.summary</ck> = <cv>$C{MyStrings/MyClass.myMethod.summary}</cv>
+	 * 		</p>
 	 * </ol>
 	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
 	 * @param req The current request.
-	 * @return The localized summary of the method, or a blank string if no summary was found.
+	 * @return The localized summary of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getMethodSummary(RestRequest req) {
-		return getMethodSummary(req.getJavaMethod().getName(), req);
+	public String getMethodSummary(Method method, RestRequest req) throws Exception {
+		VarResolverSession vr = req.getVarResolverSession();
+
+		String s = method.getAnnotation(RestMethod.class).summary();
+		if (s.isEmpty())
+			s = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".summary");
+		if (s != null)
+			return vr.resolve(s);
+		
+		Operation o = getSwaggerOperationFromFile(method, req);
+		return o == null ? null : o.getSummary();
 	}
 
 	/**
@@ -247,49 +283,539 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own description.
 	 * 
 	 * <p>
-	 * The default implementation returns the description from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link RestMethod#description() @RestMethod.description()} annotation on the method.
-	 * 	<li><ck>[ClassName].[javaMethodName].description</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>[javaMethodName].description</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link RestMethod#description() @RestMethod.description()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ja>@RestMethod</ja>(description=<js>"Description of my method"</js>)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ja>@RestMethod</ja>(description=<js>"$L{myLocalizedDescription}"</js>)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * 	<li>Localized string from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].[javaMethodName].description</ck>
+	 * 			<li><ck>[javaMethodName].description</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link RestMethod#description() @RestMethod.description()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.myMethod.description</ck> = <cv>Description of my method.</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.myMethod.description</ck> = <cv>$C{MyStrings/MyClass.myMethod.description}</cv>
+	 * 		</p>
 	 * </ol>
 	 * 
-	 * @param javaMethodName The name of the Java method whose description we're retrieving.
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
 	 * @param req The current request.
-	 * @return The localized description of the method, or a blank string if no description was found.
+	 * @return The localized description of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getMethodDescription(String javaMethodName, RestRequest req) {
-		RestJavaMethod m = context.getCallMethods().get(javaMethodName);
-		if (m != null)
-			return m.getDescription(req);
-		return "";
+	public String getMethodDescription(Method method, RestRequest req) throws Exception {
+		VarResolverSession vr = req.getVarResolverSession();
+		
+		String s = method.getAnnotation(RestMethod.class).description();
+		if (s.isEmpty())
+			s = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".description");
+		if (s != null)
+			return vr.resolve(s);
+		
+		Operation o = getSwaggerOperationFromFile(method, req);
+		return o == null ? null : o.getDescription();
 	}
 
 	/**
-	 * Returns the localized description of the invoked java method on the specified request.
+	 * Returns the localized Swagger tags for this Java method.
 	 * 
 	 * <p>
-	 * Subclasses can override this method to provide their own description.
+	 * Subclasses can override this method to provide their own tags.
+	 * 
+	 * <p>
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link MethodSwagger#tags() @MethodSwagger.tags()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(tags=<js>"foo,bar,baz"</js>)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(tags=<js>"$L{myLocalizedTags}"</js>)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * 	<li>Localized string from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].[javaMethodName].tags</ck>
+	 * 			<li><ck>[javaMethodName].tags</ck>
+	 * 		</ol>
+	 * 		<br>Value can be a comma-delimited list or JSON array.
+	 * 		<br>Value can contain any SVL variables defined on the {@link MethodSwagger#tags() @MethodSwagger.tags()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Comma-delimited list</cc>
+	 * 	<ck>MyClass.myMethod.tags</ck> = <cv>foo, bar, baz</cv>
+	 * 	
+	 * 	<cc>// JSON array</cc>
+	 * 	<ck>MyClass.myMethod.tags</ck> = <cv>["foo", "bar", "baz"]</cv>
+	 * 
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.myMethod.description</ck> = <cv>$C{MyStrings/MyClass.myMethod.tags}</cv>
+	 * 		</p>
+	 * </ol>
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The localized tags of the method, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 */
+	@Override /* RestInfoProvider */
+	public List<String> getMethodTags(Method method, RestRequest req) throws Exception {
+		JsonParser p = JsonParser.DEFAULT;
+		VarResolverSession vr = req.getVarResolverSession();
+		
+		String s = method.getAnnotation(RestMethod.class).swagger().tags();
+		if (s.isEmpty())
+			s = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".tags");
+		if (s != null) {
+			s = vr.resolve(s);
+			if (StringUtils.isObjectList(s)) 
+				return p.parse(s, ArrayList.class, String.class);
+			return Arrays.asList(StringUtils.split(s));
+		}
+
+		Operation o = getSwaggerOperationFromFile(method, req);
+		return o == null ? null : o.getTags();
+	}
+
+	/**
+	 * Returns the localized external documentation of the specified java method on this servlet.
+	 * 
+	 * <p>
+	 * Subclasses can override this method to provide their own external documentation.
+	 * 
+	 * <p>
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link MethodSwagger#externalDocs() @MethodSwagger.externalDocs()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(externalDocs=<js>"{description:'Find more info here',url:'https://swagger.io'}"</js>)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(externalDocs=<js>"$L{myLocalizedExternalDocs}"</js>)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * 	<li>Localized string from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].[javaMethodName].externalDocs</ck>
+	 * 			<li><ck>[javaMethodName].externalDocs</ck>
+	 * 		</ol>
+	 * 		<br>Value is a JSON representation of a {@link ExternalDocumentation} object.
+	 * 		<br>Value can contain any SVL variables defined on the {@link MethodSwagger#externalDocs() @MethodSwagger.externalDocs()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.myMethod.externalDocs</ck> = <cv>{description:"Find more info here",url:"https://swagger.io"}</js>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.myMethod.externalDocs</ck> = <cv>$C{MyStrings/MyClass.myMethod.externalDocs}</cv>
+	 * 		</p>
+	 * </ol>
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The localized external documentation of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 */
+	@Override /* RestInfoProvider */
+	public ExternalDocumentation getMethodExternalDocs(Method method, RestRequest req) throws Exception {
+		JsonParser p = JsonParser.DEFAULT;
+		VarResolverSession vr = req.getVarResolverSession();
+		
+		String s = method.getAnnotation(RestMethod.class).swagger().externalDocs();
+		if (s.isEmpty())
+			s = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".externalDocs");
+		if (s != null) 
+			return p.parse(vr.resolve(s), ExternalDocumentation.class);
+
+		Operation o = getSwaggerOperationFromFile(method, req);
+		return o == null ? null : o.getExternalDocs();
+	}
+	
+	/**
+	 * Returns the localized parameter info for the specified java method.
+	 * 
+	 * <p>
+	 * Subclasses can override this method to provide their own parameter info.
+	 * 
+	 * <p>
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>Operation information from swagger file.
+	 * 	<li>{@link MethodSwagger#parameters() @MethodSwagger.parameters()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(
+	 * 			parameters={
+	 * 				<ja>@Parameter</ja>(in=<js>"path"</js>, name=<js>"a"</js>, description=<js>"The 'a' attribute"</js>)
+	 * 			}
+	 * 		)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(
+	 * 			parameters={
+	 * 				<ja>@Parameter</ja>(in=<js>"path"</js>, name=<js>"a"</js>, description=<js>"$L{myLocalizedParamADescription}"</js>)
+	 * 			}
+	 * 		)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].[javaMethodName].parameters</ck>
+	 * 			<li><ck>[javaMethodName].parameters</ck>
+	 * 		</ol>
+	 * 		<br>Value is a JSON representation of a <code>{@link ParameterInfo}[]</code> object.
+	 * 		<br>Value can contain any SVL variables defined on the {@link MethodSwagger#parameters() @MethodSwagger.parameters()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.myMethod.parameters</ck> = <cv>[{name:"a",in:"path",description:"The ''a'' attribute"}]</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.myMethod.parameters</ck> = <cv>$C{MyStrings/MyClass.myMethod.parameters}</cv>
+	 * 		</p>
+	 * 	<li>Information gathered directly from the parameters on the Java method.
+	 * </ol>
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The localized parameter info of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 */
+	@Override /* RestInfoProvider */
+	public List<ParameterInfo> getMethodParameters(Method method, RestRequest req) throws Exception {
+		
+		Operation o = getSwaggerOperationFromFile(method, req);
+		if (o != null && o.getParameters() != null)
+			return o.getParameters();
+
+		VarResolverSession vr = req.getVarResolverSession();
+		JsonParser jp = JsonParser.DEFAULT;
+		Map<String,ParameterInfo> m = new TreeMap<>();
+
+		// First parse @RestMethod.parameters() annotation.
+		for (org.apache.juneau.rest.annotation.Parameter v : method.getAnnotation(RestMethod.class).swagger().parameters()) {
+			String in = vr.resolve(v.in());
+			ParameterInfo p = parameterInfo(in, vr.resolve(v.name()));
+
+			if (! v.description().isEmpty())
+				p.description(vr.resolve(v.description()));
+			if (v.required())
+				p.required(v.required());
+
+			if ("body".equals(in)) {
+				if (! v.schema().isEmpty())
+					p.schema(jp.parse(vr.resolve(v.schema()), SchemaInfo.class));
+			} else {
+				if (v.allowEmptyValue())
+					p.allowEmptyValue(v.allowEmptyValue());
+				if (! v.collectionFormat().isEmpty())
+					p.collectionFormat(vr.resolve(v.collectionFormat()));
+				if (! v._default().isEmpty())
+					p._default(vr.resolve(v._default()));
+				if (! v.format().isEmpty())
+					p.format(vr.resolve(v.format()));
+				if (! v.items().isEmpty())
+					p.items(jp.parse(vr.resolve(v.items()), Items.class));
+				p.type(vr.resolve(v.type()));
+			}
+			m.put(p.getIn() + '.' + p.getName(), p);
+		}
+
+		// Next, look in resource bundle.
+		String s = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".parameters");
+		if (s != null) {
+			for (ParameterInfo pi : jp.parse(vr.resolve(s), ParameterInfo[].class)) {
+				String key = pi.getIn() + '.' + pi.getName();
+				ParameterInfo p = m.get(key);
+				if (p == null)
+					m.put(key, pi);
+				else 
+					p.copyFrom(pi);
+			}
+		}
+
+		// Finally, look for parameters defined on method.
+		for (RestParam mp : context.getRestParams(method)) {
+			RestParamType in = mp.getParamType();
+			if (in != RestParamType.OTHER) {
+				String k2 = in.toString() + '.' + (in == RestParamType.BODY ? null : mp.getName());
+				ParameterInfo p = m.get(k2);
+				if (p == null) {
+					p = parameterInfoStrict(in.toString(), mp.getName());
+					m.put(k2, p);
+				}
+			}
+		}
+		
+		return m.isEmpty() ? null : new ArrayList<>(m.values());
+	}
+
+	/**
+	 * Returns the localized response info for the specified java method.
+	 * 
+	 * <p>
+	 * Subclasses can override this method to provide their own parameter info.
+	 * 
+	 * <p>
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>Operation information from swagger file.
+	 * 	<li>{@link MethodSwagger#responses() @MethodSwagger.responses()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(
+	 * 			responses={
+	 * 				<ja>@Response</ja>(
+	 * 					value=302,
+	 * 					description=<js>"Thing wasn't found here"</js>,
+	 * 					headers={
+	 * 						<ja>@Parameter</ja>(name=<js>"Location"</js>, description=<js>"The place to find the thing"</js>)
+	 * 					}
+	 * 				)
+	 * 			}
+	 * 		)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(
+	 * 			responses={
+	 * 				<ja>@Response</ja>(
+	 * 					value=302,
+	 * 					description=<js>"Thing wasn't found here"</js>,
+	 * 					headers={
+	 * 						<ja>@Parameter</ja>(name=<js>"Location"</js>, description=<js>"$L{myLocalizedResponseDescription}"</js>)
+	 * 					}
+	 * 				)
+	 * 			}
+	 * 		)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].[javaMethodName].responses</ck>
+	 * 			<li><ck>[javaMethodName].responses</ck>
+	 * 		</ol>
+	 * 		<br>Value is a JSON representation of a <code>Map&lt;Integer,{@link ResponseInfo}&gt;</code> object.
+	 * 		<br>Value can contain any SVL variables defined on the {@link MethodSwagger#responses() @MethodSwagger.responses()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.myMethod.responses</ck> = <cv>{302:{description:'Thing wasn''t found here',headers={Location:{description:"The place to find the thing"}}}</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.myMethod.responses</ck> = <cv>$C{MyStrings/MyClass.myMethod.responses}</cv>
+	 * 		</p>
+	 * 	<li>Information gathered directly from the parameters on the Java method.
+	 * </ol>
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The localized response info of the method, or <jk>null</jk> if none was found.
+	 * @throws Exception 
+	 */
+	@SuppressWarnings("unchecked")
+	@Override /* RestInfoProvider */
+	public Map<Integer,ResponseInfo> getMethodResponses(Method method, RestRequest req) throws Exception {
+		
+		Operation o = getSwaggerOperationFromFile(method, req);
+		if (o != null && o.getResponses() != null)
+			return o.getResponses();
+
+		VarResolverSession vr = req.getVarResolverSession();
+		JsonParser jp = JsonParser.DEFAULT;
+		Map<Integer,ResponseInfo> m = new TreeMap<>();
+		Map<String,HeaderInfo> m2 = new TreeMap<>();
+
+		// First parse @RestMethod.parameters() annotation.
+		for (Response r : method.getAnnotation(RestMethod.class).swagger().responses()) {
+			int httpCode = r.value();
+			String description = r.description().isEmpty() ? RestUtils.getHttpResponseText(r.value()) : vr.resolve(r.description());
+			ResponseInfo r2 = responseInfo(description);
+
+			if (r.headers().length > 0) {
+				for (org.apache.juneau.rest.annotation.Parameter v : r.headers()) {
+					HeaderInfo h = headerInfoStrict(vr.resolve(v.type()));
+					if (! v.collectionFormat().isEmpty())
+						h.collectionFormat(vr.resolve(v.collectionFormat()));
+					if (! v._default().isEmpty())
+						h._default(vr.resolve(v._default()));
+					if (! v.description().isEmpty())
+						h.description(vr.resolve(v.description()));
+					if (! v.format().isEmpty())
+						h.format(vr.resolve(v.format()));
+					if (! v.items().isEmpty())
+						h.items(jp.parse(vr.resolve(v.items()), Items.class));
+					r2.header(v.name(), h);
+					m2.put(httpCode + '.' + v.name(), h);
+				}
+			}
+			m.put(httpCode, r2);
+		}
+
+		// Next, look in resource bundle.
+		String s = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".responses");
+		if (s != null) {
+			for (Map.Entry<Integer,ResponseInfo> e : ((Map<Integer,ResponseInfo>)jp.parse(vr.resolve(s), Map.class, Integer.class, ResponseInfo.class)).entrySet()) {
+				Integer httpCode = e.getKey();
+				ResponseInfo ri = e.getValue();
+
+				ResponseInfo r = m.get(httpCode);
+				if (r == null)
+					m.put(httpCode, ri);
+				else
+					r.copyFrom(ri);
+			}
+		}
+
+		return m.isEmpty() ? null : m;
+	}
+
+	/**
+	 * Returns the supported <code>Accept</code> types the specified Java method.
 	 * 
 	 * <p>
-	 * The default implementation returns the description from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link RestMethod#description() @RestMethod.description()} annotation on the method.
-	 * 	<li><ck>[ClassName].[javaMethodName].description</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>[javaMethodName].description</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
+	 * Subclasses can override this method to provide their own produces info.
+	 * 
+	 * <p>
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link RestMethod#produces() @RestMethod.supportedAcceptTypes()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ja>@RestMethod</ja>(supportedAcceptTypes={<js>"text/json"</js>})
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ja>@RestMethod</ja>(supportedAcceptTypes={<js>"$C{mySupportedProduces}"</js>})
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * 	<li>Media types defined on the parsers associated with the method.
 	 * </ol>
 	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
 	 * @param req The current request.
-	 * @return The localized description of the method, or a blank string if no description was found.
+	 * @return The supported <code>Accept</code> types of the method, or <jk>null</jk> if none was found 
+	 * 	or the list of media types match those of the parent resource class.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getMethodDescription(RestRequest req) {
-		return getMethodDescription(req.getJavaMethod().getName(), req);
+	public List<MediaType> getMethodProduces(Method method, RestRequest req) throws Exception {
+		VarResolverSession vr = req.getVarResolverSession();
+		String[] s = method.getAnnotation(RestMethod.class).produces();
+		if (s.length > 0)
+			return Arrays.asList(MediaType.forStrings(vr.resolve(s)));
+		List<MediaType> l = req.getSerializers().getSupportedMediaTypes();
+		return (l.equals(context.getProduces())  ? null : l);
+	}
+	
+	/**
+	 * Returns the supported <code>Content-Type</code> types the specified Java method.
+	 * 
+	 * <p>
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link RestMethod#consumes() @RestMethod.supportedContentTypes()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ja>@RestMethod</ja>(supportedContentTypes={<js>"text/json"</js>})
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ja>@RestMethod</ja>(supportedContentTypes={<js>"$C{mySupportedConsumes}"</js>})
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * 	<li>Media types defined on the serializers associated with the method.
+	 * </ol>
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return The supported <code>Content-Type</code> types of the method, or <jk>null</jk> if none was found 
+	 * 	or the list of media types match those of the parent resource class.
+	 * @throws Exception 
+	 */
+	@Override /* RestInfoProvider */
+	public List<MediaType> getMethodConsumes(Method method, RestRequest req) throws Exception {
+		VarResolverSession vr = req.getVarResolverSession();
+		String[] s = method.getAnnotation(RestMethod.class).consumes();
+		if (s.length > 0)
+			return Arrays.asList(MediaType.forStrings(vr.resolve(s)));
+		List<MediaType> l = req.getParsers().getSupportedMediaTypes();
+		return (l.equals(context.getConsumes())  ? null : l);
+	}
+
+	/**
+	 * Returns whether the specified method is deprecated
+	 * 
+	 * <p>
+	 * The default implementation returns the value from the following location:
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link MethodSwagger#deprecated() @MethodSwagger.deprecated()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<ja>@RestMethod</ja>(
+	 * 		swagger=<ja>@MethodSwagger</ja>(
+	 * 			deprecated=<jk>true</jk>
+	 * 		)
+	 * 	)
+	 * 	<jk>public</jk> Object myMethod() {...}
+	 * 		</p>
+	 * </ol>
+	 * 
+	 * @param method The Java method annotated with {@link RestMethod @RestMethod}.
+	 * @param req The current request.
+	 * @return <jk>true</jk> if the method is deprecated.
+	 * @throws Exception 
+	 */
+	@Override /* RestInfoProvider */
+	public boolean isDeprecated(Method method, RestRequest req) throws Exception {
+		return method.getAnnotation(RestMethod.class).swagger().deprecated();
 	}
 
 	/**
@@ -299,24 +825,45 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own site name.
 	 * 
 	 * <p>
-	 * The default implementation returns the description from the following locations (whichever matches first):
-	 * <ol>
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
 	 * 	<li>{@link RestResource#siteName() @RestResource.siteName()} annotation on this class, and then any parent classes.
-	 * 	<li><ck>[ClassName].siteName</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @ResourceBundle.messages()} annotation for this class, then any parent
-	 * 		classes.
-	 * 	<li><ck>siteName</ck> in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
-	 * 		annotation for this class, then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(siteName=<js>"My Site"</js>)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(siteName=<js>"$L{myLocalizedSiteName}"</js>)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].siteName</ck>
+	 * 			<li><ck>siteName</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link RestResource#siteName() @RestResource.siteName()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.siteName</ck> = <cv>My Site</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.siteName</ck> = <cv>$C{MyStrings/MyClass.siteName}</cv>
+	 * 		</p>
 	 * </ol>
 	 * 
 	 * @param req The current request.
-	 * @return The localized description of this REST resource, or <jk>null</jk> if no resource description was found.
+	 * @return The localized site name of this REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getSiteName(RestRequest req) {
+	public String getSiteName(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
-		if (this.siteName != null)
-			return vr.resolve(this.siteName);
+		if (siteName != null)
+			return vr.resolve(siteName);
 		String siteName = context.getMessages().findFirstString(req.getLocale(), "siteName");
 		if (siteName != null)
 			return vr.resolve(siteName);
@@ -330,29 +877,50 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own title.
 	 * 
 	 * <p>
-	 * The default implementation returns the description from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link RestResource#title() @RestResource.title()} annotation on this class, and then any parent classes.
-	 * 	<li><ck>[ClassName].title</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @ResourceBundle.messages()} annotation for this class, then any parent
-	 * 		classes.
-	 * 	<li><ck>title</ck> in resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
-	 * 		annotation for this class, then any parent classes.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link RestResource#title() @RestResource.siteName()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(title=<js>"My Resource"</js>)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(title=<js>"$L{myLocalizedTitle}"</js>)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].title</ck>
+	 * 			<li><ck>title</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link RestResource#title() @RestResource.title()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.title</ck> = <cv>My Resource</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.title</ck> = <cv>$C{MyStrings/MyClass.title}</cv>
+	 * 		</p>
 	 * 	<li><ck>/info/title</ck> entry in swagger file.
 	 * </ol>
 	 * 
 	 * @param req The current request.
-	 * @return The localized description of this REST resource, or <jk>null</jk> if no resource description was found.
+	 * @return The localized title of this REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getTitle(RestRequest req) {
+	public String getTitle(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
-		if (this.title != null)
-			return vr.resolve(this.title);
+		if (title != null)
+			return vr.resolve(title);
 		String title = context.getMessages().findFirstString(req.getLocale(), "title");
 		if (title != null)
 			return vr.resolve(title);
-		Swagger s = req.getSwaggerFromFile();
+		Swagger s = getSwaggerFromFile(req);
 		if (s != null && s.getInfo() != null)
 			return s.getInfo().getTitle();
 		return null;
@@ -365,29 +933,50 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own description.
 	 * 
 	 * <p>
-	 * The default implementation returns the description from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link RestResource#description() @RestResource.description()} annotation on this class, and then any
-	 * 		parent classes.
-	 * 	<li><ck>[ClassName].description</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>description</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link RestResource#description() @RestResource.description()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(description=<js>"My Resource"</js>)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(description=<js>"$L{myLocalizedDescription}"</js>)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].description</ck>
+	 * 			<li><ck>description</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link RestResource#description() @RestResource.description()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.description</ck> = <cv>My Resource</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.description</ck> = <cv>$C{MyStrings/MyClass.description}</cv>
+	 * 		</p>
 	 * 	<li><ck>/info/description</ck> entry in swagger file.
 	 * </ol>
 	 * 
 	 * @param req The current request.
-	 * @return The localized description of this REST resource, or <jk>null</jk> if no resource description was found.
+	 * @return The localized description of this REST resource, or <jk>null</jk> if none was was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getDescription(RestRequest req) {
+	public String getDescription(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
-		if (this.description != null)
-			return vr.resolve(this.description);
+		if (description != null)
+			return vr.resolve(description);
 		String description = context.getMessages().findFirstString(req.getLocale(), "description");
 		if (description != null)
 			return vr.resolve(description);
-		Swagger s = req.getSwaggerFromFile();
+		Swagger s = getSwaggerFromFile(req);
 		if (s != null && s.getInfo() != null)
 			return s.getInfo().getDescription();
 		return null;
@@ -400,32 +989,57 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own contact information.
 	 * 
 	 * <p>
-	 * The default implementation returns the contact information from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link ResourceSwagger#contact() @ResourceSwagger.contact()} annotation on this class, and then any parent
-	 * 		classes.
-	 * 	<li><ck>[ClassName].contact</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>contact</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link ResourceSwagger#contact() @ResourceSwagger.contact()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(contact=<js>"{name:'John Smith',email:'john.smith@foo.bar'}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(contact=<js>"$C{MyStrings/MyClass.myContactInfo}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].contact</ck>
+	 * 			<li><ck>contact</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link ResourceSwagger#contact() @ResourceSwagger.contact()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.contact</ck> = <cv>{name:"John Smith",email:"john.smith@foo.bar"}</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.contact</ck> = <cv>$C{MyStrings/MyClass.myContactInfo}</cv>
+	 * 		</p>
 	 * 	<li><ck>/info/contact</ck> entry in swagger file.
 	 * </ol>
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized contact information of this REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public Contact getContact(RestRequest req) {
+	public Contact getContact(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
 		JsonParser jp = JsonParser.DEFAULT;
 		try {
-			if (this.contact != null)
-				return jp.parse(vr.resolve(this.contact), Contact.class);
+			if (contact != null)
+				return jp.parse(vr.resolve(contact), Contact.class);
 			String contact = context.getMessages().findFirstString(req.getLocale(), "contact");
 			if (contact != null)
 				return jp.parse(vr.resolve(contact), Contact.class);
-			Swagger s = req.getSwaggerFromFile();
+			Swagger s = getSwaggerFromFile(req);
 			if (s != null && s.getInfo() != null)
 				return s.getInfo().getContact();
 			return null;
@@ -441,32 +1055,57 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own license information.
 	 * 
 	 * <p>
-	 * The default implementation returns the license information from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link ResourceSwagger#license() @ResourceSwagger.license()} annotation on this class, and then any parent
-	 * 		classes.
-	 * 	<li><ck>[ClassName].license</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>license</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link ResourceSwagger#license() @ResourceSwagger.license()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(license=<js>"{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(license=<js>"$C{MyStrings/MyClass.myLicenseInfo}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].license</ck>
+	 * 			<li><ck>license</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link ResourceSwagger#license() @ResourceSwagger.license()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.license</ck> = <cv>{name:"Apache 2.0",url:"http://www.apache.org/licenses/LICENSE-2.0.html"}</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.license</ck> = <cv>$C{MyStrings/MyClass.myLicenseInfo}</cv>
+	 * 		</p>
 	 * 	<li><ck>/info/license</ck> entry in swagger file.
 	 * </ol>
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized license information of this REST resource, or <jk>null</jk> if none was found found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public License getLicense(RestRequest req) {
+	public License getLicense(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
 		JsonParser jp = JsonParser.DEFAULT;
 		try {
-			if (this.license != null)
-				return jp.parse(vr.resolve(this.license), License.class);
+			if (license != null)
+				return jp.parse(vr.resolve(license), License.class);
 			String license = context.getMessages().findFirstString(req.getLocale(), "license");
 			if (license != null)
 				return jp.parse(vr.resolve(license), License.class);
-			Swagger s = req.getSwaggerFromFile();
+			Swagger s = getSwaggerFromFile(req);
 			if (s != null && s.getInfo() != null)
 				return s.getInfo().getLicense();
 			return null;
@@ -482,31 +1121,55 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own terms-of-service information.
 	 * 
 	 * <p>
-	 * The default implementation returns the terms-of-service information from the following locations (whichever
-	 * matches first):
-	 * <ol>
-	 * 	<li>{@link ResourceSwagger#termsOfService() @ResourceSwagger.termsOfService()} annotation on this class, and
-	 * 		then any parent classes.
-	 * 	<li><ck>[ClassName].termsOfService</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>termsOfService</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link ResourceSwagger#termsOfService() @ResourceSwagger.termsOfService()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(termsOfService=<js>"You're on your own"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(termsOfService=<js>"$C{MyStrings/MyClass.myTermsOfService}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].termsOfService</ck>
+	 * 			<li><ck>termsOfService</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link ResourceSwagger#termsOfService() @ResourceSwagger.termsOfService()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.termsOfService</ck> = <cv>You''re on your own</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.termsOfService</ck> = <cv>$C{MyStrings/MyClass.myTermsOfService}</cv>
+	 * 		</p>
 	 * 	<li><ck>/info/termsOfService</ck> entry in swagger file.
 	 * </ol>
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized terms-of-service of this REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getTermsOfService(RestRequest req) {
+	public String getTermsOfService(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
-		if (this.termsOfService != null)
-			return vr.resolve(this.termsOfService);
+		if (termsOfService != null)
+			return vr.resolve(termsOfService);
 		String termsOfService = context.getMessages().findFirstString(req.getLocale(), "termsOfService");
 		if (termsOfService != null)
 			return vr.resolve(termsOfService);
-		Swagger s = req.getSwaggerFromFile();
+		Swagger s = getSwaggerFromFile(req);
 		if (s != null && s.getInfo() != null)
 			return s.getInfo().getTermsOfService();
 		return null;
@@ -519,69 +1182,186 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own version information.
 	 * 
 	 * <p>
-	 * The default implementation returns the version information from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link ResourceSwagger#version() @ResourceSwagger.version()} annotation on this class, and then any parent
-	 * 		classes.
-	 * 	<li><ck>[ClassName].version</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>version</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link ResourceSwagger#version() @ResourceSwagger.version()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(version=<js>"2.0"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(version=<js>"$C{MyStrings/MyClass.myVersion}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].version</ck>
+	 * 			<li><ck>version</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link ResourceSwagger#version() @ResourceSwagger.version()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.version</ck> = <cv>2.0</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.version</ck> = <cv>$C{MyStrings/MyClass.myVersion}</cv>
+	 * 		</p>
 	 * 	<li><ck>/info/version</ck> entry in swagger file.
 	 * </ol>
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized version of this REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public String getVersion(RestRequest req) {
+	public String getVersion(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
-		if (this.version != null)
-			return vr.resolve(this.version);
+		if (version != null)
+			return vr.resolve(version);
 		String version = context.getMessages().findFirstString(req.getLocale(), "version");
 		if (version != null)
 			return vr.resolve(version);
-		Swagger s = req.getSwaggerFromFile();
+		Swagger s = getSwaggerFromFile(req);
 		if (s != null && s.getInfo() != null)
 			return s.getInfo().getVersion();
 		return null;
 	}
 
 	/**
+	 * Returns the supported <code>Content-Type</code> request headers for the REST resource.
+	 * <p>
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link ResourceSwagger#version() @ResourceSwagger.version()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(version=<js>"2.0"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(version=<js>"$C{MyStrings/MyClass.myVersion}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].version</ck>
+	 * 			<li><ck>version</ck>
+	 * 		</ol>
+	 * 		<br>Value can contain any SVL variables defined on the {@link ResourceSwagger#version() @ResourceSwagger.version()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.version</ck> = <cv>2.0</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.version</ck> = <cv>$C{MyStrings/MyClass.myVersion}</cv>
+	 * 		</p>
+	 * 	<li><ck>/info/version</ck> entry in swagger file.
+	 * </ol>
+	 * 
+	 * @param req The current request.
+	 * @return
+	 * 	The supported <code>Content-Type</code> request headers of the REST resource, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 */
+	@Override /* RestInfoProvider */
+	public List<MediaType> getConsumes(RestRequest req) throws Exception {
+		List<MediaType> l = req.getContext().getConsumes();
+		return l.isEmpty() ? null : l;
+	}
+	
+	/**
+	 * Returns the supported <code>Accept</code> request headers for the REST resource.
+	 * 
+	 * @param req The current request.
+	 * @return
+	 * 	The supported <code>Accept</code> request headers of the REST resource, or <jk>null</jk> if none were found.
+	 * @throws Exception 
+	 */
+	@Override /* RestInfoProvider */
+	public List<MediaType> getProduces(RestRequest req) throws Exception {
+		List<MediaType> l = req.getContext().getProduces();
+		return l.isEmpty() ? null : l;
+	}
+
+	/**
 	 * Returns the version information of this REST resource.
 	 * 
 	 * <p>
 	 * Subclasses can override this method to provide their own version information.
 	 * 
 	 * <p>
-	 * The default implementation returns the version information from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link ResourceSwagger#version() @ResourceSwagger.version()} annotation on this class, and then any parent
-	 * 		classes.
-	 * 	<li><ck>[ClassName].version</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>version</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>/info/version</ck> entry in swagger file.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link ResourceSwagger#tags() @ResourceSwagger.tags()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(tags=<js>"foo,bar,baz"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(tags=<js>"$C{MyStrings/MyClass.myTags}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].tags</ck>
+	 * 			<li><ck>tags</ck>
+	 * 		</ol>
+	 * 		<br>Value is either a comma-delimited list or a JSON array.
+	 * 		<br>Value can contain any SVL variables defined on the {@link ResourceSwagger#tags() @ResourceSwagger.tags()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Comma-delimited list</cc>
+	 * 	<ck>MyClass.tags</ck> = <cv>foo,bar,baz</cv>
+	 * 	
+	 * 	<cc>// JSON array</cc>
+	 * 	<ck>MyClass.tags</ck> = <cv>["foo","bar","baz"]</cv>
+	 * 
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.tags</ck> = <cv>$C{MyStrings/MyClass.myTags}</cv>
+	 * 		</p>
+	 * 	<li><ck>tags</ck> entry in swagger file.
 	 * </ol>
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized tags of this REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public List<Tag> getTags(RestRequest req) {
+	public List<Tag> getTags(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
 		JsonParser jp = JsonParser.DEFAULT;
 		try {
-			if (this.tags != null)
-				return jp.parse(vr.resolve(this.tags), ArrayList.class, Tag.class);
+			if (tags != null)
+				return jp.parse(vr.resolve(tags), ArrayList.class, Tag.class);
 			String tags = context.getMessages().findFirstString(req.getLocale(), "tags");
 			if (tags != null)
 				return jp.parse(vr.resolve(tags), ArrayList.class, Tag.class);
-			Swagger s = req.getSwaggerFromFile();
-			if (s != null)
+			Swagger s = getSwaggerFromFile(req);
+			if (s != null && s.getTags() != null)
 				return s.getTags();
 			return null;
 		} catch (Exception e) {
@@ -596,32 +1376,58 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 	 * Subclasses can override this method to provide their own version information.
 	 * 
 	 * <p>
-	 * The default implementation returns the version information from the following locations (whichever matches first):
-	 * <ol>
-	 * 	<li>{@link ResourceSwagger#version() @ResourceSwagger.version()} annotation on this class, and then any parent
-	 * 		classes.
-	 * 	<li><ck>[ClassName].version</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>version</ck> property in resource bundle identified by
-	 * 		{@link RestResource#messages() @RestResource.messages()} annotation for this class, then any parent classes.
-	 * 	<li><ck>/info/version</ck> entry in swagger file.
+	 * The default implementation returns the value from the following locations (whichever matches first):
+	 * <ol class='spaced-list'>
+	 * 	<li>{@link ResourceSwagger#externalDocs() @ResourceSwagger.externalDocs()} annotation on this class, and then any parent classes.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<jc>// Direct value</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(externalDocs=<js>"{url:'http://juneau.apache.org'}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 	
+	 * 	<jc>// Pulled from some other location</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		swagger=<ja>@ResourceSwagger</ja>(externalDocs=<js>"$C{MyStrings/MyClass.myExternalDocs}"</js>)
+	 * 	)
+	 * 	<jk>public class</jk> MyResource {...}
+	 * 		</p>
+	 * 	<li>Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource.messages()}
+	 * 		on the resource class, then any parent classes.
+	 * 		<ol>
+	 * 			<li><ck>[ClassName].externalDocs</ck>
+	 * 			<li><ck>externalDocs</ck>
+	 * 		</ol>
+	 * 		<br>Value is a JSON objec representation of a {@link ExternalDocumentation} object.
+	 * 		<br>Value can contain any SVL variables defined on the {@link ResourceSwagger#externalDocs() @ResourceSwagger.externalDocs()} annotation.
+	 * 		<h6 class='figure'>Examples:</h6>
+	 * 		<p class='bcode'>
+	 * 	<cc>// Direct value</cc>
+	 * 	<ck>MyClass.externalDocs</ck> = <cv>{url:"http://juneau.apache.org"}</cv>
+	 * 	
+	 * 	<cc>// Pulled from some other location</cc>
+	 * 	<ck>MyClass.externalDocs</ck> = <cv>$C{MyStrings/MyClass.myExternalDocs}</cv>
+	 * 		</p>
+	 * 	<li><ck>externalDocs</ck> entry in swagger file.
 	 * </ol>
 	 * 
 	 * @param req The current request.
 	 * @return
-	 * 	The localized contact information of this REST resource, or <jk>null</jk> if no contact information was found.
+	 * 	The localized external documentation of this REST resource, or <jk>null</jk> if none was found.
+	 * @throws Exception 
 	 */
 	@Override /* RestInfoProvider */
-	public ExternalDocumentation getExternalDocs(RestRequest req) {
+	public ExternalDocumentation getExternalDocs(RestRequest req) throws Exception {
 		VarResolverSession vr = req.getVarResolverSession();
 		JsonParser jp = JsonParser.DEFAULT;
 		try {
-			if (this.externalDocs != null)
-				return jp.parse(vr.resolve(this.externalDocs), ExternalDocumentation.class);
+			if (externalDocs != null)
+				return jp.parse(vr.resolve(externalDocs), ExternalDocumentation.class);
 			String externalDocs = context.getMessages().findFirstString(req.getLocale(), "externalDocs");
 			if (externalDocs != null)
 				return jp.parse(vr.resolve(externalDocs), ExternalDocumentation.class);
-			Swagger s = req.getSwaggerFromFile();
+			Swagger s = getSwaggerFromFile(req);
 			if (s != null)
 				return s.getExternalDocs();
 			return null;
@@ -629,4 +1435,18 @@ public class RestInfoProviderDefault implements RestInfoProvider {
 			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
 		}
 	}
+	
+	private Operation getSwaggerOperationFromFile(Method method, RestRequest req) throws Exception {
+
+		Swagger s = getSwaggerFromFile(req);
+		if (s != null) {
+			Map<String,Map<String,Operation>> sp = s.getPaths();
+			if (sp != null) {
+				Map<String,Operation> spp = sp.get(method.getAnnotation(RestMethod.class).path());
+				if (spp != null)
+					return spp.get(req.getMethod());
+			}
+		}
+		return null;
+	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/62b041ab/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
index b6ef494..b4d0b1d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
@@ -14,7 +14,6 @@ package org.apache.juneau.rest;
 
 import static javax.servlet.http.HttpServletResponse.*;
 import static org.apache.juneau.BeanContext.*;
-import static org.apache.juneau.dto.swagger.SwaggerBuilder.*;
 import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.internal.Utils.*;
@@ -27,12 +26,10 @@ import java.util.*;
 import javax.servlet.http.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.widget.*;
@@ -46,17 +43,13 @@ import org.apache.juneau.utils.*;
 public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 	private final String httpMethod;
 	private final UrlPathPattern pathPattern;
-	private final RestParam[] params;
+	final RestParam[] params;
 	private final RestGuard[] guards;
 	private final RestMatcher[] optionalMatchers;
 	private final RestMatcher[] requiredMatchers;
 	private final RestConverter[] converters;
 	private final RestMethodProperties properties;
-	private final boolean deprecated;
-	private final String description, tags, summary, externalDocs;
 	private final Integer priority;
-	private final org.apache.juneau.rest.annotation.Parameter[] parameters;
-	private final Response[] responses;
 	private final RestContext context;
 	final java.lang.reflect.Method method;
 	final SerializerGroup serializers;
@@ -99,21 +92,14 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		this.defaultFormData = b.defaultFormData;
 		this.defaultCharset = b.defaultCharset;
 		this.maxInput = b.maxInput;
-		this.deprecated = b.deprecated;
-		this.description = b.description;
-		this.tags = b.tags;
-		this.summary = b.summary;
-		this.externalDocs = b.externalDocs;
 		this.priority = b.priority;
-		this.parameters = b.parameters;
-		this.responses = b.responses;
 		this.supportedAcceptTypes = b.supportedAcceptTypes;
 		this.supportedContentTypes = b.supportedContentTypes;
 		this.widgets = Collections.unmodifiableMap(b.widgets);
 	}
 
 	private static final class Builder  {
-		String httpMethod, defaultCharset, description, tags, summary, externalDocs;
+		String httpMethod, defaultCharset;
 		UrlPathPattern pathPattern;
 		RestParam[] params;
 		RestGuard[] guards;
@@ -127,11 +113,8 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 		BeanContext beanContext;
 		RestMethodProperties properties;
 		Map<String,Object> defaultRequestHeaders, defaultQuery, defaultFormData;
-		boolean deprecated;
 		long maxInput;
 		Integer priority;
-		org.apache.juneau.rest.annotation.Parameter[] parameters;
-		Response[] responses;
 		Map<String,Widget> widgets;
 		List<MediaType> supportedAcceptTypes, supportedContentTypes;
 
@@ -146,18 +129,6 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 				
 				VarResolver vr = context.getVarResolver();
 
-				if (! m.description().isEmpty())
-					description = m.description();
-				MethodSwagger sm = m.swagger();
-				if (! sm.tags().isEmpty())
-					tags = sm.tags();
-				if (! m.summary().isEmpty())
-					summary = m.summary();
-				if (! sm.externalDocs().isEmpty())
-					externalDocs = sm.externalDocs();
-				deprecated = sm.deprecated();
-				parameters = sm.parameters();
-				responses = sm.responses();
 				serializers = context.getSerializers();
 				parsers = context.getParsers();
 				partSerializer = context.getPartSerializer();
@@ -409,12 +380,12 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 					beanContext = bcb.build();
 
 				supportedAcceptTypes = 
-					m.supportedAcceptTypes().length > 0 
-					? Collections.unmodifiableList(new ArrayList<>(Arrays.asList(MediaType.forStrings(resolveVars(vr, m.supportedAcceptTypes()))))) 
+					m.produces().length > 0 
+					? Collections.unmodifiableList(new ArrayList<>(Arrays.asList(MediaType.forStrings(resolveVars(vr, m.produces()))))) 
 					: serializers.getSupportedMediaTypes();
 				supportedContentTypes =
-					m.supportedContentTypes().length > 0 
-					? Collections.unmodifiableList(new ArrayList<>(Arrays.asList(MediaType.forStrings(resolveVars(vr, m.supportedContentTypes()))))) 
+					m.consumes().length > 0 
+					? Collections.unmodifiableList(new ArrayList<>(Arrays.asList(MediaType.forStrings(resolveVars(vr, m.consumes()))))) 
 					: parsers.getSupportedMediaTypes();
 					
 				params = context.findParams(method, pathPattern, false);
@@ -451,322 +422,6 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 	}
 
 	/**
-	 * Returns the localized Swagger for this Java method.
-	 */
-	Operation getSwaggerOperation(RestRequest req) throws ParseException {
-		Operation o = operation()
-			.operationId(method.getName())
-			.description(getDescription(req))
-			.tags(getTags(req))
-			.summary(getSummary(req))
-			.externalDocs(getExternalDocs(req))
-			.parameters(getParameters(req))
-			.responses(getResponses(req));
-
-		if (isDeprecated())
-			o.deprecated(true);
-
-		if (! parsers.getSupportedMediaTypes().equals(context.getParsers().getSupportedMediaTypes()))
-			o.consumes(parsers.getSupportedMediaTypes());
-
-		if (! serializers.getSupportedMediaTypes().equals(context.getSerializers().getSupportedMediaTypes()))
-			o.produces(serializers.getSupportedMediaTypes());
-
-		return o;
-	}
-
-	private Operation getSwaggerOperationFromFile(RestRequest req) {
-		Swagger s = req.getSwaggerFromFile();
-		if (s != null && s.getPaths() != null && s.getPaths().get(pathPattern.getPatternString()) != null)
-			return s.getPaths().get(pathPattern.getPatternString()).get(httpMethod);
-		return null;
-	}
-
-	/**
-	 * Returns the localized summary for this Java method.
-	 */
-	String getSummary(RestRequest req) {
-		VarResolverSession vr = req.getVarResolverSession();
-		if (summary != null)
-			return vr.resolve(summary);
-		String summary = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".summary");
-		if (summary != null)
-			return vr.resolve(summary);
-		Operation o = getSwaggerOperationFromFile(req);
-		if (o != null)
-			return o.getSummary();
-		return null;
-	}
-
-	/**
-	 * Returns the localized description for this Java method.
-	 */
-	String getDescription(RestRequest req) {
-		VarResolverSession vr = req.getVarResolverSession();
-		if (description != null)
-			return vr.resolve(description);
-		String description = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".description");
-		if (description != null)
-			return vr.resolve(description);
-		Operation o = getSwaggerOperationFromFile(req);
-		if (o != null)
-			return o.getDescription();
-		return null;
-	}
-
-	/**
-	 * Returns the localized Swagger tags for this Java method.
-	 */
-	private List<String> getTags(RestRequest req) {
-		VarResolverSession vr = req.getVarResolverSession();
-		JsonParser jp = JsonParser.DEFAULT;
-		try {
-			if (tags != null)
-				return jp.parse(vr.resolve(tags), ArrayList.class, String.class);
-			String tags = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".tags");
-			if (tags != null)
-				return jp.parse(vr.resolve(tags), ArrayList.class, String.class);
-			Operation o = getSwaggerOperationFromFile(req);
-			if (o != null)
-				return o.getTags();
-			return null;
-		} catch (Exception e) {
-			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
-		}
-	}
-
-	/**
-	 * Returns the localized Swagger external docs for this Java method.
-	 */
-	private ExternalDocumentation getExternalDocs(RestRequest req) {
-		VarResolverSession vr = req.getVarResolverSession();
-		JsonParser jp = JsonParser.DEFAULT;
-		try {
-			if (externalDocs != null)
-				return jp.parse(vr.resolve(externalDocs), ExternalDocumentation.class);
-			String externalDocs = context.getMessages().findFirstString(req.getLocale(), method.getName() + ".externalDocs");
-			if (externalDocs != null)
-				return jp.parse(vr.resolve(externalDocs), ExternalDocumentation.class);
-			Operation o = getSwaggerOperationFromFile(req);
-			if (o != null)
-				return o.getExternalDocs();
-			return null;
-		} catch (Exception e) {
-			throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
-		}
-	}
-
-	/**
-	 * Returns the Swagger deprecated flag for this Java method.
-	 */
-	private boolean isDeprecated() {
-		return deprecated;
-	}
-
-	/**
-	 * Returns the localized Swagger parameter information for this Java method.
-	 */
-	private List<ParameterInfo> getParameters(RestRequest req) throws ParseException {
-		Operation o = getSwaggerOperationFromFile(req);
-		if (o != null && o.getParameters() != null)
-			return o.getParameters();
-
-		VarResolverSession vr = req.getVarResolverSession();
-		JsonParser jp = JsonParser.DEFAULT;
-		Map<String,ParameterInfo> m = new TreeMap<>();
-
-		// First parse @RestMethod.parameters() annotation.
-		for (org.apache.juneau.rest.annotation.Parameter v : parameters) {
-			String in = vr.resolve(v.in());
-			ParameterInfo p = parameterInfo(in, vr.resolve(v.name()));
-
-			if (! v.description().isEmpty())
-				p.description(vr.resolve(v.description()));
-			if (v.required())
-				p.required(v.required());
-
-			if ("body".equals(in)) {
-				if (! v.schema().isEmpty())
-					p.schema(jp.parse(vr.resolve(v.schema()), SchemaInfo.class));
-			} else {
-				if (v.allowEmptyValue())
-					p.allowEmptyValue(v.allowEmptyValue());
-				if (! v.collectionFormat().isEmpty())
-					p.collectionFormat(vr.resolve(v.collectionFormat()));
-				if (! v._default().isEmpty())
-					p._default(vr.resolve(v._default()));
-				if (! v.format().isEmpty())
-					p.format(vr.resolve(v.format()));
-				if (! v.items().isEmpty())
-					p.items(jp.parse(vr.resolve(v.items()), Items.class));
-				p.type(vr.resolve(v.type()));
-			}
-			m.put(p.getIn() + '.' + p.getName(), p);
-		}
-
-		// Next, look in resource bundle.
-		String prefix = method.getName() + ".req";
-		for (String key : context.getMessages().keySet(prefix)) {
-			if (key.length() > prefix.length()) {
-				String value = vr.resolve(context.getMessages().getString(key));
-				String[] parts = key.substring(prefix.length() + 1).split("\\.");
-				String in = parts[0], name, field;
-				boolean isBody = "body".equals(in);
-				if (parts.length == (isBody ? 2 : 3)) {
-					if ("body".equals(in)) {
-						name = null;
-						field = parts[1];
-					} else {
-						name = parts[1];
-						field = parts[2];
-					}
-					String k2 = in + '.' + name;
-					ParameterInfo p = m.get(k2);
-					if (p == null) {
-						p = parameterInfoStrict(in, name);
-						m.put(k2, p);
-					}
-
-					if (field.equals("description"))
-						p.description(value);
-					else if (field.equals("required"))
-						p.required(Boolean.valueOf(value));
-
-					if ("body".equals(in)) {
-						if (field.equals("schema"))
-							p.schema(jp.parse(value, SchemaInfo.class));
-					} else {
-						if (field.equals("allowEmptyValue"))
-							p.allowEmptyValue(Boolean.valueOf(value));
-						else if (field.equals("collectionFormat"))
-							p.collectionFormat(value);
-						else if (field.equals("default"))
-							p._default(value);
-						else if (field.equals("format"))
-							p.format(value);
-						else if (field.equals("items"))
-							p.items(jp.parse(value, Items.class));
-						else if (field.equals("type"))
-							p.type(value);
-					}
-				} else {
-					System.err.println("Unknown bundle key '"+key+"'");
-				}
-			}
-		}
-
-		// Finally, look for parameters defined on method.
-		for (RestParam mp : this.params) {
-			RestParamType in = mp.getParamType();
-			if (in != RestParamType.OTHER) {
-				String k2 = in.toString() + '.' + (in == RestParamType.BODY ? null : mp.getName());
-				ParameterInfo p = m.get(k2);
-				if (p == null) {
-					p = parameterInfoStrict(in.toString(), mp.getName());
-					m.put(k2, p);
-				}
-			}
-		}
-
-		if (m.isEmpty())
-			return null;
-		return new ArrayList<>(m.values());
-	}
-
-	/**
-	 * Returns the localized Swagger response information about this Java method.
-	 */
-	private Map<Integer,ResponseInfo> getResponses(RestRequest req) throws ParseException {
-		Operation o = getSwaggerOperationFromFile(req);
-		if (o != null && o.getResponses() != null)
-			return o.getResponses();
-
-		VarResolverSession vr = req.getVarResolverSession();
-		JsonParser jp = JsonParser.DEFAULT;
-		Map<Integer,ResponseInfo> m = new TreeMap<>();
-		Map<String,HeaderInfo> m2 = new TreeMap<>();
-
-		// First parse @RestMethod.parameters() annotation.
-		for (Response r : responses) {
-			int httpCode = r.value();
-			String description = r.description().isEmpty() ? RestUtils.getHttpResponseText(r.value()) : vr.resolve(r.description());
-			ResponseInfo r2 = responseInfo(description);
-
-			if (r.headers().length > 0) {
-				for (org.apache.juneau.rest.annotation.Parameter v : r.headers()) {
-					HeaderInfo h = headerInfoStrict(vr.resolve(v.type()));
-					if (! v.collectionFormat().isEmpty())
-						h.collectionFormat(vr.resolve(v.collectionFormat()));
-					if (! v._default().isEmpty())
-						h._default(vr.resolve(v._default()));
-					if (! v.description().isEmpty())
-						h.description(vr.resolve(v.description()));
-					if (! v.format().isEmpty())
-						h.format(vr.resolve(v.format()));
-					if (! v.items().isEmpty())
-						h.items(jp.parse(vr.resolve(v.items()), Items.class));
-					r2.header(v.name(), h);
-					m2.put(httpCode + '.' + v.name(), h);
-				}
-			}
-			m.put(httpCode, r2);
-		}
-
-		// Next, look in resource bundle.
-		String prefix = method.getName() + ".res";
-		for (String key : context.getMessages().keySet(prefix)) {
-			if (key.length() > prefix.length()) {
-				String value = vr.resolve(context.getMessages().getString(key));
-				String[] parts = key.substring(prefix.length() + 1).split("\\.");
-				int httpCode = Integer.parseInt(parts[0]);
-				ResponseInfo r2 = m.get(httpCode);
-				if (r2 == null) {
-					r2 = responseInfo(null);
-					m.put(httpCode, r2);
-				}
-
-				String name = parts.length > 1 ? parts[1] : "";
-
-				if ("header".equals(name) && parts.length > 3) {
-					String headerName = parts[2];
-					String field = parts[3];
-
-					String k2 = httpCode + '.' + headerName;
-					HeaderInfo h = m2.get(k2);
-					if (h == null) {
-						h = headerInfoStrict("string");
-						m2.put(k2, h);
-						r2.header(name, h);
-					}
-					if (field.equals("collectionFormat"))
-						h.collectionFormat(value);
-					else if (field.equals("default"))
-						h._default(value);
-					else if (field.equals("description"))
-						h.description(value);
-					else if (field.equals("format"))
-						h.format(value);
-					else if (field.equals("items"))
-						h.items(jp.parse(value, Items.class));
-					else if (field.equals("type"))
-						h.type(value);
-
-				} else if ("description".equals(name)) {
-					r2.description(value);
-				} else if ("schema".equals(name)) {
-					r2.schema(jp.parse(value, SchemaInfo.class));
-				} else if ("examples".equals(name)) {
-					r2.examples(jp.parse(value, TreeMap.class));
-				} else {
-					System.err.println("Unknown bundle key '"+key+"'");
-				}
-			}
-		}
-
-		return m.isEmpty() ? null : m;
-	}
-
-	/**
 	 * Returns <jk>true</jk> if the specified request object can call this method.
 	 */
 	boolean isRequestAllowed(RestRequest req) {
@@ -795,7 +450,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 			remainder = patternVals[pathPattern.getVars().length];
 		for (int i = 0; i < pathPattern.getVars().length; i++)
 			req.getPathMatch().put(pathPattern.getVars()[i], patternVals[i]);
-		req.getPathMatch().setRemainder(remainder);
+		req.getPathMatch().pattern(pathPattern.getPatternString()).remainder(remainder);
 
 		RestRequestProperties requestProperties = new RestRequestProperties(req.getVarResolverSession(), properties);