|
25 | 25 | import com.opensymphony.xwork2.ObjectFactory; |
26 | 26 | import com.opensymphony.xwork2.Result; |
27 | 27 | import com.opensymphony.xwork2.config.Configuration; |
| 28 | +import com.opensymphony.xwork2.config.ConfigurationException; |
28 | 29 | import com.opensymphony.xwork2.config.entities.ActionConfig; |
29 | 30 | import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig; |
30 | 31 | import com.opensymphony.xwork2.config.entities.InterceptorConfig; |
@@ -131,6 +132,103 @@ public void setUp() throws Exception { |
131 | 132 | .bind(); |
132 | 133 | } |
133 | 134 |
|
| 135 | + /** |
| 136 | + * Tests that duplicate @Action name detection works when execute() is annotated with @Action. |
| 137 | + * Before the fix for WW-4421, the duplicate check was inside a conditional block that was |
| 138 | + * skipped when execute() had an @Action annotation, allowing duplicate action names silently. |
| 139 | + * |
| 140 | + * @see <a href="https://issues.apache.org/jira/browse/WW-4421">WW-4421</a> |
| 141 | + */ |
| 142 | + public void testDuplicateActionNameWithAnnotatedExecute() { |
| 143 | + ResultTypeConfig defaultResult = new ResultTypeConfig.Builder("dispatcher", |
| 144 | + ServletDispatcherResult.class.getName()).defaultResultParam("location").build(); |
| 145 | + PackageConfig strutsDefault = makePackageConfig("struts-default", null, null, "dispatcher", |
| 146 | + new ResultTypeConfig[]{defaultResult}, null, null, null, true); |
| 147 | + |
| 148 | + final DummyContainer mockContainer = new DummyContainer(); |
| 149 | + Configuration configuration = new DefaultConfiguration() { |
| 150 | + @Override |
| 151 | + public Container getContainer() { |
| 152 | + return mockContainer; |
| 153 | + } |
| 154 | + }; |
| 155 | + configuration.addPackageConfig("struts-default", strutsDefault); |
| 156 | + |
| 157 | + ActionNameBuilder actionNameBuilder = new SEOActionNameBuilder("true", "-"); |
| 158 | + ObjectFactory of = new ObjectFactory(); |
| 159 | + of.setContainer(mockContainer); |
| 160 | + |
| 161 | + mockContainer.setActionNameBuilder(actionNameBuilder); |
| 162 | + mockContainer.setConventionsService(new ConventionsServiceImpl("")); |
| 163 | + |
| 164 | + PackageBasedActionConfigBuilder builder = new PackageBasedActionConfigBuilder( |
| 165 | + configuration, mockContainer, of, "false", "struts-default", "false"); |
| 166 | + builder.setActionPackages("org.apache.struts2.convention.duplicate.annotatedexecute"); |
| 167 | + builder.setActionSuffix("Action"); |
| 168 | + |
| 169 | + DefaultFileManagerFactory fileManagerFactory = new DefaultFileManagerFactory(); |
| 170 | + fileManagerFactory.setContainer(ActionContext.getContext().getContainer()); |
| 171 | + fileManagerFactory.setFileManager(new DefaultFileManager()); |
| 172 | + builder.setFileManagerFactory(fileManagerFactory); |
| 173 | + builder.setProviderAllowlist(new ProviderAllowlist()); |
| 174 | + |
| 175 | + try { |
| 176 | + builder.buildActionConfigs(); |
| 177 | + fail("Expected ConfigurationException for duplicate action names"); |
| 178 | + } catch (ConfigurationException e) { |
| 179 | + assertTrue("Exception message should mention duplicate action names", |
| 180 | + e.getMessage().contains("two methods with an action name annotation whose value is the same")); |
| 181 | + } |
| 182 | + } |
| 183 | + |
| 184 | + /** |
| 185 | + * Tests that duplicate @Action name detection works when execute() is NOT annotated with @Action. |
| 186 | + * This is a regression guard for WW-4421 — this case was already detected before the fix. |
| 187 | + * |
| 188 | + * @see <a href="https://issues.apache.org/jira/browse/WW-4421">WW-4421</a> |
| 189 | + */ |
| 190 | + public void testDuplicateActionNameWithoutAnnotatedExecute() { |
| 191 | + ResultTypeConfig defaultResult = new ResultTypeConfig.Builder("dispatcher", |
| 192 | + ServletDispatcherResult.class.getName()).defaultResultParam("location").build(); |
| 193 | + PackageConfig strutsDefault = makePackageConfig("struts-default", null, null, "dispatcher", |
| 194 | + new ResultTypeConfig[]{defaultResult}, null, null, null, true); |
| 195 | + |
| 196 | + final DummyContainer mockContainer = new DummyContainer(); |
| 197 | + Configuration configuration = new DefaultConfiguration() { |
| 198 | + @Override |
| 199 | + public Container getContainer() { |
| 200 | + return mockContainer; |
| 201 | + } |
| 202 | + }; |
| 203 | + configuration.addPackageConfig("struts-default", strutsDefault); |
| 204 | + |
| 205 | + ActionNameBuilder actionNameBuilder = new SEOActionNameBuilder("true", "-"); |
| 206 | + ObjectFactory of = new ObjectFactory(); |
| 207 | + of.setContainer(mockContainer); |
| 208 | + |
| 209 | + mockContainer.setActionNameBuilder(actionNameBuilder); |
| 210 | + mockContainer.setConventionsService(new ConventionsServiceImpl("")); |
| 211 | + |
| 212 | + PackageBasedActionConfigBuilder builder = new PackageBasedActionConfigBuilder( |
| 213 | + configuration, mockContainer, of, "false", "struts-default", "false"); |
| 214 | + builder.setActionPackages("org.apache.struts2.convention.duplicate.unannotatedexecute"); |
| 215 | + builder.setActionSuffix("Action"); |
| 216 | + |
| 217 | + DefaultFileManagerFactory fileManagerFactory = new DefaultFileManagerFactory(); |
| 218 | + fileManagerFactory.setContainer(ActionContext.getContext().getContainer()); |
| 219 | + fileManagerFactory.setFileManager(new DefaultFileManager()); |
| 220 | + builder.setFileManagerFactory(fileManagerFactory); |
| 221 | + builder.setProviderAllowlist(new ProviderAllowlist()); |
| 222 | + |
| 223 | + try { |
| 224 | + builder.buildActionConfigs(); |
| 225 | + fail("Expected ConfigurationException for duplicate action names"); |
| 226 | + } catch (ConfigurationException e) { |
| 227 | + assertTrue("Exception message should mention duplicate action names", |
| 228 | + e.getMessage().contains("two methods with an action name annotation whose value is the same")); |
| 229 | + } |
| 230 | + } |
| 231 | + |
134 | 232 | public void testActionPackages() throws MalformedURLException { |
135 | 233 | run("org.apache.struts2.convention.actions", null, null); |
136 | 234 | } |
@@ -352,7 +450,7 @@ private void run(String actionPackages, String packageLocators, String excludePa |
352 | 450 | expect(resultMapBuilder.build(GlobalResultAction.class, null, "global-result", globalResultPkg)).andReturn(results); |
353 | 451 | expect(resultMapBuilder.build(GlobalResultOverrideAction.class, null, "global-result-override", globalResultPkg)).andReturn(results); |
354 | 452 | expect(resultMapBuilder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "execute", Action.class), "action-level-results-names", resultPkg)).andReturn(results); |
355 | | - expect(resultMapBuilder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "noname", Action.class), "action-level-results-names", resultPkg)).andReturn(results); |
| 453 | + expect(resultMapBuilder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "noname", Action.class), "action-level-results-names-noname", resultPkg)).andReturn(results); |
356 | 454 |
|
357 | 455 | /* org.apache.struts2.convention.actions.resultpath */ |
358 | 456 | expect(resultMapBuilder.build(ClassLevelResultPathAction.class, null, "class-level-result-path", resultPathPkg)).andReturn(results); |
@@ -662,11 +760,12 @@ public Container getContainer() { |
662 | 760 | pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.result#struts-default#/result"); |
663 | 761 | assertNotNull(pkgConfig); |
664 | 762 | checkSmiValue(pkgConfig, strutsDefault, isSmiInheritanceEnabled); |
665 | | - assertEquals(7, pkgConfig.getActionConfigs().size()); |
| 763 | + assertEquals(8, pkgConfig.getActionConfigs().size()); |
666 | 764 | verifyActionConfig(pkgConfig, "class-level-result", ClassLevelResultAction.class, "execute", pkgConfig.getName()); |
667 | 765 | verifyActionConfig(pkgConfig, "class-level-results", ClassLevelResultsAction.class, "execute", pkgConfig.getName()); |
668 | 766 | verifyActionConfig(pkgConfig, "action-level-result", ActionLevelResultAction.class, "execute", pkgConfig.getName()); |
669 | 767 | verifyActionConfig(pkgConfig, "action-level-results", ActionLevelResultsAction.class, "execute", pkgConfig.getName()); |
| 768 | + verifyActionConfig(pkgConfig, "action-level-results-names-noname", ActionLevelResultsNamesAction.class, "noname", pkgConfig.getName()); |
670 | 769 | verifyActionConfig(pkgConfig, "inherited-result-extends", InheritedResultExtends.class, "execute", pkgConfig.getName()); |
671 | 770 |
|
672 | 771 | /* org.apache.struts2.convention.actions.resultpath */ |
|
0 commit comments