/* Copyright 2005-2006 Tim Fennell
*
* 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 net.sourceforge.stripes.controller;
import net.sourceforge.stripes.action.Resolution;
/**
* <p>Interface for classes which wish to intercept the processing of a request at various
* stages in the Stripes lifecycle. To denote the {@link LifecycleStage} (or stages) at
* which an interceptor should run, the class should be marked with an {@link Intercepts}
* annotation declaring one or more lifecycle stages.</p>
*
* <p>{@code Interceptors} execute <i>around</i> the intercepted lifecycle stage. Assuming for
* simplicity's sake that a single interceptor is configured, any code in the
* {@link #intercept(ExecutionContext)} method prior to calling {@code context.proceed()} will
* be executed immediately prior to the lifecycle code. Any code after calling
* {@code context.proceed()} will be executed immediately after the lifecycle code. For example
* the following implementation would print out a message before and after validation and
* binding occur:</p>
*
*<pre>
*{@literal @}Intercepts(LifecycleStage.BindingAndValidation)
*public class NoisyInterceptor implements Interceptor {
* public Resolution intercept(ExecutionContext context) {
* System.out.println("Before validation and binding!");
* Resolution r = context.proceed();
* System.out.println("After validation and binding!");
* return r;
* }
*}
*</pre>
*
* <p>Interceptors can, in addition to adding behaviour, divert the flow of execution. They do
* this by returning a {@link Resolution}. If an interceptor returns a Resolution Stripes will
* abort processing of the current request and immediately execute the Resolution.</p>
*
* <p>Interceptor developers must be careful to ensure that interceptors are well behaved. To
* continue normal processing interceptors <b>must invoke {@code context.proceed()}</b>. Since a
* given interceptor may be part of a stack of interceptors, or the lifecycle code may return
* a resolution, the interceptor must return the Resolution produced by {@code context.proceed()}
* unless it explicitly wishes to alter the flow of execution.</p>
*
* <p>Interceptors gain access to information about the current execution environment through
* the {@link ExecutionContext}. Through this they can access the ActionBean, the handler
* Method, the lifecycle stage etc. Care must be taken to ensure that information is available
* before using it. For example interceptors which execute around ActionBeanResolution will not
* have access to the current ActionBean until after calling context.proceed() and will not have
* access to the event name or handler method at all (HandlerResolution occurs after
* ActionBeanResolution).</p>
*
* <p>Optionally, Interceptor classes may implement the
* {@link net.sourceforge.stripes.config.ConfigurableComponent} interface. If implemented,
* the Interceptor will have its {@code init(Configuration)} method called after instantiation
* and before being placed into service.</p>
*
* <p>Interceptors are located by Stripes through its
* {@link net.sourceforge.stripes.config.Configuration}. To configure interceptors you can either
* implement your own Configuration (probably by subclassing
* {@link net.sourceforge.stripes.config.RuntimeConfiguration}), or more likely by listing out
* the interceptors desired in the web.xml as specified in the documentation for
* {@link net.sourceforge.stripes.config.RuntimeConfiguration#initInterceptors()}.</p>
*
* @author Tim Fennell
* @since Stripes 1.3
*/
public interface Interceptor {
/**
* Invoked when intercepting the flow of execution.
*
* @param context the ExecutionContext of the request currently being processed
* @return the result of calling context.proceed(), or if the interceptor wishes to change
* the flow of execution, a Resolution
* @throws Exception if any non-recoverable errors occur
*/
Resolution intercept(ExecutionContext context) throws Exception;
}