Commits

tm_jee  committed 8064df1

WW-1473
- RestfulActionMapper should return null for both getMapping(HttpServletRequest) and getUrlFromActionMapping(ActionMapping) method when it cannot handle the situation

git-svn-id: http://svn.opensymphony.com/svn/webwork/trunk@2949573baa09-0c28-0410-bef9-dab3c582ae83

  • Participants
  • Parent commits 07956e2

Comments (0)

Files changed (3)

File src/java/com/opensymphony/webwork/dispatcher/mapper/ActionMapper.java

  * HTTP requests (when shown in HTTP responses) must be in String form, a String is returned rather than an actual
  * request object.
  *
+ * <p/> ActionMapper should return null ({@link #getMapping(javax.servlet.http.HttpServletRequest)} and
+ * {@link #getUriFromActionMapping(ActionMapping)} if it cannot handle the context.
+ *
  * <!-- END SNIPPET: javadoc -->
+ *
+ * @author plightbo
+ * @author tmjee
+ *
+ * @version $Date$ $Id$
  */
 public interface ActionMapper {
+
+    /**
+     * Return the {@link ActionMapping} for the given {@link javax.servlet.http.HttpServletRequest}, the format of
+     * {@link javax.servlet.http.HttpServletRequest} url depends on the implementation of {@link ActionMapper}, eg.
+     * a {@link com.opensymphony.webwork.dispatcher.mapper.RestfulActionMapper} might handle it differently from
+     * {@link com.opensymphony.webwork.dispatcher.mapper.DefaultActionMapper}.
+     * <p/>
+     * Implementation should return null if it cannot handle the format of request (eg. if it is bad etc.) such that
+     * we could cascade {@link ActionMapping} together using
+     * {@link com.opensymphony.webwork.dispatcher.mapper.CompositeActionMapper}
+     *
+     * @param request
+     * @return ActionMapping
+     */
     ActionMapping getMapping(HttpServletRequest request);
 
+    /**
+     * Return the uri of the {@link com.opensymphony.webwork.dispatcher.mapper.ActionMapping} passed in as the argument.
+     * <p/>
+     * Implementation should return null if it cannot handle the format of request (eg. if it is bad etc.) such that
+     * we could cascade {@link ActionMapping} together using
+     * {@link com.opensymphony.webwork.dispatcher.mapper.CompositeActionMapper}
+     *
+     * @param mapping
+     * @return String
+     */
     String getUriFromActionMapping(ActionMapping mapping);
 }

File src/java/com/opensymphony/webwork/dispatcher/mapper/RestfulActionMapper.java

 import org.apache.commons.logging.LogFactory;
 
 import com.opensymphony.webwork.RequestUtils;
+import com.opensymphony.webwork.WebWorkConstants;
+import com.opensymphony.webwork.config.Configuration;
 
 import javax.servlet.http.HttpServletRequest;
 import java.net.URLDecoder;
  * Your action just needs a setArticleId() method, and requests such as /article/1, /article/2, etc will all map
  * to that URL pattern.
  * <p/>
+ * To invoke an action without any parameters, use:
+ * <ul>
+ * <tt>http://HOST/article/
+ * </ul>
+ * with a slash at the back, assuming 'article' is the action name.
+ * <p/>
  * <b>Note: The RestfulActionMapper is not supported if you use the (deprecated) ServletDispatcher!</b>
+ * <b>Note: The RestfulActionMapper doesn't takes into account the concept of namespace, hence actions
+ *          defined for RestfulActionMapper will have to resides in WebWork 'default' namespace.
  *
  * @author <a href="mailto:cameron@datacodex.net">Cameron Braid</a>
  * @author <a href="mailto:jerome.bernard@xtremejava.com">Jerome Bernard</a>
  * @author Patrick Lightbody
+ * @author tmjee
+ *
+ * @version $Date$ $Id$
  */
 public class RestfulActionMapper implements ActionMapper {
     protected static final Log LOG = LogFactory.getLog(RestfulActionMapper.class);
 
+    /**
+     * Attempt to return an {@link ActionMapping} for the supplied {@link javax.servlet.http.HttpServletRequest}.
+     * <p/>
+     * Since {@link com.opensymphony.webwork.dispatcher.mapper.RestfulActionMapper} doesn't take into
+     * account namespace, this method will not try to recognized the namespace from {@link javax.servlet.http.HttpServletRequest}
+     * but only the action name itself and its parameters as described in the javadoc of this {@link RestfulActionMapper}.
+     * <p/>
+     * This method will return null, if the {@link javax.servlet.http.HttpServletRequest} contains an extension eg.
+     * http://localhost:8080/context/someAction.action etc, because {@link com.opensymphony.webwork.dispatcher.mapper.RestfulActionMapper}'s
+     * url should not contains extension.
+     * <p/>
+     * These are such that {@link com.opensymphony.webwork.dispatcher.mapper.RestfulActionMapper} could fallback to other
+     * {@link com.opensymphony.webwork.dispatcher.mapper.ActionMapper} when used in conjuection with say a
+     * {@link com.opensymphony.webwork.dispatcher.mapper.CompositeActionMapper}.
+     *
+     * @param request
+     * @return ActionMapping
+     * @See {@link ActionMapper#getMapping(javax.servlet.http.HttpServletRequest)} 
+     */
     public ActionMapping getMapping(HttpServletRequest request) {
+
         String uri = RequestUtils.getServletPath(request);
+        if (uri.indexOf(".") != -1) {
+            // there's an extension eg. http://localhost:8080/context/someAction.action
+            // RestfulActionMapper doesn't deal with such situation, we'll return null and let the
+            // next ActionMapper eg. if a CompositeActionMapper is used, to kick in
+            return null;
+        }
+
+        if (LOG.isDebugEnabled())
+            LOG.debug("request (servlet path)="+uri);
 
         int nextSlash = uri.indexOf('/', 1);
         if (nextSlash == -1) {
             LOG.warn(e);
         }
 
+        LOG.debug("actionName="+actionName);
+        LOG.debug("params="+parameters.size());
+
         return new ActionMapping(actionName, "", "", parameters);
     }
 
+    /**
+     * Attempt to return a url, for the given {@link com.opensymphony.webwork.dispatcher.mapper.ActionMapping} passed in
+     * as its argument.
+     * <p/>
+     * This method wll return null if {@link ActionMapping} contains a non-null or non-empty namespace as
+     * {@link com.opensymphony.webwork.dispatcher.mapper.RestfulActionMapper} doesn't deal with namespace.
+     * <p/>
+     * These are such that {@link com.opensymphony.webwork.dispatcher.mapper.RestfulActionMapper} could fallback to other
+     * {@link com.opensymphony.webwork.dispatcher.mapper.ActionMapper} when used in conjuection with say a
+     * {@link com.opensymphony.webwork.dispatcher.mapper.CompositeActionMapper}.
+     *
+     * @param mapping
+     * @return String
+     */
     public String getUriFromActionMapping(ActionMapping mapping) {
-        String base = mapping.getNamespace() + mapping.getName();
-        for (Iterator iterator = mapping.getParams().entrySet().iterator(); iterator.hasNext();) {
-            Map.Entry entry = (Map.Entry) iterator.next();
-            String name = (String) entry.getKey();
-            if (name.equals(mapping.getName() + "Id")) {
-                base = base + "/" + entry.getValue();
-                break;
+        // RestfulActionMapper doesn't deals with mapping with namespace, if there's one, we'll
+        // return null, and let the next ActionMapper kicks in if say if a CompositeActionMapper
+        // is being used.
+        if ((mapping.getNamespace() == null) || (mapping.getNamespace().trim().length() <= 0)) {
+            String base = mapping.getName();
+            for (Iterator iterator = mapping.getParams().entrySet().iterator(); iterator.hasNext();) {
+                Map.Entry entry = (Map.Entry) iterator.next();
+                String name = (String) entry.getKey();
+                if (name.equals(mapping.getName() + "Id")) {
+                    base = base + "/" + entry.getValue();
+                    break;
+                }
             }
+            return base;
         }
-
-        return base;
+        return null;
     }
 }

File src/test/com/opensymphony/webwork/dispatcher/mapper/RestfulActionMapperTest.java

  * Unit test for {@link RestfulActionMapper}.
  *
  * @author Claus Ibsen
+ * @author tmjee
+ *
+ * @version $Date$ $Id$
  */
 public class RestfulActionMapperTest extends TestCase {
 
     public void testGetUri() {
         ActionMapping am = new ActionMapping();
         am.setName("view");
-        am.setNamespace("secure");
         am.setParams(Collections.EMPTY_MAP);
 
-        assertEquals("secureview", mapper.getUriFromActionMapping(am));
+        assertEquals("view", mapper.getUriFromActionMapping(am));
     }
 
     public void testGetUriParam() {
         param.put("article", "123");
         ActionMapping am = new ActionMapping();
         am.setName("view");
-        am.setNamespace("secure");
         am.setParams(param);
 
-        assertEquals("secureview", mapper.getUriFromActionMapping(am));
+        assertEquals("view", mapper.getUriFromActionMapping(am));
     }
 
     public void testGetUriParamId() {
         param.put("viewId", "456");
         ActionMapping am = new ActionMapping();
         am.setName("view");
-        am.setNamespace("secure");
         am.setParams(param);
 
-        assertEquals("secureview/456", mapper.getUriFromActionMapping(am));
+        assertEquals("view/456", mapper.getUriFromActionMapping(am));
     }
 
     public void testGetMappingNoSlash() throws Exception {