001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.rest;
014
015import java.text.*;
016import java.util.logging.*;
017
018import javax.servlet.http.*;
019
020import org.apache.juneau.dto.swagger.*;
021import org.apache.juneau.html.annotation.*;
022import org.apache.juneau.internal.*;
023import org.apache.juneau.rest.annotation.*;
024import org.apache.juneau.http.exception.*;
025
026/**
027 * Identical to {@link BasicRestServlet} but doesn't extend from {@link HttpServlet}.
028 *
029 * <ul class='seealso'>
030 *    <li class='link'>{@doc juneau-rest-server.Instantiation.BasicRest}
031 * </ul>
032 */
033@Rest(
034   // Allow OPTIONS requests to be simulated using ?method=OPTIONS query parameter.
035   allowedMethodParams="OPTIONS"
036)
037@HtmlDocConfig(
038   // Basic page navigation links.
039   navlinks={
040      "up: request:/..",
041      "options: servlet:/?method=OPTIONS",
042      "stats: servlet:/stats"
043   }
044)
045public abstract class BasicRest implements BasicRestConfig {
046
047   private JuneauLogger logger = JuneauLogger.getLogger(getClass());
048   private volatile RestContext context;
049
050   /**
051    * Post-initialization hook to retrieve the {@link RestContext} object for this resource.
052    *
053    * @param context The context for this resource.
054    */
055   @RestHook(HookEvent.POST_INIT)
056   public synchronized void onPostInit(RestContext context) {
057      this.context = context;
058   }
059
060   /**
061    * [OPTIONS /*] - Show resource options.
062    *
063    * @param req The HTTP request.
064    * @return A bean containing the contents for the OPTIONS page.
065    */
066   @Override /* BasicRestConfig */
067   public Swagger getOptions(RestRequest req) {
068      // Localized Swagger for this resource is available through the RestRequest object.
069      return req.getSwagger();
070   }
071
072   /**
073    * [* /error] - Error occurred.
074    *
075    * <p>
076    * Servlet chains will often automatically redirect to <js>"/error"</js> when any sort of error condition occurs
077    * (such as failed authentication) and will set appropriate response parameters (such as an <c>WWW-Authenticate</c>
078    * response header).
079    *
080    * <p>
081    * These responses should be left as-is without any additional processing.
082    */
083   @Override /* BasicRestConfig */
084   public void error() {}
085
086   /**
087    * [GET /stats] - Timing statistics.
088    *
089    * <p>
090    * Timing statistics for method invocations on this resource.
091    *
092    * @return A collection of timing statistics for each annotated method on this resource.
093    */
094   @Override /* BasicRestConfig */
095   public RestContextStats getStats(RestRequest req) {
096      return req.getContext().getStats();
097   }
098
099   //-----------------------------------------------------------------------------------------------------------------
100   // Context methods.
101   //-----------------------------------------------------------------------------------------------------------------
102
103   /**
104    * Returns the read-only context object that contains all the configuration information about this resource.
105    *
106    * @return The context information on this servlet.
107    */
108   protected synchronized RestContext getContext() {
109      if (context == null)
110         throw new InternalServerError("RestContext object not set on resource.");
111      return context;
112   }
113
114   //-----------------------------------------------------------------------------------------------------------------
115   // Convenience logger methods
116   //-----------------------------------------------------------------------------------------------------------------
117
118   /**
119    * Log a message.
120    *
121    * @param msg The message to log.
122    */
123   public void log(String msg) {
124      logger.info(msg);
125   }
126
127   /**
128    * Log a message.
129    *
130    * @param msg The message to log.
131    * @param cause The cause.
132    */
133   public void log(String msg, Throwable cause) {
134      logger.info(cause, msg);
135   }
136
137   /**
138    * Log a message.
139    *
140    * @param level The log level.
141    * @param msg The message to log.
142    * @param args Optional {@link MessageFormat}-style arguments.
143    */
144   public void log(Level level, String msg, Object...args) {
145      logger.log(level, msg, args);
146   }
147
148   /**
149    * Log a message.
150    *
151    * @param level The log level.
152    * @param msg The message to log.
153    * @param args Optional {@link MessageFormat}-style arguments.
154    */
155   public void logObjects(Level level, String msg, Object...args) {
156      logger.logObjects(level, msg, args);
157   }
158
159   /**
160    * Log a message.
161    *
162    * @param level The log level.
163    * @param cause The cause.
164    * @param msg The message to log.
165    * @param args Optional {@link MessageFormat}-style arguments.
166    */
167   public void log(Level level, Throwable cause, String msg, Object...args) {
168      logger.log(level, cause, msg, args);
169   }
170
171   //-----------------------------------------------------------------------------------------------------------------
172   // Request-time methods.
173   //-----------------------------------------------------------------------------------------------------------------
174
175   /**
176    * Returns the current HTTP request.
177    *
178    * @return The current HTTP request.
179    */
180   public synchronized RestRequest getRequest() {
181      return getContext().getRequest();
182   }
183
184   /**
185    * Returns the current HTTP response.
186    *
187    * @return The current HTTP response
188    */
189   public synchronized RestResponse getResponse() {
190      return getContext().getResponse();
191   }
192}