mirror of
https://github.com/apache/struts.git
synced 2026-08-11 01:27:14 +00:00
Merge pull request #912 from atlassian-forks/issue/WW-5408-add-option-to-not-fallback-to-empty-namespace-when-unresolved
WW-5408 add option to not fallback to empty namespace when unresolved
This commit is contained in:
@@ -36,6 +36,8 @@ import org.apache.commons.lang3.ClassUtils;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
|
||||
/**
|
||||
* Base JUnit TestCase to extend for XWork specific JUnit tests. Uses
|
||||
* the generic test setup for logic.
|
||||
@@ -56,9 +58,7 @@ public abstract class XWorkTestCase extends TestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
configurationManager = XWorkTestCaseHelper.setUp();
|
||||
configuration = configurationManager.getConfiguration();
|
||||
container = configuration.getContainer();
|
||||
actionProxyFactory = container.getInstance(ActionProxyFactory.class);
|
||||
reloadConfiguration(configurationManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,13 +66,17 @@ public abstract class XWorkTestCase extends TestCase {
|
||||
XWorkTestCaseHelper.tearDown(configurationManager);
|
||||
}
|
||||
|
||||
protected void loadConfigurationProviders(ConfigurationProvider... providers) {
|
||||
configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers);
|
||||
private void reloadConfiguration(ConfigurationManager configurationManager) {
|
||||
configuration = configurationManager.getConfiguration();
|
||||
container = configuration.getContainer();
|
||||
actionProxyFactory = container.getInstance(ActionProxyFactory.class);
|
||||
}
|
||||
|
||||
protected void loadConfigurationProviders(ConfigurationProvider... providers) {
|
||||
configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers);
|
||||
reloadConfiguration(configurationManager);
|
||||
}
|
||||
|
||||
protected void loadButSet(Map<String, ?> properties) {
|
||||
loadConfigurationProviders(new StubConfigurationProvider() {
|
||||
@Override
|
||||
@@ -115,4 +119,25 @@ public abstract class XWorkTestCase extends TestCase {
|
||||
.getContextMap();
|
||||
}
|
||||
|
||||
protected void setStrutsConstant(String constant, String value) {
|
||||
setStrutsConstant(singletonMap(constant, value));
|
||||
}
|
||||
|
||||
protected void setStrutsConstant(final Map<String, String> overwritePropeties) {
|
||||
configurationManager.addContainerProvider(new StubConfigurationProvider() {
|
||||
@Override
|
||||
public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
|
||||
for (Map.Entry<String, String> stringStringEntry : overwritePropeties.entrySet()) {
|
||||
props.setProperty(stringStringEntry.getKey(), stringStringEntry.getValue(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
});
|
||||
|
||||
configurationManager.reload();
|
||||
reloadConfiguration(configurationManager);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
@@ -459,9 +460,12 @@ public class DefaultConfiguration implements Configuration {
|
||||
boolean appendNamedParameters = Boolean.parseBoolean(
|
||||
container.getInstance(String.class, StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS)
|
||||
);
|
||||
boolean fallbackToEmptyNamespace = Boolean.parseBoolean(
|
||||
Optional.ofNullable(container.getInstance(String.class, StrutsConstants.STRUTS_ACTION_CONFIG_FALLBACK_TO_EMPTY_NAMESPACE)).orElse("true")
|
||||
);
|
||||
|
||||
return new RuntimeConfigurationImpl(Collections.unmodifiableMap(namespaceActionConfigs),
|
||||
Collections.unmodifiableMap(namespaceConfigs), matcher, appendNamedParameters);
|
||||
Collections.unmodifiableMap(namespaceConfigs), matcher, appendNamedParameters, fallbackToEmptyNamespace);
|
||||
}
|
||||
|
||||
private void setDefaultResults(Map<String, ResultConfig> results, PackageConfig packageContext) {
|
||||
@@ -536,14 +540,17 @@ public class DefaultConfiguration implements Configuration {
|
||||
private final Map<String, ActionConfigMatcher> namespaceActionConfigMatchers;
|
||||
private final NamespaceMatcher namespaceMatcher;
|
||||
private final Map<String, String> namespaceConfigs;
|
||||
private final boolean fallbackToEmptyNamespace;
|
||||
|
||||
public RuntimeConfigurationImpl(Map<String, Map<String, ActionConfig>> namespaceActionConfigs,
|
||||
Map<String, String> namespaceConfigs,
|
||||
PatternMatcher<int[]> matcher,
|
||||
boolean appendNamedParameters)
|
||||
boolean appendNamedParameters,
|
||||
boolean fallbackToEmptyNamespace)
|
||||
{
|
||||
this.namespaceActionConfigs = namespaceActionConfigs;
|
||||
this.namespaceConfigs = namespaceConfigs;
|
||||
this.fallbackToEmptyNamespace = fallbackToEmptyNamespace;
|
||||
|
||||
this.namespaceActionConfigMatchers = new LinkedHashMap<>();
|
||||
this.namespaceMatcher = new NamespaceMatcher(matcher, namespaceActionConfigs.keySet(), appendNamedParameters);
|
||||
@@ -583,14 +590,17 @@ public class DefaultConfiguration implements Configuration {
|
||||
}
|
||||
|
||||
// fail over to empty namespace
|
||||
if (config == null && StringUtils.isNotBlank(namespace)) {
|
||||
if (config == null && shouldFallbackToEmptyNamespace(namespace)) {
|
||||
config = findActionConfigInNamespace("", name);
|
||||
}
|
||||
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
private boolean shouldFallbackToEmptyNamespace(String namespace) {
|
||||
return StringUtils.isNotBlank(namespace) && ("/".equals(namespace) || fallbackToEmptyNamespace);
|
||||
}
|
||||
|
||||
private ActionConfig findActionConfigInNamespace(String namespace, String name) {
|
||||
ActionConfig config = null;
|
||||
if (namespace == null) {
|
||||
|
||||
@@ -230,6 +230,8 @@ public final class StrutsConstants {
|
||||
public static final String STRUTS_XWORKCONVERTER = "struts.xworkConverter";
|
||||
|
||||
public static final String STRUTS_ALWAYS_SELECT_FULL_NAMESPACE = "struts.mapper.alwaysSelectFullNamespace";
|
||||
/** Fallback to empty namespace when request namespace didn't match any in action configuration */
|
||||
public static final String STRUTS_ACTION_CONFIG_FALLBACK_TO_EMPTY_NAMESPACE = "struts.actionConfig.fallbackToEmptyNamespace";
|
||||
|
||||
/** The {@link com.opensymphony.xwork2.LocaleProviderFactory} implementation class */
|
||||
public static final String STRUTS_LOCALE_PROVIDER_FACTORY = "struts.localeProviderFactory";
|
||||
|
||||
@@ -90,6 +90,7 @@ public class ConstantConfig {
|
||||
private Boolean freemarkerWrapperAltMap;
|
||||
private BeanConfig xworkConverter;
|
||||
private Boolean mapperAlwaysSelectFullNamespace;
|
||||
private Boolean actionConfigFallbackToEmptyNamespace;
|
||||
private BeanConfig localeProviderFactory;
|
||||
private String mapperIdParameterName;
|
||||
private Boolean ognlAllowStaticFieldAccess;
|
||||
@@ -226,6 +227,7 @@ public class ConstantConfig {
|
||||
map.put(StrutsConstants.STRUTS_FREEMARKER_WRAPPER_ALT_MAP, Objects.toString(freemarkerWrapperAltMap, null));
|
||||
map.put(StrutsConstants.STRUTS_XWORKCONVERTER, beanConfToString(xworkConverter));
|
||||
map.put(StrutsConstants.STRUTS_ALWAYS_SELECT_FULL_NAMESPACE, Objects.toString(mapperAlwaysSelectFullNamespace, null));
|
||||
map.put(StrutsConstants.STRUTS_ACTION_CONFIG_FALLBACK_TO_EMPTY_NAMESPACE, Objects.toString(actionConfigFallbackToEmptyNamespace, null));
|
||||
map.put(StrutsConstants.STRUTS_LOCALE_PROVIDER_FACTORY, beanConfToString(localeProviderFactory));
|
||||
map.put(StrutsConstants.STRUTS_ID_PARAMETER_NAME, mapperIdParameterName);
|
||||
map.put(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, Objects.toString(ognlAllowStaticFieldAccess, null));
|
||||
@@ -814,6 +816,14 @@ public class ConstantConfig {
|
||||
this.mapperAlwaysSelectFullNamespace = mapperAlwaysSelectFullNamespace;
|
||||
}
|
||||
|
||||
public Boolean getActionConfigFallbackToEmptyNamespace() {
|
||||
return actionConfigFallbackToEmptyNamespace;
|
||||
}
|
||||
|
||||
public void setActionConfigFallbackToEmptyNamespace(Boolean actionConfigFallbackToEmptyNamespace) {
|
||||
this.actionConfigFallbackToEmptyNamespace = actionConfigFallbackToEmptyNamespace;
|
||||
}
|
||||
|
||||
public BeanConfig getLocaleProviderFactory() {
|
||||
return localeProviderFactory;
|
||||
}
|
||||
|
||||
@@ -215,6 +215,9 @@ struts.xslt.nocache=false
|
||||
### Whether to always select the namespace to be everything before the last slash or not
|
||||
struts.mapper.alwaysSelectFullNamespace=false
|
||||
|
||||
### Whether to fallback to empty namespace when request namespace does not match any in configuration
|
||||
struts.actionConfig.fallbackToEmptyNamespace=true
|
||||
|
||||
### Whether to allow static field access in OGNL expressions or not
|
||||
struts.ognl.allowStaticFieldAccess=true
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.opensymphony.xwork2.inject.ContainerBuilder;
|
||||
import com.opensymphony.xwork2.mock.MockInterceptor;
|
||||
import com.opensymphony.xwork2.test.StubConfigurationProvider;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.config.StrutsXmlConfigurationProvider;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
|
||||
@@ -239,6 +240,41 @@ public class ConfigurationTest extends XWorkTestCase {
|
||||
mockContainerProvider.verify();
|
||||
}
|
||||
|
||||
public void testGetActionConfigFallbackToEmptyNamespaceWhenNamespaceDontMatchAndEmptyNamespaceFallbackIsEnabled() {
|
||||
// struts.actionConfig.fallbackToEmptyNamespace default to true, so it is enabled
|
||||
RuntimeConfiguration configuration = configurationManager.getConfiguration().getRuntimeConfiguration();
|
||||
|
||||
// check namespace that doesn't match fallback to empty namespace
|
||||
ActionConfig actionConfig = configuration.getActionConfig("/something/that/is/not/in/the/namespace/config", "LazyFoo");
|
||||
assertEquals("default", actionConfig.getPackageName()); // fallback to empty namespace (package name is default)
|
||||
assertEquals("LazyFoo", actionConfig.getName());
|
||||
|
||||
// check non-empty namespace and name in config still matches
|
||||
assertNotNull(configuration.getActionConfig("includeTest", "Foo"));
|
||||
|
||||
// check root namespace and name in config still matches
|
||||
actionConfig = configuration.getActionConfig("/", "LazyFoo");
|
||||
assertEquals("default", actionConfig.getPackageName());
|
||||
assertEquals("LazyFoo", actionConfig.getName());
|
||||
}
|
||||
|
||||
public void testGetActionConfigReturnNullWhenNamespaceDontMatchAndEmptyNamespaceFallbackIsDisabled() {
|
||||
// set the struts.actionConfig.fallbackToEmptyNamespace to false and reload the configuration
|
||||
setStrutsConstant(StrutsConstants.STRUTS_ACTION_CONFIG_FALLBACK_TO_EMPTY_NAMESPACE, "false");
|
||||
RuntimeConfiguration configuration = configurationManager.getConfiguration().getRuntimeConfiguration();
|
||||
|
||||
// check namespace that doesn't match NOT fallback to empty namespace and return null
|
||||
assertNull(configuration.getActionConfig("/something/that/is/not/in/the/namespace/config", "LazyFoo"));
|
||||
|
||||
// check non-empty namespace and name in config still matches
|
||||
assertNotNull(configuration.getActionConfig("includeTest", "Foo"));
|
||||
|
||||
// check root namespace and name in config still matches
|
||||
ActionConfig actionConfig = configuration.getActionConfig("/", "LazyFoo");
|
||||
assertEquals("default", actionConfig.getPackageName());
|
||||
assertEquals("LazyFoo", actionConfig.getName());
|
||||
}
|
||||
|
||||
public void testInitForPackageProviders() {
|
||||
|
||||
loadConfigurationProviders(new StubConfigurationProvider() {
|
||||
|
||||
@@ -217,23 +217,9 @@ public class DebugTagTest extends AbstractUITagTest {
|
||||
/**
|
||||
* Overwrite the Struts Constant and reload container
|
||||
*/
|
||||
private void setStrutsConstant(final Map<String, String> overwritePropeties) {
|
||||
configurationManager.addContainerProvider(new StubConfigurationProvider() {
|
||||
@Override
|
||||
public boolean needsReload() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
|
||||
for (Map.Entry<String, String> stringStringEntry : overwritePropeties.entrySet()) {
|
||||
props.setProperty(stringStringEntry.getKey(), stringStringEntry.getValue(), null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
configurationManager.reload();
|
||||
container = configurationManager.getConfiguration().getContainer();
|
||||
@Override
|
||||
protected void setStrutsConstant(final Map<String, String> overwritePropeties) {
|
||||
super.setStrutsConstant(overwritePropeties);
|
||||
stack.getActionContext().withContainer(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user