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.io.*;
016import java.lang.reflect.*;
017import java.util.*;
018
019import javax.servlet.*;
020import javax.servlet.http.*;
021
022import org.apache.juneau.*;
023import org.apache.juneau.config.*;
024import org.apache.juneau.dto.swagger.*;
025import org.apache.juneau.http.*;
026import org.apache.juneau.http.Date;
027import org.apache.juneau.parser.*;
028import org.apache.juneau.reflect.*;
029import org.apache.juneau.utils.*;
030
031/**
032 * REST java method parameter resolver.
033 *
034 * <p>
035 * Used to resolve instances of classes being passed to Java REST methods.
036 *
037 * <p>
038 * By default, the following parameter types can be passed into Java methods in any order:
039 *
040 * <h5 class='topic'>Standard top-level objects</h5>
041 * <ul>
042 *    <li><b>Standard top-level objects</b>
043 *    <ul>
044 *       <li class='jc'>{@link HttpServletRequest}
045 *       <li class='jc'>{@link RestRequest}
046 *       <li class='jc'>{@link HttpServletResponse}
047 *       <li class='jc'>{@link RestResponse}
048 *    </ul>
049 *    <li><b>Headers</b>
050 *    <ul>
051 *       <li class='jc'>{@link Accept}
052 *       <li class='jc'>{@link AcceptCharset}
053 *       <li class='jc'>{@link AcceptEncoding}
054 *       <li class='jc'>{@link AcceptLanguage}
055 *       <li class='jc'>{@link Authorization}
056 *       <li class='jc'>{@link CacheControl}
057 *       <li class='jc'>{@link Connection}
058 *       <li class='jc'>{@link ContentLength}
059 *       <li class='jc'>{@link ContentType}
060 *       <li class='jc'>{@link Date}
061 *       <li class='jc'>{@link Expect}
062 *       <li class='jc'>{@link From}
063 *       <li class='jc'>{@link Host}
064 *       <li class='jc'>{@link IfMatch}
065 *       <li class='jc'>{@link IfModifiedSince}
066 *       <li class='jc'>{@link IfNoneMatch}
067 *       <li class='jc'>{@link IfRange}
068 *       <li class='jc'>{@link IfUnmodifiedSince}
069 *       <li class='jc'>{@link MaxForwards}
070 *       <li class='jc'>{@link Pragma}
071 *       <li class='jc'>{@link ProxyAuthorization}
072 *       <li class='jc'>{@link Range}
073 *       <li class='jc'>{@link Referer}
074 *       <li class='jc'>{@link TE}
075 *       <li class='jc'>{@link TimeZone}
076 *       <li class='jc'>{@link UserAgent}
077 *       <li class='jc'>{@link Upgrade}
078 *       <li class='jc'>{@link Via}
079 *       <li class='jc'>{@link Warning}
080 *    </ul>
081 *    <li><b>Other objects</b>
082 *    <ul>
083 *       <li class='jc'>{@link Config}
084 *       <li class='jc'>{@link HttpMethod}
085 *       <li class='jc'>{@link InputStream}
086 *       <li class='jc'>{@link Locale}
087 *       <li class='jc'>{@link MessageBundle}
088 *       <li class='jc'>{@link OutputStream}
089 *       <li class='jc'>{@link Parser}
090 *       <li class='jc'>{@link Reader}
091 *       <li class='jc'>{@link RequestBody}
092 *       <li class='jc'>{@link RequestFormData}
093 *       <li class='jc'>{@link RequestHeaders}
094 *       <li class='jc'>{@link RequestAttributes}
095 *       <li class='jc'>{@link RequestPath}
096 *       <li class='jc'>{@link RequestQuery}
097 *       <li class='jc'>{@link ResourceBundle}
098 *       <li class='jc'>{@link RestContext}
099 *       <li class='jc'>{@link ServletInputStream}
100 *       <li class='jc'>{@link ServletOutputStream}
101 *       <li class='jc'>{@link Swagger}
102 *       <li class='jc'>{@link UriContext}
103 *       <li class='jc'>{@link UriResolver}
104 *       <li class='jc'>{@link Writer}
105 *    </ul>
106 * </ul>
107 *
108 * <ul class='seealso'>
109 *    <li class='jf'>{@link RestContext#REST_paramResolvers}
110 *    <li class='link'>{@doc juneau-rest-server.RestMethod.MethodParameters}
111 * </ul>
112 */
113public abstract class RestMethodParam {
114
115   final RestParamType paramType;
116   final ParamInfo mpi;
117   final String name;
118   final Type type;
119   final Class<?> c;
120
121   /**
122    * Constructor.
123    *
124    * @param paramType The Swagger parameter type.
125    * @param mpi The method parameter.
126    * @param name
127    *    The parameter name.
128    *    Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
129    * @param type The object type to convert the parameter to.
130    */
131   protected RestMethodParam(RestParamType paramType, ParamInfo mpi, String name, Type type) {
132      this.paramType = paramType;
133      this.mpi = mpi;
134      this.name = name;
135      this.type = type;
136      this.c = type instanceof Class ? (Class<?>)type : type instanceof ParameterizedType ? (Class<?>)((ParameterizedType)type).getRawType() : null;
137   }
138
139   /**
140    * Constructor.
141    *
142    * @param paramType The Swagger parameter type.
143    * @param mpi The method parameter.
144    * @param name
145    *    The parameter name.
146    *    Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
147    */
148   protected RestMethodParam(RestParamType paramType, ParamInfo mpi, String name) {
149      this(paramType, mpi, name, mpi.getParameterType().innerType());
150   }
151
152   /**
153    * Constructor.
154    *
155    * @param paramType The Swagger parameter type.
156    * @param mpi The method parameter.
157    */
158   protected RestMethodParam(RestParamType paramType, ParamInfo mpi) {
159      this(paramType, mpi, null, mpi.getParameterType().innerType());
160   }
161
162   /**
163    * Constructor.
164    *
165    * @param paramType The Swagger parameter type.
166    * @param type The object type to convert the parameter to.
167    */
168   protected RestMethodParam(RestParamType paramType, Type type) {
169      this(paramType, null, null, type);
170   }
171
172   /**
173    * Constructor.
174    *
175    * @param paramType The Swagger parameter type.
176    * @param type The object type to convert the parameter to.
177    */
178   protected RestMethodParam(RestParamType paramType, ClassInfo type) {
179      this(paramType, null, null, type.innerType());
180   }
181
182   /**
183    * Constructor.
184    *
185    * @param paramType The Swagger parameter type.
186    * @param name
187    *    The parameter name.
188    *    Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
189    * @param type The object type to convert the parameter to.
190    */
191   protected RestMethodParam(RestParamType paramType, String name, Type type) {
192      this(paramType, null, name, type);
193   }
194
195   /**
196    * Resolves the parameter object.
197    *
198    * @param req The rest request.
199    * @param res The rest response.
200    * @return The resolved object.
201    * @throws Exception Generic error occurred.
202    */
203   public abstract Object resolve(RestRequest req, RestResponse res) throws Exception;
204
205   /**
206    * Returns the parameter class type that this parameter resolver is meant for.
207    *
208    * @return The parameter class type, or <jk>null</jk> if the type passed in isn't an instance of {@link Class}.
209    */
210   protected Class<?> forClass() {
211      if (type instanceof Class)
212         return (Class<?>)type;
213      return null;
214   }
215
216   /**
217    * Returns the swagger parameter type for this parameter as shown in the Swagger doc.
218    *
219    * @return the swagger parameter type for this parameter.
220    */
221   protected RestParamType getParamType() {
222      return paramType;
223   }
224
225   /**
226    * Returns the parameter info.
227    *
228    * @return The parameter info.
229    */
230   public ParamInfo getMethodParamInfo() {
231      return mpi;
232   }
233
234   /**
235    * Returns the parameter name for this parameter as shown in the Swagger doc.
236    *
237    * @return the parameter name for this parameter.
238    */
239   protected String getName() {
240      return name;
241   }
242
243   /**
244    * Returns the parameter class type.
245    *
246    * @return the parameter class type.
247    */
248   public Type getType() {
249      return type;
250   }
251
252   /**
253    * Returns the parameter class type.
254    *
255    * @return the parameter class type.
256    */
257   public Class<?> getTypeClass() {
258      return c;
259   }
260}