WW-5065 Defines a new flag to control appending params

This commit is contained in:
Lukasz Lenart
2020-04-22 07:59:13 +02:00
parent 5c82f0246e
commit 30b43044a3
7 changed files with 140 additions and 26 deletions
@@ -36,6 +36,9 @@ import java.util.*;
* @since 2.1
*/
public abstract class AbstractMatcher<E> implements Serializable {
private static final Logger LOG = LogManager.getLogger(AbstractMatcher.class);
/**
* <p> The logging instance </p>
*/
@@ -50,10 +53,23 @@ public abstract class AbstractMatcher<E> implements Serializable {
* <p> The compiled patterns and their associated target objects </p>
*/
List<Mapping<E>> compiledPatterns = new ArrayList<>();
;
/**
* This flag controls if passed named params should be appended
* to the map in {@link #replaceParameters(Map, Map)}
* and will be accessible in {@link com.opensymphony.xwork2.config.entities.ResultConfig}.
* If set to false, the named parameters won't be appended.
*
* This behaviour is controlled by {@link org.apache.struts2.StrutsConstants#STRUTS_MATCHER_APPEND_NAMED_PARAMETERS}
*
* @since 2.5.23
* See WW-5065
*/
private final boolean appendNamedParameters;
public AbstractMatcher(PatternMatcher<?> helper) {
public AbstractMatcher(PatternMatcher<?> helper, boolean appendNamedParameters) {
this.wildcard = (PatternMatcher<Object>) helper;
this.appendNamedParameters = appendNamedParameters;
}
/**
@@ -152,12 +168,23 @@ public abstract class AbstractMatcher<E> implements Serializable {
*/
protected Map<String,String> replaceParameters(Map<String, String> orig, Map<String,String> vars) {
Map<String, String> map = new LinkedHashMap<>();
//this will set the group index references, like {1}
for (Map.Entry<String,String> entry : orig.entrySet()) {
map.put(entry.getKey(), convertParam(entry.getValue(), vars));
}
if (appendNamedParameters) {
LOG.debug("Appending named parameters to the result map");
//the values map will contain entries like name->"Lex Luthor" and 1->"Lex Luthor"
//now add the non-numeric values
for (Map.Entry<String,String> entry: vars.entrySet()) {
if (!NumberUtils.isCreatable(entry.getKey())) {
map.put(entry.getKey(), entry.getValue());
}
}
}
return map;
}
@@ -58,7 +58,33 @@ public class ActionConfigMatcher extends AbstractMatcher<ActionConfig> implement
public ActionConfigMatcher(PatternMatcher<?> patternMatcher,
Map<String, ActionConfig> configs,
boolean looseMatch) {
super(patternMatcher);
this(patternMatcher, configs, looseMatch, true);
}
/**
* <p> Finds and precompiles the wildcard patterns from the ActionConfig
* "path" attributes. ActionConfig's will be evaluated in the order they
* exist in the config file. Only paths that actually contain a
* wildcard will be compiled. </p>
*
* <p>Patterns can optionally be matched "loosely". When
* the end of the pattern matches \*[^*]\*$ (wildcard, no wildcard,
* wildcard), if the pattern fails, it is also matched as if the
* last two characters didn't exist. The goal is to support the
* legacy "*!*" syntax, where the "!*" is optional.</p>
*
* @param patternMatcher pattern matcher
* @param configs An array of ActionConfig's to process
* @param looseMatch To loosely match wildcards or not
* @param appendNamedParameters To append named parameters or not
*
* @since 2.5.23
* See WW-5065
*/
public ActionConfigMatcher(PatternMatcher<?> patternMatcher,
Map<String, ActionConfig> configs,
boolean looseMatch, boolean appendNamedParameters) {
super(patternMatcher, appendNamedParameters);
for (Map.Entry<String, ActionConfig> entry : configs.entrySet()) {
addPattern(entry.getKey(), entry.getValue(), looseMatch);
}
@@ -289,6 +289,8 @@ public class DefaultConfiguration implements Configuration {
builder.constant(XWorkConstants.RELOAD_XML_CONFIGURATION, "false");
builder.constant(StrutsConstants.STRUTS_I18N_RELOAD, "false");
builder.constant(StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS, "true");
return builder.create(true);
}
@@ -338,8 +340,12 @@ public class DefaultConfiguration implements Configuration {
}
PatternMatcher<int[]> matcher = container.getInstance(PatternMatcher.class);
boolean appendNamedParameters = Boolean.parseBoolean(
container.getInstance(String.class, StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS)
);
return new RuntimeConfigurationImpl(Collections.unmodifiableMap(namespaceActionConfigs),
Collections.unmodifiableMap(namespaceConfigs), matcher);
Collections.unmodifiableMap(namespaceConfigs), matcher, appendNamedParameters);
}
private void setDefaultResults(Map<String, ResultConfig> results, PackageConfig packageContext) {
@@ -417,15 +423,18 @@ public class DefaultConfiguration implements Configuration {
public RuntimeConfigurationImpl(Map<String, Map<String, ActionConfig>> namespaceActionConfigs,
Map<String, String> namespaceConfigs,
PatternMatcher<int[]> matcher) {
PatternMatcher<int[]> matcher,
boolean appendNamedParameters)
{
this.namespaceActionConfigs = namespaceActionConfigs;
this.namespaceConfigs = namespaceConfigs;
this.namespaceActionConfigMatchers = new LinkedHashMap<>();
this.namespaceMatcher = new NamespaceMatcher(matcher, namespaceActionConfigs.keySet());
this.namespaceMatcher = new NamespaceMatcher(matcher, namespaceActionConfigs.keySet(), appendNamedParameters);
for (Map.Entry<String, Map<String, ActionConfig>> entry : namespaceActionConfigs.entrySet()) {
namespaceActionConfigMatchers.put(entry.getKey(), new ActionConfigMatcher(matcher, entry.getValue(), true));
ActionConfigMatcher configMatcher = new ActionConfigMatcher(matcher, entry.getValue(), true, appendNamedParameters);
namespaceActionConfigMatchers.put(entry.getKey(), configMatcher);
}
}
@@ -29,9 +29,23 @@ import java.util.Set;
* @since 2.1
*/
public class NamespaceMatcher extends AbstractMatcher<NamespaceMatch> {
public NamespaceMatcher(PatternMatcher<?> patternMatcher,
Set<String> namespaces) {
super(patternMatcher);
public NamespaceMatcher(PatternMatcher<?> patternMatcher, Set<String> namespaces) {
this(patternMatcher, namespaces, true);
}
/**
* Matches namespace strings against a wildcard pattern matcher
*
* @param patternMatcher pattern matcher
* @param namespaces A set of namespaces to process
* @param appendNamedParameters To append named parameters or not
*
* @since 2.5.23
* See WW-5065
*/
public NamespaceMatcher(PatternMatcher<?> patternMatcher, Set<String> namespaces, boolean appendNamedParameters) {
super(patternMatcher, appendNamedParameters);
for (String name : namespaces) {
if (!patternMatcher.isLiteral(name)) {
addPattern(name, new NamespaceMatch(name, null), false);
@@ -108,6 +108,7 @@ import com.opensymphony.xwork2.validator.DefaultValidatorFactory;
import com.opensymphony.xwork2.validator.DefaultValidatorFileParser;
import com.opensymphony.xwork2.validator.ValidatorFactory;
import com.opensymphony.xwork2.validator.ValidatorFileParser;
import com.sun.org.apache.xpath.internal.operations.Bool;
import ognl.MethodAccessor;
import ognl.PropertyAccessor;
import org.apache.struts2.StrutsConstants;
@@ -227,6 +228,7 @@ public class XWorkConfigurationProvider implements ConfigurationProvider {
props.setProperty(XWorkConstants.ENABLE_OGNL_EVAL_EXPRESSION, Boolean.FALSE.toString());
props.setProperty(XWorkConstants.RELOAD_XML_CONFIGURATION, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS, Boolean.TRUE.toString());
}
}
@@ -341,4 +341,7 @@ public final class StrutsConstants {
public static final String STRUTS_DISALLOW_PROXY_MEMBER_ACCESS = "struts.disallowProxyMemberAccess";
public static final String STRUTS_OGNL_AUTO_GROWTH_COLLECTION_LIMIT = "struts.ognl.autoGrowthCollectionLimit";
/** See {@link com.opensymphony.xwork2.config.impl.AbstractMatcher#appendNamedParameters */
public static final String STRUTS_MATCHER_APPEND_NAMED_PARAMETERS = "";
}
@@ -147,7 +147,7 @@ public class ActionConfigMatcherTest extends XWorkTestCase {
* Test to make sure the {@link AbstractMatcher#replaceParameters(Map, Map)} method isn't adding values to the
* return value.
*/
public void testReplaceParameters() {
public void testReplaceParametersWithNoAppendingParams() {
Map<String, ActionConfig> map = new HashMap<>();
HashMap<String, String> params = new HashMap<>();
@@ -162,25 +162,58 @@ public class ActionConfigMatcherTest extends XWorkTestCase {
.setStrictMethodInvocation(false)
.build();
map.put("foo/{one}/{two}/{three}", config);
ActionConfigMatcher replaceMatcher = new ActionConfigMatcher(new RegexPatternMatcher(), map, false);
ActionConfigMatcher replaceMatcher = new ActionConfigMatcher(new RegexPatternMatcher(), map, false, false);
ActionConfig matched = replaceMatcher.match("foo/paramOne/paramTwo/paramThree");
assertNotNull("ActionConfig should be matched", matched);
// Verify all The ActionConfig, ExceptionConfig, and ResultConfig have the correct number of params
assertTrue("The ActionConfig should have the correct number of params",
matched.getParams().size() == 1);
assertTrue("The ExceptionMappingConfigs should have the correct number of params",
matched.getExceptionMappings().get(0).getParams().size() == 1);
assertTrue("The ResultConfigs should have the correct number of params",
matched.getResults().get("successparamOne").getParams().size() == 1);
assertEquals("The ActionConfig should have the correct number of params", 1, matched.getParams().size());
assertEquals("The ExceptionMappingConfigs should have the correct number of params", 1, matched.getExceptionMappings().get(0).getParams().size());
assertEquals("The ResultConfigs should have the correct number of params", 1, matched.getResults().get("successparamOne").getParams().size());
// Verify the params are still getting their values replaced correctly
assertTrue("The ActionConfig params have replaced values",
"paramOne".equals(matched.getParams().get("first")));
assertTrue("The ActionConfig params have replaced values",
"paramOne".equals(matched.getExceptionMappings().get(0).getParams().get("first")));
assertTrue("The ActionConfig params have replaced values",
"paramOne".equals(matched.getResults().get("successparamOne").getParams().get("first")));
assertEquals("The ActionConfig params have replaced values", "paramOne", matched.getParams().get("first"));
assertEquals("The ActionConfig params have replaced values", "paramOne", matched.getExceptionMappings().get(0).getParams().get("first"));
assertEquals("The ActionConfig params have replaced values", "paramOne", matched.getResults().get("successparamOne").getParams().get("first"));
}
/**
* Test to make sure the {@link AbstractMatcher#replaceParameters(Map, Map)} method is adding values to the
* return value.
*/
public void testReplaceParametersWithAppendingParams() {
Map<String, ActionConfig> map = new HashMap<>();
HashMap<String, String> params = new HashMap<>();
params.put("first", "{1}");
ActionConfig config = new ActionConfig.Builder("package", "foo/{one}/{two}/{three}", "foo.bar.Action")
.addParams(params)
.addExceptionMapping(new ExceptionMappingConfig.Builder("foo{1}", "java.lang.{2}Exception", "success{1}")
.addParams(new HashMap<>(params))
.build())
.addResultConfig(new ResultConfig.Builder("success{1}", "foo.{2}").addParams(params).build())
.setStrictMethodInvocation(false)
.build();
map.put("foo/{one}/{two}/{three}", config);
ActionConfigMatcher replaceMatcher = new ActionConfigMatcher(new RegexPatternMatcher(), map, false, true);
ActionConfig matched = replaceMatcher.match("foo/paramOne/paramTwo/paramThree");
assertNotNull("ActionConfig should be matched", matched);
assertEquals(4, matched.getParams().size());
assertEquals(4, matched.getExceptionMappings().get(0).getParams().size());
assertEquals(4, matched.getResults().get("successparamOne").getParams().size());
// Verify the params are still getting their values replaced correctly
assertEquals("paramOne", matched.getParams().get("first"));
assertEquals("paramOne", matched.getParams().get("one"));
assertEquals("paramTwo", matched.getParams().get("two"));
assertEquals("paramThree", matched.getParams().get("three"));
assertEquals("paramOne", matched.getExceptionMappings().get(0).getParams().get("first"));
assertEquals("paramOne", matched.getExceptionMappings().get(0).getParams().get("one"));
assertEquals("paramTwo", matched.getExceptionMappings().get(0).getParams().get("two"));
assertEquals("paramThree", matched.getExceptionMappings().get(0).getParams().get("three"));
assertEquals("paramOne", matched.getResults().get("successparamOne").getParams().get("first"));
}
private Map<String,ActionConfig> buildActionConfigMap() {