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.cp.Messages;
025import org.apache.juneau.dto.swagger.*;
026import org.apache.juneau.http.header.*;
027import org.apache.juneau.http.header.Date;
028import org.apache.juneau.parser.*;
029import org.apache.juneau.reflect.*;
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 InputStream}
085 *       <li class='jc'>{@link Locale}
086 *       <li class='jc'>{@link Messages}
087 *       <li class='jc'>{@link OutputStream}
088 *       <li class='jc'>{@link Parser}
089 *       <li class='jc'>{@link Reader}
090 *       <li class='jc'>{@link RequestBody}
091 *       <li class='jc'>{@link RequestFormData}
092 *       <li class='jc'>{@link RequestHeaders}
093 *       <li class='jc'>{@link RequestAttributes}
094 *       <li class='jc'>{@link RequestPath}
095 *       <li class='jc'>{@link RequestQuery}
096 *       <li class='jc'>{@link ResourceBundle}
097 *       <li class='jc'>{@link RestContext}
098 *       <li class='jc'>{@link ServletInputStream}
099 *       <li class='jc'>{@link ServletOutputStream}
100 *       <li class='jc'>{@link Swagger}
101 *       <li class='jc'>{@link UriContext}
102 *       <li class='jc'>{@link UriResolver}
103 *       <li class='jc'>{@link Writer}
104 *    </ul>
105 * </ul>
106 *
107 * <ul class='seealso'>
108 *    <li class='jf'>{@link RestContext#REST_paramResolvers}
109 *    <li class='link'>{@doc RestmParameters}
110 * </ul>
111 */
112public abstract class RestMethodParam {
113
114   final RestParamType paramType;
115   final ParamInfo mpi;
116   final String name;
117   final Type type;
118   final Class<?> c;
119
120   /**
121    * Constructor.
122    *
123    * @param paramType The Swagger parameter type.
124    * @param mpi The method parameter.
125    * @param name
126    *    The parameter name.
127    *    Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
128    * @param type The object type to convert the parameter to.
129    */
130   protected RestMethodParam(RestParamType paramType, ParamInfo mpi, String name, Type type) {
131      this.paramType = paramType;
132      this.mpi = mpi;
133      this.name = name;
134      this.type = type;
135      this.c = type instanceof Class ? (Class<?>)type : type instanceof ParameterizedType ? (Class<?>)((ParameterizedType)type).getRawType() : null;
136   }
137
138   /**
139    * Constructor.
140    *
141    * @param paramType The Swagger parameter type.
142    * @param mpi The method parameter.
143    * @param name
144    *    The parameter name.
145    *    Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
146    */
147   protected RestMethodParam(RestParamType paramType, ParamInfo mpi, String name) {
148      this(paramType, mpi, name, mpi.getParameterType().innerType());
149   }
150
151   /**
152    * Constructor.
153    *
154    * @param paramType The Swagger parameter type.
155    * @param mpi The method parameter.
156    */
157   protected RestMethodParam(RestParamType paramType, ParamInfo mpi) {
158      this(paramType, mpi, null, mpi.getParameterType().innerType());
159   }
160
161   /**
162    * Constructor.
163    *
164    * @param paramType The Swagger parameter type.
165    * @param type The object type to convert the parameter to.
166    */
167   protected RestMethodParam(RestParamType paramType, Type type) {
168      this(paramType, null, null, type);
169   }
170
171   /**
172    * Constructor.
173    *
174    * @param paramType The Swagger parameter type.
175    * @param type The object type to convert the parameter to.
176    */
177   protected RestMethodParam(RestParamType paramType, ClassInfo type) {
178      this(paramType, null, null, type.innerType());
179   }
180
181   /**
182    * Constructor.
183    *
184    * @param paramType The Swagger parameter type.
185    * @param name
186    *    The parameter name.
187    *    Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
188    * @param type The object type to convert the parameter to.
189    */
190   protected RestMethodParam(RestParamType paramType, String name, Type type) {
191      this(paramType, null, name, type);
192   }
193
194   /**
195    * Resolves the parameter object.
196    *
197    * @param req The rest request.
198    * @param res The rest response.
199    * @return The resolved object.
200    * @throws Exception Generic error occurred.
201    */
202   public abstract Object resolve(RestRequest req, RestResponse res) throws Exception;
203
204   /**
205    * Returns the parameter class type that this parameter resolver is meant for.
206    *
207    * @return The parameter class type, or <jk>null</jk> if the type passed in isn't an instance of {@link Class}.
208    */
209   protected Class<?> forClass() {
210      if (type instanceof Class)
211         return (Class<?>)type;
212      return null;
213   }
214
215   /**
216    * Returns the swagger parameter type for this parameter as shown in the Swagger doc.
217    *
218    * @return the swagger parameter type for this parameter.
219    */
220   protected RestParamType getParamType() {
221      return paramType;
222   }
223
224   /**
225    * Returns the parameter info.
226    *
227    * @return The parameter info.
228    */
229   public ParamInfo getMethodParamInfo() {
230      return mpi;
231   }
232
233   /**
234    * Returns the parameter name for this parameter as shown in the Swagger doc.
235    *
236    * @return the parameter name for this parameter.
237    */
238   protected String getName() {
239      return name;
240   }
241
242   /**
243    * Returns the parameter class type.
244    *
245    * @return the parameter class type.
246    */
247   public Type getType() {
248      return type;
249   }
250
251   /**
252    * Returns the parameter class type.
253    *
254    * @return the parameter class type.
255    */
256   public Class<?> getTypeClass() {
257      return c;
258   }
259}