diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java index 2695e2eb6..732e452aa 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java @@ -22,11 +22,14 @@ package org.apache.struts2.dispatcher.mapper; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Scanner; import java.util.Set; +import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; @@ -178,7 +181,7 @@ public class DefaultActionMapper implements ActionMapper { protected PrefixTrie prefixTrie = null; - protected List extensions = new ArrayList() {{ add("action");}}; + protected List extensions = new ArrayList() {{ add("action"); add("");}}; protected Container container; @@ -270,7 +273,12 @@ public class DefaultActionMapper implements ActionMapper { @Inject(StrutsConstants.STRUTS_ACTION_EXTENSION) public void setExtensions(String extensions) { if (!"".equals(extensions)) { - this.extensions = Arrays.asList(extensions.split(",")); + List list = new ArrayList(); + Scanner scanner = new Scanner(extensions).useDelimiter(","); + while (scanner.hasNext()) { + list.add(scanner.next()); + } + this.extensions = Collections.unmodifiableList(list); } else { this.extensions = null; } @@ -414,13 +422,18 @@ public class DefaultActionMapper implements ActionMapper { if (extensions == null) { return name; } - Iterator it = extensions.iterator(); - while (it.hasNext()) { - String extension = "." + (String) it.next(); - if (name.endsWith(extension)) { - name = name.substring(0, name.length() - extension.length()); - return name; - } + for (String ext : extensions) { + if ("".equals(ext)) { + if (name.indexOf('.') == -1) { + return name; + } + } else { + String extension = "." + ext; + if (name.endsWith(extension)) { + name = name.substring(0, name.length() - extension.length()); + return name; + } + } } return null; } diff --git a/core/src/main/resources/org/apache/struts2/default.properties b/core/src/main/resources/org/apache/struts2/default.properties index d6ddbb158..921400da4 100644 --- a/core/src/main/resources/org/apache/struts2/default.properties +++ b/core/src/main/resources/org/apache/struts2/default.properties @@ -73,7 +73,9 @@ struts.multipart.maxSize=2097152 ### Used by the DefaultActionMapper ### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do -struts.action.extension=action +### The blank extension allows you to match directory listings as well as pure action names +### without interfering with static resources. +struts.action.extension=action,, ### Used by FilterDispatcher ### If true then Struts serves static content from inside its jar. diff --git a/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java b/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java index 1861b9707..a17a16493 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java @@ -132,8 +132,8 @@ public class FilterDispatcherTest extends StrutsTestCase { return _dispatcher; } }; - filter.setActionMapper(null); filter.init(filterConfig); + filter.setActionMapper(null); filter.doFilter(req, res, chain); assertFalse(_dispatcher.serviceRequest); diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java index f942e0aa8..6b4236740 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java @@ -411,6 +411,17 @@ public class DefaultActionMapperTest extends StrutsTestCase { assertTrue("Name not right: "+name, "foo.action".equals(name)); } + + public void testDropExtensionWhenBlank() throws Exception { + DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setExtensions("action,,"); + String name = mapper.dropExtension("foo.action"); + assertTrue("Name not right: "+name, "foo".equals(name)); + name = mapper.dropExtension("foo"); + assertTrue("Name not right: "+name, "foo".equals(name)); + assertNull(mapper.dropExtension("foo.bar")); + assertNull(mapper.dropExtension("foo.")); + } public void testGetUriFromActionMapper1() throws Exception { DefaultActionMapper mapper = new DefaultActionMapper();