1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.dispatcher.mapper;
19
20 import java.net.URLDecoder;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.StringTokenizer;
25
26 import javax.servlet.http.HttpServletRequest;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.struts2.RequestUtils;
31
32 import com.opensymphony.xwork2.config.ConfigurationManager;
33
34
35 /***
36 * A custom action mapper using the following format:
37 * <p/>
38 * <p/>
39 * <ul><tt>http://HOST/ACTION_NAME/PARAM_NAME1/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
40 * <p/>
41 * You can have as many parameters you'd like to use. Alternatively the URL can be shortened to the following:
42 * <p/>
43 * <ul><tt>http://HOST/ACTION_NAME/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
44 * <p/>
45 * This is the same as:
46 * <p/>
47 * <ul><tt>http://HOST/ACTION_NAME/ACTION_NAME + "Id"/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
48 * <p/>
49 * Suppose for example we would like to display some articles by id at using the following URL sheme:
50 * <p/>
51 * <ul><tt>http://HOST/article/Id</tt></ul>
52 * <p/>
53 * <p/>
54 * Your action just needs a setArticleId() method, and requests such as /article/1, /article/2, etc will all map
55 * to that URL pattern.
56 *
57 */
58 public class RestfulActionMapper implements ActionMapper {
59 protected static final Log LOG = LogFactory.getLog(RestfulActionMapper.class);
60
61
62
63
64 public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
65 String uri = RequestUtils.getServletPath(request);
66
67 int nextSlash = uri.indexOf('/', 1);
68 if (nextSlash == -1) {
69 return null;
70 }
71
72 String actionName = uri.substring(1, nextSlash);
73 HashMap<String,String> parameters = new HashMap<String,String>();
74 try {
75 StringTokenizer st = new StringTokenizer(uri.substring(nextSlash), "/");
76 boolean isNameTok = true;
77 String paramName = null;
78 String paramValue;
79
80
81 if ((st.countTokens() % 2) != 0) {
82 isNameTok = false;
83 paramName = actionName + "Id";
84 }
85
86 while (st.hasMoreTokens()) {
87 if (isNameTok) {
88 paramName = URLDecoder.decode(st.nextToken(), "UTF-8");
89 isNameTok = false;
90 } else {
91 paramValue = URLDecoder.decode(st.nextToken(), "UTF-8");
92
93 if ((paramName != null) && (paramName.length() > 0)) {
94 parameters.put(paramName, paramValue);
95 }
96
97 isNameTok = true;
98 }
99 }
100 } catch (Exception e) {
101 LOG.warn(e);
102 }
103
104 return new ActionMapping(actionName, "", "", parameters);
105 }
106
107
108
109
110 public String getUriFromActionMapping(ActionMapping mapping) {
111 String base = mapping.getNamespace() + mapping.getName();
112 for (Iterator iterator = mapping.getParams().entrySet().iterator(); iterator.hasNext();) {
113 Map.Entry entry = (Map.Entry) iterator.next();
114 String name = (String) entry.getKey();
115 if (name.equals(mapping.getName() + "Id")) {
116 base = base + "/" + entry.getValue();
117 break;
118 }
119 }
120
121 return base;
122 }
123 }