/*
 * Copyright 2002-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.portlet;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.EventResponse;
import javax.portlet.EventRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.ResourceRequest;

/**
 * Workflow interface that allows for customized handler execution chains.
 * Applications can register any number of existing or custom interceptors
 * for certain groups of handlers, to add common pre-processing behavior
 * without needing to modify each handler implementation.
 *
 * <p>A {@code HandlerInterceptor} gets called before the appropriate
 * {@link HandlerAdapter} triggers the
 * execution of the handler itself. This mechanism can be used for a large
 * field of preprocessing aspects, e.g. for authorization checks,
 * or common handler behavior like locale or theme changes. Its main purpose
 * is to permit the factoring out of otherwise repetitive handler code.
 *
 * <p>Typically an interceptor chain is defined per
 * {@link HandlerMapping} bean, sharing its
 * granularity. To be able to apply a certain interceptor chain to a group of
 * handlers, one needs to map the desired handlers via one
 * {@code HandlerMapping} bean. The interceptors themselves are defined as
 * beans in the application context, referenced by the mapping bean definition
 * via its
 * {@link org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors "interceptors"}
 * property (in XML: a &lt;list&gt; of &lt;ref&gt; elements).
 *
 * <p>A {@code HandlerInterceptor} is basically similar to a Servlet
 * {@link javax.servlet.Filter}, but in contrast to the latter it allows
 * custom pre-processing with the option to prohibit the execution of the handler
 * itself, and custom post-processing. {@code Filters} are more powerful;
 * for example they allow for exchanging the request and response objects that
 * are handed down the chain. Note that a filter gets configured in
 * {@code web.xml}, a {@code HandlerInterceptor} in the application context.
 *
 * <p>As a basic guideline, fine-grained handler-related pre-processing tasks are
 * candidates for {@code HandlerInterceptor} implementations, especially
 * factored-out common handler code and authorization checks. On the other hand,
 * a {@code Filter} is well-suited for request content and view content
 * handling, like multipart forms and GZIP compression. This typically shows when
 * one needs to map the filter to certain content types (e.g. images), or to all
 * requests.
 *
 * <p>Be aware that filters cannot be applied to portlet requests (they
 * only operate on servlet requests), so for portlet requests interceptors are
 * essential.
 *
 * <p>If we assume a "sunny day" request cycle (i.e. a request where nothing goes wrong
 * and all is well), the workflow of a {@code HandlerInterceptor} will be as
 * follows:
 *
 * <p><b>Action Request:</b><p>
 * <ol>
 *   <li>{@code DispatcherPortlet} maps the action request to a particular handler
 * 		 and assembles a handler execution chain consisting of the handler that
 * 		 is to be invoked and all of the {@code HandlerInterceptor}
 * 		 instances that apply to the request.</li>
 *   <li>{@link HandlerInterceptor#preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) preHandleAction(..)}
 * 		 is called; if the invocation of this method returns {@code true} then
 *		 this workflow continues</li>
 *   <li>The target handler handles the action request (via
 *          {@link HandlerAdapter#handleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) HandlerAdapter.handleAction(..)})</li>
 *   <li>{@link HandlerInterceptor#afterActionCompletion(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object, Exception) afterActionCompletion(..)}
 * 		 is called</li>
 * </ol>
 *
 * <p><b>Render Request:</b><p>
 * <ol>
 *   <li>{@code DispatcherPortlet} maps the render request to a particular handler
 * 		 and assembles a handler execution chain consisting of the handler that
 * 		 is to be invoked and all of the {@code HandlerInterceptor}
 * 		 instances that apply to the request.</li>
 *   <li>{@link HandlerInterceptor#preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) preHandleRender(..)}
 * 		 is called; if the invocation of this method returns {@code true} then
 *		 this workflow continues</li>
 *   <li>The target handler handles the render request (via
 *          {@link HandlerAdapter#handleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) HandlerAdapter.handleRender(..)})</li>
 *   <li>{@link HandlerInterceptor#postHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, ModelAndView) postHandleRender(..)}
 * 		 is called</li>
 *   <li>If the {@code HandlerAdapter} returned a {@code ModelAndView},
 *       then {@code DispatcherPortlet} renders the view accordingly
 *   <li>{@link HandlerInterceptor#afterRenderCompletion(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, Exception) afterRenderCompletion(..)}
 * 		 is called</li>
 * </ol>
 *
 * @author Juergen Hoeller
 * @author John A. Lewis
 * @since 2.0
 * @see HandlerExecutionChain#getInterceptors
 * @see HandlerMapping
 * @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors
 * @see HandlerExecutionChain
 */
public interface HandlerInterceptor {

	/**
	 * Intercept the execution of a handler in the action phase.
	 * <p>Called after a HandlerMapping determines an appropriate handler object
	 * to handle an {@link ActionRequest}, but before said HandlerAdapter actually
	 * invokes the handler.
	 * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
	 * consisting of any number of interceptors, with the handler itself at the end.
	 * With this method, each interceptor can decide to abort the execution chain,
	 * typically throwing an exception or writing a custom response.
	 * @param request current portlet action request
	 * @param response current portlet action response
	 * @param handler chosen handler to execute, for type and/or instance evaluation
	 * @return {@code true} if the execution chain should proceed with the
	 * next interceptor or the handler itself. Else, {@code DispatcherPortlet}
	 * assumes that this interceptor has already dealt with the response itself
	 * @throws Exception in case of errors
	 */
	boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler)
			throws Exception;

	/**
	 * Callback after completion of request processing in the action phase, that is,
	 * after rendering the view. Will be called on any outcome of handler execution,
	 * thus allowing for proper resource cleanup.
	 * <p>Note: Will only be called if this interceptor's
	 * {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)}
	 * method has successfully completed and returned {@code true}!
	 * @param request current portlet action request
	 * @param response current portlet action response
	 * @param handler chosen handler to execute, for type and/or instance examination
	 * @param ex exception thrown on handler execution, if any (only included as
	 * additional context information for the case where a handler threw an exception;
	 * request execution may have failed even when this argument is {@code null})
	 * @throws Exception in case of errors
	 */
	void afterActionCompletion(
			ActionRequest request, ActionResponse response, Object handler, Exception ex)
			throws Exception;

	/**
	 * Intercept the execution of a handler in the render phase.
	 * <p>Called after a HandlerMapping determines an appropriate handler object
	 * to handle a {@link RenderRequest}, but before said HandlerAdapter actually
	 * invokes the handler.
	 * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
	 * consisting of any number of interceptors, with the handler itself at the end.
	 * With this method, each interceptor can decide to abort the execution chain,
	 * typically throwing an exception or writing a custom response.
	 * @param request current portlet render request
	 * @param response current portlet render response
	 * @param handler chosen handler to execute, for type and/or instance evaluation
	 * @return {@code true} if the execution chain should proceed with the
	 * next interceptor or the handler itself. Else, {@code DispatcherPortlet}
	 * assumes that this interceptor has already dealt with the response itself
	 * @throws Exception in case of errors
	 */
	boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler)
			throws Exception;

	/**
	 * Intercept the execution of a handler in the render phase.
	 * <p>Called after a {@link HandlerAdapter} actually invoked the handler, but
	 * before the {@code DispatcherPortlet} renders the view. Can thus expose
	 * additional model objects to the view via the given {@link ModelAndView}.
	 * <p>{@code DispatcherPortlet} processes a handler in an execution chain,
	 * consisting of any number of interceptors, with the handler itself at the end.
	 * With this method, each interceptor can post-process an execution, getting
	 * applied in inverse order of the execution chain.
	 * @param request current portlet render request
	 * @param response current portlet render response
	 * @param handler chosen handler to execute, for type and/or instance examination
	 * @param modelAndView the {@code ModelAndView} that the handler returned
	 * (can also be {@code null})
	 * @throws Exception in case of errors
	 */
	void postHandleRender(
			RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView)
			throws Exception;

	/**
	 * Callback after completion of request processing, that is, after rendering
	 * the view. Will be called on any outcome of handler execution, thus allowing
	 * for proper resource cleanup.
	 * <p>Note: Will only be called if this interceptor's
	 * {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)}
	 * method has successfully completed and returned {@code true}!
	 * @param request current portlet render request
	 * @param response current portlet render response
	 * @param handler chosen handler to execute, for type and/or instance examination
	 * @param ex exception thrown on handler execution, if any
	 * @throws Exception in case of errors
	 */
	void afterRenderCompletion(
			RenderRequest request, RenderResponse response, Object handler, Exception ex)
			throws Exception;

	/**
	 * Intercept the execution of a handler in the render phase.
	 * <p>Called after a HandlerMapping determines an appropriate handler object
	 * to handle a {@link RenderRequest}, but before said HandlerAdapter actually
	 * invokes the handler.
	 * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
	 * consisting of any number of interceptors, with the handler itself at the end.
	 * With this method, each interceptor can decide to abort the execution chain,
	 * typically throwing an exception or writing a custom response.
	 * @param request current portlet render request
	 * @param response current portlet render response
	 * @param handler chosen handler to execute, for type and/or instance evaluation
	 * @return {@code true} if the execution chain should proceed with the
	 * next interceptor or the handler itself. Else, {@code DispatcherPortlet}
	 * assumes that this interceptor has already dealt with the response itself
	 * @throws Exception in case of errors
	 */
	boolean preHandleResource(ResourceRequest request, ResourceResponse response, Object handler)
			throws Exception;

	/**
	 * Intercept the execution of a handler in the render phase.
	 * <p>Called after a {@link HandlerAdapter} actually invoked the handler, but
	 * before the {@code DispatcherPortlet} renders the view. Can thus expose
	 * additional model objects to the view via the given {@link ModelAndView}.
	 * <p>{@code DispatcherPortlet} processes a handler in an execution chain,
	 * consisting of any number of interceptors, with the handler itself at the end.
	 * With this method, each interceptor can post-process an execution, getting
	 * applied in inverse order of the execution chain.
	 * @param request current portlet render request
	 * @param response current portlet render response
	 * @param handler chosen handler to execute, for type and/or instance examination
	 * @param modelAndView the {@code ModelAndView} that the handler returned
	 * (can also be {@code null})
	 * @throws Exception in case of errors
	 */
	void postHandleResource(
			ResourceRequest request, ResourceResponse response, Object handler, ModelAndView modelAndView)
			throws Exception;

	/**
	 * Callback after completion of request processing, that is, after rendering
	 * the view. Will be called on any outcome of handler execution, thus allowing
	 * for proper resource cleanup.
	 * <p>Note: Will only be called if this interceptor's
	 * {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)}
	 * method has successfully completed and returned {@code true}!
	 * @param request current portlet render request
	 * @param response current portlet render response
	 * @param handler chosen handler to execute, for type and/or instance examination
	 * @param ex exception thrown on handler execution, if any
	 * @throws Exception in case of errors
	 */
	void afterResourceCompletion(
			ResourceRequest request, ResourceResponse response, Object handler, Exception ex)
			throws Exception;


	/**
	 * Intercept the execution of a handler in the action phase.
	 * <p>Called after a HandlerMapping determines an appropriate handler object
	 * to handle an {@link ActionRequest}, but before said HandlerAdapter actually
	 * invokes the handler.
	 * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
	 * consisting of any number of interceptors, with the handler itself at the end.
	 * With this method, each interceptor can decide to abort the execution chain,
	 * typically throwing an exception or writing a custom response.
	 * @param request current portlet action request
	 * @param response current portlet action response
	 * @param handler chosen handler to execute, for type and/or instance evaluation
	 * @return {@code true} if the execution chain should proceed with the
	 * next interceptor or the handler itself. Else, {@code DispatcherPortlet}
	 * assumes that this interceptor has already dealt with the response itself
	 * @throws Exception in case of errors
	 */
	boolean preHandleEvent(EventRequest request, EventResponse response, Object handler)
			throws Exception;

	/**
	 * Callback after completion of request processing in the action phase, that is,
	 * after rendering the view. Will be called on any outcome of handler execution,
	 * thus allowing for proper resource cleanup.
	 * <p>Note: Will only be called if this interceptor's
	 * {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)}
	 * method has successfully completed and returned {@code true}!
	 * @param request current portlet action request
	 * @param response current portlet action response
	 * @param handler chosen handler to execute, for type and/or instance examination
	 * @param ex exception thrown on handler execution, if any (only included as
	 * additional context information for the case where a handler threw an exception;
	 * request execution may have failed even when this argument is {@code null})
	 * @throws Exception in case of errors
	 */
	void afterEventCompletion(
			EventRequest request, EventResponse response, Object handler, Exception ex)
			throws Exception;

}
