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