DefaultActionMapperpublic class DefaultActionMapper extends Object implements ActionMapper
Default action mapper implementation, using the standard *.[ext] (where ext
usually "action") pattern. The extension is looked up from the Struts
configuration key struts.action.exection.
To help with dealing with buttons and other related requirements, this
mapper (and other {@link ActionMapper}s, we hope) has the ability to name a
button with some predefined prefix and have that button name alter the
execution behaviour. The four prefixes are:
- Method prefix - method:default
- Action prefix - action:dashboard
- Redirect prefix - redirect:cancel.jsp
- Redirect-action prefix - redirect-action:cancel
In addition to these four prefixes, this mapper also understands the
action naming pattern of foo!bar in either the extension form (eg:
foo!bar.action) or in the prefix form (eg: action:foo!bar). This syntax tells
this mapper to map to the action named foo and the method bar.
Method Prefix
With method-prefix, instead of calling baz action's execute() method (by
default if it isn't overriden in struts.xml to be something else), the baz
action's anotherMethod() will be called. A very elegant way determine which
button is clicked. Alternatively, one would have submit button set a
particular value on the action when clicked, and the execute() method decides
on what to do with the setted value depending on which button is clicked.
<!-- START SNIPPET: method-example -->
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="method:anotherMethod" value="Cancel"/>
</a:form>
<!-- END SNIPPET: method-example -->
Action prefix
With action-prefix, instead of executing baz action's execute() method (by
default if it isn't overriden in struts.xml to be something else), the
anotherAction action's execute() method (assuming again if it isn't overriden
with something else in struts.xml) will be executed.
<!-- START SNIPPET: action-example -->
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="action:anotherAction" value="Cancel"/>
</a:form>
<!-- END SNIPPET: action-example -->
Redirect prefix
With redirect-prefix, instead of executing baz action's execute() method (by
default it isn't overriden in struts.xml to be something else), it will get
redirected to, in this case to www.google.com. Internally it uses
ServletRedirectResult to do the task.
<!-- START SNIPPET: redirect-example -->
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="redirect:www.google.com" value="Cancel"/>
</a:form>
<!-- END SNIPPET: redirect-example -->
Redirect-action prefix
With redirect-action-prefix, instead of executing baz action's execute()
method (by default it isn't overriden in struts.xml to be something else), it
will get redirected to, in this case 'dashboard.action'. Internally it uses
ServletRedirectResult to do the task and read off the extension from the
struts.properties.
<!-- START SNIPPET: redirect-action-example -->
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="redirect-action:dashboard" value="Cancel"/>
</a:form>
<!-- END SNIPPET: redirect-action-example -->
|
Fields Summary |
---|
static final String | METHOD_PREFIX | static final String | ACTION_PREFIX | static final String | REDIRECT_PREFIX | static final String | REDIRECT_ACTION_PREFIX | private boolean | allowDynamicMethodCalls | private boolean | allowSlashesInActionNames | private boolean | alwaysSelectFullNamespace | private org.apache.struts2.util.PrefixTrie | prefixTrie | List | extensions | private com.opensymphony.xwork2.inject.Container | container |
Constructors Summary |
---|
public DefaultActionMapper()
prefixTrie = new PrefixTrie() {
{
put(METHOD_PREFIX, new ParameterAction() {
public void execute(String key, ActionMapping mapping) {
mapping
.setMethod(key
.substring(METHOD_PREFIX.length()));
}
});
put(ACTION_PREFIX, new ParameterAction() {
public void execute(String key, ActionMapping mapping) {
String name = key.substring(ACTION_PREFIX.length());
if (allowDynamicMethodCalls) {
int bang = name.indexOf('!");
if (bang != -1) {
String method = name.substring(bang + 1);
mapping.setMethod(method);
name = name.substring(0, bang);
}
}
mapping.setName(name);
}
});
put(REDIRECT_PREFIX, new ParameterAction() {
public void execute(String key, ActionMapping mapping) {
ServletRedirectResult redirect = new ServletRedirectResult();
container.inject(redirect);
redirect.setLocation(key.substring(REDIRECT_PREFIX
.length()));
mapping.setResult(redirect);
}
});
put(REDIRECT_ACTION_PREFIX, new ParameterAction() {
public void execute(String key, ActionMapping mapping) {
String location = key.substring(REDIRECT_ACTION_PREFIX
.length());
ServletRedirectResult redirect = new ServletRedirectResult();
container.inject(redirect);
String extension = getDefaultExtension();
if (extension != null) {
location += "." + extension;
}
redirect.setLocation(location);
mapping.setResult(redirect);
}
});
}
};
|
Methods Summary |
---|
java.lang.String | dropExtension(java.lang.String name)Drops the extension from the action name
if (extensions == null) {
return name;
}
Iterator it = extensions.iterator();
while (it.hasNext()) {
String extension = "." + (String) it.next();
if (name.endsWith(extension)) {
name = name.substring(0, name.length() - extension.length());
return name;
}
}
return null;
| java.lang.String | getDefaultExtension()Returns null if no extension is specified.
if (extensions == null) {
return null;
} else {
return (String) extensions.get(0);
}
| public ActionMapping | getMapping(javax.servlet.http.HttpServletRequest request, com.opensymphony.xwork2.config.ConfigurationManager configManager)
ActionMapping mapping = new ActionMapping();
String uri = getUri(request);
uri = dropExtension(uri);
if (uri == null) {
return null;
}
parseNameAndNamespace(uri, mapping, configManager);
handleSpecialParameters(request, mapping);
if (mapping.getName() == null) {
return null;
}
if (allowDynamicMethodCalls) {
// handle "name!method" convention.
String name = mapping.getName();
int exclamation = name.lastIndexOf("!");
if (exclamation != -1) {
mapping.setName(name.substring(0, exclamation));
mapping.setMethod(name.substring(exclamation + 1));
}
}
return mapping;
| java.lang.String | getUri(javax.servlet.http.HttpServletRequest request)Gets the uri from the request
// handle http dispatcher includes.
String uri = (String) request
.getAttribute("javax.servlet.include.servlet_path");
if (uri != null) {
return uri;
}
uri = RequestUtils.getServletPath(request);
if (uri != null && !"".equals(uri)) {
return uri;
}
uri = request.getRequestURI();
return uri.substring(request.getContextPath().length());
| public java.lang.String | getUriFromActionMapping(ActionMapping mapping)
StringBuffer uri = new StringBuffer();
uri.append(mapping.getNamespace());
if (!"/".equals(mapping.getNamespace())) {
uri.append("/");
}
String name = mapping.getName();
String params = "";
if (name.indexOf('?") != -1) {
params = name.substring(name.indexOf('?"));
name = name.substring(0, name.indexOf('?"));
}
uri.append(name);
if (null != mapping.getMethod() && !"".equals(mapping.getMethod())) {
uri.append("!").append(mapping.getMethod());
}
String extension = getDefaultExtension();
if (extension != null) {
if (uri.indexOf('." + extension) == -1) {
uri.append(".").append(extension);
if (params.length() > 0) {
uri.append(params);
}
}
}
return uri.toString();
| public void | handleSpecialParameters(javax.servlet.http.HttpServletRequest request, ActionMapping mapping)Special parameters, as described in the class-level comment, are searched
for and handled.
// handle special parameter prefixes.
Set<String> uniqueParameters = new HashSet<String>();
Map parameterMap = request.getParameterMap();
for (Iterator iterator = parameterMap.keySet().iterator(); iterator
.hasNext();) {
String key = (String) iterator.next();
// Strip off the image button location info, if found
if (key.endsWith(".x") || key.endsWith(".y")) {
key = key.substring(0, key.length() - 2);
}
// Ensure a parameter doesn't get processed twice
if (!uniqueParameters.contains(key)) {
ParameterAction parameterAction = (ParameterAction) prefixTrie
.get(key);
if (parameterAction != null) {
parameterAction.execute(key, mapping);
uniqueParameters.add(key);
break;
}
}
}
| public boolean | isSlashesInActionNames()
return allowSlashesInActionNames;
| void | parseNameAndNamespace(java.lang.String uri, ActionMapping mapping, com.opensymphony.xwork2.config.ConfigurationManager configManager)Parses the name and namespace from the uri
String namespace, name;
int lastSlash = uri.lastIndexOf("/");
if (lastSlash == -1) {
namespace = "";
name = uri;
} else if (lastSlash == 0) {
// ww-1046, assume it is the root namespace, it will fallback to
// default
// namespace anyway if not found in root namespace.
namespace = "/";
name = uri.substring(lastSlash + 1);
} else if (alwaysSelectFullNamespace) {
// Simply select the namespace as everything before the last slash
namespace = uri.substring(0, lastSlash);
name = uri.substring(lastSlash + 1);
} else {
// Try to find the namespace in those defined, defaulting to ""
Configuration config = configManager.getConfiguration();
String prefix = uri.substring(0, lastSlash);
namespace = "";
// Find the longest matching namespace, defaulting to the default
for (Iterator i = config.getPackageConfigs().values().iterator(); i
.hasNext();) {
String ns = ((PackageConfig) i.next()).getNamespace();
if (ns != null && prefix.startsWith(ns) && (prefix.length() == ns.length() || prefix.charAt(ns.length()) == '/")) {
if (ns.length() > namespace.length()) {
namespace = ns;
}
}
}
name = uri.substring(namespace.length() + 1);
}
if (!allowSlashesInActionNames && name != null) {
int pos = name.lastIndexOf('/");
if (pos > -1 && pos < name.length() - 1) {
name = name.substring(pos + 1);
}
}
mapping.setNamespace(namespace);
mapping.setName(name);
| public void | setAllowDynamicMethodCalls(java.lang.String allow)
allowDynamicMethodCalls = "true".equals(allow);
| public void | setAlwaysSelectFullNamespace(java.lang.String val)
this.alwaysSelectFullNamespace = "true".equals(val);
| public void | setContainer(com.opensymphony.xwork2.inject.Container container)
this.container = container;
| public void | setExtensions(java.lang.String extensions)
if (!"".equals(extensions)) {
this.extensions = Arrays.asList(extensions.split(","));
} else {
this.extensions = null;
}
| public void | setSlashesInActionNames(java.lang.String allow)
allowSlashesInActionNames = "true".equals(allow);
|
|