This is an automated email from the ASF dual-hosted git repository. kusal pushed a commit to branch WW-5406-excluded-patterns in repository https://gitbox.apache.org/repos/asf/struts.git
commit b27a28d2078742bbc95e711d8f844f9948e47e25 Author: Kusal Kithul-Godage <g...@kusal.io> AuthorDate: Mon Apr 8 23:03:42 2024 +1000 WW-5406 Ensure Action excluded patterns are reinjected --- .../org/apache/struts2/dispatcher/Dispatcher.java | 29 ++++++++++++++++++++++ .../apache/struts2/dispatcher/InitOperations.java | 25 +++---------------- .../struts2/dispatcher/PrepareOperations.java | 16 ++---------- .../filter/StrutsPrepareAndExecuteFilter.java | 6 +++-- .../dispatcher/filter/StrutsPrepareFilter.java | 6 +++-- 5 files changed, 42 insertions(+), 40 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java b/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java index 5bad0b4fe..8c7aa5e67 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java @@ -78,6 +78,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -88,6 +89,10 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Pattern; +import static java.util.Collections.emptyList; +import static java.util.Collections.unmodifiableList; +import static java.util.stream.Collectors.toList; + /** * A utility class the actual dispatcher delegates most of its tasks to. Each instance * of the primary dispatcher holds an instance of this dispatcher to be shared for @@ -162,6 +167,9 @@ public class Dispatcher { */ private Pattern multipartValidationPattern = Pattern.compile(MULTIPART_FORM_DATA_REGEX); + private String actionExcludedPatternsSeparator = ","; + private List<Pattern> actionExcludedPatterns = emptyList(); + /** * Provide list of default configuration files. */ @@ -340,6 +348,27 @@ public class Dispatcher { this.multipartValidationPattern = Pattern.compile(multipartValidationRegex); } + @Inject(value = StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN_SEPARATOR, required = false) + public void setActionExcludedPatternsSeparator(String separator) { + this.actionExcludedPatternsSeparator = separator; + } + + @Inject(value = StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN, required = false) + public void setActionExcludedPatterns(String excludedPatterns) { + this.actionExcludedPatterns = buildExcludedPatternsList(actionExcludedPatternsSeparator, actionExcludedPatternsSeparator); + } + + private static List<Pattern> buildExcludedPatternsList(String patterns, String separator) { + if (patterns == null || patterns.trim().isEmpty()) { + return emptyList(); + } + return unmodifiableList(Arrays.stream(patterns.split(separator)).map(String::trim).map(Pattern::compile).collect(toList())); + } + + public List<Pattern> getActionExcludedPatterns() { + return actionExcludedPatterns; + } + @Inject public void setValueStackFactory(ValueStackFactory valueStackFactory) { this.valueStackFactory = valueStackFactory; diff --git a/core/src/main/java/org/apache/struts2/dispatcher/InitOperations.java b/core/src/main/java/org/apache/struts2/dispatcher/InitOperations.java index 367aeba55..f5cf21a91 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/InitOperations.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/InitOperations.java @@ -19,10 +19,7 @@ package org.apache.struts2.dispatcher; import com.opensymphony.xwork2.ActionContext; -import org.apache.struts2.StrutsConstants; -import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -100,27 +97,11 @@ public class InitOperations { * @param dispatcher The dispatcher to check for exclude pattern configuration * @return a List of Patterns for request to exclude if apply, or <tt>null</tt> * @see org.apache.struts2.StrutsConstants#STRUTS_ACTION_EXCLUDE_PATTERN + * @deprecated since 6.4.0, use {@link Dispatcher#getActionExcludedPatterns()} instead. */ + @Deprecated public List<Pattern> buildExcludedPatternsList(Dispatcher dispatcher) { - String excludePatterns = dispatcher.getContainer().getInstance(String.class, StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN); - String separator = dispatcher.getContainer().getInstance(String.class, StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN_SEPARATOR); - if (separator == null) { - separator = ","; - } - return buildExcludedPatternsList(excludePatterns, separator); - } - - private List<Pattern> buildExcludedPatternsList(String patterns, String separator) { - if (null != patterns && patterns.trim().length() != 0) { - List<Pattern> list = new ArrayList<>(); - String[] tokens = patterns.split(separator); - for (String token : tokens) { - list.add(Pattern.compile(token.trim())); - } - return Collections.unmodifiableList(list); - } else { - return null; - } + return dispatcher.getActionExcludedPatterns(); } } diff --git a/core/src/main/java/org/apache/struts2/dispatcher/PrepareOperations.java b/core/src/main/java/org/apache/struts2/dispatcher/PrepareOperations.java index 6888c5b7a..f1ffd79f4 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/PrepareOperations.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/PrepareOperations.java @@ -32,8 +32,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; -import java.util.List; -import java.util.regex.Pattern; /** * Contains preparation operations for a request before execution @@ -223,21 +221,11 @@ public class PrepareOperations { * Check whether the request matches a list of exclude patterns. * * @param request The request to check patterns against - * @param excludedPatterns list of patterns for exclusion - * * @return <tt>true</tt> if the request URI matches one of the given patterns */ - public boolean isUrlExcluded(HttpServletRequest request, List<Pattern> excludedPatterns) { - if (excludedPatterns == null) { - return false; - } + public boolean isUrlExcluded(HttpServletRequest request) { String uri = RequestUtils.getUri(request); - for (Pattern pattern : excludedPatterns) { - if (pattern.matcher(uri).matches()) { - return true; - } - } - return false; + return dispatcher.getActionExcludedPatterns().stream().anyMatch(pattern -> pattern.matcher(uri).matches()); } /** diff --git a/core/src/main/java/org/apache/struts2/dispatcher/filter/StrutsPrepareAndExecuteFilter.java b/core/src/main/java/org/apache/struts2/dispatcher/filter/StrutsPrepareAndExecuteFilter.java index e91a1b9a8..e6343f91d 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/filter/StrutsPrepareAndExecuteFilter.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/filter/StrutsPrepareAndExecuteFilter.java @@ -50,6 +50,8 @@ public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter { protected PrepareOperations prepare; protected ExecuteOperations execute; + + @Deprecated protected List<Pattern> excludedPatterns; public void init(FilterConfig filterConfig) throws ServletException { @@ -62,7 +64,7 @@ public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter { prepare = createPrepareOperations(dispatcher); execute = createExecuteOperations(dispatcher); - // Note: Currently, excluded patterns are not refreshed following an XWork config reload + this.excludedPatterns = init.buildExcludedPatternsList(dispatcher); postInit(dispatcher, filterConfig); @@ -121,7 +123,7 @@ public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter { try { prepare.trackRecursion(request); String uri = RequestUtils.getUri(request); - if (prepare.isUrlExcluded(request, excludedPatterns)) { + if (prepare.isUrlExcluded(request)) { LOG.trace("Request: {} is excluded from handling by Struts, passing request to other filters", uri); chain.doFilter(request, response); } else { diff --git a/core/src/main/java/org/apache/struts2/dispatcher/filter/StrutsPrepareFilter.java b/core/src/main/java/org/apache/struts2/dispatcher/filter/StrutsPrepareFilter.java index 81dffb6a7..de90ac8cf 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/filter/StrutsPrepareFilter.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/filter/StrutsPrepareFilter.java @@ -43,6 +43,8 @@ public class StrutsPrepareFilter implements StrutsStatics, Filter { protected static final String REQUEST_EXCLUDED_FROM_ACTION_MAPPING = StrutsPrepareFilter.class.getName() + ".REQUEST_EXCLUDED_FROM_ACTION_MAPPING"; protected PrepareOperations prepare; + + @Deprecated protected List<Pattern> excludedPatterns; public void init(FilterConfig filterConfig) throws ServletException { @@ -53,7 +55,7 @@ public class StrutsPrepareFilter implements StrutsStatics, Filter { dispatcher = init.initDispatcher(config); prepare = createPrepareOperations(dispatcher); - // Note: Currently, excluded patterns are not refreshed following an XWork config reload + this.excludedPatterns = init.buildExcludedPatternsList(dispatcher); postInit(dispatcher, filterConfig); @@ -102,7 +104,7 @@ public class StrutsPrepareFilter implements StrutsStatics, Filter { boolean didWrap = false; try { prepare.trackRecursion(request); - if (prepare.isUrlExcluded(request, excludedPatterns)) { + if (prepare.isUrlExcluded(request)) { request.setAttribute(REQUEST_EXCLUDED_FROM_ACTION_MAPPING, true); } else { request.setAttribute(REQUEST_EXCLUDED_FROM_ACTION_MAPPING, false);