Author: musachy Date: Wed Nov 26 13:09:54 2008 New Revision: 720977 URL: http://svn.apache.org/viewvc?rev=720977&view=rev Log: WW-2449 Support convention based action chaining
Added: struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/chain/ struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/chain/ChainedAction.java Modified: struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java Modified: struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java?rev=720977&r1=720976&r2=720977&view=diff ============================================================================== --- struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java (original) +++ struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/ConventionUnknownHandler.java Wed Nov 26 13:09:54 2008 @@ -288,6 +288,22 @@ } } + if (result == null && resultCode != null) { + //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("-").append(resultCode).toString(); + ActionConfig chainedToConfig = pkg.getActionConfigs().get(chainedTo); + if (chainedToConfig != null) { + if (LOG.isTraceEnabled()) { + LOG.trace("Action [#0] used as chain result for [#1] and result [#2]", chainedTo, actionName, resultCode); + } + + ResultTypeConfig chainResultType = pkg.getAllResultTypeConfigs().get("chain"); + result = buildResult(chainedTo, resultCode, chainResultType, actionContext); + } + } + return result; } Modified: struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java?rev=720977&r1=720976&r2=720977&view=diff ============================================================================== --- struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java (original) +++ struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java Wed Nov 26 13:09:54 2008 @@ -26,17 +26,16 @@ import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.verify; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.net.MalformedURLException; +import java.lang.reflect.Method; import junit.framework.TestCase; import org.apache.struts2.convention.actions.DefaultResultPathAction; import org.apache.struts2.convention.actions.NoAnnotationAction; import org.apache.struts2.convention.actions.Skip; +import org.apache.struts2.convention.actions.chain.ChainedAction; import org.apache.struts2.convention.actions.action.ActionNameAction; import org.apache.struts2.convention.actions.action.ActionNamesAction; import org.apache.struts2.convention.actions.action.SingleActionNameAction; @@ -71,6 +70,10 @@ import org.easymock.EasyMock; import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.Result; +import com.opensymphony.xwork2.ActionChainResult; +import com.opensymphony.xwork2.util.reflection.ReflectionException; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.entities.ActionConfig; import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig; @@ -84,6 +87,9 @@ import com.opensymphony.xwork2.inject.Container; import com.opensymphony.xwork2.inject.Scope.Strategy; import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; +import com.opensymphony.xwork2.ognl.OgnlUtil; + +import javax.servlet.ServletContext; /** * <p> @@ -91,15 +97,15 @@ * </p> */ public class PackageBasedActionConfigBuilderTest extends TestCase { - public void testActionPackages() { + public void testActionPackages() throws MalformedURLException { run("org.apache.struts2.convention.actions", null, null); } - public void testPackageLocators() { + public void testPackageLocators() throws MalformedURLException { run(null, "actions", null); } - private void run(String actionPackages, String packageLocators, String excludePackages) { + private void run(String actionPackages, String packageLocators, String excludePackages) throws MalformedURLException { //setup interceptors List<InterceptorConfig> defaultInterceptors = new ArrayList<InterceptorConfig>(); defaultInterceptors.add(makeInterceptorConfig("interceptor-1")); @@ -113,8 +119,10 @@ defaultInterceptorStacks.add(makeInterceptorStackConfig("stack-1", interceptor1, interceptor2)); //setup results - ResultTypeConfig[] defaultResults = new ResultTypeConfig[] { new ResultTypeConfig.Builder("dispatcher", - ServletDispatcherResult.class.getName()).defaultResultParam("location").build() }; + ResultTypeConfig[] defaultResults = new ResultTypeConfig[]{new ResultTypeConfig.Builder("dispatcher", + ServletDispatcherResult.class.getName()).defaultResultParam("location").build(), + new ResultTypeConfig.Builder("chain", + ActionChainResult.class.getName()).defaultResultParam("actionName").build()}; PackageConfig strutsDefault = makePackageConfig("struts-default", null, null, "dispatcher", defaultResults, defaultInterceptors, defaultInterceptorStacks); @@ -164,6 +172,8 @@ "/resultpath", strutsDefault, null); PackageConfig skipPkg = makePackageConfig("org.apache.struts2.convention.actions.skip#struts-default#/skip", "/skip", strutsDefault, null); + PackageConfig chainPkg = makePackageConfig("org.apache.struts2.convention.actions.chain#struts-default#/chain", + "/chain", strutsDefault, null); ResultMapBuilder resultMapBuilder = createStrictMock(ResultMapBuilder.class); checkOrder(resultMapBuilder, false); @@ -244,6 +254,10 @@ /* org.apache.struts2.convention.actions.skip */ expect(resultMapBuilder.build(Index.class, null, "index", skipPkg)).andReturn(results); + /* org.apache.struts2.convention.actions.chain */ + expect(resultMapBuilder.build(ChainedAction.class, getAnnotation(ChainedAction.class, "foo", Action.class), "foo", chainPkg)).andReturn(results); + expect(resultMapBuilder.build(ChainedAction.class, getAnnotation(ChainedAction.class, "bar", Action.class), "foo-bar", chainPkg)).andReturn(results); + EasyMock.replay(resultMapBuilder); Configuration configuration = new DefaultConfiguration() { @@ -469,6 +483,20 @@ verifyActionConfig(pkgConfig, "idx", org.apache.struts2.convention.actions.idx.Index.class, "execute", "org.apache.struts2.convention.actions.idx#struts-default#/idx"); + //test unknown handler automatic chaining + pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.chain#struts-default#/chain"); + ServletContext context = EasyMock.createNiceMock(ServletContext.class); + EasyMock.replay(context); + + ObjectFactory workingFactory = configuration.getContainer().getInstance(ObjectFactory.class); + ConventionUnknownHandler uh = new ConventionUnknownHandler(configuration, workingFactory, context, resultMapBuilder, new ConventionsServiceImpl(""), "struts-default", null); + ActionContext actionContext = new ActionContext(Collections.EMPTY_MAP); + + Result result = uh.handleUnknownResult(actionContext, "foo", pkgConfig.getActionConfigs().get("foo"), "bar"); + assertNotNull(result); + assertTrue(result instanceof ActionChainResult); + ActionChainResult chainResult = (ActionChainResult) result; + ActionChainResult chainResultToCompare = new ActionChainResult("/chain", "foo-bar", "bar"); } private void verifyActionConfig(PackageConfig pkgConfig, String actionName, Class<?> actionClass, @@ -560,7 +588,13 @@ ((ObjectFactory)obj).setReflectionProvider(new OgnlReflectionProvider() { @Override - public void setProperties(Map properties, Object o) { + public void setProperties(Map<String, String> properties, Object o) { + } + + public void setProperties(Map<String, String> properties, Object o, Map<String, Object> context, boolean throwPropertyExceptions) throws ReflectionException { + if (o instanceof ActionChainResult) { + ((ActionChainResult)o).setActionName(properties.get("actionName")); + } } }); } Added: struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/chain/ChainedAction.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/chain/ChainedAction.java?rev=720977&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/chain/ChainedAction.java (added) +++ struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/chain/ChainedAction.java Wed Nov 26 13:09:54 2008 @@ -0,0 +1,35 @@ +/* + * $Id: ActionNamesAction.java 655902 2008-05-13 15:15:12Z bpontarelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.convention.actions.chain; + +import org.apache.struts2.convention.annotation.Action; + +public class ChainedAction { + @Action("foo") + public String foo() { + return "bar"; + } + + @Action("foo-bar") + public String bar() { + return null; + } +}