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/18 21:43:58 UTC
[1/2] juneau git commit: RestContext refactoring.
Repository: juneau
Updated Branches:
refs/heads/master 5a36a0837 -> af355372e
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/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
new file mode 100644
index 0000000..11cad76
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProviderDefault.java
@@ -0,0 +1,632 @@
+// ***************************************************************************************************************************
+// * 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.*;
+
+/**
+ * Default implementation of {@link RestInfoProvider}.
+ *
+ * <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>
+ * <li class='jf'>{@link RestContext#REST_infoProvider}
+ * </ul>
+ */
+public class RestInfoProviderDefault implements 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<>();
+
+ /**
+ * Constructor.
+ *
+ * @param context The resource context.
+ */
+ public RestInfoProviderDefault(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 final class Builder {
+ 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 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 req The incoming HTTP request.
+ * @return The parsed swagger object, or <jk>null</jk> if the swagger file could not be found.
+ * @throws RestException
+ */
+ @Override /* RestInfoProvider */
+ public Swagger getSwaggerFromFile(RestRequest req) throws RestException {
+ 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);
+ }
+ }
+ return s == Swagger.NULL ? null : s;
+ }
+
+ /**
+ * Returns the localized swagger for this REST resource.
+ *
+ * @param req The incoming HTTP request.
+ * @return A new Swagger instance.
+ * @throws RestException
+ */
+ @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
+ );
+ }
+ }
+ return s;
+ } catch (RestException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
+ }
+ }
+
+ /**
+ * 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.
+ */
+ @Override /* RestInfoProvider */
+ public String getMethodSummary(String javaMethodName, RestRequest req) {
+ RestJavaMethod m = context.getCallMethods().get(javaMethodName);
+ if (m != null)
+ return m.getSummary(req);
+ return "";
+ }
+
+ /**
+ * Returns the localized summary of the java method invoked on the specified request.
+ *
+ * <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 req The current request.
+ * @return The localized summary of the method, or a blank string if no summary was found.
+ */
+ @Override /* RestInfoProvider */
+ public String getMethodSummary(RestRequest req) {
+ return getMethodSummary(req.getJavaMethod().getName(), req);
+ }
+
+ /**
+ * 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.
+ */
+ @Override /* RestInfoProvider */
+ public String getMethodDescription(String javaMethodName, RestRequest req) {
+ RestJavaMethod m = context.getCallMethods().get(javaMethodName);
+ if (m != null)
+ return m.getDescription(req);
+ return "";
+ }
+
+ /**
+ * Returns the localized description of the invoked java method on the specified request.
+ *
+ * <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 req The current request.
+ * @return The localized description of the method, or a blank string if no description was found.
+ */
+ @Override /* RestInfoProvider */
+ public String getMethodDescription(RestRequest req) {
+ return getMethodDescription(req.getJavaMethod().getName(), req);
+ }
+
+ /**
+ * 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.
+ */
+ @Override /* RestInfoProvider */
+ 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.
+ */
+ @Override /* RestInfoProvider */
+ 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.
+ */
+ @Override /* RestInfoProvider */
+ 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.
+ */
+ @Override /* RestInfoProvider */
+ 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.
+ */
+ @Override /* RestInfoProvider */
+ 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.
+ */
+ @Override /* RestInfoProvider */
+ 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.
+ */
+ @Override /* RestInfoProvider */
+ 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.
+ */
+ @Override /* RestInfoProvider */
+ 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.
+ */
+ @Override /* RestInfoProvider */
+ 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);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java
index 6e1ec6c..12e0b5d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLogger.java
@@ -12,72 +12,51 @@
// ***************************************************************************************************************************
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:
+ * <h5 class='topic'>Additional Information</h5>
* <ul>
- * <li>The {@link RestResource#logger @RestResource.logger()} annotation.
- * <li>The {@link RestContextBuilder#logger(Class)}/{@link RestContextBuilder#logger(RestLogger)} methods.
+ * <li class='jf'>{@link RestContext#REST_logger}
* </ul>
*/
-public abstract class RestLogger {
+public interface RestLogger {
/**
- * Returns the Java logger used for logging.
+ * Represents no RestLogger.
*
* <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.
+ * Used on annotation to indicate that the value should be inherited from the parent class, and
+ * ultimately {@link RestLoggerDefault} if not specified at any level.
*/
- protected abstract Logger getLogger();
+ public interface Null extends RestLogger {}
/**
* 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);
+ public 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);
- }
+ public void log(Level level, String msg, Object...args);
/**
* Same as {@link #log(Level, String, Object...)} excepts runs the arguments through {@link JsonSerializer#DEFAULT_LAX_READABLE}.
@@ -95,11 +74,7 @@ public abstract class RestLogger {
* @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);
- }
+ public void logObjects(Level level, String msg, Object...args);
/**
* Callback method for logging errors during HTTP requests.
@@ -138,120 +113,5 @@ public abstract class RestLogger {
* @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 contains(req.getHeader("No-Trace"), "true") || contains(req.getQueryString(), "noTrace=true");
- }
-
- private static boolean isDebug(HttpServletRequest req) {
- return contains(req.getHeader("Debug"), "true");
- }
-
- /**
- * 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);
- }
- }
+ public void onError(HttpServletRequest req, HttpServletResponse res, RestException e);
}
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLoggerDefault.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLoggerDefault.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLoggerDefault.java
new file mode 100644
index 0000000..ed4d6a0
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLoggerDefault.java
@@ -0,0 +1,225 @@
+// ***************************************************************************************************************************
+// * 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.*;
+
+/**
+ * Logging utility class.
+ *
+ * <p>
+ * Subclasses can override these methods to tailor logging of HTTP requests.
+ * <br>Subclasses MUST implement a no-arg public constructor.
+ *
+ *
+ * <h5 class='topic'>Additional Information</h5>
+ * <ul>
+ * <li class='jf'>{@link RestContext#REST_callHandler}
+ * </ul>
+ */
+public class RestLoggerDefault implements RestLogger {
+
+ private final JuneauLogger logger = JuneauLogger.getLogger(getClass());
+
+ /**
+ * 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 Logger getLogger() {
+ return logger;
+ }
+
+ /**
+ * 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.
+ */
+ @Override /* RestLogger */
+ public void log(Level level, Throwable cause, String msg, Object...args) {
+ msg = format(msg, args);
+ getLogger().log(level, msg, cause);
+ }
+
+ /**
+ * 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.
+ */
+ @Override /* RestLogger */
+ public 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.
+ */
+ @Override /* RestLogger */
+ public 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.
+ */
+ @Override /* RestLogger */
+ public 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 contains(req.getHeader("No-Trace"), "true") || contains(req.getQueryString(), "noTrace=true");
+ }
+
+ private static boolean isDebug(HttpServletRequest req) {
+ return contains(req.getHeader("Debug"), "true");
+ }
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLoggerNoOp.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLoggerNoOp.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLoggerNoOp.java
new file mode 100644
index 0000000..49e1821
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestLoggerNoOp.java
@@ -0,0 +1,47 @@
+// ***************************************************************************************************************************
+// * 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.text.*;
+import java.util.logging.*;
+
+/**
+ * Logging utility class.
+ *
+ * <p>
+ * Disables logging entirely.
+ *
+ *
+ * <h5 class='topic'>Additional Information</h5>
+ * <ul>
+ * <li class='jf'>{@link RestContext#REST_callHandler}
+ * </ul>
+ */
+public class RestLoggerNoOp extends RestLoggerDefault {
+
+ /**
+ * 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.
+ */
+ @Override /* RestLogger */
+ public void log(Level level, Throwable cause, String msg, Object...args) {}
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
index bfdefd3..633416c 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
@@ -19,7 +19,6 @@ 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.*;
@@ -101,8 +100,7 @@ class RestParamDefaults {
RequestQueryObject.class,
RequestFormDataObject.class,
HttpMethodObject.class,
- LoggerObject.class,
- JuneauLoggerObject.class,
+ RestLoggerObject.class,
RestContextObject.class,
ParserObject.class,
LocaleObject.class,
@@ -832,27 +830,15 @@ class RestParamDefaults {
}
}
- static final class LoggerObject extends RestParam {
+ static final class RestLoggerObject extends RestParam {
- protected LoggerObject() {
- super(OTHER, null, Logger.class);
+ protected RestLoggerObject() {
+ super(OTHER, null, RestLogger.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();
+ public RestLogger resolve(RestRequest req, RestResponse res) throws Exception {
+ return req.getContext().getLogger();
}
}
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/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 c36e432..2354d36 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
@@ -950,7 +950,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
*/
protected Swagger getSwaggerFromFile() {
if (fileSwagger == null)
- fileSwagger = context.getInfoProvider().getSwaggerFromFile(this.getLocale());
+ fileSwagger = context.getInfoProvider().getSwaggerFromFile(this);
if (fileSwagger == null)
fileSwagger = Swagger.NULL;
return fileSwagger == Swagger.NULL ? null : fileSwagger;
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java
index 893ef7d..5041552 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolver.java
@@ -38,6 +38,15 @@ import org.apache.juneau.rest.annotation.*;
public interface RestResourceResolver {
/**
+ * Represents no RestResourceResolver.
+ *
+ * <p>
+ * Used on annotation to indicate that the value should be inherited from the parent class, and
+ * ultimately {@link RestResourceResolverDefault} if not specified at any level.
+ */
+ public interface Null extends RestResourceResolver {}
+
+ /**
* Resolves the specified class to a resource object.
*
* <p>
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverDefault.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverDefault.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverDefault.java
new file mode 100644
index 0000000..0f319f2
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverDefault.java
@@ -0,0 +1,55 @@
+// ***************************************************************************************************************************
+// * 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.internal.*;
+
+/**
+ * Denotes the default resolver for child resources.
+ *
+ * The default implementation simply instantiates the class using one of the following constructors:
+ * <ul>
+ * <li><code><jk>public</jk> T(RestContext)</code>
+ * <li><code><jk>public</jk> T()</code>
+ * </ul>
+ *
+ * <p>
+ * The former constructor can be used to get access to the {@link RestContextBuilder} object to get access to the
+ * config file and initialization information or make programmatic modifications to the resource before
+ * full initialization.
+ *
+ * <p>
+ * Child classes can also be defined as inner-classes of the parent resource class.
+ *
+ * <p>
+ * Non-<code>RestServlet</code> classes can also add the following method to get access to the {@link RestContextBuilder}
+ * object:
+ * <ul>
+ * <li><code><jk>public void</jk> init(RestContextBuilder);</code>
+ * </ul>
+ *
+ */
+public class RestResourceResolverDefault implements RestResourceResolver {
+
+ @Override /* RestResourceResolver */
+ public Object resolve(Object parent, Class<?> c, RestContextBuilder builder) throws Exception {
+ try {
+ Object r = ClassUtils.newInstanceFromOuter(parent, Object.class, c, true, builder);
+ if (r != null)
+ return r;
+ } catch (Exception e) {
+ throw new RestServletException("Could not instantiate resource class ''{0}''", c.getName()).initCause(e);
+ }
+ throw new RestServletException("Could not find public constructor for class ''{0}''.", c);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java
deleted file mode 100644
index 3d63597..0000000
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResourceResolverSimple.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
-// * with the License. You may obtain a copy of the License at *
-// * *
-// * http://www.apache.org/licenses/LICENSE-2.0 *
-// * *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
-// * specific language governing permissions and limitations under the License. *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import org.apache.juneau.internal.*;
-
-/**
- * Denotes the default resolver for child resources.
- *
- * The default implementation simply instantiates the class using one of the following constructors:
- * <ul>
- * <li><code><jk>public</jk> T(RestContextBuilder)</code>
- * <li><code><jk>public</jk> T()</code>
- * </ul>
- *
- * <p>
- * The former constructor can be used to get access to the {@link RestContextBuilder} object to get access to the
- * config file and initialization information or make programmatic modifications to the resource before
- * full initialization.
- *
- * <p>
- * Child classes can also be defined as inner-classes of the parent resource class.
- *
- * <p>
- * Non-<code>RestServlet</code> classes can also add the following method to get access to the {@link RestContextBuilder}
- * object:
- * <ul>
- * <li><code><jk>public void</jk> init(RestContextBuilder);</code>
- * </ul>
- *
- */
-public class RestResourceResolverSimple implements RestResourceResolver {
-
- @Override /* RestResourceResolver */
- public Object resolve(Object parent, Class<?> c, RestContextBuilder builder) throws Exception {
- try {
- Object r = ClassUtils.newInstanceFromOuter(parent, Object.class, c, true, builder);
- if (r != null)
- return r;
- } catch (Exception e) {
- throw new RestServletException("Could not instantiate resource class ''{0}''", c.getName()).initCause(e);
- }
- throw new RestServletException("Could not find public constructor for class ''{0}''.", c);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/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 ca895a3..46d8497 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
@@ -160,7 +160,7 @@ public @interface RestResource {
* <li class='jf'>{@link RestContext#REST_callHandler}
* </ul>
*/
- Class<? extends RestCallHandler> callHandler() default RestCallHandler.class;
+ Class<? extends RestCallHandler> callHandler() default RestCallHandler.Null.class;
/**
* Children.
@@ -478,7 +478,7 @@ public @interface RestResource {
* <li class='jf'>{@link RestContext#REST_infoProvider}
* </ul>
*/
- Class<? extends RestInfoProvider> infoProvider() default RestInfoProvider.class;
+ Class<? extends RestInfoProvider> infoProvider() default RestInfoProvider.Null.class;
/**
* REST logger.
@@ -491,7 +491,7 @@ public @interface RestResource {
* <li class='jf'>{@link RestContext#REST_logger}
* </ul>
*/
- Class<? extends RestLogger> logger() default RestLogger.Normal.class;
+ Class<? extends RestLogger> logger() default RestLogger.Null.class;
/**
* The maximum allowed input size (in bytes) on HTTP requests.
@@ -731,7 +731,7 @@ public @interface RestResource {
* <li class='jf'>{@link RestContext#REST_resourceResolver}
* </ul>
*/
- Class<? extends RestResourceResolver> resourceResolver() default RestResourceResolverSimple.class;
+ Class<? extends RestResourceResolver> resourceResolver() default RestResourceResolver.Null.class;
/**
* Response handlers.
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/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 185e8d5..840dbbe 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
@@ -2699,17 +2699,15 @@
{@link org.apache.juneau.rest.RestLogger}
<ul>
<li class='jm'>
- {@link org.apache.juneau.rest.RestLogger#getLogger() getLogger()}
- <li class='jm'>
- {@link org.apache.juneau.rest.RestLogger#onError(HttpServletRequest,HttpServletResponse,RestException) onError(HttpServletRequest,HttpServletResponse,RestException)}
- <br>Gets called when an error occurs on a request call.
- <br>Default implementation logs the error.
- <li class='jm'>
{@link org.apache.juneau.rest.RestLogger#log(Level,String,Object[]) log(Level,String,Object[])}
<li class='jm'>
{@link org.apache.juneau.rest.RestLogger#log(Level,Throwable,String,Object[]) log(Level,Throwable,String,Object[])}
<li class='jm'>
{@link org.apache.juneau.rest.RestLogger#logObjects(Level,String,Object[]) logObject(Level,String,Object[])}
+ <li class='jm'>
+ {@link org.apache.juneau.rest.RestLogger#onError(HttpServletRequest,HttpServletResponse,RestException) onError(HttpServletRequest,HttpServletResponse,RestException)}
+ <br>Gets called when an error occurs on a request call.
+ <br>Default implementation logs the error.
</ul>
</li>
</ul>
[2/2] juneau git commit: RestContext refactoring.
Posted by ja...@apache.org.
RestContext refactoring.
Project: http://git-wip-us.apache.org/repos/asf/juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/juneau/commit/af355372
Tree: http://git-wip-us.apache.org/repos/asf/juneau/tree/af355372
Diff: http://git-wip-us.apache.org/repos/asf/juneau/diff/af355372
Branch: refs/heads/master
Commit: af355372e7fbfab62eb7daac87885a9a1e760e43
Parents: 5a36a08
Author: JamesBognar <ja...@apache.org>
Authored: Thu Jan 18 16:43:41 2018 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Thu Jan 18 16:43:41 2018 -0500
----------------------------------------------------------------------
juneau-doc/src/main/javadoc/overview.html | 12 +
.../apache/juneau/rest/test/ParamsResource.java | 13 +-
.../org/apache/juneau/rest/test/ParamsTest.java | 10 +-
.../org/apache/juneau/rest/RestCallHandler.java | 249 +-------
.../juneau/rest/RestCallHandlerDefault.java | 343 ++++++++++
.../org/apache/juneau/rest/RestContext.java | 87 ++-
.../apache/juneau/rest/RestContextBuilder.java | 26 +-
.../apache/juneau/rest/RestInfoProvider.java | 513 ++-------------
.../juneau/rest/RestInfoProviderDefault.java | 632 +++++++++++++++++++
.../java/org/apache/juneau/rest/RestLogger.java | 162 +----
.../apache/juneau/rest/RestLoggerDefault.java | 225 +++++++
.../org/apache/juneau/rest/RestLoggerNoOp.java | 47 ++
.../apache/juneau/rest/RestParamDefaults.java | 26 +-
.../org/apache/juneau/rest/RestRequest.java | 2 +-
.../juneau/rest/RestResourceResolver.java | 9 +
.../rest/RestResourceResolverDefault.java | 55 ++
.../juneau/rest/RestResourceResolverSimple.java | 55 --
.../juneau/rest/annotation/RestResource.java | 8 +-
.../java/org/apache/juneau/rest/package.html | 10 +-
19 files changed, 1486 insertions(+), 998 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/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 613c71b..fee50e3 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -9351,6 +9351,17 @@
{@link org.apache.juneau.rest.annotation.RestMethod#supportedContentTypes() supportedContentTypes()}
for overriding the supported media types inferred from the serializers and parsers.
</ul>
+ <li>
+ <code>RestCallHandler</code> split up into {@link org.apache.juneau.rest.RestCallHandler} and
+ {@link org.apache.juneau.rest.RestCallHandlerDefault}
+ <li>
+ <code>RestInfoProvider</code> split up into {@link org.apache.juneau.rest.RestInfoProvider} and
+ {@link org.apache.juneau.rest.RestInfoProviderDefault}
+ <li>
+ <code>RestLogger</code> split up into {@link org.apache.juneau.rest.RestLogger},
+ {@link org.apache.juneau.rest.RestLoggerDefault} and {@link org.apache.juneau.rest.RestLoggerNoOp}
+ <li>
+ <code>RestResourceResolverSimple</code> renamed to {@link org.apache.juneau.rest.RestResourceResolverDefault}
</ul>
<h6 class='topic'>juneau-rest-client</h6>
@@ -9401,6 +9412,7 @@
<li>{@link org.apache.juneau.BeanContextBuilder}
<li>{@link org.apache.juneau.rest.RestContext}
<li>{@link org.apache.juneau.rest.RestContextBuilder}
+ <li>Swagger DTOs.
</ul>
</ul>
</div>
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
index 3e50752..bc546c6 100644
--- a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
+++ b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.internal.IOUtils.*;
import java.io.*;
import java.util.*;
-import java.util.logging.*;
import javax.servlet.*;
import javax.servlet.http.*;
@@ -28,7 +27,6 @@ import org.apache.juneau.examples.addressbook.*;
import org.apache.juneau.http.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.ini.*;
-import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.plaintext.*;
@@ -372,16 +370,11 @@ public class ParamsResource extends RestServletDefault {
return t.toString();
}
- @RestMethod(name=GET, path="/otherObjects/Logger")
- public boolean testOtherLogger(Logger t) {
+ @RestMethod(name=GET, path="/otherObjects/RestLogger")
+ public boolean testOtherLogger(RestLogger t) {
return t != null;
}
-
- @RestMethod(name=GET, path="/otherObjects/JuneauLogger")
- public boolean testOtherJuneauLogger(JuneauLogger t) {
- return t != null;
- }
-
+
@RestMethod(name=GET, path="/otherObjects/RestContext")
public boolean testOtherRestContext(RestContext t) {
return t != null;
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java
index d655e91..b1da497 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java
@@ -798,14 +798,8 @@ public class ParamsTest extends RestTestcase {
}
@Test
- public void testOtherLogger() throws Exception {
- String r = CLIENT.doGet(URL + "/otherObjects/Logger").getResponseAsString();
- assertEquals("true", r);
- }
-
- @Test
- public void testOtherJuneauLogger() throws Exception {
- String r = CLIENT.doGet(URL + "/otherObjects/JuneauLogger").getResponseAsString();
+ public void testOtherRestLogger() throws Exception {
+ String r = CLIENT.doGet(URL + "/otherObjects/RestLogger").getResponseAsString();
assertEquals("true", r);
}
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java
index 69a5c4f..c7dabc9 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java
@@ -12,10 +12,6 @@
// ***************************************************************************************************************************
package org.apache.juneau.rest;
-import static java.util.logging.Level.*;
-import static javax.servlet.http.HttpServletResponse.*;
-import static org.apache.juneau.internal.IOUtils.*;
-import static org.apache.juneau.internal.StringUtils.*;
import java.io.*;
import java.util.*;
@@ -23,319 +19,102 @@ import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.vars.*;
-
/**
* Class that handles the basic lifecycle of an HTTP REST call.
*
- * <p>
- * Subclasses can override these methods to tailor how HTTP REST calls are handled.
- * <br>Subclasses MUST implement a public constructor that takes in a {@link RestContext} object.
- *
- * <p>
- * RestCallHandlers are associated with servlets/resources in one of the following ways:
- * <ul>
- * <li>The {@link RestResource#callHandler @RestResource.callHandler()} annotation.
- * <li>The {@link RestContextBuilder#callHandler(Class)} method.
- * </ul>
- *
* <h5 class='topic'>Additional Information</h5>
* <ul>
* <li class='jf'>{@link RestContext#REST_callHandler}
* </ul>
*/
-public class RestCallHandler {
-
- private final RestContext context;
- private final RestLogger logger;
- private final Map<String,RestCallRouter> restCallRouters;
+public interface RestCallHandler {
/**
- * Constructor.
+ * Represents no RestCallHandler.
*
- * @param context The resource context.
+ * <p>
+ * Used on annotation to indicate that the value should be inherited from the parent class, and
+ * ultimately {@link RestCallHandlerDefault} if not specified at any level.
*/
- public RestCallHandler(RestContext context) {
- this.context = context;
- this.logger = context.getLogger();
- this.restCallRouters = context.getCallRouters();
- }
+ public interface Null extends RestCallHandler {}
/**
* Creates a {@link RestRequest} object based on the specified incoming {@link HttpServletRequest} object.
*
- * <p>
- * Subclasses may choose to override this method to provide a specialized request object.
- *
* @param req The request object from the {@link #service(HttpServletRequest, HttpServletResponse)} method.
* @return The wrapped request object.
* @throws ServletException If any errors occur trying to interpret the request.
*/
- protected RestRequest createRequest(HttpServletRequest req) throws ServletException {
- return new RestRequest(context, req);
- }
+ public RestRequest createRequest(HttpServletRequest req) throws ServletException;
/**
* Creates a {@link RestResponse} object based on the specified incoming {@link HttpServletResponse} object
* and the request returned by {@link #createRequest(HttpServletRequest)}.
*
- * <p>
- * Subclasses may choose to override this method to provide a specialized response object.
- *
* @param req The request object returned by {@link #createRequest(HttpServletRequest)}.
* @param res The response object from the {@link #service(HttpServletRequest, HttpServletResponse)} method.
* @return The wrapped response object.
* @throws ServletException If any errors occur trying to interpret the request or response.
*/
- protected RestResponse createResponse(RestRequest req, HttpServletResponse res) throws ServletException {
- return new RestResponse(context, req, res);
- }
+ public RestResponse createResponse(RestRequest req, HttpServletResponse res) throws ServletException;
/**
* The main service method.
*
- * <p>
- * Subclasses can optionally override this method if they want to tailor the behavior of requests.
- *
* @param r1 The incoming HTTP servlet request object.
* @param r2 The incoming HTTP servlet response object.
* @throws ServletException
* @throws IOException
*/
- protected void service(HttpServletRequest r1, HttpServletResponse r2) throws ServletException, IOException {
-
- logger.log(FINE, "HTTP: {0} {1}", r1.getMethod(), r1.getRequestURI());
- long startTime = System.currentTimeMillis();
-
- try {
- context.checkForInitException();
-
- String pathInfo = RestUtils.getPathInfoUndecoded(r1); // Can't use r1.getPathInfo() because we don't want '%2F' resolved.
-
- // If this resource has child resources, try to recursively call them.
- if (pathInfo != null && context.hasChildResources() && (! pathInfo.equals("/"))) {
- int i = pathInfo.indexOf('/', 1);
- String pathInfoPart = i == -1 ? pathInfo.substring(1) : pathInfo.substring(1, i);
- RestContext childResource = context.getChildResource(pathInfoPart);
- if (childResource != null) {
- final String pathInfoRemainder = (i == -1 ? null : pathInfo.substring(i));
- final String servletPath = r1.getServletPath() + "/" + pathInfoPart;
- final HttpServletRequest childRequest = new HttpServletRequestWrapper(r1) {
- @Override /* ServletRequest */
- public String getPathInfo() {
- return urlDecode(pathInfoRemainder);
- }
- @Override /* ServletRequest */
- public String getServletPath() {
- return servletPath;
- }
- };
- childResource.getCallHandler().service(childRequest, r2);
- return;
- }
- }
-
- context.startCall(r1, r2);
-
- RestRequest req = createRequest(r1);
- RestResponse res = createResponse(req, r2);
- String method = req.getMethod();
- String methodUC = method.toUpperCase(Locale.ENGLISH);
-
- StreamResource r = null;
- if (pathInfo != null) {
- String p = pathInfo.substring(1);
- if (context.isStaticFile(p))
- r = context.resolveStaticFile(p);
- else if (p.equals("favicon.ico"))
- res.setOutput(null);
- }
-
- if (r != null) {
- res.setStatus(SC_OK);
- res.setOutput(r);
- } else {
- // If the specified method has been defined in a subclass, invoke it.
- int rc = SC_METHOD_NOT_ALLOWED;
- if (restCallRouters.containsKey(methodUC)) {
- rc = restCallRouters.get(methodUC).invoke(pathInfo, req, res);
- } else if (restCallRouters.containsKey("*")) {
- rc = restCallRouters.get("*").invoke(pathInfo, req, res);
- }
-
- // If not invoked above, see if it's an OPTIONs request
- if (rc != SC_OK)
- handleNotFound(rc, req, res);
- }
-
- if (res.hasOutput()) {
- Object output = res.getOutput();
-
- // Do any class-level transforming.
- for (RestConverter converter : context.getConverters())
- output = converter.convert(req, output);
-
- res.setOutput(output);
-
- // Now serialize the output if there was any.
- // Some subclasses may write to the OutputStream or Writer directly.
- handleResponse(req, res, output);
- }
-
- // Make sure our writer in RestResponse gets written.
- res.flushBuffer();
-
- r1.setAttribute("ExecTime", System.currentTimeMillis() - startTime);
-
- } catch (RestException e) {
- r1.setAttribute("Exception", e);
- r1.setAttribute("ExecTime", System.currentTimeMillis() - startTime);
- handleError(r1, r2, e);
- } catch (Throwable e) {
- RestException e2 = new RestException(SC_INTERNAL_SERVER_ERROR, e);
- r1.setAttribute("Exception", e);
- r1.setAttribute("ExecTime", System.currentTimeMillis() - startTime);
- handleError(r1, r2, e2);
- }
-
- context.finishCall(r1, r2);
-
- logger.log(FINE, "HTTP: [{0} {1}] finished in {2}ms", r1.getMethod(), r1.getRequestURI(), System.currentTimeMillis()-startTime);
- }
+ public void service(HttpServletRequest r1, HttpServletResponse r2) throws ServletException, IOException;
/**
* The main method for serializing POJOs passed in through the {@link RestResponse#setOutput(Object)} method or
* returned by the Java method.
*
- * <p>
- * Subclasses may override this method if they wish to modify the way the output is rendered or support other output
- * formats.
- *
- * <p>
- * The default implementation simply iterates through the response handlers on this resource
- * looking for the first one whose {@link ResponseHandler#handle(RestRequest, RestResponse, Object)} method returns
- * <jk>true</jk>.
- *
* @param req The HTTP request.
* @param res The HTTP response.
* @param output The output to serialize in the response.
* @throws IOException
* @throws RestException
*/
- protected void handleResponse(RestRequest req, RestResponse res, Object output) throws IOException, RestException {
- // Loop until we find the correct handler for the POJO.
- for (ResponseHandler h : context.getResponseHandlers())
- if (h.handle(req, res, output))
- return;
- throw new RestException(SC_NOT_IMPLEMENTED, "No response handlers found to process output of type '"+(output == null ? null : output.getClass().getName())+"'");
- }
+ public void handleResponse(RestRequest req, RestResponse res, Object output) throws IOException, RestException ;
/**
* Handle the case where a matching method was not found.
*
- * <p>
- * Subclasses can override this method to provide a 2nd-chance for specifying a response.
- * The default implementation will simply throw an exception with an appropriate message.
- *
* @param rc The HTTP response code.
* @param req The HTTP request.
* @param res The HTTP response.
* @throws Exception
*/
- protected void handleNotFound(int rc, RestRequest req, RestResponse res) throws Exception {
- String pathInfo = req.getPathInfo();
- String methodUC = req.getMethod();
- String onPath = pathInfo == null ? " on no pathInfo" : String.format(" on path '%s'", pathInfo);
- if (rc == SC_NOT_FOUND)
- throw new RestException(rc, "Method ''{0}'' not found on resource with matching pattern{1}.", methodUC, onPath);
- else if (rc == SC_PRECONDITION_FAILED)
- throw new RestException(rc, "Method ''{0}'' not found on resource{1} with matching matcher.", methodUC, onPath);
- else if (rc == SC_METHOD_NOT_ALLOWED)
- throw new RestException(rc, "Method ''{0}'' not found on resource.", methodUC);
- else
- throw new ServletException("Invalid method response: " + rc);
- }
+ public void handleNotFound(int rc, RestRequest req, RestResponse res) throws Exception;
/**
* Method for handling response errors.
*
- * <p>
- * The default implementation logs the error and calls
- * {@link #renderError(HttpServletRequest,HttpServletResponse,RestException)}.
- *
- * <p>
- * Subclasses can override this method to provide their own custom error response handling.
- *
* @param req The servlet request.
* @param res The servlet response.
* @param e The exception that occurred.
* @throws IOException Can be thrown if a problem occurred trying to write to the output stream.
*/
- protected synchronized void handleError(HttpServletRequest req, HttpServletResponse res, RestException e) throws IOException {
- e.setOccurrence(context == null ? 0 : context.getStackTraceOccurrence(e));
- logger.onError(req, res, e);
- renderError(req, res, e);
- }
+ public void handleError(HttpServletRequest req, HttpServletResponse res, RestException e) throws IOException;
/**
* Method for rendering response errors.
*
- * <p>
- * The default implementation renders a plain text English message, optionally with a stack trace if
- * {@link RestResource#renderResponseStackTraces() @RestResource.renderResponseStackTraces()} is enabled.
- *
- * <p>
- * Subclasses can override this method to provide their own custom error response handling.
- *
* @param req The servlet request.
* @param res The servlet response.
* @param e The exception that occurred.
* @throws IOException Can be thrown if a problem occurred trying to write to the output stream.
*/
- protected void renderError(HttpServletRequest req, HttpServletResponse res, RestException e) throws IOException {
-
- int status = e.getStatus();
- res.setStatus(status);
- res.setContentType("text/plain");
- res.setHeader("Content-Encoding", "identity");
-
- Throwable t = e.getRootCause();
- if (t != null) {
- res.setHeader("Exception-Name", t.getClass().getName());
- res.setHeader("Exception-Message", t.getMessage());
- }
-
- PrintWriter w = null;
- try {
- w = res.getWriter();
- } catch (IllegalStateException e2) {
- w = new PrintWriter(new OutputStreamWriter(res.getOutputStream(), UTF8));
- }
-
- try (PrintWriter w2 = w) {
- String httpMessage = RestUtils.getHttpResponseText(status);
- if (httpMessage != null)
- w2.append("HTTP ").append(String.valueOf(status)).append(": ").append(httpMessage).append("\n\n");
- if (context != null && context.isRenderResponseStackTraces())
- e.printStackTrace(w2);
- else
- w2.append(e.getFullStackMessage(true));
- }
- }
+ public void renderError(HttpServletRequest req, HttpServletResponse res, RestException e) throws IOException;
/**
* Returns the session objects for the specified request.
*
- * <p>
- * The default implementation simply returns a single map containing <code>{'req':req}</code>.
- *
* @param req The REST request.
* @return The session objects for that request.
*/
- protected Map<String,Object> getSessionObjects(RestRequest req) {
- Map<String,Object> m = new HashMap<>();
- m.put(RequestVar.SESSION_req, req);
- return m;
- }
+ public Map<String,Object> getSessionObjects(RestRequest req);
}
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandlerDefault.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandlerDefault.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandlerDefault.java
new file mode 100644
index 0000000..fa5408e
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandlerDefault.java
@@ -0,0 +1,343 @@
+// ***************************************************************************************************************************
+// * 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 java.util.logging.Level.*;
+import static javax.servlet.http.HttpServletResponse.*;
+import static org.apache.juneau.internal.IOUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.vars.*;
+
+/**
+ * Default implementation of {@link RestCallHandler}.
+ *
+ * <p>
+ * Subclasses can override these methods to tailor how HTTP REST calls are handled.
+ * <br>Subclasses MUST implement a public constructor that takes in a {@link RestContext} object.
+ *
+ *
+ * <h5 class='topic'>Additional Information</h5>
+ * <ul>
+ * <li class='jf'>{@link RestContext#REST_callHandler}
+ * </ul>
+ */
+public class RestCallHandlerDefault implements RestCallHandler {
+
+ private final RestContext context;
+ private final RestLogger logger;
+ private final Map<String,RestCallRouter> restCallRouters;
+
+ /**
+ * Constructor.
+ *
+ * @param context The resource context.
+ */
+ public RestCallHandlerDefault(RestContext context) {
+ this.context = context;
+ this.logger = context.getLogger();
+ this.restCallRouters = context.getCallRouters();
+ }
+
+ /**
+ * Creates a {@link RestRequest} object based on the specified incoming {@link HttpServletRequest} object.
+ *
+ * <p>
+ * Subclasses may choose to override this method to provide a specialized request object.
+ *
+ * @param req The request object from the {@link #service(HttpServletRequest, HttpServletResponse)} method.
+ * @return The wrapped request object.
+ * @throws ServletException If any errors occur trying to interpret the request.
+ */
+ @Override /* RestCallHandler */
+ public RestRequest createRequest(HttpServletRequest req) throws ServletException {
+ return new RestRequest(context, req);
+ }
+
+ /**
+ * Creates a {@link RestResponse} object based on the specified incoming {@link HttpServletResponse} object
+ * and the request returned by {@link #createRequest(HttpServletRequest)}.
+ *
+ * <p>
+ * Subclasses may choose to override this method to provide a specialized response object.
+ *
+ * @param req The request object returned by {@link #createRequest(HttpServletRequest)}.
+ * @param res The response object from the {@link #service(HttpServletRequest, HttpServletResponse)} method.
+ * @return The wrapped response object.
+ * @throws ServletException If any errors occur trying to interpret the request or response.
+ */
+ @Override /* RestCallHandler */
+ public RestResponse createResponse(RestRequest req, HttpServletResponse res) throws ServletException {
+ return new RestResponse(context, req, res);
+ }
+
+ /**
+ * The main service method.
+ *
+ * <p>
+ * Subclasses can optionally override this method if they want to tailor the behavior of requests.
+ *
+ * @param r1 The incoming HTTP servlet request object.
+ * @param r2 The incoming HTTP servlet response object.
+ * @throws ServletException
+ * @throws IOException
+ */
+ @Override /* RestCallHandler */
+ public void service(HttpServletRequest r1, HttpServletResponse r2) throws ServletException, IOException {
+
+ logger.log(FINE, "HTTP: {0} {1}", r1.getMethod(), r1.getRequestURI());
+ long startTime = System.currentTimeMillis();
+
+ try {
+ context.checkForInitException();
+
+ String pathInfo = RestUtils.getPathInfoUndecoded(r1); // Can't use r1.getPathInfo() because we don't want '%2F' resolved.
+
+ // If this resource has child resources, try to recursively call them.
+ if (pathInfo != null && context.hasChildResources() && (! pathInfo.equals("/"))) {
+ int i = pathInfo.indexOf('/', 1);
+ String pathInfoPart = i == -1 ? pathInfo.substring(1) : pathInfo.substring(1, i);
+ RestContext childResource = context.getChildResource(pathInfoPart);
+ if (childResource != null) {
+ final String pathInfoRemainder = (i == -1 ? null : pathInfo.substring(i));
+ final String servletPath = r1.getServletPath() + "/" + pathInfoPart;
+ final HttpServletRequest childRequest = new HttpServletRequestWrapper(r1) {
+ @Override /* ServletRequest */
+ public String getPathInfo() {
+ return urlDecode(pathInfoRemainder);
+ }
+ @Override /* ServletRequest */
+ public String getServletPath() {
+ return servletPath;
+ }
+ };
+ childResource.getCallHandler().service(childRequest, r2);
+ return;
+ }
+ }
+
+ context.startCall(r1, r2);
+
+ RestRequest req = createRequest(r1);
+ RestResponse res = createResponse(req, r2);
+ String method = req.getMethod();
+ String methodUC = method.toUpperCase(Locale.ENGLISH);
+
+ StreamResource r = null;
+ if (pathInfo != null) {
+ String p = pathInfo.substring(1);
+ if (context.isStaticFile(p))
+ r = context.resolveStaticFile(p);
+ else if (p.equals("favicon.ico"))
+ res.setOutput(null);
+ }
+
+ if (r != null) {
+ res.setStatus(SC_OK);
+ res.setOutput(r);
+ } else {
+ // If the specified method has been defined in a subclass, invoke it.
+ int rc = SC_METHOD_NOT_ALLOWED;
+ if (restCallRouters.containsKey(methodUC)) {
+ rc = restCallRouters.get(methodUC).invoke(pathInfo, req, res);
+ } else if (restCallRouters.containsKey("*")) {
+ rc = restCallRouters.get("*").invoke(pathInfo, req, res);
+ }
+
+ // If not invoked above, see if it's an OPTIONs request
+ if (rc != SC_OK)
+ handleNotFound(rc, req, res);
+ }
+
+ if (res.hasOutput()) {
+ Object output = res.getOutput();
+
+ // Do any class-level transforming.
+ for (RestConverter converter : context.getConverters())
+ output = converter.convert(req, output);
+
+ res.setOutput(output);
+
+ // Now serialize the output if there was any.
+ // Some subclasses may write to the OutputStream or Writer directly.
+ handleResponse(req, res, output);
+ }
+
+ // Make sure our writer in RestResponse gets written.
+ res.flushBuffer();
+
+ r1.setAttribute("ExecTime", System.currentTimeMillis() - startTime);
+
+ } catch (RestException e) {
+ r1.setAttribute("Exception", e);
+ r1.setAttribute("ExecTime", System.currentTimeMillis() - startTime);
+ handleError(r1, r2, e);
+ } catch (Throwable e) {
+ RestException e2 = new RestException(SC_INTERNAL_SERVER_ERROR, e);
+ r1.setAttribute("Exception", e);
+ r1.setAttribute("ExecTime", System.currentTimeMillis() - startTime);
+ handleError(r1, r2, e2);
+ }
+
+ context.finishCall(r1, r2);
+
+ logger.log(FINE, "HTTP: [{0} {1}] finished in {2}ms", r1.getMethod(), r1.getRequestURI(), System.currentTimeMillis()-startTime);
+ }
+
+ /**
+ * The main method for serializing POJOs passed in through the {@link RestResponse#setOutput(Object)} method or
+ * returned by the Java method.
+ *
+ * <p>
+ * Subclasses may override this method if they wish to modify the way the output is rendered or support other output
+ * formats.
+ *
+ * <p>
+ * The default implementation simply iterates through the response handlers on this resource
+ * looking for the first one whose {@link ResponseHandler#handle(RestRequest, RestResponse, Object)} method returns
+ * <jk>true</jk>.
+ *
+ * @param req The HTTP request.
+ * @param res The HTTP response.
+ * @param output The output to serialize in the response.
+ * @throws IOException
+ * @throws RestException
+ */
+ @Override /* RestCallHandler */
+ public void handleResponse(RestRequest req, RestResponse res, Object output) throws IOException, RestException {
+ // Loop until we find the correct handler for the POJO.
+ for (ResponseHandler h : context.getResponseHandlers())
+ if (h.handle(req, res, output))
+ return;
+ throw new RestException(SC_NOT_IMPLEMENTED, "No response handlers found to process output of type '"+(output == null ? null : output.getClass().getName())+"'");
+ }
+
+ /**
+ * Handle the case where a matching method was not found.
+ *
+ * <p>
+ * Subclasses can override this method to provide a 2nd-chance for specifying a response.
+ * The default implementation will simply throw an exception with an appropriate message.
+ *
+ * @param rc The HTTP response code.
+ * @param req The HTTP request.
+ * @param res The HTTP response.
+ * @throws Exception
+ */
+ @Override /* RestCallHandler */
+ public void handleNotFound(int rc, RestRequest req, RestResponse res) throws Exception {
+ String pathInfo = req.getPathInfo();
+ String methodUC = req.getMethod();
+ String onPath = pathInfo == null ? " on no pathInfo" : String.format(" on path '%s'", pathInfo);
+ if (rc == SC_NOT_FOUND)
+ throw new RestException(rc, "Method ''{0}'' not found on resource with matching pattern{1}.", methodUC, onPath);
+ else if (rc == SC_PRECONDITION_FAILED)
+ throw new RestException(rc, "Method ''{0}'' not found on resource{1} with matching matcher.", methodUC, onPath);
+ else if (rc == SC_METHOD_NOT_ALLOWED)
+ throw new RestException(rc, "Method ''{0}'' not found on resource.", methodUC);
+ else
+ throw new ServletException("Invalid method response: " + rc);
+ }
+
+ /**
+ * Method for handling response errors.
+ *
+ * <p>
+ * The default implementation logs the error and calls
+ * {@link #renderError(HttpServletRequest,HttpServletResponse,RestException)}.
+ *
+ * <p>
+ * Subclasses can override this method to provide their own custom error response handling.
+ *
+ * @param req The servlet request.
+ * @param res The servlet response.
+ * @param e The exception that occurred.
+ * @throws IOException Can be thrown if a problem occurred trying to write to the output stream.
+ */
+ @Override /* RestCallHandler */
+ public synchronized void handleError(HttpServletRequest req, HttpServletResponse res, RestException e) throws IOException {
+ e.setOccurrence(context == null ? 0 : context.getStackTraceOccurrence(e));
+ logger.onError(req, res, e);
+ renderError(req, res, e);
+ }
+
+ /**
+ * Method for rendering response errors.
+ *
+ * <p>
+ * The default implementation renders a plain text English message, optionally with a stack trace if
+ * {@link RestResource#renderResponseStackTraces() @RestResource.renderResponseStackTraces()} is enabled.
+ *
+ * <p>
+ * Subclasses can override this method to provide their own custom error response handling.
+ *
+ * @param req The servlet request.
+ * @param res The servlet response.
+ * @param e The exception that occurred.
+ * @throws IOException Can be thrown if a problem occurred trying to write to the output stream.
+ */
+ @Override /* RestCallHandler */
+ public void renderError(HttpServletRequest req, HttpServletResponse res, RestException e) throws IOException {
+
+ int status = e.getStatus();
+ res.setStatus(status);
+ res.setContentType("text/plain");
+ res.setHeader("Content-Encoding", "identity");
+
+ Throwable t = e.getRootCause();
+ if (t != null) {
+ res.setHeader("Exception-Name", t.getClass().getName());
+ res.setHeader("Exception-Message", t.getMessage());
+ }
+
+ PrintWriter w = null;
+ try {
+ w = res.getWriter();
+ } catch (IllegalStateException e2) {
+ w = new PrintWriter(new OutputStreamWriter(res.getOutputStream(), UTF8));
+ }
+
+ try (PrintWriter w2 = w) {
+ String httpMessage = RestUtils.getHttpResponseText(status);
+ if (httpMessage != null)
+ w2.append("HTTP ").append(String.valueOf(status)).append(": ").append(httpMessage).append("\n\n");
+ if (context != null && context.isRenderResponseStackTraces())
+ e.printStackTrace(w2);
+ else
+ w2.append(e.getFullStackMessage(true));
+ }
+ }
+
+ /**
+ * Returns the session objects for the specified request.
+ *
+ * <p>
+ * The default implementation simply returns a single map containing <code>{'req':req}</code>.
+ *
+ * @param req The REST request.
+ * @return The session objects for that request.
+ */
+ @Override /* RestCallHandler */
+ public Map<String,Object> getSessionObjects(RestRequest req) {
+ Map<String,Object> m = new HashMap<>();
+ m.put(RequestVar.SESSION_req, req);
+ return m;
+ }
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/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 8ca7b99..af7ac81 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
@@ -269,7 +269,7 @@ public final class RestContext extends BeanContext {
* <ul>
* <li><b>Name:</b> <js>"RestContext.callHandler.o"</js>
* <li><b>Data type:</b> <code>Class<? <jk>extends</jk> {@link RestCallHandler}> | {@link RestCallHandler}</code>
- * <li><b>Default:</b> {@link RestCallHandler}
+ * <li><b>Default:</b> {@link RestCallHandlerDefault}
* <li><b>Session-overridable:</b> <jk>false</jk>
* <li><b>Annotations:</b>
* <ul>
@@ -290,7 +290,7 @@ public final class RestContext extends BeanContext {
* <h5 class='section'>Example:</h5>
* <p class='bcode'>
* <jc>// Our customized call handler.</jc>
- * <jk>public class</jk> MyRestCallHandler <jk>extends</jk> RestCallHandler {
+ * <jk>public class</jk> MyRestCallHandler <jk>extends</jk> RestCallHandlerDefault {
*
* <jc>// Must provide this constructor!</jc>
* <jk>public</jk> MyRestCallHandler(RestContext context) {
@@ -298,19 +298,19 @@ public final class RestContext extends BeanContext {
* }
*
* <ja>@Override</ja>
- * <jk>protected</jk> RestRequest createRequest(HttpServletRequest req) <jk>throws</jk> ServletException {
+ * <jk>public</jk> RestRequest createRequest(HttpServletRequest req) <jk>throws</jk> ServletException {
* <jc>// Low-level handling of requests.</jc>
* ...
* }
*
* <ja>@Override</ja>
- * <jk>protected void</jk> handleResponse(RestRequest req, RestResponse res, Object output) <jk>throws</jk> IOException, RestException {
+ * <jk>public void</jk> handleResponse(RestRequest req, RestResponse res, Object output) <jk>throws</jk> IOException, RestException {
* <jc>// Low-level handling of responses.</jc>
* ...
* }
*
* <ja>@Override</ja>
- * <jk>protected void</jk> handleNotFound(int rc, RestRequest req, RestResponse res) <jk>throws</jk> Exception {
+ * <jk>public void</jk> handleNotFound(int rc, RestRequest req, RestResponse res) <jk>throws</jk> Exception {
* <jc>// Low-level handling of various error conditions.</jc>
* ...
* }
@@ -410,7 +410,7 @@ 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 RestResourceResolverSimple} which requires the class have one of the following
+ * by default is {@link RestResourceResolverDefault} which requires the class have one of the following
* constructors:
* <ul>
* <li><code><jk>public</jk> T(RestContextBuilder)</code>
@@ -1145,7 +1145,7 @@ public final class RestContext extends BeanContext {
* <ul>
* <li><b>Name:</b> <js>"RestContext.infoProvider.o"</js>
* <li><b>Data type:</b> <code>Class<? <jk>extends</jk> {@link RestInfoProvider}> | {@link RestInfoProvider}</code>
- * <li><b>Default:</b> {@link RestInfoProvider}
+ * <li><b>Default:</b> {@link RestInfoProviderDefault}
* <li><b>Session-overridable:</b> <jk>false</jk>
* <li><b>Annotations:</b>
* <ul>
@@ -1162,8 +1162,58 @@ public final class RestContext extends BeanContext {
* <p>
* Class used to retrieve title/description/swagger information about a resource.
*
- * <p>
- * Subclasses can be used to customize the documentation on a resource.
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode'>
+ * <jc>// Our customized info provider.</jc>
+ * <jk>public class</jk> MyRestInfoProvider <jk>extends</jk> RestInfoProviderDefault {
+ *
+ * <jc>// Must provide this constructor!</jc>
+ * <jk>public</jk> MyRestInfoProvider(RestContext context) {
+ * <jk>super</jk>(context);
+ * }
+ *
+ * <ja>@Override</ja>
+ * <jk>public</jk> Swagger getSwaggerFromFile(RestRequest req) <jk>throws</jk> RestException {
+ * <jc>// Provide our own method of retrieving swagger from file system.</jc>
+ * }
+ *
+ * <ja>@Override</ja>
+ * <jk>public</jk> Swagger getSwagger(RestRequest req) <jk>throws</jk> RestException {
+ * Swagger s = super.getSwagger(req);
+ * <jc>// Made inline modifications to generated swagger.</jc>
+ * <jk>return</jk> s;
+ * }
+ *
+ * <ja>@Override</ja>
+ * <jk>public</jk> String getSiteName(RestRequest req) {
+ * <jc>// Override the site name.</jc>
+ * }
+ * }
+ *
+ * <jc>// Registered via annotation resolving to a config file setting with default value.</jc>
+ * <ja>@RestResource</ja>(infoProvider=MyRestInfoProvider.<jk>class</jk>)
+ * <jk>public class</jk> MyResource {...}
+ *
+ * <jc>// Registered via builder passed in through resource constructor.</jc>
+ * <jk>public class</jk> MyResource {
+ * <jk>public</jk> MyResource(RestContextBuilder builder) <jk>throws</jk> Exception {
+ *
+ * <jc>// Using method on builder.</jc>
+ * builder.infoProvider(MyRestInfoProvider.<jk>class</jk>);
+ *
+ * <jc>// Same, but using property.</jc>
+ * builder.set(<jsf>REST_infoProvider</jsf>, MyRestInfoProvider.<jk>class</jk>);
+ * }
+ * }
+ *
+ * <jc>// Registered via builder passed in through init method.</jc>
+ * <jk>public class</jk> MyResource {
+ * <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * <jk>public void</jk> init(RestContextBuilder builder) <jk>throws</jk> Exception {
+ * builder.infoProvider(MyRestInfoProvider.<jk>class</jk>);
+ * }
+ * }
+ * </p>
*/
public static final String REST_infoProvider = PREFIX + "infoProvider.o";
@@ -1174,7 +1224,7 @@ public final class RestContext extends BeanContext {
* <ul>
* <li><b>Name:</b> <js>"RestContext.logger.o"</js>
* <li><b>Data type:</b> <code>Class<? <jk>extends</jk> RestLogger> | RestLogger</code>
- * <li><b>Default:</b> {@link RestLogger.Normal}
+ * <li><b>Default:</b> {@link RestLoggerDefault}
* <li><b>Session-overridable:</b> <jk>false</jk>
* <li><b>Annotations:</b>
* <ul>
@@ -1195,7 +1245,7 @@ public final class RestContext extends BeanContext {
* <h5 class='section'>Notes:</h5>
* <ul class='spaced-list'>
* <li>Property: {@link RestContext#REST_logger}
- * <li>The {@link RestLogger.Normal} logger can be used to provide basic error logging to the Java logger.
+ * <li>The {@link RestLoggerDefault} logger can be used to provide basic error logging to the Java logger.
* </ul>
*/
public static final String REST_logger = PREFIX + "logger.o";
@@ -1554,7 +1604,7 @@ public final class RestContext extends BeanContext {
* <ul>
* <li><b>Name:</b> <js>"RestContext.resourceResolver.o"</js>
* <li><b>Data type:</b> <code>Class<? <jk>extends</jk> RestResourceResolver> | RestResourceResolver</code>
- * <li><b>Default:</b> {@link RestResourceResolverSimple}
+ * <li><b>Default:</b> {@link RestResourceResolverDefault}
* <li><b>Session-overridable:</b> <jk>false</jk>
* <li><b>Annotations:</b>
* <ul>
@@ -2067,7 +2117,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, RestLogger.NoOp.class, true, ps);
+ logger = getInstanceProperty(REST_logger, resource, RestLogger.class, RestLoggerNoOp.class, true, ps);
varResolver = builder.varResolverBuilder
.vars(
@@ -2325,7 +2375,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 ? RestResourceResolverSimple.class : parentContext.resourceResolver, true, this, ps);
+ resourceResolver = getInstanceProperty(REST_resourceResolver, resource, RestResourceResolver.class, parentContext == null ? RestResourceResolverDefault.class : parentContext.resourceResolver, true, this, ps);
for (Object o : getArrayProperty(REST_children, Object.class)) {
String path = null;
Object r = null;
@@ -2365,8 +2415,8 @@ public final class RestContext extends BeanContext {
childResources.put(path, rc2);
}
- callHandler = getInstanceProperty(REST_callHandler, resource, RestCallHandler.class, RestCallHandler.class, true, this, ps);
- infoProvider = getInstanceProperty(REST_infoProvider, resource, RestInfoProvider.class, RestInfoProvider.class, true, this, ps);
+ callHandler = getInstanceProperty(REST_callHandler, resource, RestCallHandler.class, RestCallHandlerDefault.class, true, this, ps);
+ infoProvider = getInstanceProperty(REST_infoProvider, resource, RestInfoProvider.class, RestInfoProviderDefault.class, true, this, ps);
} catch (RestException e) {
_initException = e;
@@ -2805,8 +2855,9 @@ public final class RestContext extends BeanContext {
* <p>
* The logger for a resource is defined via one of the following:
* <ul>
- * <li>{@link RestResource#logger() @RestResource.logger()} annotation.
- * <li>{@link RestContextBuilder#logger(Class)}/{@link RestContextBuilder#logger(RestLogger)} methods.
+ * <li class='ja'>{@link RestResource#logger() @RestResource.logger()}\
+ * <li class='jm'>{@link RestContextBuilder#logger(Class)}
+ * <li class='jm'>{@link RestContextBuilder#logger(RestLogger)}
* </ul>
*
* @return The logger to use for this resource. Never <jk>null</jk>.
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/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 091dcc1..96f421a 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
@@ -130,7 +130,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
this.resourceClass = resourceClass;
this.parentContext = parentContext;
- logger(RestLogger.Normal.class);
+ logger(RestLoggerDefault.class);
staticFileResponseHeader("Cache-Control", "max-age=86400, public");
encoders(IdentityEncoder.INSTANCE);
@@ -220,13 +220,13 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
path(vr.resolve(r.path()));
if (! r.clientVersionHeader().isEmpty())
clientVersionHeader(vr.resolve(r.clientVersionHeader()));
- if (r.resourceResolver() != RestResourceResolver.class)
+ if (r.resourceResolver() != RestResourceResolver.Null.class)
resourceResolver(r.resourceResolver());
- if (r.logger() != RestLogger.Normal.class)
+ if (r.logger() != RestLogger.Null.class)
logger(r.logger());
- if (r.callHandler() != RestCallHandler.class)
+ if (r.callHandler() != RestCallHandler.Null.class)
callHandler(r.callHandler());
- if (r.infoProvider() != RestInfoProvider.class)
+ if (r.infoProvider() != RestInfoProvider.Null.class)
infoProvider(r.infoProvider());
if (! r.allowHeaderParams().isEmpty())
allowHeaderParams(Boolean.valueOf(vr.resolve(r.allowHeaderParams())));
@@ -598,7 +598,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
*
* @param value
* The new value for this setting.
- * <br>The default is {@link RestCallHandler}.
+ * <br>The default is {@link RestCallHandlerDefault}.
* @return This object (for method chaining).
*/
public RestContextBuilder callHandler(Class<? extends RestCallHandler> value) {
@@ -618,7 +618,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
*
* @param value
* The new value for this setting.
- * <br>The default is {@link RestCallHandler}.
+ * <br>The default is {@link RestCallHandlerDefault}.
* @return This object (for method chaining).
*/
public RestContextBuilder callHandler(RestCallHandler value) {
@@ -1024,7 +1024,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
*
* @param value
* The new value for this setting.
- * <br>The default is {@link RestInfoProvider}.
+ * <br>The default is {@link RestInfoProviderDefault}.
* @return This object (for method chaining).
*/
public RestContextBuilder infoProvider(Class<? extends RestInfoProvider> value) {
@@ -1044,7 +1044,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
*
* @param value
* The new value for this setting.
- * <br>The default is {@link RestInfoProvider}.
+ * <br>The default is {@link RestInfoProviderDefault}.
* @return This object (for method chaining).
*/
public RestContextBuilder infoProvider(RestInfoProvider value) {
@@ -1064,7 +1064,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
*
* @param value
* The new value for this setting.
- * <br>The default is {@link RestLogger.Normal}.
+ * <br>The default is {@link RestLoggerDefault}.
* <br>Can be <jk>null</jk> to disable logging.
* @return This object (for method chaining).
*/
@@ -1085,7 +1085,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
*
* @param value
* The new value for this setting.
- * <br>The default is {@link RestLogger.Normal}.
+ * <br>The default is {@link RestLoggerDefault}.
* <br>Can be <jk>null</jk> to disable logging.
* @return This object (for method chaining).
*/
@@ -1461,7 +1461,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
*
* @param value
* The new value for this setting.
- * <br>The default is {@link RestResourceResolverSimple}.
+ * <br>The default is {@link RestResourceResolverDefault}.
* @return This object (for method chaining).
*/
public RestContextBuilder resourceResolver(Class<? extends RestResourceResolver> value) {
@@ -1481,7 +1481,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
*
* @param value
* The new value for this setting.
- * <br>The default is {@link RestResourceResolverSimple}.
+ * <br>The default is {@link RestResourceResolverDefault}.
* @return This object (for method chaining).
*/
public RestContextBuilder resourceResolver(RestResourceResolver value) {
http://git-wip-us.apache.org/repos/asf/juneau/blob/af355372/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 d1f14a1..b817fb4 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,606 +12,165 @@
// ***************************************************************************************************************************
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:
+ * <h5 class='topic'>Additional Information</h5>
* <ul>
- * <li>The {@link RestResource#infoProvider @RestResource.infoProvider()} annotation.
- * <li>The {@link RestContextBuilder#infoProvider(Class)}/{@link RestContextBuilder#infoProvider(RestInfoProvider)} methods.
+ * <li class='jf'>{@link RestContext#REST_infoProvider}
* </ul>
*/
-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<>();
-
+public interface RestInfoProvider {
+
/**
- * Constructor.
+ * Represents no RestInfoProvider.
*
- * @param context The resource context.
+ * <p>
+ * Used on annotation to indicate that the value should be inherited from the parent class, and
+ * ultimately {@link RestInfoProviderDefault} if not specified at any level.
*/
- 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 final class Builder {
- 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();
- }
- }
- }
+ public interface Null extends RestInfoProvider {}
/**
- * Returns the localized swagger for this REST resource.
+ * Returns the contents of the localized swagger file for the specified request.
*
* @param req The incoming HTTP request.
- * @return A new Swagger instance.
+ * @return
+ * The contents of the parsed swagger file.
+ * Returns <jk>null</jk> if a swagger file could not be found.
* @throws RestException
*/
- 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
- );
- }
- }
- return s;
- } catch (RestException e) {
- throw e;
- } catch (Exception e) {
- throw new RestException(SC_INTERNAL_SERVER_ERROR, e);
- }
- }
+ public Swagger getSwaggerFromFile(RestRequest req) throws RestException;
/**
- * 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.
+ * Returns the localized swagger for this REST resource.
*
* <p>
- * Returned objects are cached for later quick-lookup.
+ * 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.
*
- * @param locale The locale of the swagger.
- * @return The parsed swagger object, or <jk>null</jk> if the swagger file could not be found.
+ * @param req The incoming HTTP request.
+ * @return A new Swagger instance.
* @throws RestException
*/
- protected Swagger getSwaggerFromFile(Locale locale) throws RestException {
- 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);
- }
- }
- return s == Swagger.NULL ? null : s;
- }
+ public Swagger getSwagger(RestRequest req) throws RestException;
+
/**
* 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) {
- RestJavaMethod m = context.getCallMethods().get(javaMethodName);
- if (m != null)
- return m.getSummary(req);
- return "";
- }
+ public String getMethodSummary(String javaMethodName, RestRequest req);
/**
* Returns the localized summary of the java method invoked on the specified request.
*
- * <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 req The current request.
* @return The localized summary of the method, or a blank string if no summary was found.
*/
- public String getMethodSummary(RestRequest req) {
- return getMethodSummary(req.getJavaMethod().getName(), req);
- }
+ public String getMethodSummary(RestRequest req);
/**
* 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.
*/
- public String getMethodDescription(String javaMethodName, RestRequest req) {
- RestJavaMethod m = context.getCallMethods().get(javaMethodName);
- if (m != null)
- return m.getDescription(req);
- return "";
- }
+ public String getMethodDescription(String javaMethodName, RestRequest req);
/**
* Returns the localized description of the invoked java method on the specified request.
*
- * <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 req The current request.
* @return The localized description of the method, or a blank string if no description was found.
*/
- public String getMethodDescription(RestRequest req) {
- return getMethodDescription(req.getJavaMethod().getName(), req);
- }
+ public String getMethodDescription(RestRequest req);
/**
* 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;
- }
+ public String getSiteName(RestRequest req);
/**
* 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;
- }
+ public String getTitle(RestRequest req);
/**
* 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;
- }
+ public String getDescription(RestRequest req);
/**
* 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);
- }
- }
+ public Contact getContact(RestRequest req) ;
/**
* 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);
- }
- }
+ public License getLicense(RestRequest req);
/**
* 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;
- }
+ public String getTermsOfService(RestRequest req);
/**
* 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;
- }
+ public String getVersion(RestRequest req);
/**
* 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);
- }
- }
+ public List<Tag> getTags(RestRequest req);
/**
- * 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>
+ * Returns the external documentation of this 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.
*/
- 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);
- }
- }
+ public ExternalDocumentation getExternalDocs(RestRequest req);
}