net.smartlab.web.DynaAction Maven / Gradle / Ivy
/*
* The SmartWeb Framework
* Copyright (C) 2004-2006
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* For further informations on the SmartWeb Framework please visit
*
* http://smartweb.sourceforge.net
*/
package net.smartlab.web;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections.FastHashMap;
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.config.MessageResourcesConfig;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.util.MessageResources;
/**
* This class represent the dynamic version of the basic Action class allowing
* a single class to define multiple actions.
*
* Each declared method respecting the PARAMETERS
signature and
* returning a String
or an ActionMapping
will be
* available as an action mapping in Struts.
*
* As an example both the following methods can be used in the struts
* configuration file as valid mappings.
*
*
* - public String myMethod (ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws Exception
* - public ActionMapping myOtherMethod (ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws Exception
*
*
* In addition this class supports the same features providen by the
* org.apache.struts.actions.LookupDispatchAction
but to distinguish
* between direct method naming and reverse lookup naming you have to prefix
* the reverse lookup mapping parameter with @
(at) character.
*
* @author rlogiacco
*/
public abstract class DynaAction extends Action {
/**
* Standard dynamic method parameters.
*/
public final static Class[] PARAMETERS = new Class[] {ActionForm.class, HttpServletRequest.class, HttpServletResponse.class, ActionMapping.class};
/**
* Mapping of exposed methods.
*/
private final Map methods = new FastHashMap();
/**
* Mapping of locales to resource messages for reverse lookup.
*/
private final Map locales = new HashMap();
/**
* Default constructor.
*/
public DynaAction() {
Method[] methods = this.getClass().getMethods();
for (int i = 0; i < methods.length; i++) {
if (Arrays.equals(methods[i].getParameterTypes(), PARAMETERS)) {
this.methods.put(methods[i].getName(), methods[i]);
}
}
((FastHashMap)this.methods).setFast(true);
}
/**
* @see net.smartlab.web.Action#execute(org.apache.struts.action.ActionForm,
* javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse, ActionMapping)
*/
protected ActionForward execute(ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("execute(" + mapping.getPath() + ") - start");
}
String method = mapping.getParameter();
if (mapping == null) {
throw new ActionException("action.parameter.null");
}
if (method.startsWith("@")) {
// Strip the leading char
method = method.substring(1);
// Dynamically find the method using the request parameter value
method = request.getParameter(method);
if (!methods.containsKey(method)) {
// Try to reverse resolve using the resource bundle
// Based on this request's Locale get the lookupMap
Map lookup = null;
Locale locale = request.getLocale();
boolean exists = true;
synchronized (locales) {
lookup = (Map)this.locales.get(locale);
if (lookup == null) {
exists = false;
lookup = new HashMap();
locales.put(locale, lookup);
}
}
if (!exists) {
synchronized (lookup) {
/*
* This is the first time this Locale is used so build
* the reverse lookup Map. Search for message keys in
* all configured MessageResources for the current
* module.
*/
ModuleConfig module = (ModuleConfig)request.getAttribute(Globals.MODULE_KEY);
MessageResourcesConfig[] messages = module.findMessageResourcesConfigs();
// Look through all module's MessageResources
for (int i = 0; i < messages.length; i++) {
MessageResources resources = this.getResources(request, messages[i].getKey());
// Look for method name in Messages
Iterator names = this.methods.keySet().iterator();
while (names.hasNext()) {
String name = (String)names.next();
String message = resources.getMessage(locale, name);
if ((message != null) && !lookup.containsKey(message)) {
// Found method name and haven't added to
// Map yet, so add the text
if (name.indexOf('.') > -1) {
// Strip out any dot
name = name.substring(name.lastIndexOf('.') + 1);
}
if (methods.containsKey(name)) {
lookup.put(message, name);
}
}
}
}
}
}
// Find the method
method = (String)lookup.get(method);
}
}
// Execute the specified method
if (logger.isTraceEnabled()) {
logger.trace(" method = " + method);
}
try {
Object forward = ((Method)methods.get(method)).invoke(this, new Object[] {form, request, response, mapping});
if (forward instanceof String) {
return mapping.findForward((String)forward);
} else {
return (ActionForward)forward;
}
} catch (InvocationTargetException ite) {
Throwable cause = ite.getTargetException();
if (cause instanceof Exception) {
throw (Exception)cause;
} else {
logger.debug("execute( " + mapping.getPath() + ") - error", cause);
throw new ActionException("action.error.method", cause);
}
} catch (Exception e) {
logger.debug("execute( " + mapping.getPath() + ") - error", e);
throw new ActionException("action.error.method.unknown", e);
}
}
/**
* Default method action used to simply forward requests to the resource mapped as success
.
*
* @return success
*/
public final String forward(ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) {
return "success";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy