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 2017/09/08 23:25:37 UTC
svn commit: r21540 [14/27] - in /release/incubator/juneau:
juneau-rest-client/ juneau-rest-client/.settings/ juneau-rest-client/bin/
juneau-rest-client/src/ juneau-rest-client/src/main/
juneau-rest-client/src/main/java/ juneau-rest-client/src/main/java...
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestGuard.java
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestGuard.java (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestGuard.java Fri Sep 8 23:25:34 2017
@@ -0,0 +1,101 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static javax.servlet.http.HttpServletResponse.*;
+
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * REST method guard.
+ *
+ * <h5 class='section'>Description:</h5>
+ *
+ * Implements a guard mechanism for REST method calls that allows requests to be rejected before invocation of the REST
+ * method.
+ * For example, guards can be used to ensure that only administrators can call certain methods.
+ *
+ * <p>
+ * Guards are applied to REST methods declaratively through the {@link RestResource#guards()} or
+ * {@link RestMethod#guards()} annotations.
+ *
+ * <p>
+ * If multiple guards are specified, ALL guards must pass in order for the request to proceed.
+ *
+ * <h6 class='topic'>How to implement</h6>
+ *
+ * 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.
+ *
+ * <p>
+ * Implementers should simply throw a {@link RestException} from the {@link #guard(RestRequest, RestResponse)}
+ * method to abort processing on the current request.
+ *
+ * <p>
+ * Guards must implement a no-args constructor.
+ *
+ * <h6 class='topic'>Example usage:</h6>
+ * <p class='bcode'>
+ * <jk>public</jk> MyResource <jk>extends</jk> RestServlet {
+ *
+ * <jc>// Delete method with guard that only allows Billy to call it.</jc>
+ * <ja>@RestMethod</ja>(name=<js>"DELETE"</js>, guards=BillyGuard.<jk>class</jk>)
+ * <jk>public</jk> doDelete(RestRequest req, RestResponse res) <jk>throws</jk> Exception {...}
+ * }
+ * </p>
+ *
+ * <h6 class='topic'>Example implementation:</h6>
+ * <p class='bcode'>
+ * <jc>// Define a guard that only lets Billy make a request</jc>
+ * <jk>public</jk> BillyGuard <jk>extends</jk> RestGuard {
+ *
+ * <ja>@Override</ja>
+ * <jk>public boolean</jk> isRequestAllowed(RestRequest req) {
+ * return req.getUserPrincipal().getName().contains(<js>"Billy"</js>);
+ * }
+ * }
+ * </p>
+ */
+public abstract class RestGuard {
+
+ /**
+ * Checks the current HTTP request and throws a {@link RestException} if the guard does not permit the request.
+ *
+ * <p>
+ * By default, throws an <jsf>SC_FORBIDDEN</jsf> exception if {@link #isRequestAllowed(RestRequest)} returns
+ * <jk>false</jk>.
+ *
+ * <p>
+ * Subclasses are free to override this method to tailor the behavior of how to handle unauthorized requests.
+ *
+ * @param req The servlet request.
+ * @param res The servlet response.
+ * @throws RestException Thrown to abort processing on current request.
+ * @return
+ * <jk>true</jk> if request can proceed.
+ * Specify <jk>false</jk> if you're doing something like a redirection to a login page.
+ */
+ public boolean guard(RestRequest req, RestResponse res) throws RestException {
+ if (! isRequestAllowed(req))
+ throw new RestException(SC_FORBIDDEN, "Access denied by guard");
+ return true;
+ }
+
+ /**
+ * Returns <jk>true</jk> if the specified request can pass through this guard.
+ *
+ * @param req The servlet request.
+ * @return <jk>true</jk> if the specified request can pass through this guard.
+ */
+ public abstract boolean isRequestAllowed(RestRequest req);
+}
Propchange: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestGuard.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java Fri Sep 8 23:25:34 2017
@@ -0,0 +1,572 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static javax.servlet.http.HttpServletResponse.*;
+import static org.apache.juneau.dto.swagger.SwaggerBuilder.*;
+import static org.apache.juneau.internal.ReflectionUtils.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.svl.*;
+
+/**
+ * Class that provides documentation and other related information about a REST resource.
+ *
+ * <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.
+ *
+ * <p>
+ * RestInfoProviders are associated with servlets/resources in one of the following ways:
+ * <ul>
+ * <li>The {@link RestResource#infoProvider @RestResource.infoProvider()} annotation.
+ * <li>The {@link RestConfig#setInfoProvider(Class)}/{@link RestConfig#setInfoProvider(RestInfoProvider)} methods.
+ * </ul>
+ */
+@SuppressWarnings("hiding")
+public class RestInfoProvider {
+
+ private final RestContext context;
+ private final String
+ siteName,
+ title,
+ description,
+ termsOfService,
+ contact,
+ license,
+ version,
+ tags,
+ externalDocs;
+ private final ConcurrentHashMap<Locale,Swagger> swaggers = new ConcurrentHashMap<Locale,Swagger>();
+
+ /**
+ * Constructor.
+ *
+ * @param context The resource context.
+ */
+ public RestInfoProvider(RestContext context) {
+ this.context = context;
+
+ Builder b = new Builder(context);
+ this.siteName = b.siteName;
+ this.title = b.title;
+ this.description = b.description;
+ this.termsOfService = b.termsOfService;
+ this.contact = b.contact;
+ this.license = b.license;
+ this.version = b.version;
+ this.tags = b.tags;
+ this.externalDocs = b.externalDocs;
+ }
+
+ private static class Builder {
+ private String
+ siteName,
+ title,
+ description,
+ termsOfService,
+ contact,
+ license,
+ version,
+ tags,
+ externalDocs;
+
+ Builder(RestContext context) {
+
+ LinkedHashMap<Class<?>,RestResource> restResourceAnnotationsParentFirst = findAnnotationsMapParentFirst(RestResource.class, context.getResource().getClass());
+
+ for (RestResource r : restResourceAnnotationsParentFirst.values()) {
+ if (! r.siteName().isEmpty())
+ siteName = r.siteName();
+ if (! r.title().isEmpty())
+ title = r.title();
+ if (! r.description().isEmpty())
+ description = r.description();
+ ResourceSwagger sr = r.swagger();
+ if (! sr.termsOfService().isEmpty())
+ termsOfService = sr.termsOfService();
+ if (! sr.contact().isEmpty())
+ contact = sr.contact();
+ if (! sr.license().isEmpty())
+ license = sr.license();
+ if (! sr.version().isEmpty())
+ version = sr.version();
+ if (! sr.tags().isEmpty())
+ tags = sr.tags();
+ if (! sr.externalDocs().isEmpty())
+ externalDocs = sr.externalDocs();
+ }
+ }
+ }
+
+ /**
+ * Returns the localized swagger for this REST resource.
+ *
+ * @param req The incoming HTTP request.
+ * @return A new Swagger instance.
+ * @throws RestException
+ */
+ protected 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(context.getSupportedAcceptTypes())
+ .produces(context.getSupportedContentTypes())
+ .tags(getTags(req))
+ .externalDocs(getExternalDocs(req));
+
+ for (CallMethod sm : context.getCallMethods().values()) {
+ if (sm.isRequestAllowed(req)) {
+ Operation o = sm.getSwaggerOperation(req);
+ s.path(
+ sm.getPathPattern(),
+ sm.getHttpMethod().toLowerCase(),
+ o
+ );
+ }
+ }
+ return s;
+ } catch (RestException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @param locale The locale of the swagger.
+ * @return The parsed swagger object, or <jk>null</jk> if the swagger file could not be found.
+ * @throws RestException
+ */
+ protected Swagger getSwaggerFromFile(Locale locale) throws RestException {
+ Swagger s = swaggers.get(locale);
+ if (s == null) {
+ try {
+ s = context.getResource(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);
+ }
+ }
+ return s == Swagger.NULL ? null : s;
+ }
+
+ /**
+ * 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.
+ * </ol>
+ *
+ * @param javaMethodName The name of the Java method whose description we're retrieving.
+ * @param req The current request.
+ * @return The localized summary of the method, or a blank string if no summary was found.
+ */
+ public String getMethodSummary(String javaMethodName, RestRequest req) {
+ CallMethod m = context.getCallMethods().get(javaMethodName);
+ if (m != null)
+ return m.getSummary(req);
+ return "";
+ }
+
+ /**
+ * Returns the localized description of the specified java method on this servlet.
+ *
+ * <p>
+ * 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.
+ * </ol>
+ *
+ * @param javaMethodName The name of the Java method whose description we're retrieving.
+ * @param req The current request.
+ * @return The localized description of the method, or a blank string if no description was found.
+ */
+ protected String getMethodDescription(String javaMethodName, RestRequest req) {
+ CallMethod m = context.getCallMethods().get(javaMethodName);
+ if (m != null)
+ return m.getDescription(req);
+ return "";
+ }
+
+ /**
+ * Returns the localized site name of this REST resource.
+ *
+ * <p>
+ * 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>
+ * <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.
+ * </ol>
+ *
+ * @param req The current request.
+ * @return The localized description of this REST resource, or <jk>null</jk> if no resource description was found.
+ */
+ public String getSiteName(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ if (this.siteName != null)
+ return vr.resolve(this.siteName);
+ String siteName = context.getMessages().findFirstString(req.getLocale(), "siteName");
+ if (siteName != null)
+ return vr.resolve(siteName);
+ return null;
+ }
+
+ /**
+ * Returns the localized title of this REST resource.
+ *
+ * <p>
+ * 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.
+ * <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.
+ */
+ public String getTitle(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ if (this.title != null)
+ return vr.resolve(this.title);
+ String title = context.getMessages().findFirstString(req.getLocale(), "title");
+ if (title != null)
+ return vr.resolve(title);
+ Swagger s = req.getSwaggerFromFile();
+ if (s != null && s.getInfo() != null)
+ return s.getInfo().getTitle();
+ return null;
+ }
+
+ /**
+ * Returns the localized description of this REST resource.
+ *
+ * <p>
+ * 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.
+ * <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.
+ */
+ public String getDescription(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ if (this.description != null)
+ return vr.resolve(this.description);
+ String description = context.getMessages().findFirstString(req.getLocale(), "description");
+ if (description != null)
+ return vr.resolve(description);
+ Swagger s = req.getSwaggerFromFile();
+ if (s != null && s.getInfo() != null)
+ return s.getInfo().getDescription();
+ return null;
+ }
+
+ /**
+ * Returns the localized contact information of this REST resource.
+ *
+ * <p>
+ * 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.
+ * <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.
+ */
+ public Contact getContact(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ JsonParser jp = JsonParser.DEFAULT;
+ try {
+ if (this.contact != null)
+ return jp.parse(vr.resolve(this.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();
+ if (s != null && s.getInfo() != null)
+ return s.getInfo().getContact();
+ return null;
+ } catch (ParseException e) {
+ throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+ }
+ }
+
+ /**
+ * Returns the localized license information of this REST resource.
+ *
+ * <p>
+ * 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.
+ * <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.
+ */
+ public License getLicense(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ JsonParser jp = JsonParser.DEFAULT;
+ try {
+ if (this.license != null)
+ return jp.parse(vr.resolve(this.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();
+ if (s != null && s.getInfo() != null)
+ return s.getInfo().getLicense();
+ return null;
+ } catch (ParseException e) {
+ throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+ }
+ }
+
+ /**
+ * Returns the terms-of-service information of this REST resource.
+ *
+ * <p>
+ * 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.
+ * <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.
+ */
+ public String getTermsOfService(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ if (this.termsOfService != null)
+ return vr.resolve(this.termsOfService);
+ String termsOfService = context.getMessages().findFirstString(req.getLocale(), "termsOfService");
+ if (termsOfService != null)
+ return vr.resolve(termsOfService);
+ Swagger s = req.getSwaggerFromFile();
+ if (s != null && s.getInfo() != null)
+ return s.getInfo().getTermsOfService();
+ return null;
+ }
+
+ /**
+ * 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.
+ * </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.
+ */
+ public String getVersion(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ if (this.version != null)
+ return vr.resolve(this.version);
+ String version = context.getMessages().findFirstString(req.getLocale(), "version");
+ if (version != null)
+ return vr.resolve(version);
+ Swagger s = req.getSwaggerFromFile();
+ if (s != null && s.getInfo() != null)
+ return s.getInfo().getVersion();
+ return null;
+ }
+
+ /**
+ * 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.
+ * </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.
+ */
+ public List<Tag> getTags(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ JsonParser jp = JsonParser.DEFAULT;
+ try {
+ if (this.tags != null)
+ return jp.parse(vr.resolve(this.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)
+ return s.getTags();
+ return null;
+ } catch (Exception e) {
+ throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+ }
+ }
+
+ /**
+ * 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.
+ * </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.
+ */
+ public ExternalDocumentation getExternalDocs(RestRequest req) {
+ VarResolverSession vr = req.getVarResolverSession();
+ JsonParser jp = JsonParser.DEFAULT;
+ try {
+ if (this.externalDocs != null)
+ return jp.parse(vr.resolve(this.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();
+ if (s != null)
+ return s.getExternalDocs();
+ return null;
+ } catch (Exception e) {
+ throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+ }
+ }
+}
Propchange: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java Fri Sep 8 23:25:34 2017
@@ -0,0 +1,257 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static javax.servlet.http.HttpServletResponse.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.text.*;
+import java.util.logging.*;
+
+import javax.servlet.http.*;
+
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Logging utility class.
+ *
+ * <p>
+ * Subclasses can override these methods to tailor logging of HTTP requests.
+ * Subclasses MUST implement a no-arg public constructor.
+ *
+ * <p>
+ * RestLoggers are associated with servlets/resources in one of the following ways:
+ * <ul>
+ * <li>The {@link RestResource#logger @RestResource.logger()} annotation.
+ * <li>The {@link RestConfig#setLogger(Class)}/{@link RestConfig#setLogger(RestLogger)} methods.
+ * </ul>
+ */
+public abstract class RestLogger {
+
+ /**
+ * Returns the Java logger used for logging.
+ *
+ * <p>
+ * Subclasses can provide their own logger.
+ * The default implementation returns the logger created using <code>Logger.getLogger(getClass())</code>.
+ *
+ * @return The logger used for logging.
+ */
+ protected abstract Logger getLogger();
+
+ /**
+ * Log a message to the logger.
+ *
+ * <p>
+ * Subclasses can override this method if they wish to log messages using a library other than Java Logging
+ * (e.g. Apache Commons Logging).
+ *
+ * @param level The log level.
+ * @param cause The cause.
+ * @param msg The message to log.
+ * @param args Optional {@link MessageFormat}-style arguments.
+ */
+ protected abstract void log(Level level, Throwable cause, String msg, Object...args);
+
+ /**
+ * Log a message.
+ *
+ * <p>
+ * Equivalent to calling <code>log(level, <jk>null</jk>, msg, args);</code>
+ *
+ * @param level The log level.
+ * @param msg The message to log.
+ * @param args Optional {@link MessageFormat}-style arguments.
+ */
+ protected void log(Level level, String msg, Object...args) {
+ log(level, null, msg, args);
+ }
+
+ /**
+ * Same as {@link #log(Level, String, Object...)} excepts runs the arguments through {@link JsonSerializer#DEFAULT_LAX_READABLE}.
+ *
+ * <p>
+ * Serialization of arguments do not occur if message is not logged, so it's safe to use this method from within
+ * debug log statements.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode'>
+ * logObjects(<jsf>DEBUG</jsf>, <js>"Pojo contents:\n{0}"</js>, myPojo);
+ * </p>
+ *
+ * @param level The log level.
+ * @param msg The message to log.
+ * @param args Optional {@link MessageFormat}-style arguments.
+ */
+ protected void logObjects(Level level, String msg, Object...args) {
+ for (int i = 0; i < args.length; i++)
+ args[i] = JsonSerializer.DEFAULT_LAX_READABLE.toStringObject(args[i]);
+ log(level, null, msg, args);
+ }
+
+ /**
+ * Callback method for logging errors during HTTP requests.
+ *
+ * <p>
+ * Typically, subclasses will override this method and log errors themselves.
+ *
+ * <p>
+ * The default implementation simply logs errors to the <code>RestServlet</code> logger.
+ *
+ * <p>
+ * Here's a typical implementation showing how stack trace hashing can be used to reduce log file sizes...
+ * <p class='bcode'>
+ * <jk>protected void</jk> onError(HttpServletRequest req, HttpServletResponse res, RestException e, <jk>boolean</jk> noTrace) {
+ * String qs = req.getQueryString();
+ * String msg = <js>"HTTP "</js> + req.getMethod() + <js>" "</js> + e.getStatus() + <js>" "</js> + req.getRequestURI() + (qs == <jk>null</jk> ? <js>""</js> : <js>"?"</js> + qs);
+ * <jk>int</jk> c = e.getOccurrence();
+ *
+ * <jc>// REST_useStackTraceHashes is disabled, so we have to log the exception every time.</jc>
+ * <jk>if</jk> (c == 0)
+ * myLogger.log(Level.<jsf>WARNING</jsf>, <jsm>format</jsm>(<js>"[%s] %s"</js>, e.getStatus(), msg), e);
+ *
+ * <jc>// This is the first time we've countered this error, so log a stack trace
+ * // unless ?noTrace was passed in as a URL parameter.</jc>
+ * <jk>else if</jk> (c == 1 && ! noTrace)
+ * myLogger.log(Level.<jsf>WARNING</jsf>, <jsm>format</jsm>(<js>"[%h.%s.%s] %s"</js>, e.hashCode(), e.getStatus(), c, msg), e);
+ *
+ * <jc>// This error occurred before.
+ * // Only log the message, not the stack trace.</jc>
+ * <jk>else</jk>
+ * myLogger.log(Level.<jsf>WARNING</jsf>, <jsm>format</jsm>(<js>"[%h.%s.%s] %s, %s"</js>, e.hashCode(), e.getStatus(), c, msg, e.getLocalizedMessage()));
+ * }
+ * </p>
+ *
+ * @param req The servlet request object.
+ * @param res The servlet response object.
+ * @param e Exception indicating what error occurred.
+ */
+ protected void onError(HttpServletRequest req, HttpServletResponse res, RestException e) {
+ if (shouldLog(req, res, e)) {
+ String qs = req.getQueryString();
+ String msg = "HTTP " + req.getMethod() + " " + e.getStatus() + " " + req.getRequestURI() + (qs == null ? "" : "?" + qs);
+ int c = e.getOccurrence();
+ if (shouldLogStackTrace(req, res, e)) {
+ msg = '[' + Integer.toHexString(e.hashCode()) + '.' + e.getStatus() + '.' + c + "] " + msg;
+ log(Level.WARNING, e, msg);
+ } else {
+ msg = '[' + Integer.toHexString(e.hashCode()) + '.' + e.getStatus() + '.' + c + "] " + msg + ", " + e.getLocalizedMessage();
+ log(Level.WARNING, msg);
+ }
+ }
+ }
+
+ /**
+ * Returns <jk>true</jk> if the specified exception should be logged.
+ *
+ * <p>
+ * Subclasses can override this method to provide their own logic for determining when exceptions are logged.
+ *
+ * <p>
+ * The default implementation will return <jk>false</jk> if <js>"noTrace=true"</js> is passed in the query string
+ * or <code>No-Trace: true</code> is specified in the header.
+ *
+ * @param req The HTTP request.
+ * @param res The HTTP response.
+ * @param e The exception.
+ * @return <jk>true</jk> if exception should be logged.
+ */
+ protected boolean shouldLog(HttpServletRequest req, HttpServletResponse res, RestException e) {
+ if (isNoTrace(req) && ! isDebug(req))
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns <jk>true</jk> if a stack trace should be logged for this exception.
+ *
+ * <p>
+ * Subclasses can override this method to provide their own logic for determining when stack traces are logged.
+ *
+ * <p>
+ * The default implementation will only log a stack trace if {@link RestException#getOccurrence()} returns
+ * <code>1</code> and the exception is not one of the following:
+ * <ul>
+ * <li>{@link HttpServletResponse#SC_UNAUTHORIZED}
+ * <li>{@link HttpServletResponse#SC_FORBIDDEN}
+ * <li>{@link HttpServletResponse#SC_NOT_FOUND}
+ * </ul>
+ *
+ * @param req The HTTP request.
+ * @param res The HTTP response.
+ * @param e The exception.
+ * @return <jk>true</jk> if stack trace should be logged.
+ */
+ protected boolean shouldLogStackTrace(HttpServletRequest req, HttpServletResponse res, RestException e) {
+ if (e.getOccurrence() == 1) {
+ switch (e.getStatus()) {
+ case SC_UNAUTHORIZED:
+ case SC_FORBIDDEN:
+ case SC_NOT_FOUND: return false;
+ default: return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isNoTrace(HttpServletRequest req) {
+ return "true".equals(req.getHeader("No-Trace")) || (req.getQueryString() != null && req.getQueryString().contains("noTrace=true"));
+ }
+
+ private static boolean isDebug(HttpServletRequest req) {
+ return "true".equals(req.getHeader("Debug"));
+ }
+
+ /**
+ * NO-OP logger.
+ *
+ * <p>
+ * Disables all logging.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+ public static class NoOp extends RestLogger {
+
+ @Override /* RestLogger */
+ protected Logger getLogger() {
+ return null;
+ }
+
+ @Override /* RestLogger */
+ protected void log(Level level, Throwable cause, String msg, Object...args) {}
+ }
+
+ /**
+ * Default logger.
+ *
+ * <p>
+ * Logs all messages to the logger returned by <code>Logger.<jsm>getLogger</jsm>(getClass().getName())</code>
+ */
+ public static class Normal extends RestLogger {
+
+ private final JuneauLogger logger = JuneauLogger.getLogger(getClass());
+
+ @Override /* RestLogger */
+ protected Logger getLogger() {
+ return logger;
+ }
+
+ @Override /* RestLogger */
+ protected void log(Level level, Throwable cause, String msg, Object...args) {
+ msg = format(msg, args);
+ getLogger().log(level, msg, cause);
+ }
+ }
+}
Propchange: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMatcher.java
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMatcher.java (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMatcher.java Fri Sep 8 23:25:34 2017
@@ -0,0 +1,79 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Class used for defining method-level matchers using the {@link RestMethod#matchers()} annotation.
+ *
+ * <p>
+ * Matchers are used to allow multiple Java methods to handle requests assigned to the same URL path pattern, but
+ * differing based on some request attribute, such as a specific header value.
+ * For example, matchers can be used to provide two different methods for handling requests from two different client
+ * versions.
+ *
+ * <p>
+ * Java methods with matchers associated with them are always attempted before Java methods without matchers.
+ * This allows a 'default' method to be defined to handle requests where no matchers match.
+ *
+ * <p>
+ * When multiple matchers are specified on a method, only one matcher is required to match.
+ * This is opposite from the {@link RestMethod#guards()} annotation, where all guards are required to match in order to
+ * execute the method.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode'>
+ * <jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
+ *
+ * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo"</js>, matchers=IsDNT.<jk>class</jk>)
+ * <jk>public</jk> Object doGetWithDNT() {
+ * <jc>// Handle request with Do-Not-Track specified</jc>
+ * }
+ *
+ * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo"</js>)
+ * <jk>public</jk> Object doGetWithoutDNT() {
+ * <jc>// Handle request without Do-Not-Track specified</jc>
+ * }
+ * }
+ *
+ * <jk>public class</jk> IsDNT <jk>extends</jk> RestMatcher {
+ * <ja>@Override</ja>
+ * <jk>public boolean</jk> matches(RestRequest req) {
+ * <jk>return</jk> req.getHeader(<jk>int</jk>.<jk>class</jk>, <js>"DNT"</js>, 0) == 1;
+ * }
+ * }
+ * </p>
+ */
+public abstract class RestMatcher {
+
+ /**
+ * Returns <jk>true</jk> if the specified request matches this matcher.
+ *
+ * @param req The servlet request.
+ * @return <jk>true</jk> if the specified request matches this matcher.
+ */
+ public abstract boolean matches(RestRequest req);
+
+ /**
+ * Returns <jk>true</jk> if this matcher is required to match in order for the method to be invoked.
+ *
+ * <p>
+ * If <jk>false</jk>, then only one of the matchers must match.
+ *
+ * @return <jk>true</jk> if this matcher is required to match in order for the method to be invoked.
+ */
+ public boolean mustMatch() {
+ return false;
+ }
+}
Propchange: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMatcher.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMatcherReflecting.java
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMatcherReflecting.java (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMatcherReflecting.java Fri Sep 8 23:25:34 2017
@@ -0,0 +1,33 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import java.lang.reflect.*;
+
+/**
+ * Subclass of {@link RestMatcher} that gives access to the servlet/resource and Java method it's applied to.
+ *
+ * <p>
+ * Essentially the same as {@link RestMatcher} except has a constructor where the Java method is passed in so that you
+ * can access annotations defined on it to tailor the behavior of the matcher.
+ */
+public abstract class RestMatcherReflecting extends RestMatcher {
+
+ /**
+ * Constructor.
+ *
+ * @param resource The REST servlet.
+ * @param javaMethod The Java method that this rest matcher is defined on.
+ */
+ protected RestMatcherReflecting(Object resource, Method javaMethod) {}
+}
Propchange: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMatcherReflecting.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParam.java
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParam.java (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParam.java Fri Sep 8 23:25:34 2017
@@ -0,0 +1,97 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import java.lang.reflect.*;
+
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * REST java method parameter resolver.
+ *
+ * <p>
+ * Used to resolve instances of classes being passed to Java REST methods.
+ *
+ * <p>
+ * This class is associated with REST classes via the {@link RestResource#paramResolvers()} annotation and
+ * {@link RestConfig#addParamResolvers(Class...)} method.
+ */
+public abstract class RestParam {
+
+ final RestParamType paramType;
+ final String name;
+ final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param paramType The Swagger parameter type.
+ * @param name
+ * The parameter name.
+ * Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
+ * @param type The object type to convert the parameter to.
+ */
+ protected RestParam(RestParamType paramType, String name, Type type) {
+ this.paramType = paramType;
+ this.name = name;
+ this.type = type;
+ }
+
+ /**
+ * Resolves the parameter object.
+ *
+ * @param req The rest request.
+ * @param res The rest response.
+ * @return The resolved object.
+ * @throws Exception
+ */
+ public abstract Object resolve(RestRequest req, RestResponse res) throws Exception;
+
+ /**
+ * Returns the parameter class type that this parameter resolver is meant for.
+ *
+ * @return The parameter class type, or <jk>null</jk> if the type passed in isn't an instance of {@link Class}.
+ */
+ protected Class<?> forClass() {
+ if (type instanceof Class)
+ return (Class<?>)type;
+ return null;
+ }
+
+ /**
+ * Returns the swagger parameter type for this parameter as shown in the Swagger doc.
+ *
+ * @return the swagger parameter type for this parameter.
+ */
+ protected RestParamType getParamType() {
+ return paramType;
+ }
+
+ /**
+ * Returns the parameter name for this parameter as shown in the Swagger doc.
+ *
+ * @return the parameter name for this parameter.
+ */
+ protected String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the parameter class type.
+ *
+ * @return the parameter class type.
+ */
+ public Type getType() {
+ return type;
+ }
+}
Propchange: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParam.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java Fri Sep 8 23:25:34 2017
@@ -0,0 +1,971 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.rest.RestParamType.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.logging.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.Date;
+import org.apache.juneau.ini.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * Default REST method parameter resolvers.
+ */
+class RestParamDefaults {
+
+ /**
+ * Standard set of method parameter resolvers.
+ */
+ static final Map<Class<?>,RestParam> STANDARD_RESOLVERS;
+
+ static {
+ Map<Class<?>,RestParam> m = new HashMap<Class<?>,RestParam>();
+
+ @SuppressWarnings("rawtypes")
+ Class[] r = new Class[] {
+
+ // Standard top-level objects
+ HttpServletRequestObject.class,
+ RestRequestObject.class,
+ HttpServletResponseObject.class,
+ RestResponseObject.class,
+
+ // Headers
+ AcceptHeader.class,
+ AcceptCharsetHeader.class,
+ AcceptEncodingHeader.class,
+ AcceptLanguageHeader.class,
+ AuthorizationHeader.class,
+ CacheControlHeader.class,
+ ConnectionHeader.class,
+ ContentLengthHeader.class,
+ ContentTypeHeader.class,
+ DateHeader.class,
+ ExpectHeader.class,
+ FromHeader.class,
+ HostHeader.class,
+ IfMatchHeader.class,
+ IfModifiedSinceHeader.class,
+ IfNoneMatchHeader.class,
+ IfRangeHeader.class,
+ IfUnmodifiedSinceHeader.class,
+ MaxForwardsHeader.class,
+ PragmaHeader.class,
+ ProxyAuthorizationHeader.class,
+ RangeHeader.class,
+ RefererHeader.class,
+ TEHeader.class,
+ UserAgentHeader.class,
+ UpgradeHeader.class,
+ ViaHeader.class,
+ WarningHeader.class,
+ TimeZoneHeader.class,
+
+ // Other objects
+ ResourceBundleObject.class,
+ MessageBundleObject.class,
+ InputStreamObject.class,
+ ServletInputStreamObject.class,
+ ReaderObject.class,
+ OutputStreamObject.class,
+ ServletOutputStreamObject.class,
+ WriterObject.class,
+ RequestHeadersObject.class,
+ RequestQueryObject.class,
+ RequestFormDataObject.class,
+ HttpMethodObject.class,
+ LoggerObject.class,
+ JuneauLoggerObject.class,
+ RestContextObject.class,
+ ParserObject.class,
+ LocaleObject.class,
+ SwaggerObject.class,
+ RequestPathMatchObject.class,
+ RequestBodyObject.class,
+ ConfigFileObject.class,
+ UriContextObject.class,
+ UriResolverObject.class,
+ };
+
+ for (Class<?> c : r) {
+ try {
+ RestParam mpr = (RestParam)c.newInstance();
+ m.put(mpr.forClass(), mpr);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ STANDARD_RESOLVERS = Collections.unmodifiableMap(m);
+ }
+
+ //-------------------------------------------------------------------------------------------------------------------
+ // Request / Response retrievers
+ //-------------------------------------------------------------------------------------------------------------------
+
+ static final class HttpServletRequestObject extends RestParam {
+
+ protected HttpServletRequestObject() {
+ super(OTHER, null, HttpServletRequest.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) {
+ return req;
+ }
+ }
+
+ static final class HttpServletResponseObject extends RestParam {
+
+ protected HttpServletResponseObject() {
+ super(OTHER, null, HttpServletResponse.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) {
+ return res;
+ }
+ }
+
+ static final class RestRequestObject extends RestParam {
+
+ protected RestRequestObject() {
+ super(OTHER, null, RestRequest.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) {
+ return req;
+ }
+ }
+
+ static final class RestResponseObject extends RestParam {
+
+ protected RestResponseObject() {
+ super(OTHER, null, RestResponse.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) {
+ return res;
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------------------------
+ // Header retrievers
+ //-------------------------------------------------------------------------------------------------------------------
+
+ static final class AcceptHeader extends RestParam {
+
+ protected AcceptHeader() {
+ super(HEADER, "Accept-Header", Accept.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getAccept();
+ }
+ }
+
+ static final class AcceptCharsetHeader extends RestParam {
+
+ protected AcceptCharsetHeader() {
+ super(HEADER, "Accept-Charset", AcceptCharset.class);
+ }
+
+ @Override /* RestParam */
+ public AcceptCharset resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getAcceptCharset();
+ }
+ }
+
+ static final class AcceptEncodingHeader extends RestParam {
+
+ protected AcceptEncodingHeader() {
+ super(HEADER, "Accept-Encoding", AcceptEncoding.class);
+ }
+
+ @Override
+ public AcceptEncoding resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getAcceptEncoding();
+ }
+ }
+
+ static final class AcceptLanguageHeader extends RestParam {
+
+ protected AcceptLanguageHeader() {
+ super(HEADER, "Accept-Language", AcceptLanguage.class);
+ }
+
+ @Override
+ public AcceptLanguage resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getAcceptLanguage();
+ }
+ }
+
+ static final class AuthorizationHeader extends RestParam {
+
+ protected AuthorizationHeader() {
+ super(HEADER, "Authorization", Authorization.class);
+ }
+
+ @Override
+ public Authorization resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getAuthorization();
+ }
+ }
+
+ static final class CacheControlHeader extends RestParam {
+
+ protected CacheControlHeader() {
+ super(HEADER, "Cache-Control", CacheControl.class);
+ }
+
+ @Override
+ public CacheControl resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getCacheControl();
+ }
+ }
+
+ static final class ConnectionHeader extends RestParam {
+
+ protected ConnectionHeader() {
+ super(HEADER, "Connection", Connection.class);
+ }
+
+ @Override
+ public Connection resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getConnection();
+ }
+ }
+
+ static final class ContentLengthHeader extends RestParam {
+
+ protected ContentLengthHeader() {
+ super(HEADER, "Content-Length", ContentLength.class);
+ }
+
+ @Override
+ public ContentLength resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getContentLength();
+ }
+ }
+
+ static final class ContentTypeHeader extends RestParam {
+
+ protected ContentTypeHeader() {
+ super(HEADER, "Content-Type", ContentType.class);
+ }
+
+ @Override
+ public ContentType resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getContentType();
+ }
+ }
+
+ static final class DateHeader extends RestParam {
+
+ protected DateHeader() {
+ super(HEADER, "Date", Date.class);
+ }
+
+ @Override
+ public Date resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getDate();
+ }
+ }
+
+ static final class ExpectHeader extends RestParam {
+
+ protected ExpectHeader() {
+ super(HEADER, "Expect", Expect.class);
+ }
+
+ @Override
+ public Expect resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getExpect();
+ }
+ }
+
+ static final class FromHeader extends RestParam {
+
+ protected FromHeader() {
+ super(HEADER, "From", From.class);
+ }
+
+ @Override
+ public From resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getFrom();
+ }
+ }
+
+ static final class HostHeader extends RestParam {
+
+ protected HostHeader() {
+ super(HEADER, "Host", Host.class);
+ }
+
+ @Override
+ public Host resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getHost();
+ }
+ }
+
+ static final class IfMatchHeader extends RestParam {
+
+ protected IfMatchHeader() {
+ super(HEADER, "If-Match", IfMatch.class);
+ }
+
+ @Override
+ public IfMatch resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getIfMatch();
+ }
+ }
+
+ static final class IfModifiedSinceHeader extends RestParam {
+
+ protected IfModifiedSinceHeader() {
+ super(HEADER, "If-Modified-Since", IfModifiedSince.class);
+ }
+
+ @Override
+ public IfModifiedSince resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getIfModifiedSince();
+ }
+ }
+
+ static final class IfNoneMatchHeader extends RestParam {
+
+ protected IfNoneMatchHeader() {
+ super(HEADER, "If-None-Match", IfNoneMatch.class);
+ }
+
+ @Override
+ public IfNoneMatch resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getIfNoneMatch();
+ }
+ }
+
+ static final class IfRangeHeader extends RestParam {
+
+ protected IfRangeHeader() {
+ super(HEADER, "If-Range", IfRange.class);
+ }
+
+ @Override
+ public IfRange resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getIfRange();
+ }
+ }
+
+ static final class IfUnmodifiedSinceHeader extends RestParam {
+
+ protected IfUnmodifiedSinceHeader() {
+ super(HEADER, "If-Unmodified-Since", IfUnmodifiedSince.class);
+ }
+
+ @Override
+ public IfUnmodifiedSince resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getIfUnmodifiedSince();
+ }
+ }
+
+ static final class MaxForwardsHeader extends RestParam {
+
+ protected MaxForwardsHeader() {
+ super(HEADER, "Max-Forwards", MaxForwards.class);
+ }
+
+ @Override
+ public MaxForwards resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getMaxForwards();
+ }
+ }
+
+ static final class PragmaHeader extends RestParam {
+
+ protected PragmaHeader() {
+ super(HEADER, "Pragma", Pragma.class);
+ }
+
+ @Override
+ public Pragma resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getPragma();
+ }
+ }
+
+ static final class ProxyAuthorizationHeader extends RestParam {
+
+ protected ProxyAuthorizationHeader() {
+ super(HEADER, "Proxy-Authorization", ProxyAuthorization.class);
+ }
+
+ @Override
+ public ProxyAuthorization resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getProxyAuthorization();
+ }
+ }
+
+ static final class RangeHeader extends RestParam {
+
+ protected RangeHeader() {
+ super(HEADER, "Range", Range.class);
+ }
+
+ @Override
+ public Range resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getRange();
+ }
+ }
+
+ static final class RefererHeader extends RestParam {
+
+ protected RefererHeader() {
+ super(HEADER, "Referer", Referer.class);
+ }
+
+ @Override
+ public Referer resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getReferer();
+ }
+ }
+
+ static final class TEHeader extends RestParam {
+
+ protected TEHeader() {
+ super(HEADER, "TE", TE.class);
+ }
+
+ @Override
+ public TE resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getTE();
+ }
+ }
+
+ static final class UserAgentHeader extends RestParam {
+
+ protected UserAgentHeader() {
+ super(HEADER, "User-Agent", UserAgent.class);
+ }
+
+ @Override
+ public UserAgent resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getUserAgent();
+ }
+ }
+
+ static final class UpgradeHeader extends RestParam {
+
+ protected UpgradeHeader() {
+ super(HEADER, "Upgrade", Upgrade.class);
+ }
+
+ @Override
+ public Upgrade resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getUpgrade();
+ }
+ }
+
+ static final class ViaHeader extends RestParam {
+
+ protected ViaHeader() {
+ super(HEADER, "Via", Via.class);
+ }
+
+ @Override
+ public Via resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getVia();
+ }
+ }
+
+ static final class WarningHeader extends RestParam {
+
+ protected WarningHeader() {
+ super(HEADER, "Warning", Warning.class);
+ }
+
+ @Override
+ public Warning resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getWarning();
+ }
+ }
+
+ static final class TimeZoneHeader extends RestParam {
+
+ protected TimeZoneHeader() {
+ super(HEADER, "Time-Zone", TimeZone.class);
+ }
+
+ @Override
+ public TimeZone resolve(RestRequest req, RestResponse res) {
+ return req.getHeaders().getTimeZone();
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------------------------
+ // Annotated retrievers
+ //-------------------------------------------------------------------------------------------------------------------
+
+ static final class PathParameterObject extends RestParam {
+
+ protected PathParameterObject(String name, Type type) {
+ super(PATH, name, type);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getPathMatch().get(name, type);
+ }
+ }
+
+ static final class BodyObject extends RestParam {
+
+ protected BodyObject(Type type) {
+ super(BODY, null, type);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getBody().asType(type);
+ }
+ }
+
+ static final class HeaderObject extends RestParam {
+
+ protected HeaderObject(Header a, Type type) {
+ super(HEADER, firstNonEmpty(a.name(), a.value()), type);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getHeaders().get(name, type);
+ }
+ }
+
+ static final class MethodObject extends RestParam {
+
+ protected MethodObject(Method method, Type type) throws ServletException {
+ super(OTHER, null, null);
+ if (type != String.class)
+ throw new RestServletException("Use of @Method annotation on parameter that is not a String on method ''{0}''", method);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getMethod();
+ }
+ }
+
+ static final class FormDataObject extends RestParam {
+ private final boolean multiPart, plainParams;
+
+ protected FormDataObject(Method method, FormData a, Type type, boolean methodPlainParams) throws ServletException {
+ super(FORMDATA, firstNonEmpty(a.name(), a.value()), type);
+ if (a.multipart() && ! isCollection(type))
+ throw new RestServletException("Use of multipart flag on @FormData parameter that's not an array or Collection on method ''{0}''", method);
+ this.multiPart = a.multipart();
+ this.plainParams = a.format().equals("INHERIT") ? methodPlainParams : a.format().equals("PLAIN");
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ BeanSession bs = req.getBeanSession();
+ if (multiPart)
+ return req.getFormData().getAll(name, type);
+ if (plainParams)
+ return bs.convertToType(req.getFormData().getString(name), bs.getClassMeta(type));
+ return req.getFormData().get(name, type);
+ }
+ }
+
+ static final class QueryObject extends RestParam {
+ private final boolean multiPart, plainParams;
+
+ protected QueryObject(Method method, Query a, Type type, boolean methodPlainParams) throws ServletException {
+ super(QUERY, firstNonEmpty(a.name(), a.value()), type);
+ if (a.multipart() && ! isCollection(type))
+ throw new RestServletException("Use of multipart flag on @Query parameter that's not an array or Collection on method ''{0}''", method);
+ this.multiPart = a.multipart();
+ this.plainParams = a.format().equals("INHERIT") ? methodPlainParams : a.format().equals("PLAIN");
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ BeanSession bs = req.getBeanSession();
+ if (multiPart)
+ return req.getQuery().getAll(name, type);
+ if (plainParams)
+ return bs.convertToType(req.getQuery().getString(name), bs.getClassMeta(type));
+ return req.getQuery().get(name, type);
+ }
+ }
+
+ static final class HasFormDataObject extends RestParam {
+
+ protected HasFormDataObject(Method method, HasFormData a, Type type) throws ServletException {
+ super(FORMDATA, firstNonEmpty(a.name(), a.value()), type);
+ if (type != Boolean.class && type != boolean.class)
+ throw new RestServletException("Use of @HasForm annotation on parameter that is not a boolean on method ''{0}''", method);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ BeanSession bs = req.getBeanSession();
+ return bs.convertToType(req.getFormData().containsKey(name), bs.getClassMeta(type));
+ }
+ }
+
+ static final class HasQueryObject extends RestParam {
+
+ protected HasQueryObject(Method method, HasQuery a, Type type) throws ServletException {
+ super(QUERY, firstNonEmpty(a.name(), a.value()), type);
+ if (type != Boolean.class && type != boolean.class)
+ throw new RestServletException("Use of @HasQuery annotation on parameter that is not a boolean on method ''{0}''", method);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ BeanSession bs = req.getBeanSession();
+ return bs.convertToType(req.getQuery().containsKey(name), bs.getClassMeta(type));
+ }
+ }
+
+ static final class PathRemainderObject extends RestParam {
+
+ protected PathRemainderObject(Method method, Type type) throws ServletException {
+ super(OTHER, null, null);
+ if (type != String.class)
+ throw new RestServletException("Use of @PathRemainder annotation on parameter that is not a String on method ''{0}''", method);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getPathMatch().getRemainder();
+ }
+ }
+
+ static final class PropsObject extends RestParam {
+
+ protected PropsObject(Method method, Type type) throws ServletException {
+ super(OTHER, null, null);
+ if (type != ObjectMap.class)
+ throw new RestServletException("Use of @Properties annotation on parameter that is not an ObjectMap on method ''{0}''", method);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getProperties();
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------------------------
+ // Other retrievers
+ //-------------------------------------------------------------------------------------------------------------------
+
+ static final class ResourceBundleObject extends RestParam {
+
+ protected ResourceBundleObject() {
+ super(OTHER, null, ResourceBundle.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getResourceBundle();
+ }
+ }
+
+ static final class MessageBundleObject extends RestParam {
+
+ protected MessageBundleObject() {
+ super(OTHER, null, MessageBundle.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getResourceBundle();
+ }
+ }
+
+ static final class InputStreamObject extends RestParam {
+
+ protected InputStreamObject() {
+ super(OTHER, null, InputStream.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getInputStream();
+ }
+ }
+
+ static final class ServletInputStreamObject extends RestParam {
+
+ protected ServletInputStreamObject() {
+ super(OTHER, null, ServletInputStream.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getInputStream();
+ }
+ }
+
+ static final class ReaderObject extends RestParam {
+
+ protected ReaderObject() {
+ super(OTHER, null, Reader.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getReader();
+ }
+ }
+
+ static final class OutputStreamObject extends RestParam {
+
+ protected OutputStreamObject() {
+ super(OTHER, null, OutputStream.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return res.getOutputStream();
+ }
+ }
+
+ static final class ServletOutputStreamObject extends RestParam {
+
+ protected ServletOutputStreamObject() {
+ super(OTHER, null, ServletOutputStream.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return res.getOutputStream();
+ }
+ }
+
+ static final class WriterObject extends RestParam {
+
+ protected WriterObject() {
+ super(OTHER, null, Writer.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return res.getWriter();
+ }
+ }
+
+ static final class RequestHeadersObject extends RestParam {
+
+ protected RequestHeadersObject() {
+ super(OTHER, null, RequestHeaders.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getHeaders();
+ }
+ }
+
+ static final class RequestQueryObject extends RestParam {
+
+ protected RequestQueryObject() {
+ super(OTHER, null, RequestQuery.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getQuery();
+ }
+ }
+
+ static final class RequestFormDataObject extends RestParam {
+
+ protected RequestFormDataObject() {
+ super(OTHER, null, RequestFormData.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getFormData();
+ }
+ }
+
+ static final class HttpMethodObject extends RestParam {
+
+ protected HttpMethodObject() {
+ super(OTHER, null, HttpMethod.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getHttpMethod();
+ }
+ }
+
+ static final class LoggerObject extends RestParam {
+
+ protected LoggerObject() {
+ super(OTHER, null, Logger.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getContext().getLogger().getLogger();
+ }
+ }
+
+ static final class JuneauLoggerObject extends RestParam {
+
+ protected JuneauLoggerObject() {
+ super(OTHER, null, JuneauLogger.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getContext().getLogger().getLogger();
+ }
+ }
+
+ static final class RestContextObject extends RestParam {
+
+ protected RestContextObject() {
+ super(OTHER, null, RestContext.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getContext();
+ }
+ }
+
+ static final class ParserObject extends RestParam {
+
+ protected ParserObject() {
+ super(OTHER, null, Parser.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getBody().getParser();
+ }
+ }
+
+ static final class LocaleObject extends RestParam {
+
+ protected LocaleObject() {
+ super(OTHER, null, Locale.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getLocale();
+ }
+ }
+
+ static final class SwaggerObject extends RestParam {
+
+ protected SwaggerObject() {
+ super(OTHER, null, Swagger.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getSwagger();
+ }
+ }
+
+ static final class RequestPathMatchObject extends RestParam {
+
+ protected RequestPathMatchObject() {
+ super(OTHER, null, RequestPathMatch.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getPathMatch();
+ }
+ }
+
+ static final class RequestBodyObject extends RestParam {
+
+ protected RequestBodyObject() {
+ super(BODY, null, RequestBody.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getBody();
+ }
+ }
+
+ static final class ConfigFileObject extends RestParam {
+
+ protected ConfigFileObject() {
+ super(OTHER, null, ConfigFile.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getConfigFile();
+ }
+ }
+
+ static final class UriContextObject extends RestParam {
+
+ protected UriContextObject() {
+ super(OTHER, null, UriContext.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getUriContext();
+ }
+ }
+
+ static final class UriResolverObject extends RestParam {
+
+ protected UriResolverObject() {
+ super(OTHER, null, UriResolver.class);
+ }
+
+ @Override /* RestParam */
+ public Object resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getUriResolver();
+ }
+ }
+
+ private static boolean isCollection(Type t) {
+ return BeanContext.DEFAULT.getClassMeta(t).isCollectionOrArray();
+ }
+}
Propchange: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java Fri Sep 8 23:25:34 2017
@@ -0,0 +1,48 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+/**
+ * Represents the possible parameter types as defined by the Swagger 2.0 specification.
+ */
+public enum RestParamType {
+
+ /** Path variable */
+ PATH("path"),
+
+ /** Header value */
+ HEADER("header"),
+
+ /** Form data entry */
+ FORMDATA("formData"),
+
+ /** Query parameter */
+ QUERY("query"),
+
+ /** Request body */
+ BODY("body"),
+
+ /** Not a standard Swagger-defined field */
+ OTHER("other");
+
+ private final String value;
+
+ private RestParamType(String value) {
+ this.value = value;
+ }
+
+ @Override /* Object */
+ public String toString() {
+ return value;
+ }
+}
Propchange: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
------------------------------------------------------------------------------
svn:mime-type = text/plain