You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2012/12/18 19:36:10 UTC
svn commit: r1423571 - in /struts/struts2/trunk/plugins/convention/src:
main/java/org/apache/struts2/convention/ConventionUnknownHandler.java
test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java
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;
}