package org.appfuse.webapp.action; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.converters.IntegerConverter; import org.apache.commons.beanutils.converters.LongConverter; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.Globals; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessages; import org.apache.struts.actions.DispatchAction; import org.appfuse.Constants; import org.appfuse.util.ConvertUtil; import org.appfuse.util.CurrencyConverter; import org.appfuse.util.DateConverter; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; /** * Implementation of Action that contains base methods for * Actions as well as determines with methods to call in subclasses. This class * uses the name of the button to determine which method to execute on the * Action.
* *For example look at the following two buttons:
* ** <html:submit property="method.findName"> * <bean:message key="email.find"/> * </html:submit> * * <html:submit property="method.findEmail"> * <bean:message key="email.find"/> * </html:submit> ** *
The name of the button is set with the property parameter, i.e., the * name of the first button is method.findName. The name of the second button * is method.findEmail.
* *As per HTML/HTTP, whatever submit button that is pushed causes only that * submit button's name to be sent as a request parameter to the action.
* *This action looks for the name by removing the prepender string "method.". * The remaining part of the string is the name of the method to execute, e.g., * pushing the first button will execute the findName method and the second * button will execute the findEmail method.
* *This class extends DispatchAction and allows methods to be sent as * regular GETs as well, i.e., <a href="emailAction.do?method=findEmail"/> * would cause the findEmail method to be executed just as it would in a * DispatchAction. Thus, you configure a ButtonNameDispatchAction exactly * the way you configure a DispatchAction, i.e., set the mapping parameter * to the name of the request parameter that holds the mehtod name.
* ** View Source * * @author Matt Raible * @author Rick Hightower (based on his ButtonNameDispatchAction) */ public class BaseAction extends DispatchAction { protected final Log log = LogFactory.getLog(getClass()); private static final Long defaultLong = null; static { ConvertUtils.register(new CurrencyConverter(), Double.class); ConvertUtils.register(new DateConverter(), Date.class); ConvertUtils.register(new DateConverter(), String.class); ConvertUtils.register(new LongConverter(defaultLong), Long.class); ConvertUtils.register(new IntegerConverter(defaultLong), Integer.class); } /** * Convenience method to get Spring-initialized beans * * @param name * @return Object bean from ApplicationContext */ public Object getBean(String name) { ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servlet.getServletContext()); return ctx.getBean(name); } /** * @see org.appfuse.util.ConvertUtil#convert(java.lang.Object) */ protected Object convert(Object o) throws Exception { return ConvertUtil.convert(o); } /** * @see org.appfuse.util.ConvertUtil#convertLists(java.lang.Object) */ protected Object convertLists(Object o) throws Exception { return ConvertUtil.convertLists(o); } /** * Convenience method to initialize messages in a subclass. * * @param request the current request * @return the populated (or empty) messages */ public ActionMessages getMessages(HttpServletRequest request) { ActionMessages messages = null; HttpSession session = request.getSession(); if (request.getAttribute(Globals.MESSAGE_KEY) != null) { messages = (ActionMessages) request.getAttribute(Globals.MESSAGE_KEY); saveMessages(request, messages); } else if (session.getAttribute(Globals.MESSAGE_KEY) != null) { messages = (ActionMessages) session.getAttribute(Globals.MESSAGE_KEY); saveMessages(request, messages); session.removeAttribute(Globals.MESSAGE_KEY); } else { messages = new ActionMessages(); } return messages; } /** * Gets the method name based on the mapping passed to it */ private String getActionMethodWithMapping(HttpServletRequest request, ActionMapping mapping) { return getActionMethod(request, mapping.getParameter()); } /** * Gets the method name based on the prepender passed to it. */ protected String getActionMethod(HttpServletRequest request, String prepend) { String name = null; // for backwards compatibility, try with no prepend first name = request.getParameter(prepend); if (name != null) { // trim any whitespace around - this might happen on buttons name = name.trim(); // lowercase first letter return name.replace(name.charAt(0), Character.toLowerCase(name.charAt(0))); } Enumeration e = request.getParameterNames(); while (e.hasMoreElements()) { String currentName = (String) e.nextElement(); if (currentName.startsWith(prepend + ".")) { if (log.isDebugEnabled()) { log.debug("calling method: " + currentName); } String[] parameterMethodNameAndArgs = StringUtils.split(currentName, "."); name = parameterMethodNameAndArgs[1]; break; } } return name; } /** * Override the execute method in DispatchAction to parse * URLs and forward to methods without parameters.
** This is based on the following system: *
*