Author: lukaszlenart Date: Tue Jun 22 09:37:57 2010 New Revision: 956835 URL: http://svn.apache.org/viewvc?rev=956835&view=rev Log: Solved WW-3260 - added prefix base mapper
Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/PrefixBasedActionMapper.java Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java?rev=956835&r1=956834&r2=956835&view=diff ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java Tue Jun 22 09:37:57 2010 @@ -150,6 +150,13 @@ public final class StrutsConstants { /** The org.apache.struts2.dispatcher.mapper.ActionMapper implementation class */ public static final String STRUTS_MAPPER_CLASS = "struts.mapper.class"; + /** + * A prefix based action mapper that is capable of delegating to other + * {...@link org.apache.struts2.dispatcher.mapper.ActionMapper}s based on the request's prefix + * You can specify different prefixes that will be handled by different mappers + */ + public static final String PREFIX_BASED_MAPPER_CONFIGURATION = "struts.mapper.prefixMapping"; + /** Whether the Struts filter should serve static content or not */ public static final String STRUTS_SERVE_STATIC_CONTENT = "struts.serve.static"; Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/PrefixBasedActionMapper.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/PrefixBasedActionMapper.java?rev=956835&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/PrefixBasedActionMapper.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/PrefixBasedActionMapper.java Tue Jun 22 09:37:57 2010 @@ -0,0 +1,133 @@ +package org.apache.struts2.dispatcher.mapper; + +import java.util.HashMap; +import java.util.Map; +import java.util.Arrays; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.opensymphony.xwork2.config.ConfigurationManager; +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.inject.Inject; +import org.apache.struts2.StrutsConstants; + +/** + * + * A prefix based action mapper that is capable of delegating to other {...@link ActionMapper}s based on the request's prefix + * + * It is configured through struts.xml + * + * For example, with the following entries in struts.properties + * + * <pre> + * <constant name="struts.mapper.class" value="org.apache.struts2.dispatcher.mapper.PrefixBasedActionMapper"/> + * <constant name="struts.mapper.prefixMapping" value="/communities:pseudoRestful,/communityTags:pseudoRestful,/events:pseudoRestful,/mediaList:pseudoRestful,/users:pseudoRestful,/community:struts,/communityTag:struts,/event:struts,/media:struts,/user:struts,:struts"/> + * </pre> + * <p/> + * When {...@link PrefixBasedActionMapper#getMapping(HttpServletRequest, ConfigurationManager)} or + * {...@link PrefixBasedActionMapper#getUriFromActionMapping(ActionMapping)} is invoked, + * {...@link PrefixBasedActionMapper} will check each possible prefix (url prefix terminating just before a /) to find the most specific ActionMapper that returns a mapping when asked to map the request. If none are found, null is returned for both + * {...@link PrefixBasedActionMapper#getMapping(HttpServletRequest, ConfigurationManager)} and + * {...@link PrefixBasedActionMapper#getUriFromActionMapping(ActionMapping)} methods. + * <p/> + * + * @see ActionMapper + * @see ActionMapping + * + */ +public class PrefixBasedActionMapper extends DefaultActionMapper implements ActionMapper { + protected transient final Log log = LogFactory.getLog(getClass()); + protected Container container; + protected Map<String,ActionMapper> actionMappers = new HashMap<String,ActionMapper>(); + + @Inject + public void setContainer(Container container) { + this.container = container; + } + + @Inject(StrutsConstants.PREFIX_BASED_MAPPER_CONFIGURATION) + public void setPrefixBasedActionMappers(String list) { + if (list != null) { + String[] mappers = list.split(","); + for (String mapper : mappers) { + String[] thisMapper = mapper.split(":"); + if ((thisMapper != null) && (thisMapper.length == 2)) { + String mapperPrefix = thisMapper[0].trim(); + String mapperName = thisMapper[1].trim(); + Object obj = container.getInstance(ActionMapper.class, mapperName); + if (obj != null) { + actionMappers.put(mapperPrefix, (ActionMapper) obj); + } else if (log.isDebugEnabled()) { + log.debug("invalid PrefixBasedActionMapper config entry: " + mapper); + } + } + } + } + } + + + @SuppressWarnings("unchecked") + public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) { + String uri = getUri(request); + for (int lastIndex = uri.lastIndexOf('/'); lastIndex > (-1); lastIndex = uri.lastIndexOf('/', lastIndex-1)) { + ActionMapper actionMapper = actionMappers.get(uri.substring(0,lastIndex)); + if (actionMapper != null) { + ActionMapping actionMapping = actionMapper.getMapping(request, configManager); + if (log.isDebugEnabled()) { + log.debug("Using ActionMapper "+actionMapper); + } + if (actionMapping != null) { + if (log.isDebugEnabled()) { + if (actionMapping.getParams() != null) { + log.debug("ActionMapper found mapping. Parameters: "+actionMapping.getParams()); + for (Map.Entry<String,Object> mappingParameterEntry : ((Map<String,Object>)(actionMapping.getParams())).entrySet()) { + Object paramValue = mappingParameterEntry.getValue(); + if (paramValue == null) { + log.debug(mappingParameterEntry.getKey()+" : null!"); + } else if (paramValue instanceof String[]) { + log.debug(mappingParameterEntry.getKey()+" : (String[]) "+Arrays.toString((String[])paramValue)); + } else if (paramValue instanceof String) { + log.debug(mappingParameterEntry.getKey()+" : (String) "+(String)paramValue); + } else { + log.debug(mappingParameterEntry.getKey()+" : (Object) "+(paramValue.toString())); + } + } + } + } + return actionMapping; + } else if (log.isDebugEnabled()) { + log.debug("ActionMapper "+actionMapper+" failed to return an ActionMapping"); + } + } + } + if (log.isDebugEnabled()) { + log.debug("no ActionMapper found"); + } + return null; + } + + public String getUriFromActionMapping(ActionMapping mapping) { + String namespace = mapping.getNamespace(); + for (int lastIndex = namespace.length(); lastIndex > (-1); lastIndex = namespace.lastIndexOf('/', lastIndex-1)) { + ActionMapper actionMapper = actionMappers.get(namespace.substring(0,lastIndex)); + if (actionMapper != null) { + String uri = actionMapper.getUriFromActionMapping(mapping); + if (log.isDebugEnabled()) { + log.debug("Using ActionMapper "+actionMapper); + } + if (uri != null) { + return uri; + } else if (log.isDebugEnabled()) { + log.debug("ActionMapper "+actionMapper+" failed to return an ActionMapping (null)"); + } + } + } + if (log.isDebugEnabled()) { + log.debug("ActionMapper failed to return a uri"); + } + return null; + } +}