View Javadoc

1   /*
2    * $Id: RestfulActionMapper.java 449367 2006-09-24 06:49:04Z mrdon $
3    *
4    * Copyright 2006 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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      /* (non-Javadoc)
62       * @see org.apache.struts2.dispatcher.mapper.ActionMapper#getMapping(javax.servlet.http.HttpServletRequest)
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              // check if we have the first parameter name
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     /* (non-Javadoc)
108      * @see org.apache.struts2.dispatcher.mapper.ActionMapper#getUriFromActionMapping(org.apache.struts2.dispatcher.mapper.ActionMapping)
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 }