001: package com.opensymphony.webwork.dispatcher.mapper;
002:
003: import org.apache.commons.logging.Log;
004: import org.apache.commons.logging.LogFactory;
005:
006: import com.opensymphony.webwork.RequestUtils;
007:
008: import javax.servlet.http.HttpServletRequest;
009: import java.net.URLDecoder;
010: import java.util.HashMap;
011: import java.util.Iterator;
012: import java.util.Map;
013: import java.util.StringTokenizer;
014:
015: /**
016: * A custom action mapper using the following format:
017: * <p/>
018: * <p/>
019: * <ul><tt>http://HOST/ACTION_NAME/PARAM_NAME1/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
020: * <p/>
021: * You can have as many parameters you'd like to use. Alternatively the URL can be shortened to the following:
022: * <p/>
023: * <ul><tt>http://HOST/ACTION_NAME/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
024: * <p/>
025: * This is the same as:
026: * <p/>
027: * <ul><tt>http://HOST/ACTION_NAME/ACTION_NAME + "Id"/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
028: * <p/>
029: * Suppose for example we would like to display some articles by id at using the following URL sheme:
030: * <p/>
031: * <ul><tt>http://HOST/article/Id</tt></ul>
032: * <p/>
033: * <p/>
034: * Your action just needs a setArticleId() method, and requests such as /article/1, /article/2, etc will all map
035: * to that URL pattern.
036: * <p/>
037: * <b>Note: The RestfulActionMapper is not supported if you use the (deprecated) ServletDispatcher!</b>
038: *
039: * @author <a href="mailto:cameron@datacodex.net">Cameron Braid</a>
040: * @author <a href="mailto:jerome.bernard@xtremejava.com">Jerome Bernard</a>
041: * @author Patrick Lightbody
042: */
043: public class RestfulActionMapper implements ActionMapper {
044: protected static final Log LOG = LogFactory
045: .getLog(RestfulActionMapper.class);
046:
047: public ActionMapping getMapping(HttpServletRequest request) {
048: String uri = RequestUtils.getServletPath(request);
049:
050: int nextSlash = uri.indexOf('/', 1);
051: if (nextSlash == -1) {
052: return null;
053: }
054:
055: String actionName = uri.substring(1, nextSlash);
056: HashMap parameters = new HashMap();
057: try {
058: StringTokenizer st = new StringTokenizer(uri
059: .substring(nextSlash), "/");
060: boolean isNameTok = true;
061: String paramName = null;
062: String paramValue;
063:
064: // check if we have the first parameter name
065: if ((st.countTokens() % 2) != 0) {
066: isNameTok = false;
067: paramName = actionName + "Id";
068: }
069:
070: while (st.hasMoreTokens()) {
071: if (isNameTok) {
072: paramName = URLDecoder.decode(st.nextToken(),
073: "UTF-8");
074: isNameTok = false;
075: } else {
076: paramValue = URLDecoder.decode(st.nextToken(),
077: "UTF-8");
078:
079: if ((paramName != null) && (paramName.length() > 0)) {
080: parameters.put(paramName, paramValue);
081: }
082:
083: isNameTok = true;
084: }
085: }
086: } catch (Exception e) {
087: LOG.warn(e);
088: }
089:
090: return new ActionMapping(actionName, "", "", parameters);
091: }
092:
093: public String getUriFromActionMapping(ActionMapping mapping) {
094: String base = mapping.getNamespace() + mapping.getName();
095: for (Iterator iterator = mapping.getParams().entrySet()
096: .iterator(); iterator.hasNext();) {
097: Map.Entry entry = (Map.Entry) iterator.next();
098: String name = (String) entry.getKey();
099: if (name.equals(mapping.getName() + "Id")) {
100: base = base + "/" + entry.getValue();
101: break;
102: }
103: }
104:
105: return base;
106: }
107: }
|