001: /*
002: * Copyright 2002-2006 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: * http://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:
017: package org.springframework.web.portlet;
018:
019: import javax.portlet.ActionRequest;
020: import javax.portlet.ActionResponse;
021: import javax.portlet.RenderRequest;
022: import javax.portlet.RenderResponse;
023:
024: /**
025: * Workflow interface that allows for customized handler execution chains.
026: * Applications can register any number of existing or custom interceptors
027: * for certain groups of handlers, to add common preprocessing behavior
028: * without needing to modify each handler implementation.
029: *
030: * <p>A <code>HandlerInterceptor</code> gets called before the appropriate
031: * {@link org.springframework.web.portlet.HandlerAdapter} triggers the
032: * execution of the handler itself. This mechanism can be used for a large
033: * field of preprocessing aspects, e.g. for authorization checks,
034: * or common handler behavior like locale or theme changes. Its main purpose
035: * is to permit the factoring out of otherwise repetitive handler code.
036: *
037: * <p>Typically an interceptor chain is defined per
038: * {@link org.springframework.web.portlet.HandlerMapping} bean, sharing its
039: * granularity. To be able to apply a certain interceptor chain to a group of
040: * handlers, one needs to map the desired handlers via one
041: * <code>HandlerMapping</code> bean. The interceptors themselves are defined as
042: * beans in the application context, referenced by the mapping bean definition
043: * via its
044: * {@link org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors "interceptors"}
045: * property (in XML: a <list> of <ref> elements).
046: *
047: * <p>A <code>HandlerInterceptor</code> is basically similar to a Servlet 2.3
048: * {@link javax.servlet.Filter}, but in contrast to the latter it allows
049: * custom pre-processing with the option to prohibit the execution of the handler
050: * itself, and custom post-processing. <code>Filters</code> are more powerful;
051: * for example they allow for exchanging the request and response objects that
052: * are handed down the chain. Note that a filter gets configured in
053: * <code>web.xml</code>, a <code>HandlerInterceptor</code> in the application context.
054: *
055: * <p>As a basic guideline, fine-grained handler-related preprocessing tasks are
056: * candidates for <code>HandlerInterceptor</code> implementations, especially
057: * factored-out common handler code and authorization checks. On the other hand,
058: * a <code>Filter</code> is well-suited for request content and view content
059: * handling, like multipart forms and GZIP compression. This typically shows when
060: * one needs to map the filter to certain content types (e.g. images), or to all
061: * requests. Be aware that filters cannot be applied to portlet requests (they
062: * only operate on servlet requests), so for portlet requests interceptors are
063: * essential.
064: *
065: * <p>If we assume a "sunny day" request (i.e. a request where nothing goes wrong
066: * and all is well), the workflow of a <code>HandlerInterceptor</code> will be as
067: * follows:
068: *
069: * <ol>
070: * <li><i>(<code>DispatcherServlet</code> maps a request to particular handler
071: * and assembles a handler execution chain consisting of the handler that
072: * is to be invoked and all of the <code>HandlerInterceptor</code>
073: * instances that apply to the request.)</i></li>
074: * <li>{@link org.springframework.web.portlet.HandlerInterceptor#preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) preHandleAction(..)}
075: * is called; if the invocation of this method returns <code>true</code> then
076: * this workflow continues</li>
077: * <li>The target handler handles the action phase of the request (via
078: * {@link org.springframework.web.portlet.HandlerAdapter#handleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) HandlerAdapter.handleAction(..)})</li>
079: * <li>{@link org.springframework.web.portlet.HandlerInterceptor#afterActionCompletion(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object, Exception) afterActionCompletion(..)}
080: * is called</li>
081: * <li>{@link org.springframework.web.portlet.HandlerInterceptor#preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) preHandleRender(..)}
082: * is called; if the invocation of this method returns <code>true</code> then
083: * this workflow continues</li>
084: * <li>The target handler handles the render phase of the request (via
085: * {@link org.springframework.web.portlet.HandlerAdapter#handleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) HandlerAdapter.handleRender(..)})</li>
086: * <li>{@link org.springframework.web.portlet.HandlerInterceptor#postHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, ModelAndView) postHandleRender(..)}
087: * is called</li>
088: * <li>{@link org.springframework.web.portlet.HandlerInterceptor#afterRenderCompletion(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, Exception) afterRenderCompletion(..)}
089: * is called</li>
090: * </ol>
091: *
092: * @author Juergen Hoeller
093: * @author John A. Lewis
094: * @since 2.0
095: * @see HandlerExecutionChain#getInterceptors
096: * @see org.springframework.web.portlet.HandlerMapping
097: * @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors
098: * @see org.springframework.web.portlet.HandlerExecutionChain
099: */
100: public interface HandlerInterceptor {
101:
102: /**
103: * Intercept the execution of a handler in the action phase.
104: * <p>Called after a HandlerMapping determines an appropriate handler object
105: * to handle an {@link ActionRequest}, but before said HandlerAdapter actually
106: * invokes the handler.
107: * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
108: * consisting of any number of interceptors, with the handler itself at the end.
109: * With this method, each interceptor can decide to abort the execution chain,
110: * typically throwing an exception or writing a custom response.
111: * @param request current portlet action request
112: * @param response current portlet action response
113: * @param handler chosen handler to execute, for type and/or instance evaluation
114: * @return <code>true</code> if the execution chain should proceed with the
115: * next interceptor or the handler itself. Else, <code>DispatcherPortlet</code>
116: * assumes that this interceptor has already dealt with the response itself
117: * @throws Exception in case of errors
118: */
119: boolean preHandleAction(ActionRequest request,
120: ActionResponse response, Object handler) throws Exception;
121:
122: /**
123: * Callback after completion of request processing in the action phase, that is,
124: * after rendering the view. Will be called on any outcome of handler execution,
125: * thus allowing for proper resource cleanup.
126: * <p>Note: Will only be called if this interceptor's
127: * {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)}
128: * method has successfully completed and returned <code>true</code>!
129: * @param request current portlet action request
130: * @param response current portlet action response
131: * @param handler chosen handler to execute, for type and/or instance examination
132: * @param ex exception thrown on handler execution, if any (only included as
133: * additional context information for the case where a handler threw an exception;
134: * request execution may have failed even when this argument is <code>null</code>)
135: * @throws Exception in case of errors
136: */
137: void afterActionCompletion(ActionRequest request,
138: ActionResponse response, Object handler, Exception ex)
139: throws Exception;
140:
141: /**
142: * Intercept the execution of a handler in the render phase.
143: * <p>Called after a HandlerMapping determines an appropriate handler object
144: * to handle a {@link RenderRequest}, but before said HandlerAdapter actually
145: * invokes the handler.
146: * <p>{@link DispatcherPortlet} processes a handler in an execution chain,
147: * consisting of any number of interceptors, with the handler itself at the end.
148: * With this method, each interceptor can decide to abort the execution chain,
149: * typically throwing an exception or writing a custom response.
150: * @param request current portlet render request
151: * @param response current portlet render response
152: * @param handler chosen handler to execute, for type and/or instance evaluation
153: * @return <code>true</code> if the execution chain should proceed with the
154: * next interceptor or the handler itself. Else, <code>DispatcherPortlet</code>
155: * assumes that this interceptor has already dealt with the response itself
156: * @throws Exception in case of errors
157: */
158: boolean preHandleRender(RenderRequest request,
159: RenderResponse response, Object handler) throws Exception;
160:
161: /**
162: * Intercept the execution of a handler in the render phase.
163: * <p>Called after a {@link HandlerAdapter} actually invoked the handler, but
164: * before the <code>DispatcherPortlet</code> renders the view. Can thus expose
165: * additional model objects to the view via the given {@link ModelAndView}.
166: * <p><code>DispatcherPortlet</code> processes a handler in an execution chain,
167: * consisting of any number of interceptors, with the handler itself at the end.
168: * With this method, each interceptor can post-process an execution, getting
169: * applied in inverse order of the execution chain.
170: * @param request current portlet render request
171: * @param response current portlet render response
172: * @param handler chosen handler to execute, for type and/or instance examination
173: * @param modelAndView the <code>ModelAndView</code> that the handler returned
174: * (can also be <code>null</code>)
175: * @throws Exception in case of errors
176: */
177: void postHandleRender(RenderRequest request,
178: RenderResponse response, Object handler,
179: ModelAndView modelAndView) throws Exception;
180:
181: /**
182: * Callback after completion of request processing, that is, after rendering
183: * the view. Will be called on any outcome of handler execution, thus allowing
184: * for proper resource cleanup.
185: * <p>Note: Will only be called if this interceptor's
186: * {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)}
187: * method has successfully completed and returned <code>true</code>!
188: * @param request current portlet render request
189: * @param response current portlet render response
190: * @param handler chosen handler to execute, for type and/or instance examination
191: * @param ex exception thrown on handler execution, if any
192: * @throws Exception in case of errors
193: */
194: void afterRenderCompletion(RenderRequest request,
195: RenderResponse response, Object handler, Exception ex)
196: throws Exception;
197:
198: }
|