net.sourceforge.stripes.controller
Class AnnotatedClassActionResolver

java.lang.Object
  extended by net.sourceforge.stripes.controller.AnnotatedClassActionResolver
All Implemented Interfaces:
ConfigurableComponent, ActionResolver
Direct Known Subclasses:
NameBasedActionResolver

public class AnnotatedClassActionResolver
extends Object
implements ActionResolver

Uses Annotations on classes to identify the ActionBean that corresponds to the current request. ActionBeans are annotated with an @UrlBinding annotation, which denotes the web application relative URL that the ActionBean should respond to.

Individual methods on ActionBean classes are expected to be annotated with @HandlesEvent annotations, and potentially a @DefaultHandler annotation. Using these annotations the Resolver will determine which method should be executed for the current request.

Author:
Tim Fennell
See Also:
UrlBinding

Field Summary
static String PACKAGES
          Configuration key used to lookup a comma-separated list of package names.
 
Fields inherited from interface net.sourceforge.stripes.controller.ActionResolver
RESOLVED_ACTION
 
Constructor Summary
AnnotatedClassActionResolver()
           
 
Method Summary
protected  void addActionBean(Class<? extends ActionBean> clazz)
          Adds an ActionBean class to the set that this resolver can resolve.
protected  void assertGetContextWorks(ActionBean bean)
          Since many down stream parts of Stripes rely on the ActionBean properly returning the context it is given, we'll just test it up front.
protected  Set<Class<? extends ActionBean>> findClasses()
          Helper method to find implementations of ActionBean in the packages specified in Configuration using the ResolverUtil class.
 ActionBean getActionBean(ActionBeanContext context)
          Gets the logical name of the ActionBean that should handle the request.
 ActionBean getActionBean(ActionBeanContext context, String path)
          Returns the ActionBean class that is bound to the UrlBinding supplied.
 Collection<Class<? extends ActionBean>> getActionBeanClasses()
          Get all the classes implementing ActionBean that are recognized by this ActionResolver.
 Class<? extends ActionBean> getActionBeanType(String path)
          Fetches the Class representing the type of ActionBean that would respond were a request made with the path specified.
protected  Configuration getConfiguration()
          Provides subclasses with access to the configuration object.
 Method getDefaultHandler(Class<? extends ActionBean> bean)
          Returns the Method that is the default handler for events in the ActionBean class supplied.
 String getEventName(Class<? extends ActionBean> bean, ActionBeanContext context)
           Try various means to determine which event is to be executed on the current ActionBean.
protected  String getEventNameFromEventNameParam(Class<? extends ActionBean> bean, ActionBeanContext context)
          Looks to see if there is a single non-empty parameter value for the parameter name specified by StripesConstants.URL_KEY_EVENT_NAME.
protected  String getEventNameFromPath(Class<? extends ActionBean> bean, ActionBeanContext context)
          Looks to see if there is extra path information beyond simply the url binding of the bean.
protected  String getEventNameFromRequestAttribute(Class<? extends ActionBean> bean, ActionBeanContext context)
          Checks a special request attribute to get the event name.
protected  String getEventNameFromRequestParams(Class<? extends ActionBean> bean, ActionBeanContext context)
          Loops through the set of known events for the ActionBean to see if the event names are present as parameter names in the request.
 String getHandledEvent(Method handler)
          Responsible for determining the name of the event handled by this method, if indeed it handles one at all.
 Method getHandler(Class<? extends ActionBean> bean, String eventName)
          Uses the Maps constructed earlier to locate the Method which can handle the event.
protected  String getRequestedPath(HttpServletRequest request)
          Deprecated. Use HttpUtil.getRequestedPath(HttpServletRequest) instead.
 String getUrlBinding(Class<? extends ActionBean> clazz)
          Takes a class that implements ActionBean and returns the URL binding of that class.
 String getUrlBindingFromPath(String path)
          Returns the URL binding that is a substring of the path provided.
 void init(Configuration configuration)
          Scans the classpath of the current classloader (not including parents) to find implementations of the ActionBean interface.
protected  ActionBean makeNewActionBean(Class<? extends ActionBean> type, ActionBeanContext context)
          Helper method to construct and return a new ActionBean instance.
protected  void processMethods(Class<?> clazz, Map<String,Method> classMappings)
          Helper method that examines a class, starting at it's highest super class and working it's way down again, to find method annotations and ensure that child class annotations take precedence.
protected  void removeActionBean(Class<? extends ActionBean> clazz)
          Removes an ActionBean class from the set that this resolver can resolve.
protected  void setActionBeanContext(ActionBean bean, ActionBeanContext context)
          Calls ActionBean.setContext(ActionBeanContext) with the given context only if necessary.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

PACKAGES

public static final String PACKAGES
Configuration key used to lookup a comma-separated list of package names. The packages (and their sub-packages) will be scanned for implementations of ActionBean.

Since:
Stripes 1.5
See Also:
Constant Field Values
Constructor Detail

AnnotatedClassActionResolver

public AnnotatedClassActionResolver()
Method Detail

init

public void init(Configuration configuration)
          throws Exception
Scans the classpath of the current classloader (not including parents) to find implementations of the ActionBean interface. Examines annotations on the classes found to determine what forms and events they map to, and stores this information in a pair of maps for fast access during request processing.

Specified by:
init in interface ConfigurableComponent
Parameters:
configuration - the Configuration object being used by Stripes
Throws:
Exception - should be thrown if the component cannot be configured well enough to use.

addActionBean

protected void addActionBean(Class<? extends ActionBean> clazz)
Adds an ActionBean class to the set that this resolver can resolve. Identifies the URL binding and the events managed by the class and stores them in Maps for fast lookup.

Parameters:
clazz - a class that implements ActionBean

removeActionBean

protected void removeActionBean(Class<? extends ActionBean> clazz)
Removes an ActionBean class from the set that this resolver can resolve. The URL binding and the events managed by the class are removed from the cache.

Parameters:
clazz - a class that implements ActionBean

getUrlBindingFromPath

public String getUrlBindingFromPath(String path)
Returns the URL binding that is a substring of the path provided. For example, if there is an ActionBean bound to /user/Profile.action the path /user/Profile.action/view would return /user/Profile.action.

Specified by:
getUrlBindingFromPath in interface ActionResolver
Parameters:
path - the path being used to access an ActionBean, either in a form or link tag, or in a request that is hitting the DispatcherServlet.
Returns:
the UrlBinding of the ActionBean appropriate for the request, or null if the path supplied cannot be mapped to an ActionBean.

getUrlBinding

public String getUrlBinding(Class<? extends ActionBean> clazz)
Takes a class that implements ActionBean and returns the URL binding of that class. The default implementation retrieves the UrlBinding annotations and returns its value. Subclasses could do more complex things like parse the class and package names and construct a "default" binding when one is not specified.

Specified by:
getUrlBinding in interface ActionResolver
Parameters:
clazz - a class that implements ActionBean
Returns:
the UrlBinding or null if none can be determined

processMethods

protected void processMethods(Class<?> clazz,
                              Map<String,Method> classMappings)
Helper method that examines a class, starting at it's highest super class and working it's way down again, to find method annotations and ensure that child class annotations take precedence.


getHandledEvent

public String getHandledEvent(Method handler)
Responsible for determining the name of the event handled by this method, if indeed it handles one at all. By default looks for the HandlesEvent annotations and returns it's value if present.

Specified by:
getHandledEvent in interface ActionResolver
Parameters:
handler - a method that might or might not be a handler method
Returns:
the name of the event handled, or null

getActionBeanType

public Class<? extends ActionBean> getActionBeanType(String path)

Fetches the Class representing the type of ActionBean that would respond were a request made with the path specified. Checks to see if the full path matches any bean's UrlBinding. If no ActionBean matches then successively removes path segments (separated by slashes) from the end of the path until a match is found.

Specified by:
getActionBeanType in interface ActionResolver
Parameters:
path - the path segment of a URL
Returns:
the Class object for the type of action bean that will respond if a request is made using the path specified or null if no ActionBean matches.

getActionBean

public ActionBean getActionBean(ActionBeanContext context)
                         throws StripesServletException
Gets the logical name of the ActionBean that should handle the request. Implemented to look up the name of the form based on the name assigned to the form in the form tag, and encoded in a hidden field.

Specified by:
getActionBean in interface ActionResolver
Parameters:
context - the ActionBeanContext for the current request
Returns:
the name of the form to be used for this request
Throws:
StripesServletException - thrown if a ActionBean cannot be resolved for any reason

getRequestedPath

@Deprecated
protected String getRequestedPath(HttpServletRequest request)
Deprecated. Use HttpUtil.getRequestedPath(HttpServletRequest) instead.

Simple helper method that extracts the servlet path and any extra path info and puts them back together handling nulls correctly.

Parameters:
request - the current HttpServletRequest
Returns:
the servlet-context relative path that is being requested

getActionBean

public ActionBean getActionBean(ActionBeanContext context,
                                String path)
                         throws StripesServletException
Returns the ActionBean class that is bound to the UrlBinding supplied. If the action bean already exists in the appropriate scope (request or session) then the existing instance will be supplied. If not, then a new instance will be manufactured and have the supplied ActionBeanContext set on it.

Specified by:
getActionBean in interface ActionResolver
Parameters:
path - a URL to which an ActionBean is bound, or a path starting with the URL to which an ActionBean has been bound.
context - the current ActionBeanContext
Returns:
a Class for the ActionBean requested
Throws:
StripesServletException - if the UrlBinding does not match an ActionBean binding

setActionBeanContext

protected void setActionBeanContext(ActionBean bean,
                                    ActionBeanContext context)
Calls ActionBean.setContext(ActionBeanContext) with the given context only if necessary. Subclasses should use this method instead of setting the context directly because it can be somewhat tricky to determine when it needs to be done.

Parameters:
bean - The bean whose context may need to be set.
context - The context to pass to the bean if necessary.

assertGetContextWorks

protected void assertGetContextWorks(ActionBean bean)
                              throws StripesServletException
Since many down stream parts of Stripes rely on the ActionBean properly returning the context it is given, we'll just test it up front. Called after the bean is instantiated.

Parameters:
bean - the ActionBean to test to see if getContext() works correctly
Throws:
StripesServletException - if getContext() returns null

makeNewActionBean

protected ActionBean makeNewActionBean(Class<? extends ActionBean> type,
                                       ActionBeanContext context)
                                throws Exception
Helper method to construct and return a new ActionBean instance. Called whenever a new instance needs to be manufactured. Provides a convenient point for subclasses to add specific behaviour during action bean creation.

Parameters:
type - the type of ActionBean to create
context - the current ActionBeanContext
Returns:
the new ActionBean instance
Throws:
Exception - if anything goes wrong!

getEventName

public String getEventName(Class<? extends ActionBean> bean,
                           ActionBeanContext context)

Try various means to determine which event is to be executed on the current ActionBean. If a 'special' request attribute (StripesConstants.REQ_ATTR_EVENT_NAME) is present in the request, then return its value. This attribute is used to handle internal forwards, when request parameters are merged and cannot reliably determine the desired event name.

If that doesn't work, the value of a 'special' request parameter (StripesConstants.URL_KEY_EVENT_NAME) is checked to see if contains a single value matching an event name.

Failing that, search for a parameter in the request whose name matches one of the named events handled by the ActionBean. For example, if the ActionBean can handle events foo and bar, this method will scan the request for foo=somevalue and bar=somevalue. If it finds a request parameter with a matching name it will return that name. If there are multiple matching names, the result of this method cannot be guaranteed and a StripesRuntimeException will be thrown.

Finally, if the event name cannot be determined through the parameter names and there is extra path information beyond the URL binding of the ActionBean, it is checked to see if it matches an event name.

Specified by:
getEventName in interface ActionResolver
Parameters:
bean - the ActionBean type bound to the request
context - the ActionBeanContect for the current request
Returns:
String the name of the event submitted, or null if none can be found

getEventNameFromRequestAttribute

protected String getEventNameFromRequestAttribute(Class<? extends ActionBean> bean,
                                                  ActionBeanContext context)
Checks a special request attribute to get the event name. This attribute may be set when the presence of the original request parameters on a forwarded request makes it difficult to determine which event to fire.

Parameters:
bean - the ActionBean type bound to the request
context - the ActionBeanContect for the current request
Returns:
the name of the event submitted, or null if none can be found
See Also:
StripesConstants.REQ_ATTR_EVENT_NAME

getEventNameFromRequestParams

protected String getEventNameFromRequestParams(Class<? extends ActionBean> bean,
                                               ActionBeanContext context)
Loops through the set of known events for the ActionBean to see if the event names are present as parameter names in the request. Returns the first event name found in the request, or null if none is found.

Parameters:
bean - the ActionBean type bound to the request
context - the ActionBeanContext for the current request
Returns:
String the name of the event submitted, or null if none can be found

getEventNameFromPath

protected String getEventNameFromPath(Class<? extends ActionBean> bean,
                                      ActionBeanContext context)
Looks to see if there is extra path information beyond simply the url binding of the bean. If it does and the next /-separated part of the path matches one of the known event names for the bean, that event name will be returned, otherwise null.

Parameters:
bean - the ActionBean type bound to the request
context - the ActionBeanContect for the current request
Returns:
String the name of the event submitted, or null if none can be found

getEventNameFromEventNameParam

protected String getEventNameFromEventNameParam(Class<? extends ActionBean> bean,
                                                ActionBeanContext context)
Looks to see if there is a single non-empty parameter value for the parameter name specified by StripesConstants.URL_KEY_EVENT_NAME. If there is, and it matches a known event it is returned, otherwise returns null.

Parameters:
bean - the ActionBean type bound to the request
context - the ActionBeanContect for the current request
Returns:
String the name of the event submitted, or null if none can be found

getHandler

public Method getHandler(Class<? extends ActionBean> bean,
                         String eventName)
                  throws StripesServletException
Uses the Maps constructed earlier to locate the Method which can handle the event.

Specified by:
getHandler in interface ActionResolver
Parameters:
bean - the subclass of ActionBean that is bound to the request.
eventName - the name of the event being handled
Returns:
a Method object representing the handling method.
Throws:
StripesServletException - thrown when no method handles the named event.

getDefaultHandler

public Method getDefaultHandler(Class<? extends ActionBean> bean)
                         throws StripesServletException
Returns the Method that is the default handler for events in the ActionBean class supplied. If only one handler method is defined in the class, that is assumed to be the default. If there is more than one then the method marked with @DefaultHandler will be returned.

Specified by:
getDefaultHandler in interface ActionResolver
Parameters:
bean - the ActionBean type bound to the request
Returns:
Method object that should handle the request
Throws:
StripesServletException - if no default handler could be located

getConfiguration

protected Configuration getConfiguration()
Provides subclasses with access to the configuration object.


findClasses

protected Set<Class<? extends ActionBean>> findClasses()
Helper method to find implementations of ActionBean in the packages specified in Configuration using the ResolverUtil class.

Returns:
a set of Class objects that represent subclasses of ActionBean

getActionBeanClasses

public Collection<Class<? extends ActionBean>> getActionBeanClasses()
Get all the classes implementing ActionBean that are recognized by this ActionResolver.

Specified by:
getActionBeanClasses in interface ActionResolver


? Copyright 2005-2006, Stripes Development Team.