View Javadoc

    1   /*
    2    * $Id: RestfulActionMapper.java 471756 2006-11-06 15:01:43Z husted $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
    10   * with the License.  You may obtain a copy of the License at
    11   *
    12   *  http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing,
    15   * software distributed under the License is distributed on an
    16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    17   * KIND, either express or implied.  See the License for the
    18   * specific language governing permissions and limitations
    19   * under the License.
    20   */
    21  package org.apache.struts2.dispatcher.mapper;
    22
    23  import java.net.URLDecoder;
    24  import java.util.HashMap;
    25  import java.util.Iterator;
    26  import java.util.Map;
    27  import java.util.StringTokenizer;
    28
    29  import javax.servlet.http.HttpServletRequest;
    30
    31  import org.apache.commons.logging.Log;
    32  import org.apache.commons.logging.LogFactory;
    33  import org.apache.struts2.RequestUtils;
    34
    35  import com.opensymphony.xwork2.config.ConfigurationManager;
    36
    37
    38  /***
    39   * <!-- START SNIPPET: description -->
    40   *
    41   * A custom action mapper using the following format:
    42   * <p/>
    43   * <p/>
    44   * <ul><tt>http://HOST/ACTION_NAME/PARAM_NAME1/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
    45   * <p/>
    46   * You can have as many parameters you'd like to use. Alternatively the URL can be shortened to the following:
    47   * <p/>
    48   * <ul><tt>http://HOST/ACTION_NAME/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
    49   * <p/>
    50   * This is the same as:
    51   * <p/>
    52   * <ul><tt>http://HOST/ACTION_NAME/ACTION_NAME + "Id"/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2</tt></ul>
    53   * <p/>
    54   * Suppose for example we would like to display some articles by id at using the following URL sheme:
    55   * <p/>
    56   * <ul><tt>http://HOST/article/Id</tt></ul>
    57   * <p/>
    58   * <p/>
    59   * Your action just needs a setArticleId() method, and requests such as /article/1, /article/2, etc will all map
    60   * to that URL pattern.
    61   *
    62   * <!-- END SNIPPET: description -->
    63   *
    64   */
    65  public class RestfulActionMapper implements ActionMapper {
    66      protected static final Log LOG = LogFactory.getLog(RestfulActionMapper.class);
    67
    68      /* (non-Javadoc)
    69       * @see org.apache.struts2.dispatcher.mapper.ActionMapper#getMapping(javax.servlet.http.HttpServletRequest)
    70       */
    71      public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
    72          String uri = RequestUtils.getServletPath(request);
    73
    74          int nextSlash = uri.indexOf('/', 1);
    75          if (nextSlash == -1) {
    76              return null;
    77          }
    78
    79          String actionName = uri.substring(1, nextSlash);
    80          HashMap<String,String> parameters = new HashMap<String,String>();
    81          try {
    82              StringTokenizer st = new StringTokenizer(uri.substring(nextSlash), "/");
    83              boolean isNameTok = true;
    84              String paramName = null;
    85              String paramValue;
    86
    87              // check if we have the first parameter name
    88              if ((st.countTokens() % 2) != 0) {
    89                  isNameTok = false;
    90                  paramName = actionName + "Id";
    91              }
    92
    93              while (st.hasMoreTokens()) {
    94                  if (isNameTok) {
    95                      paramName = URLDecoder.decode(st.nextToken(), "UTF-8");
    96                      isNameTok = false;
    97                  } else {
    98                      paramValue = URLDecoder.decode(st.nextToken(), "UTF-8");
    99
    100                     if ((paramName != null) && (paramName.length() > 0)) {
    101                         parameters.put(paramName, paramValue);
    102                     }
    103
    104                     isNameTok = true;
    105                 }
    106             }
    107         } catch (Exception e) {
    108             LOG.warn(e);
    109         }
    110
    111         return new ActionMapping(actionName, "", "", parameters);
    112     }
    113
    114     /* (non-Javadoc)
    115      * @see org.apache.struts2.dispatcher.mapper.ActionMapper#getUriFromActionMapping(org.apache.struts2.dispatcher.mapper.ActionMapping)
    116      */
    117     public String getUriFromActionMapping(ActionMapping mapping) {
    118         String base = mapping.getNamespace() + mapping.getName();
    119         for (Iterator iterator = mapping.getParams().entrySet().iterator(); iterator.hasNext();) {
    120             Map.Entry entry = (Map.Entry) iterator.next();
    121             String name = (String) entry.getKey();
    122             if (name.equals(mapping.getName() + "Id")) {
    123                 base = base + "/" + entry.getValue();
    124                 break;
    125             }
    126         }
    127
    128         return base;
    129     }
    130 }