Author: lukaszlenart
Date: Tue Dec 18 18:36:09 2012
New Revision: 1423571

URL: http://svn.apache.org/viewvc?rev=1423571&view=rev
Log:
WW-3925 adds better support for looking index action when user hits default 
namespace

Modified:
    
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java
    
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java

Modified: 
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java?rev=1423571&r1=1423570&r2=1423571&view=diff
==============================================================================
--- 
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java
 (original)
+++ 
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java
 Tue Dec 18 18:36:09 2012
@@ -66,7 +66,9 @@ import java.util.Map;
  * </p>
  */
 public class ConventionUnknownHandler implements UnknownHandler {
+
     private static final Logger LOG = 
LoggerFactory.getLogger(ConventionUnknownHandler.class);
+
     protected Configuration configuration;
     protected ObjectFactory objectFactory;
     protected ServletContext servletContext;
@@ -81,24 +83,24 @@ public class ConventionUnknownHandler im
     /**
      * Constructs the unknown handler.
      *
-     * @param   configuration The XWork configuration.
-     * @param   objectFactory The XWork object factory used to create result 
instances.
-     * @param   servletContext The servlet context used to help build the 
action configurations.
-     * @param   container The Xwork container
-     * @param   defaultParentPackageName The default XWork package that the 
unknown handler will use as
-     *          the parent package for new actions and results.
-     * @param   redirectToSlash A boolean parameter that controls whether or 
not this will handle
-     *          unknown actions in the same manner as Apache, Tomcat and other 
web servers. This
-     *          handling will send back a redirect for URLs such as /foo to 
/foo/ if there doesn't
-     *          exist an action that responds to /foo.
-     * @param   nameSeparator The character used as word separator in the 
action names. "-" by default
+     * @param configuration            The XWork configuration.
+     * @param objectFactory            The XWork object factory used to create 
result instances.
+     * @param servletContext           The servlet context used to help build 
the action configurations.
+     * @param container                The Xwork container
+     * @param defaultParentPackageName The default XWork package that the 
unknown handler will use as
+     *                                 the parent package for new actions and 
results.
+     * @param redirectToSlash          A boolean parameter that controls 
whether or not this will handle
+     *                                 unknown actions in the same manner as 
Apache, Tomcat and other web servers. This
+     *                                 handling will send back a redirect for 
URLs such as /foo to /foo/ if there doesn't
+     *                                 exist an action that responds to /foo.
+     * @param nameSeparator            The character used as word separator in 
the action names. "-" by default
      */
     @Inject
     public ConventionUnknownHandler(Configuration configuration, ObjectFactory 
objectFactory,
-            ServletContext servletContext, Container container,
-            @Inject("struts.convention.default.parent.package") String 
defaultParentPackageName,
-            @Inject("struts.convention.redirect.to.slash") String 
redirectToSlash,
-            @Inject("struts.convention.action.name.separator") String 
nameSeparator) {
+                                    ServletContext servletContext, Container 
container,
+                                    
@Inject("struts.convention.default.parent.package") String 
defaultParentPackageName,
+                                    
@Inject("struts.convention.redirect.to.slash") String redirectToSlash,
+                                    
@Inject("struts.convention.action.name.separator") String nameSeparator) {
         this.configuration = configuration;
         this.objectFactory = objectFactory;
         this.servletContext = servletContext;
@@ -116,7 +118,7 @@ public class ConventionUnknownHandler im
     }
 
     public ActionConfig handleUnknownAction(String namespace, String 
actionName)
-    throws XWorkException {
+            throws XWorkException {
         // Strip the namespace if it is just a slash
         if (namespace == null || "/".equals(namespace)) {
             namespace = "";
@@ -173,6 +175,14 @@ public class ConventionUnknownHandler im
                 // Otherwise, if the URL is /foo or /foo/ look for index pages 
in /foo/
                 actionConfig = buildActionConfig(resource.path, 
resultsByExtension.get(resource.ext));
             }
+
+            // try to find index action in current namespace or in default one
+            if (actionConfig == null) {
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Looking for action named [index] in namespace 
[#0] or in default namespace", namespace);
+                }
+                actionConfig = 
configuration.getRuntimeConfiguration().getActionConfig(namespace, "index");
+            }
         }
 
         return actionConfig;
@@ -181,9 +191,9 @@ public class ConventionUnknownHandler im
     /**
      * Finds a resource using the given path parts and all of the extensions 
in the map.
      *
-     * @param   resultsByExtension Map of extension to result type config 
objects.
-     * @param   parts The parts of the resource.
-     * @return  The resource path or null.
+     * @param resultsByExtension Map of extension to result type config 
objects.
+     * @param parts              The parts of the resource.
+     * @return The resource path or null.
      */
     protected Resource findResource(Map<String, ResultTypeConfig> 
resultsByExtension, String... parts) {
         for (String ext : resultsByExtension.keySet()) {
@@ -197,8 +207,9 @@ public class ConventionUnknownHandler im
                     return new Resource(canonicalPath, ext);
                 }
             } catch (MalformedURLException e) {
-                if (LOG.isErrorEnabled())
+                if (LOG.isErrorEnabled()) {
                     LOG.error("Unable to parse path to the web application 
resource [#0] skipping...", canonicalPath);
+                }
             }
         }
 
@@ -214,7 +225,7 @@ public class ConventionUnknownHandler im
     }
 
     protected ActionConfig buildActionConfig(String path, ResultTypeConfig 
resultTypeConfig) {
-        Map<String, ResultConfig> results = new HashMap<String,ResultConfig>();
+        Map<String, ResultConfig> results = new HashMap<String, 
ResultConfig>();
         HashMap<String, String> params = new HashMap<String, String>();
         if (resultTypeConfig.getParams() != null) {
             params.putAll(resultTypeConfig.getParams());
@@ -222,17 +233,17 @@ public class ConventionUnknownHandler im
         params.put(resultTypeConfig.getDefaultResultParam(), path);
 
         PackageConfig pkg = 
configuration.getPackageConfig(defaultParentPackageName);
-        List<InterceptorMapping> interceptors = 
InterceptorBuilder.constructInterceptorReference(pkg, 
pkg.getFullDefaultInterceptorRef(), Collections.EMPTY_MAP, null, objectFactory);
+        List<InterceptorMapping> interceptors = 
InterceptorBuilder.constructInterceptorReference(pkg, 
pkg.getFullDefaultInterceptorRef(), Collections.<String, String>emptyMap(), 
null, objectFactory);
         ResultConfig config = new ResultConfig.Builder(Action.SUCCESS, 
resultTypeConfig.getClassName()).
-            addParams(params).build();
+                addParams(params).build();
         results.put(Action.SUCCESS, config);
 
         return new ActionConfig.Builder(defaultParentPackageName, "execute", 
ActionSupport.class.getName()).
-            addInterceptors(interceptors).addResultConfigs(results).build();
+                
addInterceptors(interceptors).addResultConfigs(results).build();
     }
 
     private Result scanResultsByExtension(String ns, String actionName, String 
pathPrefix,
-            String resultCode, ActionContext actionContext) {
+                                          String resultCode, ActionContext 
actionContext) {
         Map<String, ResultTypeConfig> resultsByExtension = 
conventionsService.getResultTypesByExtension(parentPackage);
         Result result = null;
         for (String ext : resultsByExtension.keySet()) {
@@ -243,31 +254,31 @@ public class ConventionUnknownHandler im
                         fqan, ext, pathPrefix, resultCode);
             }
 
-            String path = string(pathPrefix, actionName, nameSeparator, 
resultCode, "." , ext);
+            String path = string(pathPrefix, actionName, nameSeparator, 
resultCode, ".", ext);
             result = findResult(path, resultCode, ext, actionContext, 
resultsByExtension);
             if (result != null) {
                 break;
             }
 
-            path = string(pathPrefix, actionName, "." , ext);
+            path = string(pathPrefix, actionName, ".", ext);
             result = findResult(path, resultCode, ext, actionContext, 
resultsByExtension);
             if (result != null) {
                 break;
             }
 
             // Issue #6 - Scan for result-code as page name
-            path = string(pathPrefix, resultCode, "." , ext);
+            path = string(pathPrefix, resultCode, ".", ext);
             result = findResult(path, resultCode, ext, actionContext, 
resultsByExtension);
             if (result != null) {
                 break;
             }
 
         }
-      return result;
+        return result;
     }
 
     public Result handleUnknownResult(ActionContext actionContext, String 
actionName,
-            ActionConfig actionConfig, String resultCode) throws 
XWorkException {
+                                      ActionConfig actionConfig, String 
resultCode) throws XWorkException {
 
         PackageConfig pkg = 
configuration.getPackageConfig(actionConfig.getPackageName());
         String ns = pkg.getNamespace();
@@ -290,7 +301,7 @@ public class ConventionUnknownHandler im
                     break;
                 }
 
-                path = string(pathPrefix, actionName, "/index." , ext);
+                path = string(pathPrefix, actionName, "/index.", ext);
                 result = findResult(path, resultCode, ext, actionContext, 
resultsByExtension);
                 if (result != null) {
                     break;
@@ -302,7 +313,7 @@ public class ConventionUnknownHandler im
             //try to find an action to chain to. If the source action is "foo" 
and
             //the result is "bar", we will try to find an action called 
"foo-bar"
             //in the same package
-            String chainedTo = new 
StringBuilder(actionName).append(nameSeparator).append(resultCode).toString();
+            String chainedTo = actionName + nameSeparator + resultCode;
             ActionConfig chainedToConfig = 
pkg.getActionConfigs().get(chainedTo);
             if (chainedToConfig != null) {
                 if (LOG.isTraceEnabled()) {
@@ -318,7 +329,7 @@ public class ConventionUnknownHandler im
     }
 
     protected Result findResult(String path, String resultCode, String ext, 
ActionContext actionContext,
-            Map<String, ResultTypeConfig> resultsByExtension) {
+                                Map<String, ResultTypeConfig> 
resultsByExtension) {
         try {
             boolean traceEnabled = LOG.isTraceEnabled();
             if (traceEnabled)
@@ -350,7 +361,7 @@ public class ConventionUnknownHandler im
     protected Result buildResult(String path, String resultCode, 
ResultTypeConfig config, ActionContext invocationContext) {
         String resultClass = config.getClassName();
 
-        Map<String,String> params = new LinkedHashMap<String,String>();
+        Map<String, String> params = new LinkedHashMap<String, String>();
         if (config.getParams() != null) {
             params.putAll(config.getParams());
         }
@@ -376,10 +387,10 @@ public class ConventionUnknownHandler im
      * Determines the result path prefix that the request URL is for, minus 
the action name. This includes
      * the base result location and the namespace, with all the slashes 
handled.
      *
-     * @param   actionConfig (Optional) The might be a ConventionActionConfig, 
from which we can get the
-     *          default base result location of that specific action.
-     * @param   namespace The current URL namespace.
-     * @return  The path prefix and never null.
+     * @param actionConfig (Optional) The might be a ConventionActionConfig, 
from which we can get the
+     *                     default base result location of that specific 
action.
+     * @param namespace    The current URL namespace.
+     * @return The path prefix and never null.
      */
     protected String determinePath(ActionConfig actionConfig, String 
namespace) {
         String finalPrefix = 
conventionsService.determineResultPath(actionConfig);
@@ -408,9 +419,9 @@ public class ConventionUnknownHandler im
     /**
      * Not used
      */
-       public Object handleUnknownActionMethod(Object action, String 
methodName) throws NoSuchMethodException {
-               throw null;
-       }
+    public Object handleUnknownActionMethod(Object action, String methodName) 
throws NoSuchMethodException {
+        throw null;
+    }
 
     public static class Resource {
         final String path;

Modified: 
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java?rev=1423571&r1=1423570&r2=1423571&view=diff
==============================================================================
--- 
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java
 (original)
+++ 
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java
 Tue Dec 18 18:36:09 2012
@@ -21,10 +21,22 @@
 package org.apache.struts2.convention;
 
 import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.RuntimeConfiguration;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
 import com.opensymphony.xwork2.config.entities.PackageConfig;
 import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
 import com.opensymphony.xwork2.inject.Container;
 import junit.framework.TestCase;
+import org.apache.struts2.dispatcher.ServletDispatcherResult;
+import org.easymock.EasyMock;
+
+import javax.servlet.ServletContext;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
 import static org.easymock.EasyMock.expect;
 import static org.easymock.classextension.EasyMock.createMock;
 import static org.easymock.classextension.EasyMock.createNiceMock;
@@ -32,13 +44,10 @@ import static org.easymock.classextensio
 import static org.easymock.classextension.EasyMock.replay;
 import static org.easymock.classextension.EasyMock.verify;
 
-import javax.servlet.ServletContext;
-import java.net.URL;
-import java.util.Map;
-import java.util.Set;
-import java.util.Iterator;
-
 public class ConventionUnknownHandlerTest extends TestCase {
+
+    private PackageConfig packageConfiguration;
+
     public void testCanonicalizeShouldReturnNullWhenPathIsNull() throws 
Exception {
         final ConventionUnknownHandler handler = conventionUnknownHandler();
 
@@ -59,6 +68,24 @@ public class ConventionUnknownHandlerTes
                 handler.canonicalize("/should/not/modify/single/slashes.ext"));
     }
 
+    public void testHandleUnknownActionPointToIndex() throws Exception {
+        // given
+        ServletContext servletContext = createStrictMock(ServletContext.class);
+        
expect(servletContext.getResource("/does-not-exist.jsp")).andReturn(null);
+        
expect(servletContext.getResource("/does-not-exist/index.jsp")).andReturn(null);
+        replay(servletContext);
+
+        ConventionUnknownHandler handler = 
conventionUnknownHandler(servletContext);
+
+        // when
+        ActionConfig config = handler.handleUnknownAction("", 
"/does-not-exist");
+
+        // then
+        assertNotNull(config);
+        assertEquals("", config.getPackageName());
+        assertEquals("index", config.getName());
+    }
+
     public void 
testFindResourceShouldReturnNullAfterTryingEveryExtensionWithoutSuccess() 
throws Exception {
         final ServletContext servletContext = 
createStrictMock(ServletContext.class);  // Verifies method call order
 
@@ -114,18 +141,31 @@ public class ConventionUnknownHandlerTes
     private Configuration configuration(final String packageName) {
         final Configuration mock = createNiceMock(Configuration.class);
 
-        final PackageConfig packageConfiguration = packageConfiguration();
+        packageConfiguration = packageConfiguration();
         
expect(mock.getPackageConfig(packageName)).andStubReturn(packageConfiguration);
+        RuntimeConfiguration runtime = 
createNiceMock(RuntimeConfiguration.class);
+        expect(runtime.getActionConfig("", "index")).andStubReturn(new 
ActionConfig.Builder("", "index", "").build());
+        expect(mock.getRuntimeConfiguration()).andStubReturn(runtime);
 
-        replay(mock);
+        replay(mock, runtime);
 
         return mock;
     }
 
     private Container container() {
         final Container mock = createNiceMock(Container.class);
+        ConventionsService service = 
EasyMock.createNiceMock(ConventionsService.class);
 
-        replay(mock);
+        expect(mock.getInstance(String.class, 
ConventionConstants.CONVENTION_CONVENTIONS_SERVICE)).andReturn("test");
+        expect(mock.getInstance(ConventionsService.class, 
"test")).andStubReturn(service);
+
+        ActionConfig actionConfig = null;
+        expect(service.determineResultPath(actionConfig)).andReturn("");
+        Map<String, ResultTypeConfig> results = new HashMap<String, 
ResultTypeConfig>();
+        results.put("jsp", new ResultTypeConfig.Builder("dispatcher", 
ServletDispatcherResult.class.getName()).build());
+        
expect(service.getResultTypesByExtension(packageConfiguration)).andReturn(results);
+
+        replay(mock, service);
 
         return mock;
     }


Reply via email to