001/*
002 * Copyright 2002-2014 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.portlet;
018
019import javax.portlet.ActionRequest;
020import javax.portlet.ActionResponse;
021import javax.portlet.EventRequest;
022import javax.portlet.EventResponse;
023import javax.portlet.RenderRequest;
024import javax.portlet.RenderResponse;
025import javax.portlet.ResourceRequest;
026import javax.portlet.ResourceResponse;
027
028/**
029 * Workflow interface that allows for customized handler execution chains.
030 * Applications can register any number of existing or custom interceptors
031 * for certain groups of handlers, to add common pre-processing behavior
032 * without needing to modify each handler implementation.
033 *
034 * <p>A {@code HandlerInterceptor} gets called before the appropriate
035 * {@link HandlerAdapter} triggers the
036 * execution of the handler itself. This mechanism can be used for a large
037 * field of preprocessing aspects, e.g. for authorization checks,
038 * or common handler behavior like locale or theme changes. Its main purpose
039 * is to permit the factoring out of otherwise repetitive handler code.
040 *
041 * <p>Typically an interceptor chain is defined per
042 * {@link HandlerMapping} bean, sharing its
043 * granularity. To be able to apply a certain interceptor chain to a group of
044 * handlers, one needs to map the desired handlers via one
045 * {@code HandlerMapping} bean. The interceptors themselves are defined as
046 * beans in the application context, referenced by the mapping bean definition
047 * via its
048 * {@link org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors "interceptors"}
049 * property (in XML: a &lt;list&gt; of &lt;ref&gt; elements).
050 *
051 * <p>A {@code HandlerInterceptor} is basically similar to a Servlet
052 * {@link javax.servlet.Filter}, but in contrast to the latter it allows
053 * custom pre-processing with the option to prohibit the execution of the handler
054 * itself, and custom post-processing. {@code Filters} are more powerful;
055 * for example they allow for exchanging the request and response objects that
056 * are handed down the chain. Note that a filter gets configured in
057 * {@code web.xml}, a {@code HandlerInterceptor} in the application context.
058 *
059 * <p>As a basic guideline, fine-grained handler-related pre-processing tasks are
060 * candidates for {@code HandlerInterceptor} implementations, especially
061 * factored-out common handler code and authorization checks. On the other hand,
062 * a {@code Filter} is well-suited for request content and view content
063 * handling, like multipart forms and GZIP compression. This typically shows when
064 * one needs to map the filter to certain content types (e.g. images), or to all
065 * requests.
066 *
067 * <p>Be aware that filters cannot be applied to portlet requests (they
068 * only operate on servlet requests), so for portlet requests interceptors are
069 * essential.
070 *
071 * <p>If we assume a "sunny day" request cycle (i.e. a request where nothing goes wrong
072 * and all is well), the workflow of a {@code HandlerInterceptor} will be as
073 * follows:
074 *
075 * <p><b>Action Request:</b><p>
076 * <ol>
077 * <li>{@code DispatcherPortlet} maps the action request to a particular handler and
078 * assembles a handler execution chain consisting of the handler that is to be invoked
079 * and all of the {@code HandlerInterceptor} instances that apply to the request.</li>
080 * <li>{@link HandlerInterceptor#preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) preHandleAction(..)}
081 * is called; if the invocation of this method returns {@code true} then this workflow continues.</li>
082 * <li>The target handler handles the action request (via
083 * {@link HandlerAdapter#handleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) HandlerAdapter.handleAction(..)}).</li>
084 * <li>{@link HandlerInterceptor#afterActionCompletion(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object, Exception) afterActionCompletion(..)}
085 * is called.</li>
086 * </ol>
087 *
088 * <p><b>Render Request:</b><p>
089 * <ol>
090 * <li>{@code DispatcherPortlet} maps the render request to a particular handler and
091 * assembles a handler execution chain consisting of the handler that is to be invoked
092 * and all of the {@code HandlerInterceptor} instances that apply to the request.</li>
093 * <li>{@link HandlerInterceptor#preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) preHandleRender(..)}
094 * is called; if the invocation of this method returns {@code true} then this workflow continues.</li>
095 * <li>The target handler handles the render request (via
096 * {@link HandlerAdapter#handleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) HandlerAdapter.handleRender(..)}).</li>
097 * <li>{@link HandlerInterceptor#postHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, ModelAndView) postHandleRender(..)}
098 * is called.</li>
099 * <li>If the {@code HandlerAdapter} returned a {@code ModelAndView}, then
100 * {@code DispatcherPortlet} renders the view accordingly.
101 * <li>{@link HandlerInterceptor#afterRenderCompletion(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, Exception) afterRenderCompletion(..)}
102 * is called.</li>
103 * </ol>
104 *
105 * @author Juergen Hoeller
106 * @author John A. Lewis
107 * @since 2.0
108 * @see HandlerExecutionChain#getInterceptors
109 * @see HandlerMapping
110 * @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors
111 * @see HandlerExecutionChain
112 */
113public interface HandlerInterceptor {
114
115        /**
116         * Intercept the execution of a handler in the action phase.
117         * <p>Called after a HandlerMapping determines an appropriate handler object
118         * to handle an {@link ActionRequest}, but before said HandlerAdapter actually
119         * invokes the handler.
120         * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
121         * consisting of any number of interceptors, with the handler itself at the end.
122         * With this method, each interceptor can decide to abort the execution chain,
123         * typically throwing an exception or writing a custom response.
124         * @param request current portlet action request
125         * @param response current portlet action response
126         * @param handler chosen handler to execute, for type and/or instance evaluation
127         * @return {@code true} if the execution chain should proceed with the
128         * next interceptor or the handler itself. Else, {@code DispatcherPortlet}
129         * assumes that this interceptor has already dealt with the response itself
130         * @throws Exception in case of errors
131         */
132        boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler)
133                        throws Exception;
134
135        /**
136         * Callback after completion of request processing in the action phase, that is,
137         * after rendering the view. Will be called on any outcome of handler execution,
138         * thus allowing for proper resource cleanup.
139         * <p>Note: Will only be called if this interceptor's
140         * {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)}
141         * method has successfully completed and returned {@code true}!
142         * @param request current portlet action request
143         * @param response current portlet action response
144         * @param handler chosen handler to execute, for type and/or instance examination
145         * @param ex exception thrown on handler execution, if any (only included as
146         * additional context information for the case where a handler threw an exception;
147         * request execution may have failed even when this argument is {@code null})
148         * @throws Exception in case of errors
149         */
150        void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex)
151                        throws Exception;
152
153        /**
154         * Intercept the execution of a handler in the render phase.
155         * <p>Called after a HandlerMapping determines an appropriate handler object
156         * to handle a {@link RenderRequest}, but before said HandlerAdapter actually
157         * invokes the handler.
158         * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
159         * consisting of any number of interceptors, with the handler itself at the end.
160         * With this method, each interceptor can decide to abort the execution chain,
161         * typically throwing an exception or writing a custom response.
162         * @param request current portlet render request
163         * @param response current portlet render response
164         * @param handler chosen handler to execute, for type and/or instance evaluation
165         * @return {@code true} if the execution chain should proceed with the
166         * next interceptor or the handler itself. Else, {@code DispatcherPortlet}
167         * assumes that this interceptor has already dealt with the response itself
168         * @throws Exception in case of errors
169         */
170        boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler)
171                        throws Exception;
172
173        /**
174         * Intercept the execution of a handler in the render phase.
175         * <p>Called after a {@link HandlerAdapter} actually invoked the handler, but
176         * before the {@code DispatcherPortlet} renders the view. Can thus expose
177         * additional model objects to the view via the given {@link ModelAndView}.
178         * <p>{@code DispatcherPortlet} processes a handler in an execution chain,
179         * consisting of any number of interceptors, with the handler itself at the end.
180         * With this method, each interceptor can post-process an execution, getting
181         * applied in inverse order of the execution chain.
182         * @param request current portlet render request
183         * @param response current portlet render response
184         * @param handler chosen handler to execute, for type and/or instance examination
185         * @param modelAndView the {@code ModelAndView} that the handler returned
186         * (can also be {@code null})
187         * @throws Exception in case of errors
188         */
189        void postHandleRender(RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView)
190                        throws Exception;
191
192        /**
193         * Callback after completion of request processing, that is, after rendering
194         * the view. Will be called on any outcome of handler execution, thus allowing
195         * for proper resource cleanup.
196         * <p>Note: Will only be called if this interceptor's
197         * {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)}
198         * method has successfully completed and returned {@code true}!
199         * @param request current portlet render request
200         * @param response current portlet render response
201         * @param handler chosen handler to execute, for type and/or instance examination
202         * @param ex exception thrown on handler execution, if any
203         * @throws Exception in case of errors
204         */
205        void afterRenderCompletion(RenderRequest request, RenderResponse response, Object handler, Exception ex)
206                        throws Exception;
207
208        /**
209         * Intercept the execution of a handler in the render phase.
210         * <p>Called after a HandlerMapping determines an appropriate handler object
211         * to handle a {@link RenderRequest}, but before said HandlerAdapter actually
212         * invokes the handler.
213         * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
214         * consisting of any number of interceptors, with the handler itself at the end.
215         * With this method, each interceptor can decide to abort the execution chain,
216         * typically throwing an exception or writing a custom response.
217         * @param request current portlet render request
218         * @param response current portlet render response
219         * @param handler chosen handler to execute, for type and/or instance evaluation
220         * @return {@code true} if the execution chain should proceed with the
221         * next interceptor or the handler itself. Else, {@code DispatcherPortlet}
222         * assumes that this interceptor has already dealt with the response itself
223         * @throws Exception in case of errors
224         */
225        boolean preHandleResource(ResourceRequest request, ResourceResponse response, Object handler)
226                        throws Exception;
227
228        /**
229         * Intercept the execution of a handler in the render phase.
230         * <p>Called after a {@link HandlerAdapter} actually invoked the handler, but
231         * before the {@code DispatcherPortlet} renders the view. Can thus expose
232         * additional model objects to the view via the given {@link ModelAndView}.
233         * <p>{@code DispatcherPortlet} processes a handler in an execution chain,
234         * consisting of any number of interceptors, with the handler itself at the end.
235         * With this method, each interceptor can post-process an execution, getting
236         * applied in inverse order of the execution chain.
237         * @param request current portlet render request
238         * @param response current portlet render response
239         * @param handler chosen handler to execute, for type and/or instance examination
240         * @param modelAndView the {@code ModelAndView} that the handler returned
241         * (can also be {@code null})
242         * @throws Exception in case of errors
243         */
244        void postHandleResource(ResourceRequest request, ResourceResponse response, Object handler, ModelAndView modelAndView)
245                        throws Exception;
246
247        /**
248         * Callback after completion of request processing, that is, after rendering
249         * the view. Will be called on any outcome of handler execution, thus allowing
250         * for proper resource cleanup.
251         * <p>Note: Will only be called if this interceptor's
252         * {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)}
253         * method has successfully completed and returned {@code true}!
254         * @param request current portlet render request
255         * @param response current portlet render response
256         * @param handler chosen handler to execute, for type and/or instance examination
257         * @param ex exception thrown on handler execution, if any
258         * @throws Exception in case of errors
259         */
260        void afterResourceCompletion(ResourceRequest request, ResourceResponse response, Object handler, Exception ex)
261                        throws Exception;
262
263        /**
264         * Intercept the execution of a handler in the action phase.
265         * <p>Called after a HandlerMapping determines an appropriate handler object
266         * to handle an {@link ActionRequest}, but before said HandlerAdapter actually
267         * invokes the handler.
268         * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
269         * consisting of any number of interceptors, with the handler itself at the end.
270         * With this method, each interceptor can decide to abort the execution chain,
271         * typically throwing an exception or writing a custom response.
272         * @param request current portlet action request
273         * @param response current portlet action response
274         * @param handler chosen handler to execute, for type and/or instance evaluation
275         * @return {@code true} if the execution chain should proceed with the
276         * next interceptor or the handler itself. Else, {@code DispatcherPortlet}
277         * assumes that this interceptor has already dealt with the response itself
278         * @throws Exception in case of errors
279         */
280        boolean preHandleEvent(EventRequest request, EventResponse response, Object handler)
281                        throws Exception;
282
283        /**
284         * Callback after completion of request processing in the action phase, that is,
285         * after rendering the view. Will be called on any outcome of handler execution,
286         * thus allowing for proper resource cleanup.
287         * <p>Note: Will only be called if this interceptor's
288         * {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)}
289         * method has successfully completed and returned {@code true}!
290         * @param request current portlet action request
291         * @param response current portlet action response
292         * @param handler chosen handler to execute, for type and/or instance examination
293         * @param ex exception thrown on handler execution, if any (only included as
294         * additional context information for the case where a handler threw an exception;
295         * request execution may have failed even when this argument is {@code null})
296         * @throws Exception in case of errors
297         */
298        void afterEventCompletion(EventRequest request, EventResponse response, Object handler, Exception ex)
299                        throws Exception;
300
301}