From 105b22fb9a4a02a1719f73cb035a8e249d876554 Mon Sep 17 00:00:00 2001 From: Brian Andle Date: Sat, 4 Jun 2022 18:03:57 -0700 Subject: [PATCH 001/143] WW-5184 - Add optional parameter value check to ParametersInterceptor --- .../interceptor/ParametersInterceptor.java | 137 +++++++++++++++++- .../ParametersInterceptorTest.java | 112 ++++++++++++++ 2 files changed, 246 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java index 781a8f3e5..21154d546 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java @@ -37,10 +37,14 @@ import org.apache.struts2.dispatcher.Parameter; import org.apache.struts2.dispatcher.HttpParameters; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import java.util.regex.Pattern; +import com.opensymphony.xwork2.util.TextParseUtil; /** * This interceptor sets all parameters on the value stack. @@ -62,6 +66,9 @@ public class ParametersInterceptor extends MethodFilterInterceptor { private ValueStackFactory valueStackFactory; private ExcludedPatternsChecker excludedPatterns; private AcceptedPatternsChecker acceptedPatterns; + private Set excludedValuePatterns = null; + private Set acceptedValuePatterns = null; + @Inject public void setValueStackFactory(ValueStackFactory valueStackFactory) { @@ -183,8 +190,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor { for (Map.Entry entry : params.entrySet()) { String parameterName = entry.getKey(); + boolean isAcceptableParameter = isAcceptableParameter(parameterName, action); + isAcceptableParameter &= isAcceptableParameterValue(entry.getValue()); - if (isAcceptableParameter(parameterName, action)) { + if (isAcceptableParameter) { acceptableParameters.put(parameterName, entry.getValue()); } } @@ -263,6 +272,23 @@ public class ParametersInterceptor extends MethodFilterInterceptor { ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware) ? (ParameterNameAware) action : null; return acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name)); } + + /** + * Checks if parameter value can be accepted or thrown away + * + * @param param the parameter + * @param action current action + * @return true if parameter is accepted + */ + protected boolean isAcceptableParameterValue(Parameter param) { + if(hasParamValuesToExclude() || hasParamValuesToAccept()) { + // We have something to check. + return acceptableValue(param.getName(), param.getValue()); + } else { + // No exclude/accept defined. Return true/allowed. + return true; + } + } /** * Gets an instance of the comparator to use for the ordered sorting. Override this @@ -290,7 +316,16 @@ public class ParametersInterceptor extends MethodFilterInterceptor { return logEntry.toString(); } - + + /** + * Validates the name passed is: + * * Within the max length of a parameter name + * * Is not excluded + * * Is accepted + * + * @param name - Name to check + * @return true if accepted + */ protected boolean acceptableName(String name) { if (isIgnoredDMI(name)) { LOG.trace("DMI is enabled, ignoring DMI method: {}", name); @@ -311,6 +346,24 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } } + /** + * Validates: + * * Value is null/blank + * * Value is not excluded + * * Value is accepted + * + * @param name - Param name (for logging) + * @param value - value to check + * @return true if accepted + */ + protected boolean acceptableValue(String name, String value) { + boolean accepted = (value == null || value.isEmpty() || (!isParamValueExcluded(value) && isParamValueAccepted(value))); + if (!accepted) { + LOG.info("Parameter [{}] was not accepted with value [{}] and will be dropped!", name, value); + } + return accepted; + } + protected boolean isWithinLengthLimit(String name) { boolean matchLength = name.length() <= paramNameMaxLength; if (!matchLength) { @@ -354,7 +407,86 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } return false; } + + public void setAcceptedValuePatterns(String commaDelimitedPatterns) { + Set patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns); + if (acceptedValuePatterns == null) { + // Limit unwanted log entries (for 1st call, acceptedValuePatterns null) + LOG.debug("Sets accepted value patterns to [{}], note this may impact the safety of your application!", patterns); + } else { + LOG.warn("Replacing accepted patterns [{}] with [{}], be aware that this affects all instances and may impact the safety of your application!", + acceptedValuePatterns, patterns); + } + acceptedValuePatterns = new HashSet<>(patterns.size()); + try { + for (String pattern : patterns) { + acceptedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); + } + } finally { + acceptedValuePatterns = Collections.unmodifiableSet(acceptedValuePatterns); + } + } + + public void setExcludeValuePatterns(String commaDelimitedPatterns) { + Set patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns); + if (excludedValuePatterns == null) { + // Limit unwanted log entries (for 1st call, excludedValuePatterns null) + LOG.debug("Setting excluded value patterns to [{}]", patterns); + } else { + LOG.warn("Replacing accepted patterns [{}] with [{}], be aware that this affects all instances and may impact safety of your application!", + excludedValuePatterns, patterns); + } + excludedValuePatterns = new HashSet<>(patterns.size()); + try { + for (String pattern : patterns) { + excludedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); + } + } finally { + excludedValuePatterns = Collections.unmodifiableSet(excludedValuePatterns); + } + } + + protected boolean isParamValueExcluded(String value) { + if (hasParamValuesToExclude()) { + for (Pattern excludedPattern : excludedValuePatterns) { + if (value != null) { + if (excludedPattern.matcher(value).matches()) { + LOG.info("Parameter value [{}] matches excluded pattern [{}] and will be dropped.", value, + excludedPattern); + return true; + } + } + } + } + return false; + } + + protected boolean isParamValueAccepted(String value) { + if (hasParamValuesToAccept()) { + for (Pattern excludedPattern : acceptedValuePatterns) { + if (value != null) { + if (excludedPattern.matcher(value).matches()) { + return true; + } + } + } + } else { + // acceptedValuePatterns not defined so anything is allowed + return true; + } + LOG.info("Parameter value [{}] did not match any acceptedValuePattern pattern and will be dropped.", value); + return false; + } + + private boolean hasParamValuesToExclude() { + return excludedValuePatterns != null && excludedValuePatterns.size() > 0; + } + + private boolean hasParamValuesToAccept() { + return acceptedValuePatterns != null && acceptedValuePatterns.size() > 0; + } + /** * Whether to order the parameters or not * @@ -396,5 +528,4 @@ public class ParametersInterceptor extends MethodFilterInterceptor { public void setExcludeParams(String commaDelim) { excludedPatterns.setExcludedPatterns(commaDelim); } - } diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java index 69d9b03a6..d26ceef81 100644 --- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java @@ -778,6 +778,118 @@ public class ParametersInterceptorTest extends XWorkTestCase { assertFalse(action.getBeanList().isEmpty()); } + public void testExcludedParametersValuesAreIgnored() throws Exception { + ParametersInterceptor pi = createParametersInterceptor(); + // Contains (based on pattern) + pi.setExcludeValuePatterns(".*\\$\\{.*?\\}.*,.*%\\{.*?\\}.*"); + + assertTrue("${2*2} was excluded by isParamValueExcluded", pi.isParamValueExcluded("${2*2}")); + + final Map actual = injectValueStackFactory(pi); + ValueStack stack = injectValueStack(actual); + + final Map expected = new HashMap() { + { + put("fooKey", "fooValue"); + put("fooKey2", ""); + } + }; + + Map parameters = new HashMap() { + { + put("barKey$", "${2+2}"); + put("barKey2$", "foo${2+2}"); + put("barKey3$", "foo${2+2}foo"); + put("barKey%", "%{2+2}"); + put("barKey2%", "foo%{2+2}"); + put("barKey3%", "foo%{2+2}foo"); + put("allowedKey", "${foo}"); + put("allowedKey2", "%{bar}"); + put("fooKey", "fooValue"); + put("fooKey2", ""); + } + }; + pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build()); + assertEquals(expected, actual); + } + + public void testAcceptedParametersValuesAreIgnored() throws Exception { + ParametersInterceptor pi = createParametersInterceptor(); + // Starts with (based on pattern) + pi.setAcceptedValuePatterns("^\\$\\{foo\\}.*,^%\\{bar\\}.*,^fooValue"); + + assertTrue("${foo} was allowed by isParamValueAccepted", pi.isParamValueAccepted("${foo}")); + + final Map actual = injectValueStackFactory(pi); + ValueStack stack = injectValueStack(actual); + + final Map expected = new HashMap() { + { + put("fooKey", "fooValue"); + put("fooKey2", ""); + put("allowedKey", "${foo}"); + put("allowedKey2", "%{bar}"); + } + }; + + Map parameters = new HashMap() { + { + put("barKey$", "${2+2}"); + put("barKey2$", "foo${2+2}"); + put("barKey3$", "foo${2+2}foo"); + put("barKey%", "%{2+2}"); + put("barKey2%", "foo%{2+2}"); + put("barKey3%", "foo%{2+2}foo"); + put("allowedKey", "${foo}"); + put("allowedKey2", "%{bar}"); + put("fooKey", "fooValue"); + put("fooKey2", ""); + } + }; + pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build()); + assertEquals(expected, actual); + } + + public void testAcceptedAndExcludedParametersValuesAreIgnored() throws Exception { + ParametersInterceptor pi = createParametersInterceptor(); + // Starts with (based on pattern) + pi.setAcceptedValuePatterns("^\\$\\{foo\\}.*,^%\\{bar\\}.*,^fooValue"); + pi.setExcludeValuePatterns(".*\\$\\{2.*2\\}.*,.*\\%\\{2.*2\\}.*"); + + assertTrue("${foo} was allowed by isParamValueAccepted", pi.isParamValueAccepted("${foo}")); + assertTrue("${2*2} was excluded by isParamValueExcluded", pi.isParamValueExcluded("${2*2}")); + + final Map actual = injectValueStackFactory(pi); + ValueStack stack = injectValueStack(actual); + + final Map expected = new HashMap() { + { + put("fooKey", "fooValue"); + put("allowedKey", "${foo}"); + put("allowedKey2", "%{bar}"); + put("fooKey2", ""); + } + }; + + Map parameters = new HashMap() { + { + put("barKey$", "${2+2}"); + put("barKey2$", "foo${2+2}"); + put("barKey%", "%{2+2}"); + put("barKey2%", "foo%{2+2}"); + put("barKey3", "nothing"); + + put("allowedKey", "${foo}"); + put("allowedKey2", "%{bar}"); + put("fooKey", "fooValue"); + put("fooKey2", ""); + } + }; + pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build()); + assertEquals(expected, actual); + } + + private ValueStack injectValueStack(Map actual) { ValueStack stack = createStubValueStack(actual); container.inject(stack); From 5763476830bcb71cef69fbd602f491330fa159fe Mon Sep 17 00:00:00 2001 From: Brian Andle Date: Mon, 6 Jun 2022 11:11:20 -0700 Subject: [PATCH 002/143] WW-5184 - Change info to warn from peer review --- .../xwork2/interceptor/ParametersInterceptor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java index 21154d546..b592cfb13 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java @@ -359,7 +359,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { protected boolean acceptableValue(String name, String value) { boolean accepted = (value == null || value.isEmpty() || (!isParamValueExcluded(value) && isParamValueAccepted(value))); if (!accepted) { - LOG.info("Parameter [{}] was not accepted with value [{}] and will be dropped!", name, value); + LOG.warn("Parameter [{}] was not accepted with value [{}] and will be dropped!", name, value); } return accepted; } @@ -452,7 +452,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { for (Pattern excludedPattern : excludedValuePatterns) { if (value != null) { if (excludedPattern.matcher(value).matches()) { - LOG.info("Parameter value [{}] matches excluded pattern [{}] and will be dropped.", value, + LOG.warn("Parameter value [{}] matches excluded pattern [{}] and will be dropped.", value, excludedPattern); return true; } @@ -475,7 +475,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { // acceptedValuePatterns not defined so anything is allowed return true; } - LOG.info("Parameter value [{}] did not match any acceptedValuePattern pattern and will be dropped.", value); + LOG.warn("Parameter value [{}] did not match any acceptedValuePattern pattern and will be dropped.", value); return false; } From 584634a9b5ed66eabc5655a49d704a7038bd1e27 Mon Sep 17 00:00:00 2001 From: Brian Andle Date: Tue, 7 Jun 2022 21:50:34 -0700 Subject: [PATCH 003/143] WW-5184 - Added ParameterValueAware interface and unit test --- .../interceptor/ParameterValueAware.java | 37 ++++++++++++++++ .../interceptor/ParametersInterceptor.java | 14 +++--- .../ParametersInterceptorTest.java | 44 +++++++++++++++++++ 3 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterValueAware.java diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterValueAware.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterValueAware.java new file mode 100644 index 000000000..7f077f7c9 --- /dev/null +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterValueAware.java @@ -0,0 +1,37 @@ +/* + * 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 com.opensymphony.xwork2.interceptor; + +/** + * This interface is implemented by actions that want to declare acceptable parameter value. Works in conjunction with {@link + * ParametersInterceptor}. For example, actions may want to create a white list of parameter values they will accept or a + * blacklist of parameter values they will reject to prevent clients from setting other unexpected (and possibly dangerous) + * parameter values. + */ +public interface ParameterValueAware { + + /** + * Tests if the the action will accept the parameter with the given value. + * + * @param parameterValue the parameter value + * @return true if accepted, false otherwise + */ + boolean acceptableParameterValue(String parameterValue); + +} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java index b592cfb13..f81ba15fd 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java @@ -191,7 +191,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { for (Map.Entry entry : params.entrySet()) { String parameterName = entry.getKey(); boolean isAcceptableParameter = isAcceptableParameter(parameterName, action); - isAcceptableParameter &= isAcceptableParameterValue(entry.getValue()); + isAcceptableParameter &= isAcceptableParameterValue(entry.getValue(), action); if (isAcceptableParameter) { acceptableParameters.put(parameterName, entry.getValue()); @@ -280,14 +280,14 @@ public class ParametersInterceptor extends MethodFilterInterceptor { * @param action current action * @return true if parameter is accepted */ - protected boolean isAcceptableParameterValue(Parameter param) { + protected boolean isAcceptableParameterValue(Parameter param, Object action) { + ParameterValueAware parameterValueAware = (action instanceof ParameterValueAware) ? (ParameterValueAware) action : null; + boolean acceptableParmValue = (parameterValueAware == null || parameterValueAware.acceptableParameterValue(param.getValue())); if(hasParamValuesToExclude() || hasParamValuesToAccept()) { - // We have something to check. - return acceptableValue(param.getName(), param.getValue()); - } else { - // No exclude/accept defined. Return true/allowed. - return true; + // Additional validations to process + acceptableParmValue &= acceptableValue(param.getName(), param.getValue()); } + return acceptableParmValue; } /** diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java index d26ceef81..ce8fe8498 100644 --- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java @@ -888,6 +888,50 @@ public class ParametersInterceptorTest extends XWorkTestCase { pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build()); assertEquals(expected, actual); } + + public void testExcludedParametersValuesAreIgnoredWithParameterValueAware() throws Exception { + ParametersInterceptor pi = createParametersInterceptor(); + // Contains (based on pattern) + pi.setExcludeValuePatterns(".*\\$\\{.*?\\}.*,.*%\\{.*?\\}.*"); + + assertTrue("${2*2} was excluded by isParamValueExcluded", pi.isParamValueExcluded("${2*2}")); + + final Map actual = injectValueStackFactory(pi); + ValueStack stack = injectValueStack(actual); + + final Map expected = new HashMap() { + { + // acceptableParameterValue only allows fooValue even though fooKey2 and fooKey3 pass the excludeValuePatterns check + put("fooKey", "fooValue"); + } + }; + + Object a = new ParameterValueAware() { + @Override + public boolean acceptableParameterValue(String parameterValue) { + // Only fooValue will be allowed because the excludeValuePatterns will block ${2+2} + return parameterValue.equals("fooValue") || parameterValue.equals("${2+2}"); + } + }; + + Map parameters = new HashMap() { + { + put("barKey$", "${2+2}"); + put("barKey2$", "foo${2+2}"); + put("barKey3$", "foo${2+2}foo"); + put("barKey%", "%{2+2}"); + put("barKey2%", "foo%{2+2}"); + put("barKey3%", "foo%{2+2}foo"); + put("allowedKey", "${foo}"); + put("allowedKey2", "%{bar}"); + put("fooKey", "fooValue"); + put("fooKey2", "fooValue2"); + put("fooKey3", ""); + } + }; + pi.setParameters(a, stack, HttpParameters.create(parameters).build()); + assertEquals(expected, actual); + } private ValueStack injectValueStack(Map actual) { From 963b473e6c99fd1a79962bad4b16f0a6c6c82993 Mon Sep 17 00:00:00 2001 From: JCgH4164838Gh792C124B5 <43964333+JCgH4164838Gh792C124B5@users.noreply.github.com> Date: Mon, 20 Jun 2022 17:07:57 -0400 Subject: [PATCH 004/143] Initial commit: - Update to use consistent name for expression and BeanInfo factories in default configuration implementation and provider. - Add inject annotation to the non-default constructor to ensure the proper constructor is called during DI for containers. - Use fully-qualified factory names for defaults in default.properties. - Ensure unique types for each cache factory in struts-default.xml --- .../opensymphony/xwork2/config/impl/DefaultConfiguration.java | 4 ++-- .../config/providers/StrutsDefaultConfigurationProvider.java | 4 ++-- core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java | 1 + core/src/main/resources/org/apache/struts2/default.properties | 4 ++-- core/src/main/resources/struts-default.xml | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java index 91b1b9a33..fea65cbf6 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java @@ -298,8 +298,8 @@ public class DefaultConfiguration implements Configuration { builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON); builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON); - builder.factory(ExpressionCacheFactory.class, "defaultOgnlExpressionCacheFactory", DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON); - builder.factory(BeanInfoCacheFactory.class, "defaultOgnlBeanInfoCacheFactory", DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON); + builder.factory(ExpressionCacheFactory.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON); + builder.factory(BeanInfoCacheFactory.class, StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON); builder.factory(OgnlUtil.class, Scope.SINGLETON); builder.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON); diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java index 1442e920f..394aaa69d 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java @@ -217,8 +217,8 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider .factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON) .factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON) - .factory(ExpressionCacheFactory.class, "defaultOgnlExpressionCacheFactory", DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON) - .factory(BeanInfoCacheFactory.class, "defaultOgnlBeanInfoCacheFactory", DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON) + .factory(ExpressionCacheFactory.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON) + .factory(BeanInfoCacheFactory.class, StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON) .factory(OgnlUtil.class, Scope.SINGLETON) .factory(CollectionConverter.class, Scope.SINGLETON) .factory(ArrayConverter.class, Scope.SINGLETON) diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java index 5cb12f8a1..560f18968 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java +++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java @@ -96,6 +96,7 @@ public class OgnlUtil { * @param ognlExpressionCacheFactory factory for Expression cache instance. If null, it uses a default * @param ognlBeanInfoCacheFactory factory for BeanInfo cache instance. If null, it uses a default */ + @Inject public OgnlUtil( @Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, required = false) ExpressionCacheFactory ognlExpressionCacheFactory, @Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, required = false) BeanInfoCacheFactory, BeanInfo> ognlBeanInfoCacheFactory diff --git a/core/src/main/resources/org/apache/struts2/default.properties b/core/src/main/resources/org/apache/struts2/default.properties index 6c6e06497..edc327810 100644 --- a/core/src/main/resources/org/apache/struts2/default.properties +++ b/core/src/main/resources/org/apache/struts2/default.properties @@ -231,8 +231,8 @@ struts.ognl.enableExpressionCache=true ### Specify the OGNL expression cache factory and BeanInfo cache factory to use. ### Currently, the default implementations are used, but can be replaced with custom ones if desired. -struts.ognl.expressionCacheFactory=defaultOgnlExpressionCacheFactory -struts.ognl.beanInfoCacheFactory=defaultOgnlBeanInfoCacheFactory +struts.ognl.expressionCacheFactory=com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory +struts.ognl.beanInfoCacheFactory=com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory ### Specify a limit to the number of entries in the OGNL expressionCache. ### For the standard expressionCache mode, when the limit is exceeded the entire cache's diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml index f493fceac..b6ade6a74 100644 --- a/core/src/main/resources/struts-default.xml +++ b/core/src/main/resources/struts-default.xml @@ -231,8 +231,8 @@ - - + + From 24e279b16556aa974352132f5b84c8bf5c0f737d Mon Sep 17 00:00:00 2001 From: JCgH4164838Gh792C124B5 <43964333+JCgH4164838Gh792C124B5@users.noreply.github.com> Date: Sun, 3 Jul 2022 17:37:58 -0400 Subject: [PATCH 005/143] Update: - Added arbitrary code coverage test. --- .../StrutsJavaConfigurationProviderTest.java | 56 +++++++++++++++++++ .../config/TestBeanSelectionProvider.java | 6 ++ 2 files changed, 62 insertions(+) diff --git a/core/src/test/java/org/apache/struts2/config/StrutsJavaConfigurationProviderTest.java b/core/src/test/java/org/apache/struts2/config/StrutsJavaConfigurationProviderTest.java index 5e08f9822..b361cf837 100644 --- a/core/src/test/java/org/apache/struts2/config/StrutsJavaConfigurationProviderTest.java +++ b/core/src/test/java/org/apache/struts2/config/StrutsJavaConfigurationProviderTest.java @@ -104,4 +104,60 @@ public class StrutsJavaConfigurationProviderTest { Assert.assertTrue(names.contains("struts")); Assert.assertTrue(names.contains("struts.test.bean")); } + + @Test + /** + * This test is purely to provide code coverage for {@link AbstractBeanSelectionProvider}. + * It uses an arbitrary setup to ensure a code path not followed in the registration test + * is traversed. + */ + public void testAbstractBeanProviderCoverage() throws Exception { + final ConstantConfig constantConfig = new ConstantConfig(); + final String expectedUnknownHandler = "expectedUnknownHandler"; + + StrutsJavaConfiguration javaConfig = new StrutsJavaConfiguration() { + @Override + public List unknownHandlerStack() { + return Collections.singletonList(expectedUnknownHandler); + } + + @Override + public List constants() { + return Collections.singletonList(constantConfig); + } + + @Override + public List beans() { + return Arrays.asList( + new BeanConfig(TestBean.class, "struts") + ); + } + + @Override + public Optional beanSelection() { + return Optional.of(new BeanSelectionConfig(TestBeanSelectionProvider.class, "testBeans")); + } + }; + + StrutsJavaConfigurationProvider provider = new StrutsJavaConfigurationProvider(javaConfig); + Configuration configuration = new MockConfiguration(); + ContainerBuilder builder = new ContainerBuilder(); + LocatableProperties props = new LocatableProperties(); + + provider.init(configuration); + provider.register(builder, props); + + props.put(CodeCoverageTestClass1.ALIAS_KEY, CodeCoverageTestClass1.ALIAS_VALUE); + TestBeanSelectionProvider testBeanSelectionProvider = new TestBeanSelectionProvider(); + testBeanSelectionProvider.aliasCallCoverage(CodeCoverageTestClass1.class, builder, props, CodeCoverageTestClass1.ALIAS_KEY, Scope.THREAD); + } + + final class CodeCoverageTestClass1 extends Object { + public static final String ALIAS_KEY = "testAliasKey"; + public static final String ALIAS_VALUE = "testAliasValue"; + + public CodeCoverageTestClass1() { + super(); + } + } } diff --git a/core/src/test/java/org/apache/struts2/config/TestBeanSelectionProvider.java b/core/src/test/java/org/apache/struts2/config/TestBeanSelectionProvider.java index 79d6dd28c..27fa961c3 100644 --- a/core/src/test/java/org/apache/struts2/config/TestBeanSelectionProvider.java +++ b/core/src/test/java/org/apache/struts2/config/TestBeanSelectionProvider.java @@ -21,6 +21,7 @@ package org.apache.struts2.config; import com.opensymphony.xwork2.TestBean; import com.opensymphony.xwork2.config.ConfigurationException; import com.opensymphony.xwork2.inject.ContainerBuilder; +import com.opensymphony.xwork2.inject.Scope; import com.opensymphony.xwork2.util.location.LocatableProperties; public class TestBeanSelectionProvider extends AbstractBeanSelectionProvider { @@ -30,4 +31,9 @@ public class TestBeanSelectionProvider extends AbstractBeanSelectionProvider { alias(TestBean.class, "struts.test.bean", builder, props); } + public void aliasCallCoverage(Class aliasClass, ContainerBuilder builder, LocatableProperties props, String aliasKey, Scope scope) throws ConfigurationException { + // Allow for coverage testing of AbstractBeanSelectionProvider. + alias(aliasClass, aliasKey, builder, props, scope); + } + } From 15bbf0ef1d21ae75f6eec243c613527fe9e90f79 Mon Sep 17 00:00:00 2001 From: JCgH4164838Gh792C124B5 <43964333+JCgH4164838Gh792C124B5@users.noreply.github.com> Date: Sun, 31 Jul 2022 18:23:10 -0400 Subject: [PATCH 006/143] Updated commit: - Incorporate changes from Y. Zamani's PR #581 manually, which appears to fix the previous issue that prevented customized cache factory implementations from being used (tested with sample app). Credit goes to Yasser Zamani for the fixes. - Updated unit tests and slight modifications to the changes from the PR #581. --- .../config/impl/DefaultConfiguration.java | 4 +- .../StrutsDefaultConfigurationProvider.java | 4 +- .../opensymphony/xwork2/ognl/OgnlUtil.java | 21 ++++--- .../org/apache/struts2/default.properties | 4 +- core/src/main/resources/struts-default.xml | 4 +- .../xwork2/ognl/OgnlUtilTest.java | 61 +++++-------------- 6 files changed, 35 insertions(+), 63 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java index fea65cbf6..71fdf2ff8 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java @@ -298,8 +298,8 @@ public class DefaultConfiguration implements Configuration { builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON); builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON); - builder.factory(ExpressionCacheFactory.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON); - builder.factory(BeanInfoCacheFactory.class, StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON); + builder.factory(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON); + builder.factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON); builder.factory(OgnlUtil.class, Scope.SINGLETON); builder.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON); diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java index 394aaa69d..49308d263 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java @@ -217,8 +217,8 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider .factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON) .factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON) - .factory(ExpressionCacheFactory.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON) - .factory(BeanInfoCacheFactory.class, StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON) + .factory(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON) + .factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON) .factory(OgnlUtil.class, Scope.SINGLETON) .factory(CollectionConverter.class, Scope.SINGLETON) .factory(ArrayConverter.class, Scope.SINGLETON) diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java index 560f18968..49be23790 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java +++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java @@ -82,7 +82,9 @@ public class OgnlUtil { */ @Deprecated public OgnlUtil() { - this(null, null); // Instantiate default Expression and BeanInfo caches (null factories) + // Instantiate default Expression and BeanInfo caches (factories must be non-null). + this(new DefaultOgnlExpressionCacheFactory(), + new DefaultOgnlBeanInfoCacheFactory, BeanInfo>()); } /** @@ -98,9 +100,15 @@ public class OgnlUtil { */ @Inject public OgnlUtil( - @Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, required = false) ExpressionCacheFactory ognlExpressionCacheFactory, - @Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, required = false) BeanInfoCacheFactory, BeanInfo> ognlBeanInfoCacheFactory + @Inject ExpressionCacheFactory ognlExpressionCacheFactory, + @Inject BeanInfoCacheFactory, BeanInfo> ognlBeanInfoCacheFactory ) { + if (ognlExpressionCacheFactory == null) { + throw new IllegalArgumentException("ExpressionCacheFactory parameter cannot be null"); + } + if (ognlBeanInfoCacheFactory == null) { + throw new IllegalArgumentException("BeanInfoCacheFactory parameter cannot be null"); + } excludedClasses = Collections.unmodifiableSet(new HashSet<>()); excludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>()); excludedPackageNames = Collections.unmodifiableSet(new HashSet<>()); @@ -109,11 +117,8 @@ public class OgnlUtil { devModeExcludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>()); devModeExcludedPackageNames = Collections.unmodifiableSet(new HashSet<>()); - OgnlCacheFactory ognlExpressionCacheFactory1 = (ognlExpressionCacheFactory != null ? ognlExpressionCacheFactory : new DefaultOgnlExpressionCacheFactory<>()); - OgnlCacheFactory, BeanInfo> ognlBeanInfoCacheFactory1 = (ognlBeanInfoCacheFactory != null ? ognlBeanInfoCacheFactory : new DefaultOgnlBeanInfoCacheFactory<>()); - - this.expressionCache = ognlExpressionCacheFactory1.buildOgnlCache(); - this.beanInfoCache = ognlBeanInfoCacheFactory1.buildOgnlCache(); + this.expressionCache = ognlExpressionCacheFactory.buildOgnlCache(); + this.beanInfoCache = ognlBeanInfoCacheFactory.buildOgnlCache(); } @Inject diff --git a/core/src/main/resources/org/apache/struts2/default.properties b/core/src/main/resources/org/apache/struts2/default.properties index edc327810..753a80b8d 100644 --- a/core/src/main/resources/org/apache/struts2/default.properties +++ b/core/src/main/resources/org/apache/struts2/default.properties @@ -231,8 +231,8 @@ struts.ognl.enableExpressionCache=true ### Specify the OGNL expression cache factory and BeanInfo cache factory to use. ### Currently, the default implementations are used, but can be replaced with custom ones if desired. -struts.ognl.expressionCacheFactory=com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory -struts.ognl.beanInfoCacheFactory=com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory +# struts.ognl.expressionCacheFactory=customOgnlExpressionCacheFactory +# struts.ognl.beanInfoCacheFactory=customOgnlBeanInfoCacheFactory ### Specify a limit to the number of entries in the OGNL expressionCache. ### For the standard expressionCache mode, when the limit is exceeded the entire cache's diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml index b6ade6a74..f06a338d7 100644 --- a/core/src/main/resources/struts-default.xml +++ b/core/src/main/resources/struts-default.xml @@ -231,8 +231,8 @@ - - + + diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java index 8549fe8b2..b5795a326 100644 --- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java @@ -1313,11 +1313,20 @@ public class OgnlUtilTest extends XWorkTestCase { internalTestOgnlUtilExclusionsImmutable(basicOgnlUtil); } - public void testDefaultOgnlUtilExclusionsAlternateConstructor() { - OgnlUtil basicOgnlUtil = new OgnlUtil(null, null); - - internalTestInitialEmptyOgnlUtilExclusions(basicOgnlUtil); - internalTestOgnlUtilExclusionsImmutable(basicOgnlUtil); + public void testDefaultOgnlUtilAlternateConstructorArguments() { + // Code coverage test for the OgnlUtil alternate constructor method, and verify expected behaviour. + try { + OgnlUtil basicOgnlUtil = new OgnlUtil(new DefaultOgnlExpressionCacheFactory(), null); + fail("null beanInfoCacheFactory should result in exception"); + } catch (IllegalArgumentException iaex) { + // expected result + } + try { + OgnlUtil basicOgnlUtil = new OgnlUtil(null, new DefaultOgnlBeanInfoCacheFactory, BeanInfo>()); + fail("null expressionCacheFactory should result in exception"); + } catch (IllegalArgumentException iaex) { + // expected result + } } public void testDefaultOgnlUtilExclusionsAlternateConstructorPopulated() { @@ -1690,20 +1699,6 @@ public class OgnlUtilTest extends XWorkTestCase { } } - public void testGetExcludedPackageNamesAlternateConstructor() { - // Getter should return an immutable collection - OgnlUtil util = new OgnlUtil(null, null); - util.setExcludedPackageNames("java.lang,java.awt"); - assertEquals(util.getExcludedPackageNames().size(), 2); - try { - util.getExcludedPackageNames().clear(); - } catch (Exception ex) { - assertTrue(ex instanceof UnsupportedOperationException); - } finally { - assertEquals(util.getExcludedPackageNames().size(), 2); - } - } - public void testGetExcludedPackageNamesAlternateConstructorPopulated() { // Getter should return an immutable collection OgnlUtil util = new OgnlUtil(new DefaultOgnlExpressionCacheFactory(), new DefaultOgnlBeanInfoCacheFactory, BeanInfo>()); @@ -1732,20 +1727,6 @@ public class OgnlUtilTest extends XWorkTestCase { } } - public void testGetExcludedClassesAlternateConstructor() { - // Getter should return an immutable collection - OgnlUtil util = new OgnlUtil(null, null); - util.setExcludedClasses("java.lang.Runtime,java.lang.ProcessBuilder,java.net.URL"); - assertEquals(util.getExcludedClasses().size(), 3); - try { - util.getExcludedClasses().clear(); - } catch (Exception ex) { - assertTrue(ex instanceof UnsupportedOperationException); - } finally { - assertEquals(util.getExcludedClasses().size(), 3); - } - } - public void testGetExcludedClassesAlternateConstructorPopulated() { // Getter should return an immutable collection OgnlUtil util = new OgnlUtil(new DefaultOgnlExpressionCacheFactory(), new DefaultOgnlBeanInfoCacheFactory, BeanInfo>()); @@ -1774,20 +1755,6 @@ public class OgnlUtilTest extends XWorkTestCase { } } - public void testGetExcludedPackageNamePatternsAlternateConstructor() { - // Getter should return an immutable collection - OgnlUtil util = new OgnlUtil(null, null); - util.setExcludedPackageNamePatterns("java.lang."); - assertEquals(util.getExcludedPackageNamePatterns().size(), 1); - try { - util.getExcludedPackageNamePatterns().clear(); - } catch (Exception ex) { - assertTrue(ex instanceof UnsupportedOperationException); - } finally { - assertEquals(util.getExcludedPackageNamePatterns().size(), 1); - } - } - public void testGetExcludedPackageNamePatternsAlternateConstructorPopulated() { // Getter should return an immutable collection OgnlUtil util = new OgnlUtil(new DefaultOgnlExpressionCacheFactory(), new DefaultOgnlBeanInfoCacheFactory, BeanInfo>()); From 86b45e96fcd4155b68c3d18e18719fba9584d66e Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 8 Aug 2022 17:00:42 +0200 Subject: [PATCH 007/143] WW-5207 Uses ASM 9 by default --- .../xwork2/util/finder/ClassFinder.java | 55 +++--- .../convention/DefaultClassFinder.java | 170 ++++++------------ 2 files changed, 80 insertions(+), 145 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinder.java b/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinder.java index fcbd08e4e..92e213655 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinder.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinder.java @@ -29,11 +29,11 @@ import java.util.List; /** * ClassFinder searches the classpath of the specified ClassLoaderInterface for * packages, classes, constructors, methods, or fields with specific annotations. - * + *

* For security reasons ASM is used to find the annotations. Classes are not * loaded unless they match the requirements of a called findAnnotated* method. * Once loaded, these classes are cached. - * + *

* The getClassesNotLoaded() method can be used immediately after any find* * method to get a list of classes which matched the find requirements (i.e. * contained the annotation), but were unable to be loaded. @@ -67,32 +67,32 @@ public interface ClassFinder { List findAnnotatedPackages(Class annotation); - List findAnnotatedClasses(Class annotation); + List> findAnnotatedClasses(Class annotation); List findAnnotatedMethods(Class annotation); - List findAnnotatedConstructors(Class annotation); + List> findAnnotatedConstructors(Class annotation); List findAnnotatedFields(Class annotation); - List findClassesInPackage(String packageName, boolean recursive); + List> findClassesInPackage(String packageName, boolean recursive); - List findClasses(Test test); + List> findClasses(Test test); - List findClasses(); + List> findClasses(); ClassLoaderInterface getClassLoaderInterface(); - public static interface Info { + interface Info { String getName(); List getAnnotations(); } - public class AnnotationInfo extends Annotatable implements Info { + class AnnotationInfo extends Annotatable implements Info { private final String name; - public AnnotationInfo(Annotation annotation){ + public AnnotationInfo(Annotation annotation) { this(annotation.getClass().getName()); } @@ -116,7 +116,7 @@ public interface ClassFinder { } } - public class Annotatable { + class Annotatable { private final List annotations = new ArrayList<>(); public Annotatable(AnnotatedElement element) { @@ -134,12 +134,12 @@ public interface ClassFinder { } - public class PackageInfo extends Annotatable implements Info { + class PackageInfo extends Annotatable implements Info { private final String name; private final ClassInfo info; private final Package pkg; - public PackageInfo(Package pkg){ + public PackageInfo(Package pkg) { super(pkg); this.pkg = pkg; this.name = pkg.getName(); @@ -157,11 +157,11 @@ public interface ClassFinder { } public Package get() throws ClassNotFoundException { - return (pkg != null)?pkg:info.get().getPackage(); + return (pkg != null) ? pkg : info.get().getPackage(); } } - public class ClassInfo extends Annotatable implements Info { + class ClassInfo extends Annotatable implements Info { private final String name; private final List methods = new ArrayList<>(); private final List constructors = new ArrayList<>(); @@ -169,17 +169,18 @@ public interface ClassFinder { private final List interfaces = new ArrayList<>(); private final List superInterfaces = new ArrayList<>(); private final List fields = new ArrayList<>(); + private final ClassFinder classFinder; + private Class clazz; - private ClassFinder classFinder; private ClassNotFoundException notFound; - public ClassInfo(Class clazz, ClassFinder classFinder) { + public ClassInfo(Class clazz, ClassFinder classFinder) { super(clazz); this.clazz = clazz; this.classFinder = classFinder; this.name = clazz.getName(); - Class superclass = clazz.getSuperclass(); - this.superType = superclass != null ? superclass.getName(): null; + Class superclass = clazz.getSuperclass(); + this.superType = superclass != null ? superclass.getName() : null; } public ClassInfo(String name, String superType, ClassFinder classFinder) { @@ -188,8 +189,8 @@ public interface ClassFinder { this.classFinder = classFinder; } - public String getPackageName(){ - return name.indexOf('.') > 0 ? name.substring(0, name.lastIndexOf('.')) : "" ; + public String getPackageName() { + return name.indexOf('.') > 0 ? name.substring(0, name.lastIndexOf('.')) : ""; } public List getConstructors() { @@ -220,7 +221,7 @@ public interface ClassFinder { return superType; } - public Class get() throws ClassNotFoundException { + public Class get() throws ClassNotFoundException { if (clazz != null) return clazz; if (notFound != null) throw notFound; try { @@ -239,20 +240,20 @@ public interface ClassFinder { } } - public class MethodInfo extends Annotatable implements Info { + class MethodInfo extends Annotatable implements Info { private final ClassInfo declaringClass; private final String returnType; private final String name; private final List> parameterAnnotations = new ArrayList<>(); - public MethodInfo(ClassInfo info, Constructor constructor){ + public MethodInfo(ClassInfo info, Constructor constructor) { super(constructor); this.declaringClass = info; this.name = ""; this.returnType = Void.TYPE.getName(); } - public MethodInfo(ClassInfo info, Method method){ + public MethodInfo(ClassInfo info, Method method) { super(method); this.declaringClass = info; this.name = method.getName(); @@ -297,12 +298,12 @@ public interface ClassFinder { } } - public class FieldInfo extends Annotatable implements Info { + class FieldInfo extends Annotatable implements Info { private final String name; private final String type; private final ClassInfo declaringClass; - public FieldInfo(ClassInfo info, Field field){ + public FieldInfo(ClassInfo info, Field field) { super(field); this.declaringClass = info; this.name = field.getName(); diff --git a/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultClassFinder.java b/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultClassFinder.java index 54d535811..9b6fdb86d 100644 --- a/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultClassFinder.java +++ b/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultClassFinder.java @@ -38,6 +38,7 @@ import org.objectweb.asm.Opcodes; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -45,7 +46,15 @@ import java.lang.reflect.Method; import java.net.JarURLConnection; import java.net.URL; import java.net.URLDecoder; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; @@ -57,9 +66,9 @@ public class DefaultClassFinder implements ClassFinder { private final List classesNotLoaded = new ArrayList<>(); - private boolean extractBaseInterfaces; - private ClassLoaderInterface classLoaderInterface; - private FileManager fileManager; + private final ClassLoaderInterface classLoaderInterface; + private final boolean extractBaseInterfaces; + private final FileManager fileManager; public DefaultClassFinder(ClassLoaderInterface classLoaderInterface, Collection urls, boolean extractBaseInterfaces, Set protocols, Test classNameFilter) { this.classLoaderInterface = classLoaderInterface; @@ -97,46 +106,6 @@ public class DefaultClassFinder implements ClassFinder { } } - public DefaultClassFinder(Class... classes){ - this(Arrays.asList(classes)); - } - - public DefaultClassFinder(List classes){ - this.classLoaderInterface = null; - List infos = new ArrayList<>(); - List packages = new ArrayList<>(); - for (Class clazz : classes) { - - Package aPackage = clazz.getPackage(); - if (aPackage != null && !packages.contains(aPackage)){ - infos.add(new PackageInfo(aPackage)); - packages.add(aPackage); - } - - ClassInfo classInfo = new ClassInfo(clazz, this); - infos.add(classInfo); - classInfos.put(classInfo.getName(), classInfo); - for (Method method : clazz.getDeclaredMethods()) { - infos.add(new MethodInfo(classInfo, method)); - } - - for (Constructor constructor : clazz.getConstructors()) { - infos.add(new MethodInfo(classInfo, constructor)); - } - - for (Field field : clazz.getDeclaredFields()) { - infos.add(new FieldInfo(classInfo, field)); - } - } - - for (Info info : infos) { - for (AnnotationInfo annotation : info.getAnnotations()) { - List annotationInfos = getAnnotationInfos(annotation.getName()); - annotationInfos.add(info); - } - } - } - public ClassLoaderInterface getClassLoaderInterface() { return classLoaderInterface; } @@ -171,15 +140,15 @@ public class DefaultClassFinder implements ClassFinder { return packages; } - public List findAnnotatedClasses(Class annotation) { + public List> findAnnotatedClasses(Class annotation) { classesNotLoaded.clear(); - List classes = new ArrayList<>(); + List> classes = new ArrayList<>(); List infos = getAnnotationInfos(annotation.getName()); for (Info info : infos) { if (info instanceof ClassInfo) { ClassInfo classInfo = (ClassInfo) info; try { - Class clazz = classInfo.get(); + Class clazz = classInfo.get(); // double check via proper reflection if (clazz.isAnnotationPresent(annotation)) { classes.add(clazz); @@ -208,7 +177,7 @@ public class DefaultClassFinder implements ClassFinder { seen.add(classInfo); try { - Class clazz = classInfo.get(); + Class clazz = classInfo.get(); for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(annotation)) { methods.add(method); @@ -223,10 +192,10 @@ public class DefaultClassFinder implements ClassFinder { return methods; } - public List findAnnotatedConstructors(Class annotation) { + public List> findAnnotatedConstructors(Class annotation) { classesNotLoaded.clear(); List seen = new ArrayList<>(); - List constructors = new ArrayList<>(); + List> constructors = new ArrayList<>(); List infos = getAnnotationInfos(annotation.getName()); for (Info info : infos) { if (info instanceof MethodInfo && "".equals(info.getName())) { @@ -238,8 +207,8 @@ public class DefaultClassFinder implements ClassFinder { seen.add(classInfo); try { - Class clazz = classInfo.get(); - for (Constructor constructor : clazz.getConstructors()) { + Class clazz = classInfo.get(); + for (Constructor constructor : clazz.getConstructors()) { if (constructor.isAnnotationPresent(annotation)) { constructors.add(constructor); } @@ -270,7 +239,7 @@ public class DefaultClassFinder implements ClassFinder { seen.add(classInfo); try { - Class clazz = classInfo.get(); + Class clazz = classInfo.get(); for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(annotation)) { fields.add(field); @@ -285,14 +254,14 @@ public class DefaultClassFinder implements ClassFinder { return fields; } - public List findClassesInPackage(String packageName, boolean recursive) { + public List> findClassesInPackage(String packageName, boolean recursive) { classesNotLoaded.clear(); - List classes = new ArrayList<>(); + List> classes = new ArrayList<>(); for (ClassInfo classInfo : classInfos.values()) { try { - if (recursive && classInfo.getPackageName().startsWith(packageName)){ + if (recursive && classInfo.getPackageName().startsWith(packageName)) { classes.add(classInfo.get()); - } else if (classInfo.getPackageName().equals(packageName)){ + } else if (classInfo.getPackageName().equals(packageName)) { classes.add(classInfo.get()); } } catch (Throwable e) { @@ -303,9 +272,9 @@ public class DefaultClassFinder implements ClassFinder { return classes; } - public List findClasses(Test test) { + public List> findClasses(Test test) { classesNotLoaded.clear(); - List classes = new ArrayList<>(); + List> classes = new ArrayList<>(); for (ClassInfo classInfo : classInfos.values()) { try { if (test.test(classInfo)) { @@ -319,9 +288,9 @@ public class DefaultClassFinder implements ClassFinder { return classes; } - public List findClasses() { + public List> findClasses() { classesNotLoaded.clear(); - List classes = new ArrayList<>(); + List> classes = new ArrayList<>(); for (ClassInfo classInfo : classInfos.values()) { try { classes.add(classInfo.get()); @@ -333,9 +302,9 @@ public class DefaultClassFinder implements ClassFinder { return classes; } - private List file(URL location) { + private List file(URL location) throws UnsupportedEncodingException { List classNames = new ArrayList<>(); - File dir = new File(URLDecoder.decode(location.getPath())); + File dir = new File(URLDecoder.decode(location.getPath(), "UTF-8")); if ("META-INF".equals(dir.getName())) { dir = dir.getParentFile(); // Scrape "META-INF" off } @@ -347,15 +316,17 @@ public class DefaultClassFinder implements ClassFinder { private void scanDir(File dir, List classNames, String packageName) { File[] files = dir.listFiles(); - for (File file : files) { - if (file.isDirectory()) { - scanDir(file, classNames, packageName + file.getName() + "."); - } else if (file.getName().endsWith(".class")) { - String name = file.getName(); - name = name.replaceFirst(".class$", ""); - // Classes packaged in an exploded .war (e.g. in a VFS file system) should not - // have WEB-INF.classes in their package name. - classNames.add(StringUtils.removeStart(packageName, "WEB-INF.classes.") + name); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + scanDir(file, classNames, packageName + file.getName() + "."); + } else if (file.getName().endsWith(".class")) { + String name = file.getName(); + name = name.replaceFirst(".class$", ""); + // Classes packaged in an exploded .war (e.g. in a VFS file system) should not + // have WEB-INF.classes in their package name. + classNames.add(StringUtils.removeStart(packageName, "WEB-INF.classes.") + name); + } } } } @@ -363,12 +334,9 @@ public class DefaultClassFinder implements ClassFinder { private List jar(URL location) throws IOException { URL url = fileManager.normalizeToFileProtocol(location); if (url != null) { - InputStream in = url.openStream(); - try { + try (InputStream in = url.openStream()) { JarInputStream jarStream = new JarInputStream(in); return jar(jarStream); - } finally { - in.close(); } } else { LOG.debug("Unable to read [{}]", location.toExternalForm()); @@ -388,7 +356,7 @@ public class DefaultClassFinder implements ClassFinder { className = className.replaceFirst(".class$", ""); //war files are treated as .jar files, so takeout WEB-INF/classes - className = StringUtils.removeStart(className, "WEB-INF/classes/"); + className = StringUtils.removeStart(className, "WEB-INF/classes/"); className = className.replace('/', '.'); classNames.add(className); @@ -397,40 +365,8 @@ public class DefaultClassFinder implements ClassFinder { return classNames; } - public class PackageInfo extends Annotatable implements Info { - private final String name; - private final ClassInfo info; - private final Package pkg; - - public PackageInfo(Package pkg){ - super(pkg); - this.pkg = pkg; - this.name = pkg.getName(); - this.info = null; - } - - public PackageInfo(String name, ClassFinder classFinder) { - info = new ClassInfo(name, null, classFinder); - this.name = name; - this.pkg = null; - } - - public String getName() { - return name; - } - - public Package get() throws ClassNotFoundException { - return (pkg != null)?pkg:info.get().getPackage(); - } - } - private List getAnnotationInfos(String name) { - List infos = annotated.get(name); - if (infos == null) { - infos = new ArrayList<>(); - annotated.put(name, infos); - } - return infos; + return annotated.computeIfAbsent(name, k -> new ArrayList<>()); } private void readClassDef(String className) { @@ -454,19 +390,16 @@ public class DefaultClassFinder implements ClassFinder { } public class InfoBuildingVisitor extends ClassVisitor { + + private final ClassFinder classFinder; + private Info info; - private ClassFinder classFinder; public InfoBuildingVisitor(ClassFinder classFinder) { - super(Opcodes.ASM7); + super(Opcodes.ASM9); this.classFinder = classFinder; } - public InfoBuildingVisitor(Info info, ClassFinder classFinder) { - this(classFinder); - this.info = info; - } - @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { if (name.endsWith("package-info")) { @@ -480,8 +413,9 @@ public class DefaultClassFinder implements ClassFinder { info = classInfo; classInfos.put(classInfo.getName(), classInfo); - if (extractBaseInterfaces) + if (extractBaseInterfaces) { extractSuperInterfaces(classInfo); + } } } From d119ba8e13ffe6807bad7d0f5480cca98b7233b0 Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Sat, 6 Aug 2022 15:03:38 +0200 Subject: [PATCH 008/143] Migrate vom ubuntu trusty to jammy see https://docs.travis-ci.com/user/reference/jammy/ --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5fb7347f5..68156311e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -dist: trusty +dist: jammy language: java sudo: false From 09472808aac31b0fd3770c6e14221b0a3fc6fcc5 Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Sat, 6 Aug 2022 15:04:25 +0200 Subject: [PATCH 009/143] Add openjdk17 to build, remove oraclejdk9 (EOL) and switch from oraclejdk to openjdk to fix Travis CI build --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 68156311e..e86980e60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,8 @@ language: java sudo: false jdk: - - oraclejdk9 - - oraclejdk11 + - openjdk11 + - openjdk17 install: true @@ -13,8 +13,8 @@ global: - secure: iI7IpfDtS+LUyS2yNuRCR3KelNyvBHuoMQ3gb1UNmR5SSL7jO/p3olQWrQROs28FJ+dpE3lHyIjoHrebKQGJHHAgTG2XWxn+G3fDsf+wSSFSLoDGj0o2SgGXooBbR2dccnNZHCyQaOyE2cIPWaOxrQZFE4No70LQB4mrP/gdkoc= matrix: include: - - jdk: oraclejdk8 - env: STRUTS_IT=true # do integration tests and coverage reports when jdk 9 and 11 tests prospered + - jdk: openjdk8 + env: STRUTS_IT=true # do integration tests and coverage reports when jdk 11 and 17 tests prospered script: - if [ "$STRUTS_IT" == "true" ]; then From 71c7064f29096483a645d7f32d920eb350f6235f Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Mon, 8 Aug 2022 22:27:47 +0200 Subject: [PATCH 010/143] Update maven-surefire-plugin to 3.0.0-M7 see https://github.com/apache/maven-surefire/releases/tag/surefire-3.0.0-M7 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3a30a76e3..7b9401ae6 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ 5.3.20 3.0.8 1.0.7 - 3.0.0-M4 + 3.0.0-M7 6.2.4.Final From b62e583646ad95bdb34e3d4a1eb72bad6347c65c Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 9 Aug 2022 15:19:02 +0200 Subject: [PATCH 011/143] WW-5203 Re-builds policy string on each call --- .../interceptor/csp/DefaultCspSettings.java | 47 ++++++++----------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java b/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java index 9a3f764a8..5a99c0a5b 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java +++ b/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java @@ -18,16 +18,15 @@ */ package org.apache.struts2.interceptor.csp; -import static java.lang.String.format; - import com.opensymphony.xwork2.ActionContext; -import java.util.function.Supplier; import javax.servlet.http.HttpServletResponse; import java.security.SecureRandom; import java.util.Base64; import java.util.Map; +import java.util.function.Supplier; +import static java.lang.String.format; /** * Default implementation of {@link CspSettings}. @@ -37,36 +36,30 @@ import java.util.Map; * @see CspInterceptor */ public class DefaultCspSettings implements CspSettings { - private final SecureRandom sRand = new SecureRandom(); - // this lazy supplier computes a policy format the first time it's called and caches the result - // to reduce string operations when attaching policies to HTTP responses - private final Supplier lazyPolicyBuilder = new Supplier() { - boolean hasBeenCalled; - String policyFormat; + private final SecureRandom sRand = new SecureRandom(); + + // this supplier computes a policy format + private final Supplier lazyPolicyBuilder = new Supplier() { @Override public String get() { - if (!hasBeenCalled) { - StringBuilder policyFormatBuilder = new StringBuilder() - .append(OBJECT_SRC) - .append(format(" '%s'; ", NONE)) - .append(SCRIPT_SRC) - .append(" 'nonce-%s' ") // nonce placeholder - .append(format("'%s' ", STRICT_DYNAMIC)) - .append(format("%s %s; ", HTTP, HTTPS)) - .append(BASE_URI) - .append(format(" '%s'; ", NONE)); + StringBuilder policyFormatBuilder = new StringBuilder() + .append(OBJECT_SRC) + .append(format(" '%s'; ", NONE)) + .append(SCRIPT_SRC) + .append(" 'nonce-%s' ") // nonce placeholder + .append(format("'%s' ", STRICT_DYNAMIC)) + .append(format("%s %s; ", HTTP, HTTPS)) + .append(BASE_URI) + .append(format(" '%s'; ", NONE)); - if (reportUri != null) { - policyFormatBuilder - .append(REPORT_URI) - .append(format(" %s", reportUri)); - } - - policyFormat = policyFormatBuilder.toString(); + if (reportUri != null) { + policyFormatBuilder + .append(REPORT_URI) + .append(format(" %s", reportUri)); } - return format(policyFormat, getNonceString()); + return format(policyFormatBuilder.toString(), getNonceString()); } }; From 6536dc65d8a3b3e2effeb0b5f3b768bc77b8ced6 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 12 Aug 2022 17:26:47 +0200 Subject: [PATCH 012/143] [maven-release-plugin] prepare release STRUTS_6_0_1 --- apps/pom.xml | 2 +- apps/rest-showcase/pom.xml | 4 ++-- apps/showcase/pom.xml | 2 +- assembly/pom.xml | 2 +- bom/pom.xml | 6 +++--- bundles/admin/pom.xml | 2 +- bundles/demo/pom.xml | 2 +- bundles/pom.xml | 2 +- core/pom.xml | 2 +- plugins/async/pom.xml | 2 +- plugins/bean-validation/pom.xml | 2 +- plugins/cdi/pom.xml | 2 +- plugins/config-browser/pom.xml | 2 +- plugins/convention/pom.xml | 2 +- plugins/dwr/pom.xml | 2 +- plugins/embeddedjsp/pom.xml | 2 +- plugins/gxp/pom.xml | 2 +- plugins/jasperreports/pom.xml | 2 +- plugins/javatemplates/pom.xml | 2 +- plugins/jfreechart/pom.xml | 2 +- plugins/json/pom.xml | 2 +- plugins/junit/pom.xml | 2 +- plugins/osgi/pom.xml | 2 +- plugins/oval/pom.xml | 2 +- plugins/pell-multipart/pom.xml | 2 +- plugins/plexus/pom.xml | 2 +- plugins/pom.xml | 2 +- plugins/portlet-mocks/pom.xml | 2 +- plugins/portlet-tiles/pom.xml | 2 +- plugins/portlet/pom.xml | 2 +- plugins/rest/pom.xml | 2 +- plugins/sitemesh/pom.xml | 2 +- plugins/spring/pom.xml | 2 +- plugins/testng/pom.xml | 2 +- plugins/tiles/pom.xml | 2 +- plugins/velocity/pom.xml | 2 +- pom.xml | 6 +++--- 37 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apps/pom.xml b/apps/pom.xml index ab8a81107..f1aaeeb1d 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.1 struts2-apps pom diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml index 870683b81..1920093dc 100644 --- a/apps/rest-showcase/pom.xml +++ b/apps/rest-showcase/pom.xml @@ -24,12 +24,12 @@ org.apache.struts struts2-apps - 6.1.0-SNAPSHOT + 6.0.1 struts2-rest-showcase war - 6.1.0-SNAPSHOT + 6.0.1 Struts 2 Rest Showcase Webapp Struts 2 Rest Showcase Example diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index 51b87ae26..cf8702009 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-apps - 6.1.0-SNAPSHOT + 6.0.1 struts2-showcase diff --git a/assembly/pom.xml b/assembly/pom.xml index 6773c74bd..c002a9c17 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.1 struts2-assembly diff --git a/bom/pom.xml b/bom/pom.xml index e25ca89dd..01d358f1c 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -29,7 +29,7 @@ struts2-bom - 6.1.0-SNAPSHOT + 6.0.1 pom Struts 2 Bill of Materials @@ -44,7 +44,7 @@ - 6.1.0-SNAPSHOT + 6.0.1 true true @@ -185,7 +185,7 @@ - HEAD + STRUTS_6_0_1 scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ diff --git a/bundles/admin/pom.xml b/bundles/admin/pom.xml index 395dcb80f..6ef14ab77 100644 --- a/bundles/admin/pom.xml +++ b/bundles/admin/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.1.0-SNAPSHOT + 6.0.1 struts2-osgi-admin-bundle diff --git a/bundles/demo/pom.xml b/bundles/demo/pom.xml index 7258e0dd7..3db877722 100644 --- a/bundles/demo/pom.xml +++ b/bundles/demo/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.1.0-SNAPSHOT + 6.0.1 struts2-osgi-demo-bundle diff --git a/bundles/pom.xml b/bundles/pom.xml index af4fd2d53..717927e2f 100755 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.1 struts2-osgi-bundles diff --git a/core/pom.xml b/core/pom.xml index d7cee0c16..26ff202e7 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.1 struts2-core jar diff --git a/plugins/async/pom.xml b/plugins/async/pom.xml index 4135b3e35..6305055ce 100644 --- a/plugins/async/pom.xml +++ b/plugins/async/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-async-plugin diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml index 56fe9b03d..7b9ceced8 100644 --- a/plugins/bean-validation/pom.xml +++ b/plugins/bean-validation/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 4.0.0 diff --git a/plugins/cdi/pom.xml b/plugins/cdi/pom.xml index c56349ee1..64079672b 100644 --- a/plugins/cdi/pom.xml +++ b/plugins/cdi/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-cdi-plugin diff --git a/plugins/config-browser/pom.xml b/plugins/config-browser/pom.xml index cef8a3f81..0ae43460e 100644 --- a/plugins/config-browser/pom.xml +++ b/plugins/config-browser/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-config-browser-plugin diff --git a/plugins/convention/pom.xml b/plugins/convention/pom.xml index 0157bc957..84a3346e9 100644 --- a/plugins/convention/pom.xml +++ b/plugins/convention/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-convention-plugin diff --git a/plugins/dwr/pom.xml b/plugins/dwr/pom.xml index 9f94008f0..611536f7d 100644 --- a/plugins/dwr/pom.xml +++ b/plugins/dwr/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-dwr-plugin diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml index 9da33bbc1..a9f7e0af0 100644 --- a/plugins/embeddedjsp/pom.xml +++ b/plugins/embeddedjsp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-embeddedjsp-plugin diff --git a/plugins/gxp/pom.xml b/plugins/gxp/pom.xml index d64ae471a..d0486cd05 100644 --- a/plugins/gxp/pom.xml +++ b/plugins/gxp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-gxp-plugin diff --git a/plugins/jasperreports/pom.xml b/plugins/jasperreports/pom.xml index 767d417ab..1f859e048 100644 --- a/plugins/jasperreports/pom.xml +++ b/plugins/jasperreports/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-jasperreports-plugin diff --git a/plugins/javatemplates/pom.xml b/plugins/javatemplates/pom.xml index 7b68afa12..f7c5d4984 100644 --- a/plugins/javatemplates/pom.xml +++ b/plugins/javatemplates/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-javatemplates-plugin diff --git a/plugins/jfreechart/pom.xml b/plugins/jfreechart/pom.xml index 2a587272c..d9d2abfc8 100644 --- a/plugins/jfreechart/pom.xml +++ b/plugins/jfreechart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-jfreechart-plugin diff --git a/plugins/json/pom.xml b/plugins/json/pom.xml index 047ee5ff2..6a0837c9d 100644 --- a/plugins/json/pom.xml +++ b/plugins/json/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-json-plugin diff --git a/plugins/junit/pom.xml b/plugins/junit/pom.xml index 9c43045a3..2c2c796d2 100644 --- a/plugins/junit/pom.xml +++ b/plugins/junit/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-junit-plugin diff --git a/plugins/osgi/pom.xml b/plugins/osgi/pom.xml index 98a251676..bb14a3d8a 100644 --- a/plugins/osgi/pom.xml +++ b/plugins/osgi/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-osgi-plugin diff --git a/plugins/oval/pom.xml b/plugins/oval/pom.xml index f981ae5dd..85ff250d8 100644 --- a/plugins/oval/pom.xml +++ b/plugins/oval/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-oval-plugin diff --git a/plugins/pell-multipart/pom.xml b/plugins/pell-multipart/pom.xml index 417199369..b53e4e4c9 100644 --- a/plugins/pell-multipart/pom.xml +++ b/plugins/pell-multipart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-pell-multipart-plugin diff --git a/plugins/plexus/pom.xml b/plugins/plexus/pom.xml index ca58f500e..525a455fd 100644 --- a/plugins/plexus/pom.xml +++ b/plugins/plexus/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-plexus-plugin diff --git a/plugins/pom.xml b/plugins/pom.xml index c26c1af41..69daa8687 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.1 struts2-plugins diff --git a/plugins/portlet-mocks/pom.xml b/plugins/portlet-mocks/pom.xml index a3e42df93..5cb083401 100644 --- a/plugins/portlet-mocks/pom.xml +++ b/plugins/portlet-mocks/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-portlet-mocks-plugin diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml index c13e058e5..2eec75cb2 100644 --- a/plugins/portlet-tiles/pom.xml +++ b/plugins/portlet-tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-portlet-tiles-plugin diff --git a/plugins/portlet/pom.xml b/plugins/portlet/pom.xml index 151dab478..107fe4f8a 100644 --- a/plugins/portlet/pom.xml +++ b/plugins/portlet/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-portlet-plugin diff --git a/plugins/rest/pom.xml b/plugins/rest/pom.xml index ef9792d55..d5c7a10c3 100644 --- a/plugins/rest/pom.xml +++ b/plugins/rest/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-rest-plugin diff --git a/plugins/sitemesh/pom.xml b/plugins/sitemesh/pom.xml index e0492252f..37fed246c 100644 --- a/plugins/sitemesh/pom.xml +++ b/plugins/sitemesh/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-sitemesh-plugin diff --git a/plugins/spring/pom.xml b/plugins/spring/pom.xml index b2b0d5662..bfcab1e11 100644 --- a/plugins/spring/pom.xml +++ b/plugins/spring/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-spring-plugin diff --git a/plugins/testng/pom.xml b/plugins/testng/pom.xml index 823941ba1..92a441627 100644 --- a/plugins/testng/pom.xml +++ b/plugins/testng/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-testng-plugin diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index 21eb1a95f..47708a2ef 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-tiles-plugin diff --git a/plugins/velocity/pom.xml b/plugins/velocity/pom.xml index 4edd24379..a5f058d92 100644 --- a/plugins/velocity/pom.xml +++ b/plugins/velocity/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.1 struts2-velocity-plugin diff --git a/pom.xml b/pom.xml index 7b9401ae6..61cb25208 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 4.0.0 struts2-parent - 6.1.0-SNAPSHOT + 6.0.1 pom Struts 2 http://struts.apache.org/ @@ -51,7 +51,7 @@ scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ - HEAD + STRUTS_6_0_1 @@ -104,7 +104,7 @@ UTF-8 - 2022-06-02T07:11:11Z + 2022-08-12T15:22:43Z 1.8 1.8 From b1c1be6e405f8be5afa150b06f439c1d8adc0529 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 12 Aug 2022 17:26:55 +0200 Subject: [PATCH 013/143] [maven-release-plugin] prepare for next development iteration --- apps/pom.xml | 2 +- apps/rest-showcase/pom.xml | 4 ++-- apps/showcase/pom.xml | 2 +- assembly/pom.xml | 2 +- bom/pom.xml | 6 +++--- bundles/admin/pom.xml | 2 +- bundles/demo/pom.xml | 2 +- bundles/pom.xml | 2 +- core/pom.xml | 2 +- plugins/async/pom.xml | 2 +- plugins/bean-validation/pom.xml | 2 +- plugins/cdi/pom.xml | 2 +- plugins/config-browser/pom.xml | 2 +- plugins/convention/pom.xml | 2 +- plugins/dwr/pom.xml | 2 +- plugins/embeddedjsp/pom.xml | 2 +- plugins/gxp/pom.xml | 2 +- plugins/jasperreports/pom.xml | 2 +- plugins/javatemplates/pom.xml | 2 +- plugins/jfreechart/pom.xml | 2 +- plugins/json/pom.xml | 2 +- plugins/junit/pom.xml | 2 +- plugins/osgi/pom.xml | 2 +- plugins/oval/pom.xml | 2 +- plugins/pell-multipart/pom.xml | 2 +- plugins/plexus/pom.xml | 2 +- plugins/pom.xml | 2 +- plugins/portlet-mocks/pom.xml | 2 +- plugins/portlet-tiles/pom.xml | 2 +- plugins/portlet/pom.xml | 2 +- plugins/rest/pom.xml | 2 +- plugins/sitemesh/pom.xml | 2 +- plugins/spring/pom.xml | 2 +- plugins/testng/pom.xml | 2 +- plugins/tiles/pom.xml | 2 +- plugins/velocity/pom.xml | 2 +- pom.xml | 6 +++--- 37 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apps/pom.xml b/apps/pom.xml index f1aaeeb1d..ab8a81107 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.1 + 6.1.0-SNAPSHOT struts2-apps pom diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml index 1920093dc..870683b81 100644 --- a/apps/rest-showcase/pom.xml +++ b/apps/rest-showcase/pom.xml @@ -24,12 +24,12 @@ org.apache.struts struts2-apps - 6.0.1 + 6.1.0-SNAPSHOT struts2-rest-showcase war - 6.0.1 + 6.1.0-SNAPSHOT Struts 2 Rest Showcase Webapp Struts 2 Rest Showcase Example diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index cf8702009..51b87ae26 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-apps - 6.0.1 + 6.1.0-SNAPSHOT struts2-showcase diff --git a/assembly/pom.xml b/assembly/pom.xml index c002a9c17..6773c74bd 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.1 + 6.1.0-SNAPSHOT struts2-assembly diff --git a/bom/pom.xml b/bom/pom.xml index 01d358f1c..e25ca89dd 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -29,7 +29,7 @@ struts2-bom - 6.0.1 + 6.1.0-SNAPSHOT pom Struts 2 Bill of Materials @@ -44,7 +44,7 @@ - 6.0.1 + 6.1.0-SNAPSHOT true true @@ -185,7 +185,7 @@ - STRUTS_6_0_1 + HEAD scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ diff --git a/bundles/admin/pom.xml b/bundles/admin/pom.xml index 6ef14ab77..395dcb80f 100644 --- a/bundles/admin/pom.xml +++ b/bundles/admin/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.0.1 + 6.1.0-SNAPSHOT struts2-osgi-admin-bundle diff --git a/bundles/demo/pom.xml b/bundles/demo/pom.xml index 3db877722..7258e0dd7 100644 --- a/bundles/demo/pom.xml +++ b/bundles/demo/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.0.1 + 6.1.0-SNAPSHOT struts2-osgi-demo-bundle diff --git a/bundles/pom.xml b/bundles/pom.xml index 717927e2f..af4fd2d53 100755 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.1 + 6.1.0-SNAPSHOT struts2-osgi-bundles diff --git a/core/pom.xml b/core/pom.xml index 26ff202e7..d7cee0c16 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.1 + 6.1.0-SNAPSHOT struts2-core jar diff --git a/plugins/async/pom.xml b/plugins/async/pom.xml index 6305055ce..4135b3e35 100644 --- a/plugins/async/pom.xml +++ b/plugins/async/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-async-plugin diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml index 7b9ceced8..56fe9b03d 100644 --- a/plugins/bean-validation/pom.xml +++ b/plugins/bean-validation/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/plugins/cdi/pom.xml b/plugins/cdi/pom.xml index 64079672b..c56349ee1 100644 --- a/plugins/cdi/pom.xml +++ b/plugins/cdi/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-cdi-plugin diff --git a/plugins/config-browser/pom.xml b/plugins/config-browser/pom.xml index 0ae43460e..cef8a3f81 100644 --- a/plugins/config-browser/pom.xml +++ b/plugins/config-browser/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-config-browser-plugin diff --git a/plugins/convention/pom.xml b/plugins/convention/pom.xml index 84a3346e9..0157bc957 100644 --- a/plugins/convention/pom.xml +++ b/plugins/convention/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-convention-plugin diff --git a/plugins/dwr/pom.xml b/plugins/dwr/pom.xml index 611536f7d..9f94008f0 100644 --- a/plugins/dwr/pom.xml +++ b/plugins/dwr/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-dwr-plugin diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml index a9f7e0af0..9da33bbc1 100644 --- a/plugins/embeddedjsp/pom.xml +++ b/plugins/embeddedjsp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-embeddedjsp-plugin diff --git a/plugins/gxp/pom.xml b/plugins/gxp/pom.xml index d0486cd05..d64ae471a 100644 --- a/plugins/gxp/pom.xml +++ b/plugins/gxp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-gxp-plugin diff --git a/plugins/jasperreports/pom.xml b/plugins/jasperreports/pom.xml index 1f859e048..767d417ab 100644 --- a/plugins/jasperreports/pom.xml +++ b/plugins/jasperreports/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-jasperreports-plugin diff --git a/plugins/javatemplates/pom.xml b/plugins/javatemplates/pom.xml index f7c5d4984..7b68afa12 100644 --- a/plugins/javatemplates/pom.xml +++ b/plugins/javatemplates/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-javatemplates-plugin diff --git a/plugins/jfreechart/pom.xml b/plugins/jfreechart/pom.xml index d9d2abfc8..2a587272c 100644 --- a/plugins/jfreechart/pom.xml +++ b/plugins/jfreechart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-jfreechart-plugin diff --git a/plugins/json/pom.xml b/plugins/json/pom.xml index 6a0837c9d..047ee5ff2 100644 --- a/plugins/json/pom.xml +++ b/plugins/json/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-json-plugin diff --git a/plugins/junit/pom.xml b/plugins/junit/pom.xml index 2c2c796d2..9c43045a3 100644 --- a/plugins/junit/pom.xml +++ b/plugins/junit/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-junit-plugin diff --git a/plugins/osgi/pom.xml b/plugins/osgi/pom.xml index bb14a3d8a..98a251676 100644 --- a/plugins/osgi/pom.xml +++ b/plugins/osgi/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-osgi-plugin diff --git a/plugins/oval/pom.xml b/plugins/oval/pom.xml index 85ff250d8..f981ae5dd 100644 --- a/plugins/oval/pom.xml +++ b/plugins/oval/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-oval-plugin diff --git a/plugins/pell-multipart/pom.xml b/plugins/pell-multipart/pom.xml index b53e4e4c9..417199369 100644 --- a/plugins/pell-multipart/pom.xml +++ b/plugins/pell-multipart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-pell-multipart-plugin diff --git a/plugins/plexus/pom.xml b/plugins/plexus/pom.xml index 525a455fd..ca58f500e 100644 --- a/plugins/plexus/pom.xml +++ b/plugins/plexus/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-plexus-plugin diff --git a/plugins/pom.xml b/plugins/pom.xml index 69daa8687..c26c1af41 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.1 + 6.1.0-SNAPSHOT struts2-plugins diff --git a/plugins/portlet-mocks/pom.xml b/plugins/portlet-mocks/pom.xml index 5cb083401..a3e42df93 100644 --- a/plugins/portlet-mocks/pom.xml +++ b/plugins/portlet-mocks/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-portlet-mocks-plugin diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml index 2eec75cb2..c13e058e5 100644 --- a/plugins/portlet-tiles/pom.xml +++ b/plugins/portlet-tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-portlet-tiles-plugin diff --git a/plugins/portlet/pom.xml b/plugins/portlet/pom.xml index 107fe4f8a..151dab478 100644 --- a/plugins/portlet/pom.xml +++ b/plugins/portlet/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-portlet-plugin diff --git a/plugins/rest/pom.xml b/plugins/rest/pom.xml index d5c7a10c3..ef9792d55 100644 --- a/plugins/rest/pom.xml +++ b/plugins/rest/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-rest-plugin diff --git a/plugins/sitemesh/pom.xml b/plugins/sitemesh/pom.xml index 37fed246c..e0492252f 100644 --- a/plugins/sitemesh/pom.xml +++ b/plugins/sitemesh/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-sitemesh-plugin diff --git a/plugins/spring/pom.xml b/plugins/spring/pom.xml index bfcab1e11..b2b0d5662 100644 --- a/plugins/spring/pom.xml +++ b/plugins/spring/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-spring-plugin diff --git a/plugins/testng/pom.xml b/plugins/testng/pom.xml index 92a441627..823941ba1 100644 --- a/plugins/testng/pom.xml +++ b/plugins/testng/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-testng-plugin diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index 47708a2ef..21eb1a95f 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-tiles-plugin diff --git a/plugins/velocity/pom.xml b/plugins/velocity/pom.xml index a5f058d92..4edd24379 100644 --- a/plugins/velocity/pom.xml +++ b/plugins/velocity/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.1 + 6.1.0-SNAPSHOT struts2-velocity-plugin diff --git a/pom.xml b/pom.xml index 61cb25208..ddf08f831 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 4.0.0 struts2-parent - 6.0.1 + 6.1.0-SNAPSHOT pom Struts 2 http://struts.apache.org/ @@ -51,7 +51,7 @@ scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ - STRUTS_6_0_1 + HEAD @@ -104,7 +104,7 @@ UTF-8 - 2022-08-12T15:22:43Z + 2022-08-12T15:26:55Z 1.8 1.8 From 74d4e2371616f4e51fe9986f916271554080ddd1 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 23 Aug 2022 20:31:39 +0200 Subject: [PATCH 014/143] WW-5215 Checks is session was already created before applying CSP settings --- .../interceptor/csp/CspInterceptor.java | 5 +- .../struts2/interceptor/csp/CspSettings.java | 9 ++ .../interceptor/csp/DefaultCspSettings.java | 83 ++++++++++------- .../interceptor/CspInterceptorTest.java | 91 +++++++++++-------- 4 files changed, 112 insertions(+), 76 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java index 250179636..ca77436cc 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java @@ -23,6 +23,7 @@ import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import com.opensymphony.xwork2.interceptor.PreResultListener; import java.net.URI; import java.util.Optional; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** @@ -36,6 +37,7 @@ import javax.servlet.http.HttpServletResponse; * @see DefaultCspSettings **/ public final class CspInterceptor extends AbstractInterceptor implements PreResultListener { + private final CspSettings settings = new DefaultCspSettings(); @Override @@ -45,8 +47,9 @@ public final class CspInterceptor extends AbstractInterceptor implements PreResu } public void beforeResult(ActionInvocation invocation, String resultCode) { + HttpServletRequest request = invocation.getInvocationContext().getServletRequest(); HttpServletResponse response = invocation.getInvocationContext().getServletResponse(); - settings.addCspHeaders(response); + settings.addCspHeaders(request, response); } public void setReportUri(String reportUri) { diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/CspSettings.java b/core/src/main/java/org/apache/struts2/interceptor/csp/CspSettings.java index 9699ab291..adf5b5072 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspSettings.java +++ b/core/src/main/java/org/apache/struts2/interceptor/csp/CspSettings.java @@ -18,6 +18,7 @@ */ package org.apache.struts2.interceptor.csp; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** @@ -42,9 +43,17 @@ public interface CspSettings { String HTTPS = "https:"; String CSP_REPORT_TYPE = "application/csp-report"; + /** + * @deprecated use {@link #addCspHeaders(HttpServletRequest, HttpServletResponse)} instead + */ + @Deprecated void addCspHeaders(HttpServletResponse response); + + void addCspHeaders(HttpServletRequest request, HttpServletResponse response); + // sets the uri where csp violation reports will be sent void setReportUri(String uri); + // sets CSP headers in enforcing mode when true, and report-only when false void setEnforcingMode(boolean value); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java b/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java index 5a99c0a5b..7ab70d226 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java +++ b/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java @@ -18,13 +18,14 @@ */ package org.apache.struts2.interceptor.csp; -import com.opensymphony.xwork2.ActionContext; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.security.SecureRandom; import java.util.Base64; -import java.util.Map; -import java.util.function.Supplier; +import java.util.Objects; import static java.lang.String.format; @@ -37,50 +38,61 @@ import static java.lang.String.format; */ public class DefaultCspSettings implements CspSettings { + private final static Logger LOG = LogManager.getLogger(DefaultCspSettings.class); + private final SecureRandom sRand = new SecureRandom(); - // this supplier computes a policy format - private final Supplier lazyPolicyBuilder = new Supplier() { - @Override - public String get() { - StringBuilder policyFormatBuilder = new StringBuilder() - .append(OBJECT_SRC) - .append(format(" '%s'; ", NONE)) - .append(SCRIPT_SRC) - .append(" 'nonce-%s' ") // nonce placeholder - .append(format("'%s' ", STRICT_DYNAMIC)) - .append(format("%s %s; ", HTTP, HTTPS)) - .append(BASE_URI) - .append(format(" '%s'; ", NONE)); - - if (reportUri != null) { - policyFormatBuilder - .append(REPORT_URI) - .append(format(" %s", reportUri)); - } - - return format(policyFormatBuilder.toString(), getNonceString()); - } - }; - private String reportUri; // default to reporting mode private String cspHeader = CSP_REPORT_HEADER; + @Override public void addCspHeaders(HttpServletResponse response) { - associateNonceWithSession(); - response.setHeader(cspHeader, lazyPolicyBuilder.get()); + throw new UnsupportedOperationException("Unsupported implementation, use #addCspHeaders(HttpServletRequest request, HttpServletResponse response)"); } - private String getNonceString() { - Map session = ActionContext.getContext().getSession(); - return (String) session.get("nonce"); + public void addCspHeaders(HttpServletRequest request, HttpServletResponse response) { + if (isSessionActive(request)) { + LOG.debug("Session is active, applying CSP settings"); + associateNonceWithSession(request); + response.setHeader(cspHeader, cratePolicyFormat(request)); + } else { + LOG.debug("Session is not active, ignoring CSP settings"); + } } - private void associateNonceWithSession() { - Map session = ActionContext.getContext().getSession(); + private boolean isSessionActive(HttpServletRequest request) { + return request.getSession(false) != null; + } + + private void associateNonceWithSession(HttpServletRequest request) { String nonceValue = Base64.getUrlEncoder().encodeToString(getRandomBytes()); - session.put("nonce", nonceValue); + request.getSession().setAttribute("nonce", nonceValue); + } + + private String cratePolicyFormat(HttpServletRequest request) { + StringBuilder policyFormatBuilder = new StringBuilder() + .append(OBJECT_SRC) + .append(format(" '%s'; ", NONE)) + .append(SCRIPT_SRC) + .append(" 'nonce-%s' ") // nonce placeholder + .append(format("'%s' ", STRICT_DYNAMIC)) + .append(format("%s %s; ", HTTP, HTTPS)) + .append(BASE_URI) + .append(format(" '%s'; ", NONE)); + + if (reportUri != null) { + policyFormatBuilder + .append(REPORT_URI) + .append(format(" %s", reportUri)); + } + + return format(policyFormatBuilder.toString(), getNonceString(request)); + } + + private String getNonceString(HttpServletRequest request) { + Object nonce = request.getSession().getAttribute("nonce"); + return Objects.toString(nonce); } private byte[] getRandomBytes() { @@ -98,4 +110,5 @@ public class DefaultCspSettings implements CspSettings { public void setReportUri(String reportUri) { this.reportUri = reportUri; } + } diff --git a/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java index 504be8bb4..a9ee1be11 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java @@ -21,16 +21,25 @@ package org.apache.struts2.interceptor; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.mock.MockActionInvocation; import org.apache.logging.log4j.util.Strings; -import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsInternalTestCase; +import org.apache.struts2.dispatcher.SessionMap; import org.apache.struts2.interceptor.csp.CspInterceptor; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; -import java.util.HashMap; -import java.util.Map; +import javax.servlet.http.HttpSession; -import static org.apache.struts2.interceptor.csp.CspSettings.*; +import static org.apache.struts2.interceptor.csp.CspSettings.BASE_URI; +import static org.apache.struts2.interceptor.csp.CspSettings.CSP_ENFORCE_HEADER; +import static org.apache.struts2.interceptor.csp.CspSettings.CSP_REPORT_HEADER; +import static org.apache.struts2.interceptor.csp.CspSettings.HTTP; +import static org.apache.struts2.interceptor.csp.CspSettings.HTTPS; +import static org.apache.struts2.interceptor.csp.CspSettings.NONE; +import static org.apache.struts2.interceptor.csp.CspSettings.OBJECT_SRC; +import static org.apache.struts2.interceptor.csp.CspSettings.REPORT_URI; +import static org.apache.struts2.interceptor.csp.CspSettings.SCRIPT_SRC; +import static org.apache.struts2.interceptor.csp.CspSettings.STRICT_DYNAMIC; +import static org.junit.Assert.assertNotEquals; public class CspInterceptorTest extends StrutsInternalTestCase { @@ -38,7 +47,8 @@ public class CspInterceptorTest extends StrutsInternalTestCase { private final MockActionInvocation mai = new MockActionInvocation(); private final MockHttpServletRequest request = new MockHttpServletRequest(); private final MockHttpServletResponse response = new MockHttpServletResponse(); - private final Map session = new HashMap<>(); + + private HttpSession session; public void test_whenRequestReceived_thenNonceIsSetInSession_andCspHeaderContainsIt() throws Exception { String reportUri = "/barfoo"; @@ -48,8 +58,8 @@ public class CspInterceptorTest extends StrutsInternalTestCase { interceptor.intercept(mai); - assertTrue("Nonce key does not exist", session.containsKey("nonce")); - assertFalse("Nonce value is empty", Strings.isEmpty((String) session.get("nonce"))); + assertNotNull("Nonce key does not exist", session.getAttribute("nonce")); + assertFalse("Nonce value is empty", Strings.isEmpty((String) session.getAttribute("nonce"))); checkHeader(reportUri, reporting); } @@ -58,13 +68,13 @@ public class CspInterceptorTest extends StrutsInternalTestCase { String enforcingMode = "true"; interceptor.setReportUri(reportUri); interceptor.setEnforcingMode(enforcingMode); - session.put("nonce", "foo"); + session.setAttribute("nonce", "foo"); interceptor.intercept(mai); - assertTrue("Nonce key does not exist", session.containsKey("nonce")); - assertFalse("Nonce value is empty", Strings.isEmpty((String) session.get("nonce"))); - assertFalse("New nonce value couldn't be set", session.get("nonce").equals("foo")); + assertNotNull("Nonce key does not exist", session.getAttribute("nonce")); + assertFalse("Nonce value is empty", Strings.isEmpty((String) session.getAttribute("nonce"))); + assertNotEquals("New nonce value couldn't be set", "foo", session.getAttribute("nonce")); checkHeader(reportUri, enforcingMode); } @@ -73,13 +83,13 @@ public class CspInterceptorTest extends StrutsInternalTestCase { String enforcingMode = "true"; interceptor.setReportUri(reportUri); interceptor.setEnforcingMode(enforcingMode); - session.put("nonce", "foo"); + session.setAttribute("nonce", "foo"); interceptor.intercept(mai); - assertTrue("Nonce key does not exist", session.containsKey("nonce")); - assertFalse("Nonce value is empty", Strings.isEmpty((String) session.get("nonce"))); - assertFalse("New nonce value couldn't be set", session.get("nonce").equals("foo")); + assertNotNull("Nonce key does not exist", session.getAttribute("nonce")); + assertFalse("Nonce value is empty", Strings.isEmpty((String) session.getAttribute("nonce"))); + assertNotEquals("New nonce value couldn't be set", "foo", session.getAttribute("nonce")); checkHeader(reportUri, enforcingMode); } @@ -88,13 +98,12 @@ public class CspInterceptorTest extends StrutsInternalTestCase { String enforcingMode = "false"; interceptor.setReportUri(reportUri); interceptor.setEnforcingMode(enforcingMode); - session.put("nonce", "foo"); + session.setAttribute("nonce", "foo"); interceptor.intercept(mai); - assertTrue("Nonce key does not exist", session.containsKey("nonce")); - assertFalse("Nonce value is empty", Strings.isEmpty((String) session.get("nonce"))); - assertFalse("New nonce value couldn't be set", session.get("nonce").equals("foo")); + assertNotNull("Nonce value is empty", session.getAttribute("nonce")); + assertNotEquals("New nonce value couldn't be set", "foo", session.getAttribute("nonce")); checkHeader(reportUri, enforcingMode); } @@ -116,11 +125,11 @@ public class CspInterceptorTest extends StrutsInternalTestCase { String enforcingMode = "false"; interceptor.setEnforcingMode(enforcingMode); - try{ + try { interceptor.setReportUri("ww w. google.@com"); - assert(false); - } catch (IllegalArgumentException e){ - assert(true); + assert (false); + } catch (IllegalArgumentException e) { + assert (true); } } @@ -128,33 +137,33 @@ public class CspInterceptorTest extends StrutsInternalTestCase { String enforcingMode = "false"; interceptor.setEnforcingMode(enforcingMode); - try{ + try { interceptor.setReportUri("some-uri"); - assert(false); - } catch (IllegalArgumentException e){ - assert(true); + assert (false); + } catch (IllegalArgumentException e) { + assert (true); } } - public void checkHeader(String reportUri, String enforcingMode){ + public void checkHeader(String reportUri, String enforcingMode) { String expectedCspHeader = ""; if (Strings.isEmpty(reportUri)) { expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s '%s'; ", - OBJECT_SRC, NONE, - SCRIPT_SRC, session.get("nonce"), STRICT_DYNAMIC, HTTP, HTTPS, - BASE_URI, NONE + OBJECT_SRC, NONE, + SCRIPT_SRC, session.getAttribute("nonce"), STRICT_DYNAMIC, HTTP, HTTPS, + BASE_URI, NONE ); } else { expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s '%s'; %s %s", - OBJECT_SRC, NONE, - SCRIPT_SRC, session.get("nonce"), STRICT_DYNAMIC, HTTP, HTTPS, - BASE_URI, NONE, - REPORT_URI, reportUri + OBJECT_SRC, NONE, + SCRIPT_SRC, session.getAttribute("nonce"), STRICT_DYNAMIC, HTTP, HTTPS, + BASE_URI, NONE, + REPORT_URI, reportUri ); } String header = ""; - if (enforcingMode.equals("true")){ + if (enforcingMode.equals("true")) { header = response.getHeader(CSP_ENFORCE_HEADER); } else { header = response.getHeader(CSP_REPORT_HEADER); @@ -168,10 +177,12 @@ public class CspInterceptorTest extends StrutsInternalTestCase { protected void setUp() throws Exception { super.setUp(); container.inject(interceptor); - ServletActionContext.setRequest(request); - ServletActionContext.setResponse(response); - ActionContext context = ServletActionContext.getActionContext().bind(); - context.withSession(session); + ActionContext context = ActionContext.getContext() + .withServletRequest(request) + .withServletResponse(response) + .withSession(new SessionMap<>(request)) + .bind(); mai.setInvocationContext(context); + session = request.getSession(); } } From 2707bf04893f1594186020e8b33028c75f9e0c2c Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 23 Aug 2022 20:50:39 +0200 Subject: [PATCH 015/143] WW-5215 Explicitly creates session in test --- .../struts2/views/freemarker/FreemarkerResultMockedTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerResultMockedTest.java b/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerResultMockedTest.java index 49e7abeae..f0fa5d3ba 100644 --- a/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerResultMockedTest.java +++ b/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerResultMockedTest.java @@ -259,6 +259,8 @@ public class FreemarkerResultMockedTest extends StrutsInternalTestCase { EasyMock.replay(servletContext); init(); + // create session + request.getSession(); request.setRequestURI("/tutorial/test10.action"); ActionMapping mapping = container.getInstance(ActionMapper.class).getMapping(request, configurationManager); From 23969abc196b27adb1ad606b2fd7db6fbd5ec0d1 Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Wed, 24 Aug 2022 22:54:37 +0200 Subject: [PATCH 016/143] Update maven-enforcer-plugin to 3.1.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ddf08f831..63dddbc80 100644 --- a/pom.xml +++ b/pom.xml @@ -392,7 +392,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M3 + 3.1.0 enforce From 1380802b75adc662145fcf5c367bd73db3d3d1a0 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 25 Aug 2022 07:39:40 +0200 Subject: [PATCH 017/143] [maven-release-plugin] prepare release STRUTS_6_0_2 --- apps/pom.xml | 2 +- apps/rest-showcase/pom.xml | 4 ++-- apps/showcase/pom.xml | 2 +- assembly/pom.xml | 2 +- bom/pom.xml | 6 +++--- bundles/admin/pom.xml | 2 +- bundles/demo/pom.xml | 2 +- bundles/pom.xml | 2 +- core/pom.xml | 2 +- plugins/async/pom.xml | 2 +- plugins/bean-validation/pom.xml | 2 +- plugins/cdi/pom.xml | 2 +- plugins/config-browser/pom.xml | 2 +- plugins/convention/pom.xml | 2 +- plugins/dwr/pom.xml | 2 +- plugins/embeddedjsp/pom.xml | 2 +- plugins/gxp/pom.xml | 2 +- plugins/jasperreports/pom.xml | 2 +- plugins/javatemplates/pom.xml | 2 +- plugins/jfreechart/pom.xml | 2 +- plugins/json/pom.xml | 2 +- plugins/junit/pom.xml | 2 +- plugins/osgi/pom.xml | 2 +- plugins/oval/pom.xml | 2 +- plugins/pell-multipart/pom.xml | 2 +- plugins/plexus/pom.xml | 2 +- plugins/pom.xml | 2 +- plugins/portlet-mocks/pom.xml | 2 +- plugins/portlet-tiles/pom.xml | 2 +- plugins/portlet/pom.xml | 2 +- plugins/rest/pom.xml | 2 +- plugins/sitemesh/pom.xml | 2 +- plugins/spring/pom.xml | 2 +- plugins/testng/pom.xml | 2 +- plugins/tiles/pom.xml | 2 +- plugins/velocity/pom.xml | 2 +- pom.xml | 6 +++--- 37 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apps/pom.xml b/apps/pom.xml index ab8a81107..b500bd893 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.2 struts2-apps pom diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml index 870683b81..45748bcd8 100644 --- a/apps/rest-showcase/pom.xml +++ b/apps/rest-showcase/pom.xml @@ -24,12 +24,12 @@ org.apache.struts struts2-apps - 6.1.0-SNAPSHOT + 6.0.2 struts2-rest-showcase war - 6.1.0-SNAPSHOT + 6.0.2 Struts 2 Rest Showcase Webapp Struts 2 Rest Showcase Example diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index 51b87ae26..7c78a2666 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-apps - 6.1.0-SNAPSHOT + 6.0.2 struts2-showcase diff --git a/assembly/pom.xml b/assembly/pom.xml index 6773c74bd..c49b5f1cb 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.2 struts2-assembly diff --git a/bom/pom.xml b/bom/pom.xml index e25ca89dd..266ba5d51 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -29,7 +29,7 @@ struts2-bom - 6.1.0-SNAPSHOT + 6.0.2 pom Struts 2 Bill of Materials @@ -44,7 +44,7 @@ - 6.1.0-SNAPSHOT + 6.0.2 true true @@ -185,7 +185,7 @@ - HEAD + STRUTS_6_0_2 scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ diff --git a/bundles/admin/pom.xml b/bundles/admin/pom.xml index 395dcb80f..3553e30dd 100644 --- a/bundles/admin/pom.xml +++ b/bundles/admin/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.1.0-SNAPSHOT + 6.0.2 struts2-osgi-admin-bundle diff --git a/bundles/demo/pom.xml b/bundles/demo/pom.xml index 7258e0dd7..951a590b7 100644 --- a/bundles/demo/pom.xml +++ b/bundles/demo/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.1.0-SNAPSHOT + 6.0.2 struts2-osgi-demo-bundle diff --git a/bundles/pom.xml b/bundles/pom.xml index af4fd2d53..0822084ba 100755 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.2 struts2-osgi-bundles diff --git a/core/pom.xml b/core/pom.xml index d7cee0c16..ae398b37d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.2 struts2-core jar diff --git a/plugins/async/pom.xml b/plugins/async/pom.xml index 4135b3e35..6b1bbac34 100644 --- a/plugins/async/pom.xml +++ b/plugins/async/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-async-plugin diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml index 56fe9b03d..4af66aff7 100644 --- a/plugins/bean-validation/pom.xml +++ b/plugins/bean-validation/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 4.0.0 diff --git a/plugins/cdi/pom.xml b/plugins/cdi/pom.xml index c56349ee1..6bf5fcf78 100644 --- a/plugins/cdi/pom.xml +++ b/plugins/cdi/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-cdi-plugin diff --git a/plugins/config-browser/pom.xml b/plugins/config-browser/pom.xml index cef8a3f81..1c4b00514 100644 --- a/plugins/config-browser/pom.xml +++ b/plugins/config-browser/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-config-browser-plugin diff --git a/plugins/convention/pom.xml b/plugins/convention/pom.xml index 0157bc957..71a54a81a 100644 --- a/plugins/convention/pom.xml +++ b/plugins/convention/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-convention-plugin diff --git a/plugins/dwr/pom.xml b/plugins/dwr/pom.xml index 9f94008f0..2b660d5ec 100644 --- a/plugins/dwr/pom.xml +++ b/plugins/dwr/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-dwr-plugin diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml index 9da33bbc1..ee4eb76c3 100644 --- a/plugins/embeddedjsp/pom.xml +++ b/plugins/embeddedjsp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-embeddedjsp-plugin diff --git a/plugins/gxp/pom.xml b/plugins/gxp/pom.xml index d64ae471a..42765df4f 100644 --- a/plugins/gxp/pom.xml +++ b/plugins/gxp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-gxp-plugin diff --git a/plugins/jasperreports/pom.xml b/plugins/jasperreports/pom.xml index 767d417ab..a6de5f8d6 100644 --- a/plugins/jasperreports/pom.xml +++ b/plugins/jasperreports/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-jasperreports-plugin diff --git a/plugins/javatemplates/pom.xml b/plugins/javatemplates/pom.xml index 7b68afa12..4eabfa7cc 100644 --- a/plugins/javatemplates/pom.xml +++ b/plugins/javatemplates/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-javatemplates-plugin diff --git a/plugins/jfreechart/pom.xml b/plugins/jfreechart/pom.xml index 2a587272c..ff6253eff 100644 --- a/plugins/jfreechart/pom.xml +++ b/plugins/jfreechart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-jfreechart-plugin diff --git a/plugins/json/pom.xml b/plugins/json/pom.xml index 047ee5ff2..5804ad25f 100644 --- a/plugins/json/pom.xml +++ b/plugins/json/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-json-plugin diff --git a/plugins/junit/pom.xml b/plugins/junit/pom.xml index 9c43045a3..b7e601b28 100644 --- a/plugins/junit/pom.xml +++ b/plugins/junit/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-junit-plugin diff --git a/plugins/osgi/pom.xml b/plugins/osgi/pom.xml index 98a251676..7928b58bc 100644 --- a/plugins/osgi/pom.xml +++ b/plugins/osgi/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-osgi-plugin diff --git a/plugins/oval/pom.xml b/plugins/oval/pom.xml index f981ae5dd..d1be18b4e 100644 --- a/plugins/oval/pom.xml +++ b/plugins/oval/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-oval-plugin diff --git a/plugins/pell-multipart/pom.xml b/plugins/pell-multipart/pom.xml index 417199369..2546e7644 100644 --- a/plugins/pell-multipart/pom.xml +++ b/plugins/pell-multipart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-pell-multipart-plugin diff --git a/plugins/plexus/pom.xml b/plugins/plexus/pom.xml index ca58f500e..25b597612 100644 --- a/plugins/plexus/pom.xml +++ b/plugins/plexus/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-plexus-plugin diff --git a/plugins/pom.xml b/plugins/pom.xml index c26c1af41..61741cb7a 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.2 struts2-plugins diff --git a/plugins/portlet-mocks/pom.xml b/plugins/portlet-mocks/pom.xml index a3e42df93..ceb81fa0a 100644 --- a/plugins/portlet-mocks/pom.xml +++ b/plugins/portlet-mocks/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-portlet-mocks-plugin diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml index c13e058e5..83370cc21 100644 --- a/plugins/portlet-tiles/pom.xml +++ b/plugins/portlet-tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-portlet-tiles-plugin diff --git a/plugins/portlet/pom.xml b/plugins/portlet/pom.xml index 151dab478..468a7d8c5 100644 --- a/plugins/portlet/pom.xml +++ b/plugins/portlet/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-portlet-plugin diff --git a/plugins/rest/pom.xml b/plugins/rest/pom.xml index ef9792d55..4e6a16b48 100644 --- a/plugins/rest/pom.xml +++ b/plugins/rest/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-rest-plugin diff --git a/plugins/sitemesh/pom.xml b/plugins/sitemesh/pom.xml index e0492252f..080596e23 100644 --- a/plugins/sitemesh/pom.xml +++ b/plugins/sitemesh/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-sitemesh-plugin diff --git a/plugins/spring/pom.xml b/plugins/spring/pom.xml index b2b0d5662..508d01306 100644 --- a/plugins/spring/pom.xml +++ b/plugins/spring/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-spring-plugin diff --git a/plugins/testng/pom.xml b/plugins/testng/pom.xml index 823941ba1..01c32a7e8 100644 --- a/plugins/testng/pom.xml +++ b/plugins/testng/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-testng-plugin diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index 21eb1a95f..a04fe7528 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-tiles-plugin diff --git a/plugins/velocity/pom.xml b/plugins/velocity/pom.xml index 4edd24379..f3cb13e79 100644 --- a/plugins/velocity/pom.xml +++ b/plugins/velocity/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.2 struts2-velocity-plugin diff --git a/pom.xml b/pom.xml index 63dddbc80..f59b9828c 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 4.0.0 struts2-parent - 6.1.0-SNAPSHOT + 6.0.2 pom Struts 2 http://struts.apache.org/ @@ -51,7 +51,7 @@ scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ - HEAD + STRUTS_6_0_2 @@ -104,7 +104,7 @@ UTF-8 - 2022-08-12T15:26:55Z + 2022-08-25T05:35:35Z 1.8 1.8 From cdb70e6bed4fa57c880384603ef68b81056fea5a Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 25 Aug 2022 07:39:48 +0200 Subject: [PATCH 018/143] [maven-release-plugin] prepare for next development iteration --- apps/pom.xml | 2 +- apps/rest-showcase/pom.xml | 4 ++-- apps/showcase/pom.xml | 2 +- assembly/pom.xml | 2 +- bom/pom.xml | 6 +++--- bundles/admin/pom.xml | 2 +- bundles/demo/pom.xml | 2 +- bundles/pom.xml | 2 +- core/pom.xml | 2 +- plugins/async/pom.xml | 2 +- plugins/bean-validation/pom.xml | 2 +- plugins/cdi/pom.xml | 2 +- plugins/config-browser/pom.xml | 2 +- plugins/convention/pom.xml | 2 +- plugins/dwr/pom.xml | 2 +- plugins/embeddedjsp/pom.xml | 2 +- plugins/gxp/pom.xml | 2 +- plugins/jasperreports/pom.xml | 2 +- plugins/javatemplates/pom.xml | 2 +- plugins/jfreechart/pom.xml | 2 +- plugins/json/pom.xml | 2 +- plugins/junit/pom.xml | 2 +- plugins/osgi/pom.xml | 2 +- plugins/oval/pom.xml | 2 +- plugins/pell-multipart/pom.xml | 2 +- plugins/plexus/pom.xml | 2 +- plugins/pom.xml | 2 +- plugins/portlet-mocks/pom.xml | 2 +- plugins/portlet-tiles/pom.xml | 2 +- plugins/portlet/pom.xml | 2 +- plugins/rest/pom.xml | 2 +- plugins/sitemesh/pom.xml | 2 +- plugins/spring/pom.xml | 2 +- plugins/testng/pom.xml | 2 +- plugins/tiles/pom.xml | 2 +- plugins/velocity/pom.xml | 2 +- pom.xml | 6 +++--- 37 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apps/pom.xml b/apps/pom.xml index b500bd893..ab8a81107 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.2 + 6.1.0-SNAPSHOT struts2-apps pom diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml index 45748bcd8..870683b81 100644 --- a/apps/rest-showcase/pom.xml +++ b/apps/rest-showcase/pom.xml @@ -24,12 +24,12 @@ org.apache.struts struts2-apps - 6.0.2 + 6.1.0-SNAPSHOT struts2-rest-showcase war - 6.0.2 + 6.1.0-SNAPSHOT Struts 2 Rest Showcase Webapp Struts 2 Rest Showcase Example diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index 7c78a2666..51b87ae26 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-apps - 6.0.2 + 6.1.0-SNAPSHOT struts2-showcase diff --git a/assembly/pom.xml b/assembly/pom.xml index c49b5f1cb..6773c74bd 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.2 + 6.1.0-SNAPSHOT struts2-assembly diff --git a/bom/pom.xml b/bom/pom.xml index 266ba5d51..e25ca89dd 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -29,7 +29,7 @@ struts2-bom - 6.0.2 + 6.1.0-SNAPSHOT pom Struts 2 Bill of Materials @@ -44,7 +44,7 @@ - 6.0.2 + 6.1.0-SNAPSHOT true true @@ -185,7 +185,7 @@ - STRUTS_6_0_2 + HEAD scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ diff --git a/bundles/admin/pom.xml b/bundles/admin/pom.xml index 3553e30dd..395dcb80f 100644 --- a/bundles/admin/pom.xml +++ b/bundles/admin/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.0.2 + 6.1.0-SNAPSHOT struts2-osgi-admin-bundle diff --git a/bundles/demo/pom.xml b/bundles/demo/pom.xml index 951a590b7..7258e0dd7 100644 --- a/bundles/demo/pom.xml +++ b/bundles/demo/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.0.2 + 6.1.0-SNAPSHOT struts2-osgi-demo-bundle diff --git a/bundles/pom.xml b/bundles/pom.xml index 0822084ba..af4fd2d53 100755 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.2 + 6.1.0-SNAPSHOT struts2-osgi-bundles diff --git a/core/pom.xml b/core/pom.xml index ae398b37d..d7cee0c16 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.2 + 6.1.0-SNAPSHOT struts2-core jar diff --git a/plugins/async/pom.xml b/plugins/async/pom.xml index 6b1bbac34..4135b3e35 100644 --- a/plugins/async/pom.xml +++ b/plugins/async/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-async-plugin diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml index 4af66aff7..56fe9b03d 100644 --- a/plugins/bean-validation/pom.xml +++ b/plugins/bean-validation/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/plugins/cdi/pom.xml b/plugins/cdi/pom.xml index 6bf5fcf78..c56349ee1 100644 --- a/plugins/cdi/pom.xml +++ b/plugins/cdi/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-cdi-plugin diff --git a/plugins/config-browser/pom.xml b/plugins/config-browser/pom.xml index 1c4b00514..cef8a3f81 100644 --- a/plugins/config-browser/pom.xml +++ b/plugins/config-browser/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-config-browser-plugin diff --git a/plugins/convention/pom.xml b/plugins/convention/pom.xml index 71a54a81a..0157bc957 100644 --- a/plugins/convention/pom.xml +++ b/plugins/convention/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-convention-plugin diff --git a/plugins/dwr/pom.xml b/plugins/dwr/pom.xml index 2b660d5ec..9f94008f0 100644 --- a/plugins/dwr/pom.xml +++ b/plugins/dwr/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-dwr-plugin diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml index ee4eb76c3..9da33bbc1 100644 --- a/plugins/embeddedjsp/pom.xml +++ b/plugins/embeddedjsp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-embeddedjsp-plugin diff --git a/plugins/gxp/pom.xml b/plugins/gxp/pom.xml index 42765df4f..d64ae471a 100644 --- a/plugins/gxp/pom.xml +++ b/plugins/gxp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-gxp-plugin diff --git a/plugins/jasperreports/pom.xml b/plugins/jasperreports/pom.xml index a6de5f8d6..767d417ab 100644 --- a/plugins/jasperreports/pom.xml +++ b/plugins/jasperreports/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-jasperreports-plugin diff --git a/plugins/javatemplates/pom.xml b/plugins/javatemplates/pom.xml index 4eabfa7cc..7b68afa12 100644 --- a/plugins/javatemplates/pom.xml +++ b/plugins/javatemplates/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-javatemplates-plugin diff --git a/plugins/jfreechart/pom.xml b/plugins/jfreechart/pom.xml index ff6253eff..2a587272c 100644 --- a/plugins/jfreechart/pom.xml +++ b/plugins/jfreechart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-jfreechart-plugin diff --git a/plugins/json/pom.xml b/plugins/json/pom.xml index 5804ad25f..047ee5ff2 100644 --- a/plugins/json/pom.xml +++ b/plugins/json/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-json-plugin diff --git a/plugins/junit/pom.xml b/plugins/junit/pom.xml index b7e601b28..9c43045a3 100644 --- a/plugins/junit/pom.xml +++ b/plugins/junit/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-junit-plugin diff --git a/plugins/osgi/pom.xml b/plugins/osgi/pom.xml index 7928b58bc..98a251676 100644 --- a/plugins/osgi/pom.xml +++ b/plugins/osgi/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-osgi-plugin diff --git a/plugins/oval/pom.xml b/plugins/oval/pom.xml index d1be18b4e..f981ae5dd 100644 --- a/plugins/oval/pom.xml +++ b/plugins/oval/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-oval-plugin diff --git a/plugins/pell-multipart/pom.xml b/plugins/pell-multipart/pom.xml index 2546e7644..417199369 100644 --- a/plugins/pell-multipart/pom.xml +++ b/plugins/pell-multipart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-pell-multipart-plugin diff --git a/plugins/plexus/pom.xml b/plugins/plexus/pom.xml index 25b597612..ca58f500e 100644 --- a/plugins/plexus/pom.xml +++ b/plugins/plexus/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-plexus-plugin diff --git a/plugins/pom.xml b/plugins/pom.xml index 61741cb7a..c26c1af41 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.2 + 6.1.0-SNAPSHOT struts2-plugins diff --git a/plugins/portlet-mocks/pom.xml b/plugins/portlet-mocks/pom.xml index ceb81fa0a..a3e42df93 100644 --- a/plugins/portlet-mocks/pom.xml +++ b/plugins/portlet-mocks/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-portlet-mocks-plugin diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml index 83370cc21..c13e058e5 100644 --- a/plugins/portlet-tiles/pom.xml +++ b/plugins/portlet-tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-portlet-tiles-plugin diff --git a/plugins/portlet/pom.xml b/plugins/portlet/pom.xml index 468a7d8c5..151dab478 100644 --- a/plugins/portlet/pom.xml +++ b/plugins/portlet/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-portlet-plugin diff --git a/plugins/rest/pom.xml b/plugins/rest/pom.xml index 4e6a16b48..ef9792d55 100644 --- a/plugins/rest/pom.xml +++ b/plugins/rest/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-rest-plugin diff --git a/plugins/sitemesh/pom.xml b/plugins/sitemesh/pom.xml index 080596e23..e0492252f 100644 --- a/plugins/sitemesh/pom.xml +++ b/plugins/sitemesh/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-sitemesh-plugin diff --git a/plugins/spring/pom.xml b/plugins/spring/pom.xml index 508d01306..b2b0d5662 100644 --- a/plugins/spring/pom.xml +++ b/plugins/spring/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-spring-plugin diff --git a/plugins/testng/pom.xml b/plugins/testng/pom.xml index 01c32a7e8..823941ba1 100644 --- a/plugins/testng/pom.xml +++ b/plugins/testng/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-testng-plugin diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index a04fe7528..21eb1a95f 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-tiles-plugin diff --git a/plugins/velocity/pom.xml b/plugins/velocity/pom.xml index f3cb13e79..4edd24379 100644 --- a/plugins/velocity/pom.xml +++ b/plugins/velocity/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.2 + 6.1.0-SNAPSHOT struts2-velocity-plugin diff --git a/pom.xml b/pom.xml index f59b9828c..1caec3f64 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 4.0.0 struts2-parent - 6.0.2 + 6.1.0-SNAPSHOT pom Struts 2 http://struts.apache.org/ @@ -51,7 +51,7 @@ scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ - STRUTS_6_0_2 + HEAD @@ -104,7 +104,7 @@ UTF-8 - 2022-08-25T05:35:35Z + 2022-08-25T05:39:47Z 1.8 1.8 From b5e802174aaf9b441ed374c2afcc85285f9d0943 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 29 Aug 2022 08:03:02 +0200 Subject: [PATCH 019/143] WW-5212 Upgrades to Spring 5.3.22 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1caec3f64..993c3cfdd 100644 --- a/pom.xml +++ b/pom.xml @@ -115,7 +115,7 @@ 2.18.0 3.3.3 1.7.32 - 5.3.20 + 5.3.22 3.0.8 1.0.7 3.0.0-M7 From 16c2948f1aac775dbd2cd66f891e62c55882923f Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 1 Sep 2022 08:15:48 +0200 Subject: [PATCH 020/143] WW-5218 Allows to disable CSP related interceptors --- .../struts2/interceptor/CoepInterceptor.java | 19 ++++-- .../struts2/interceptor/CoopInterceptor.java | 22 ++++-- .../interceptor/FetchMetadataInterceptor.java | 67 +++++++++++-------- .../interceptor/csp/CspInterceptor.java | 26 +++++-- .../interceptor/csp/DefaultCspSettings.java | 4 +- core/src/main/resources/struts-default.xml | 8 ++- .../interceptor/CoopInterceptorTest.java | 12 +++- .../interceptor/CspInterceptorTest.java | 19 ++++-- .../FetchMetadataInterceptorTest.java | 56 +++++++++------- 9 files changed, 156 insertions(+), 77 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java index 1c1b7ee28..6f9df6e11 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java @@ -52,21 +52,30 @@ public class CoepInterceptor extends AbstractInterceptor implements PreResultLis @Override public String intercept(ActionInvocation invocation) throws Exception { - invocation.addPreResultListener(this); + if (disabled) { + LOG.trace("COEP interceptor has been disabled"); + } else { + invocation.addPreResultListener(this); + } return invocation.invoke(); } @Override public void beforeResult(ActionInvocation invocation, String resultCode) { + if (disabled) { + return; + } + HttpServletRequest req = invocation.getInvocationContext().getServletRequest(); - HttpServletResponse res = invocation.getInvocationContext().getServletResponse(); final String path = req.getContextPath(); if (exemptedPaths.contains(path)) { // no need to add headers - LOG.debug("Skipping COEP header for exempted path {}", path); - } else if (!disabled) { - res.setHeader(header, REQUIRE_COEP_HEADER); + LOG.debug("Skipping COEP header for exempted path: {}", path); + } else { + LOG.trace("Applying COEP header: {} with value: {}", header, REQUIRE_COEP_HEADER); + HttpServletResponse response = invocation.getInvocationContext().getServletResponse(); + response.setHeader(header, REQUIRE_COEP_HEADER); } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java index 97043ac7b..ed1af3a04 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java @@ -49,25 +49,34 @@ public class CoopInterceptor extends AbstractInterceptor implements PreResultLis private static final String COOP_HEADER = "Cross-Origin-Opener-Policy"; private final Set exemptedPaths = new HashSet<>(); + private boolean disabled = false; private String mode = SAME_ORIGIN; @Override public String intercept(ActionInvocation invocation) throws Exception { - invocation.addPreResultListener(this); + if (disabled) { + LOG.trace("COOP interceptor has been disabled"); + } else { + invocation.addPreResultListener(this); + } return invocation.invoke(); } @Override public void beforeResult(ActionInvocation invocation, String resultCode) { + if (disabled) { + return; + } HttpServletRequest request = invocation.getInvocationContext().getServletRequest(); - HttpServletResponse response = invocation.getInvocationContext().getServletResponse(); String path = request.getContextPath(); if (isExempted(path)) { // no need to add headers LOG.debug("Skipping COOP header for exempted path {}", path); } else { - response.setHeader(COOP_HEADER, getMode()); + LOG.trace("Applying COOP header: {} with value: {}", COOP_HEADER, mode); + HttpServletResponse response = invocation.getInvocationContext().getServletResponse(); + response.setHeader(COOP_HEADER, mode); } } @@ -79,10 +88,6 @@ public class CoopInterceptor extends AbstractInterceptor implements PreResultLis exemptedPaths.addAll(TextParseUtil.commaDelimitedStringToSet(paths)); } - private String getMode() { - return mode; - } - public void setMode(String mode) { if (!(mode.equals(SAME_ORIGIN) || mode.equals(SAME_ORIGIN_ALLOW_POPUPS) || mode.equals(UNSAFE_NONE))) { throw new IllegalArgumentException(String.format("Mode '%s' not recognized!", mode)); @@ -90,4 +95,7 @@ public class CoopInterceptor extends AbstractInterceptor implements PreResultLis this.mode = mode; } + public void setDisabled(String value) { + this.disabled = Boolean.parseBoolean(value); + } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java index 9535b3a60..5c119dd84 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java @@ -18,24 +18,25 @@ */ package org.apache.struts2.interceptor; -import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SEC_FETCH_DEST_HEADER; -import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SEC_FETCH_MODE_HEADER; -import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SEC_FETCH_SITE_HEADER; -import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SEC_FETCH_USER_HEADER; -import static org.apache.struts2.interceptor.ResourceIsolationPolicy.VARY_HEADER; - import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import com.opensymphony.xwork2.util.TextParseUtil; -import java.util.HashSet; -import java.util.Set; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.HashSet; +import java.util.Set; + +import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SEC_FETCH_DEST_HEADER; +import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SEC_FETCH_MODE_HEADER; +import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SEC_FETCH_SITE_HEADER; +import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SEC_FETCH_USER_HEADER; +import static org.apache.struts2.interceptor.ResourceIsolationPolicy.VARY_HEADER; + /** * Interceptor that implements Fetch Metadata policy on incoming requests used to protect against * CSRF, XSSI, and cross-origin information leaks. Uses {@link StrutsResourceIsolationPolicy} to @@ -46,6 +47,7 @@ import org.apache.logging.log4j.Logger; **/ public class FetchMetadataInterceptor extends AbstractInterceptor { + private static final Logger LOG = LogManager.getLogger(FetchMetadataInterceptor.class); private static final String VARY_HEADER_VALUE = String.format("%s,%s,%s,%s", SEC_FETCH_DEST_HEADER, SEC_FETCH_MODE_HEADER, SEC_FETCH_SITE_HEADER, SEC_FETCH_USER_HEADER); private static final String SC_FORBIDDEN = String.valueOf(HttpServletResponse.SC_FORBIDDEN); @@ -53,13 +55,19 @@ public class FetchMetadataInterceptor extends AbstractInterceptor { private final Set exemptedPaths = new HashSet<>(); private final ResourceIsolationPolicy resourceIsolationPolicy = new StrutsResourceIsolationPolicy(); - @Inject (required=false) + private boolean disabled = false; + + @Inject(required = false) public void setExemptedPaths(String paths) { this.exemptedPaths.addAll(TextParseUtil.commaDelimitedStringToSet(paths)); } @Override public String intercept(ActionInvocation invocation) throws Exception { + if (disabled) { + LOG.trace("Fetch Metadata interceptor has been disabled"); + return invocation.invoke(); + } ActionContext context = invocation.getInvocationContext(); HttpServletRequest request = context.getServletRequest(); @@ -76,31 +84,34 @@ public class FetchMetadataInterceptor extends AbstractInterceptor { return invocation.invoke(); } - LOG.info("Fetch metadata rejected cross-origin request to [{}]", contextPath); + LOG.warn("Fetch metadata rejected cross-origin request to: {}", contextPath); return SC_FORBIDDEN; } /** - * Sets {@link SEC_FETCH_DEST_HEADER}, {@link SEC_FETCH_MODE_HEADER}, {@link SEC_FETCH_SITE_HEADER}, and {@link SEC_FETCH_USER_HEADER} - * elements in the provided ActionInvocation's HttpServletResponse {@link VARY_HEADER} response header. - * + * Sets {@link ResourceIsolationPolicy#SEC_FETCH_DEST_HEADER}, {@link ResourceIsolationPolicy#SEC_FETCH_MODE_HEADER}, + * {@link ResourceIsolationPolicy#SEC_FETCH_SITE_HEADER}, and {@link ResourceIsolationPolicy#SEC_FETCH_USER_HEADER} + * elements in the provided ActionInvocation's HttpServletResponse {@link ResourceIsolationPolicy#VARY_HEADER} response header. + *

* Note: This method will replace any previous Vary header content already set for the response. - * Note: In order to be effective, the Vary header modification must take place at (or very near) the start of this interceptor's processing. - * - * @param invocation Supplies the HttpServletResponse (if present) to which the SEC_FETCH_* header names are be added to its {@link VARY_HEADER} response header. + * Note: In order to be effective, the Vary header modification must take place at (or very near) the start of this + * interceptor's processing. + * + * @param invocation Supplies the HttpServletResponse (if present) to which the SEC_FETCH_* header names are be added + * to its {@link ResourceIsolationPolicy#VARY_HEADER} response header. */ private void addVaryHeaders(ActionInvocation invocation) { HttpServletResponse response = invocation.getInvocationContext().getServletResponse(); - if (response != null) { - // TODO: Whenever servlet 3.x becomes the baseline for Struts, consider revising this method to use - // getHeader(VARY_HEADER) and preserve any VARY_HEADER content already set in the response. - // This will probably require some tokenization logic for the header contents. - if (LOG.isDebugEnabled() && response.containsHeader(VARY_HEADER)) { - LOG.debug("HTTP response already has a [{}] header set, the old value will be overwritten (replaced)", VARY_HEADER); - } - response.setHeader(VARY_HEADER, VARY_HEADER_VALUE); - } else { - LOG.debug("HTTP response is null, cannot add a new [{}] header", VARY_HEADER); + // TODO: Whenever servlet 3.x becomes the baseline for Struts, consider revising this method to use + // getHeader(VARY_HEADER) and preserve any VARY_HEADER content already set in the response. + // This will probably require some tokenization logic for the header contents. + if (LOG.isDebugEnabled() && response.containsHeader(VARY_HEADER)) { + LOG.debug("HTTP response already has header: {} set, the old value will be overwritten (replaced)", VARY_HEADER); } + response.setHeader(VARY_HEADER, VARY_HEADER_VALUE); + } + + public void setDisabled(String value) { + this.disabled = Boolean.parseBoolean(value); } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java index ca77436cc..ecf9697a9 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java @@ -21,10 +21,13 @@ package org.apache.struts2.interceptor.csp; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import com.opensymphony.xwork2.interceptor.PreResultListener; -import java.net.URI; -import java.util.Optional; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.net.URI; +import java.util.Optional; /** * Interceptor that implements Content Security Policy on incoming requests used to protect against @@ -38,15 +41,26 @@ import javax.servlet.http.HttpServletResponse; **/ public final class CspInterceptor extends AbstractInterceptor implements PreResultListener { + private static final Logger LOG = LogManager.getLogger(CspInterceptor.class); + private final CspSettings settings = new DefaultCspSettings(); + private boolean disabled = false; + @Override public String intercept(ActionInvocation invocation) throws Exception { - invocation.addPreResultListener(this); + if (disabled) { + LOG.trace("CSP interceptor has been disabled"); + } else { + invocation.addPreResultListener(this); + } return invocation.invoke(); } public void beforeResult(ActionInvocation invocation, String resultCode) { + if (disabled) { + return; + } HttpServletRequest request = invocation.getInvocationContext().getServletRequest(); HttpServletResponse response = invocation.getInvocationContext().getServletResponse(); settings.addCspHeaders(request, response); @@ -74,8 +88,12 @@ public final class CspInterceptor extends AbstractInterceptor implements PreResu return Optional.empty(); } - public void setEnforcingMode(String value){ + public void setEnforcingMode(String value) { boolean enforcingMode = Boolean.parseBoolean(value); settings.setEnforcingMode(enforcingMode); } + + public void setDisabled(String value) { + this.disabled = Boolean.parseBoolean(value); + } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java b/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java index 7ab70d226..199859ad4 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java +++ b/core/src/main/java/org/apache/struts2/interceptor/csp/DefaultCspSettings.java @@ -53,11 +53,11 @@ public class DefaultCspSettings implements CspSettings { public void addCspHeaders(HttpServletRequest request, HttpServletResponse response) { if (isSessionActive(request)) { - LOG.debug("Session is active, applying CSP settings"); + LOG.trace("Session is active, applying CSP settings"); associateNonceWithSession(request); response.setHeader(cspHeader, cratePolicyFormat(request)); } else { - LOG.debug("Session is not active, ignoring CSP settings"); + LOG.trace("Session is not active, ignoring CSP settings"); } } diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml index 4b8f6b3f3..a75c14ec0 100644 --- a/core/src/main/resources/struts-default.xml +++ b/core/src/main/resources/struts-default.xml @@ -392,6 +392,7 @@ + false false @@ -407,15 +408,18 @@ - false false + false + false same-origin - + + false + input,back,cancel,browse diff --git a/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java index 856a4337e..8e9e9d4ec 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/CoopInterceptorTest.java @@ -34,7 +34,6 @@ public class CoopInterceptorTest extends StrutsInternalTestCase { private final MockHttpServletResponse response = new MockHttpServletResponse(); String SAME_ORIGIN = "same-origin"; - String SAME_SITE = "same-site"; String UNSAFE_NONE = "unsafe-none"; String COOP_HEADER = "Cross-Origin-Opener-Policy"; @@ -65,7 +64,7 @@ public class CoopInterceptorTest extends StrutsInternalTestCase { assertEquals("Coop header is not same-origin", UNSAFE_NONE, header); } - public void testErrorNotRecognizedMode() throws Exception { + public void testErrorNotRecognizedMode() { request.setContextPath("/some"); try{ @@ -76,6 +75,15 @@ public class CoopInterceptorTest extends StrutsInternalTestCase { } } + public void testDisabled() throws Exception { + interceptor.setDisabled("true"); + + interceptor.intercept(mai); + + String header = response.getHeader(COOP_HEADER); + assertTrue("COOP is not disabled", Strings.isEmpty(header)); + } + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java index a9ee1be11..a091b93c7 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java @@ -121,7 +121,7 @@ public class CspInterceptorTest extends StrutsInternalTestCase { checkHeader(reportUri, enforcingMode); } - public void testCannotParseUri() throws Exception { + public void testCannotParseUri() { String enforcingMode = "false"; interceptor.setEnforcingMode(enforcingMode); @@ -133,7 +133,7 @@ public class CspInterceptorTest extends StrutsInternalTestCase { } } - public void testCannotParseRelativeUri() throws Exception { + public void testCannotParseRelativeUri() { String enforcingMode = "false"; interceptor.setEnforcingMode(enforcingMode); @@ -145,8 +145,19 @@ public class CspInterceptorTest extends StrutsInternalTestCase { } } + public void testDisabled() throws Exception { + interceptor.setDisabled("true"); + + interceptor.intercept(mai); + + String header = response.getHeader(CSP_ENFORCE_HEADER); + assertTrue("CSP is not disabled", Strings.isEmpty(header)); + header = response.getHeader(CSP_REPORT_HEADER); + assertTrue("CSP is not disabled", Strings.isEmpty(header)); + } + public void checkHeader(String reportUri, String enforcingMode) { - String expectedCspHeader = ""; + String expectedCspHeader; if (Strings.isEmpty(reportUri)) { expectedCspHeader = String.format("%s '%s'; %s 'nonce-%s' '%s' %s %s; %s '%s'; ", OBJECT_SRC, NONE, @@ -162,7 +173,7 @@ public class CspInterceptorTest extends StrutsInternalTestCase { ); } - String header = ""; + String header; if (enforcingMode.equals("true")) { header = response.getHeader(CSP_ENFORCE_HEADER); } else { diff --git a/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java index 7d7c4bd21..4b8403c47 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/FetchMetadataInterceptorTest.java @@ -18,6 +18,27 @@ */ package org.apache.struts2.interceptor; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.XWorkTestCase; +import com.opensymphony.xwork2.config.RuntimeConfiguration; +import com.opensymphony.xwork2.config.entities.ActionConfig; +import com.opensymphony.xwork2.config.entities.InterceptorMapping; +import com.opensymphony.xwork2.config.entities.InterceptorStackConfig; +import com.opensymphony.xwork2.config.entities.PackageConfig; +import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider; +import com.opensymphony.xwork2.mock.MockActionInvocation; +import org.apache.logging.log4j.util.Strings; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.config.StrutsXmlConfigurationProvider; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +import javax.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Objects; + import static org.apache.struts2.interceptor.ResourceIsolationPolicy.DEST_EMBED; import static org.apache.struts2.interceptor.ResourceIsolationPolicy.DEST_OBJECT; import static org.apache.struts2.interceptor.ResourceIsolationPolicy.DEST_SCRIPT; @@ -32,25 +53,6 @@ import static org.apache.struts2.interceptor.ResourceIsolationPolicy.SITE_SAME_S import static org.apache.struts2.interceptor.ResourceIsolationPolicy.VARY_HEADER; import static org.junit.Assert.assertNotEquals; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.XWorkTestCase; -import com.opensymphony.xwork2.config.RuntimeConfiguration; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.InterceptorMapping; -import com.opensymphony.xwork2.config.entities.InterceptorStackConfig; -import com.opensymphony.xwork2.config.entities.PackageConfig; -import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider; -import com.opensymphony.xwork2.mock.MockActionInvocation; -import org.apache.struts2.ServletActionContext; -import org.apache.struts2.config.StrutsXmlConfigurationProvider; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import javax.servlet.http.HttpServletResponse; - public class FetchMetadataInterceptorTest extends XWorkTestCase { private final FetchMetadataInterceptor interceptor = new FetchMetadataInterceptor(); @@ -79,7 +81,7 @@ public class FetchMetadataInterceptorTest extends XWorkTestCase { } public void testValidSite() throws Exception { - for (String header : Arrays.asList(SITE_SAME_ORIGIN, SITE_SAME_SITE, SITE_NONE)){ + for (String header : Arrays.asList(SITE_SAME_ORIGIN, SITE_SAME_SITE, SITE_NONE)) { request.addHeader(SEC_FETCH_SITE_HEADER, header); assertNotEquals("Expected interceptor to accept this request", SC_FORBIDDEN, interceptor.intercept(mai)); @@ -147,12 +149,12 @@ public class FetchMetadataInterceptorTest extends XWorkTestCase { interceptor.intercept(mai); assertTrue("Expected vary header to be included", response.containsHeader(VARY_HEADER)); - assertFalse("Expected original vary header content to be replaced", response.getHeader(VARY_HEADER).contains(ACCEPT_ENCODING_VALUE)); - assertTrue("Expected added vary header content to be present", response.getHeader(VARY_HEADER).contains(VARY_HEADER_VALUE)); + assertFalse("Expected original vary header content to be replaced", Objects.requireNonNull(response.getHeader(VARY_HEADER)).contains(ACCEPT_ENCODING_VALUE)); + assertTrue("Expected added vary header content to be present", Objects.requireNonNull(response.getHeader(VARY_HEADER)).contains(VARY_HEADER_VALUE)); } public void testSetExemptedPathsInjectionIndirectly() throws Exception { - // Perform a multi-step test to confirm (indirectly) that the method parameter injection of setExemptedPaths() for + // Perform a multistep test to confirm (indirectly) that the method parameter injection of setExemptedPaths() for // the FetchMetadataInterceptor is functioning as expected, when configured appropriately. // Ensure we're using the specific test configuration, not the default simple configuration. XmlConfigurationProvider configurationProvider = new StrutsXmlConfigurationProvider("struts-testing.xml"); @@ -259,4 +261,12 @@ public class FetchMetadataInterceptorTest extends XWorkTestCase { assertNotEquals("Expected interceptor to accept this request [" + "/" + fetchMetadataExemptedGlobalActionConfig.getName() + "]", SC_FORBIDDEN, configuredFetchMetadataInterceptor.intercept(mai)); } + public void testDisabled() throws Exception { + interceptor.setDisabled("true"); + + interceptor.intercept(mai); + + String header = response.getHeader(VARY_HEADER); + assertTrue("Fetch Metadata is not disabled", Strings.isEmpty(header)); + } } From 941d88d115ca21517cdfa09cb71512c818d0d471 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 2 Sep 2022 14:41:49 +0200 Subject: [PATCH 021/143] [maven-release-plugin] prepare release STRUTS_6_0_3 --- apps/pom.xml | 2 +- apps/rest-showcase/pom.xml | 4 ++-- apps/showcase/pom.xml | 2 +- assembly/pom.xml | 2 +- bom/pom.xml | 6 +++--- bundles/admin/pom.xml | 2 +- bundles/demo/pom.xml | 2 +- bundles/pom.xml | 2 +- core/pom.xml | 2 +- plugins/async/pom.xml | 2 +- plugins/bean-validation/pom.xml | 2 +- plugins/cdi/pom.xml | 2 +- plugins/config-browser/pom.xml | 2 +- plugins/convention/pom.xml | 2 +- plugins/dwr/pom.xml | 2 +- plugins/embeddedjsp/pom.xml | 2 +- plugins/gxp/pom.xml | 2 +- plugins/jasperreports/pom.xml | 2 +- plugins/javatemplates/pom.xml | 2 +- plugins/jfreechart/pom.xml | 2 +- plugins/json/pom.xml | 2 +- plugins/junit/pom.xml | 2 +- plugins/osgi/pom.xml | 2 +- plugins/oval/pom.xml | 2 +- plugins/pell-multipart/pom.xml | 2 +- plugins/plexus/pom.xml | 2 +- plugins/pom.xml | 2 +- plugins/portlet-mocks/pom.xml | 2 +- plugins/portlet-tiles/pom.xml | 2 +- plugins/portlet/pom.xml | 2 +- plugins/rest/pom.xml | 2 +- plugins/sitemesh/pom.xml | 2 +- plugins/spring/pom.xml | 2 +- plugins/testng/pom.xml | 2 +- plugins/tiles/pom.xml | 2 +- plugins/velocity/pom.xml | 2 +- pom.xml | 6 +++--- 37 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apps/pom.xml b/apps/pom.xml index ab8a81107..ec4fd09cc 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.3 struts2-apps pom diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml index 870683b81..92292612a 100644 --- a/apps/rest-showcase/pom.xml +++ b/apps/rest-showcase/pom.xml @@ -24,12 +24,12 @@ org.apache.struts struts2-apps - 6.1.0-SNAPSHOT + 6.0.3 struts2-rest-showcase war - 6.1.0-SNAPSHOT + 6.0.3 Struts 2 Rest Showcase Webapp Struts 2 Rest Showcase Example diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index 51b87ae26..abc5d9f48 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-apps - 6.1.0-SNAPSHOT + 6.0.3 struts2-showcase diff --git a/assembly/pom.xml b/assembly/pom.xml index 6773c74bd..b875c81b2 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.3 struts2-assembly diff --git a/bom/pom.xml b/bom/pom.xml index e25ca89dd..64e5c5be0 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -29,7 +29,7 @@ struts2-bom - 6.1.0-SNAPSHOT + 6.0.3 pom Struts 2 Bill of Materials @@ -44,7 +44,7 @@ - 6.1.0-SNAPSHOT + 6.0.3 true true @@ -185,7 +185,7 @@ - HEAD + STRUTS_6_0_3 scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ diff --git a/bundles/admin/pom.xml b/bundles/admin/pom.xml index 395dcb80f..3bc51f0f8 100644 --- a/bundles/admin/pom.xml +++ b/bundles/admin/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.1.0-SNAPSHOT + 6.0.3 struts2-osgi-admin-bundle diff --git a/bundles/demo/pom.xml b/bundles/demo/pom.xml index 7258e0dd7..d48bcfc5e 100644 --- a/bundles/demo/pom.xml +++ b/bundles/demo/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.1.0-SNAPSHOT + 6.0.3 struts2-osgi-demo-bundle diff --git a/bundles/pom.xml b/bundles/pom.xml index af4fd2d53..2583e2c86 100755 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.3 struts2-osgi-bundles diff --git a/core/pom.xml b/core/pom.xml index d7cee0c16..116b5ff50 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.3 struts2-core jar diff --git a/plugins/async/pom.xml b/plugins/async/pom.xml index 4135b3e35..76d53520e 100644 --- a/plugins/async/pom.xml +++ b/plugins/async/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-async-plugin diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml index 56fe9b03d..cbe34f81e 100644 --- a/plugins/bean-validation/pom.xml +++ b/plugins/bean-validation/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 4.0.0 diff --git a/plugins/cdi/pom.xml b/plugins/cdi/pom.xml index c56349ee1..e1b03a06d 100644 --- a/plugins/cdi/pom.xml +++ b/plugins/cdi/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-cdi-plugin diff --git a/plugins/config-browser/pom.xml b/plugins/config-browser/pom.xml index cef8a3f81..80486e83c 100644 --- a/plugins/config-browser/pom.xml +++ b/plugins/config-browser/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-config-browser-plugin diff --git a/plugins/convention/pom.xml b/plugins/convention/pom.xml index 0157bc957..93f0e5ec2 100644 --- a/plugins/convention/pom.xml +++ b/plugins/convention/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-convention-plugin diff --git a/plugins/dwr/pom.xml b/plugins/dwr/pom.xml index 9f94008f0..aa5f7f13f 100644 --- a/plugins/dwr/pom.xml +++ b/plugins/dwr/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-dwr-plugin diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml index 9da33bbc1..eadb8cb98 100644 --- a/plugins/embeddedjsp/pom.xml +++ b/plugins/embeddedjsp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-embeddedjsp-plugin diff --git a/plugins/gxp/pom.xml b/plugins/gxp/pom.xml index d64ae471a..9a5b945d6 100644 --- a/plugins/gxp/pom.xml +++ b/plugins/gxp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-gxp-plugin diff --git a/plugins/jasperreports/pom.xml b/plugins/jasperreports/pom.xml index 767d417ab..2c56be206 100644 --- a/plugins/jasperreports/pom.xml +++ b/plugins/jasperreports/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-jasperreports-plugin diff --git a/plugins/javatemplates/pom.xml b/plugins/javatemplates/pom.xml index 7b68afa12..83f3b7386 100644 --- a/plugins/javatemplates/pom.xml +++ b/plugins/javatemplates/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-javatemplates-plugin diff --git a/plugins/jfreechart/pom.xml b/plugins/jfreechart/pom.xml index 2a587272c..1fbffcb83 100644 --- a/plugins/jfreechart/pom.xml +++ b/plugins/jfreechart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-jfreechart-plugin diff --git a/plugins/json/pom.xml b/plugins/json/pom.xml index 047ee5ff2..a8c6a1ad6 100644 --- a/plugins/json/pom.xml +++ b/plugins/json/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-json-plugin diff --git a/plugins/junit/pom.xml b/plugins/junit/pom.xml index 9c43045a3..94bc58b34 100644 --- a/plugins/junit/pom.xml +++ b/plugins/junit/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-junit-plugin diff --git a/plugins/osgi/pom.xml b/plugins/osgi/pom.xml index 98a251676..2965d2a91 100644 --- a/plugins/osgi/pom.xml +++ b/plugins/osgi/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-osgi-plugin diff --git a/plugins/oval/pom.xml b/plugins/oval/pom.xml index f981ae5dd..bd1f3d308 100644 --- a/plugins/oval/pom.xml +++ b/plugins/oval/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-oval-plugin diff --git a/plugins/pell-multipart/pom.xml b/plugins/pell-multipart/pom.xml index 417199369..4b557bac5 100644 --- a/plugins/pell-multipart/pom.xml +++ b/plugins/pell-multipart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-pell-multipart-plugin diff --git a/plugins/plexus/pom.xml b/plugins/plexus/pom.xml index ca58f500e..3c1d7c653 100644 --- a/plugins/plexus/pom.xml +++ b/plugins/plexus/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-plexus-plugin diff --git a/plugins/pom.xml b/plugins/pom.xml index c26c1af41..726865a5a 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.1.0-SNAPSHOT + 6.0.3 struts2-plugins diff --git a/plugins/portlet-mocks/pom.xml b/plugins/portlet-mocks/pom.xml index a3e42df93..a6072ef52 100644 --- a/plugins/portlet-mocks/pom.xml +++ b/plugins/portlet-mocks/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-portlet-mocks-plugin diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml index c13e058e5..cf3fda7a8 100644 --- a/plugins/portlet-tiles/pom.xml +++ b/plugins/portlet-tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-portlet-tiles-plugin diff --git a/plugins/portlet/pom.xml b/plugins/portlet/pom.xml index 151dab478..7b74cca9a 100644 --- a/plugins/portlet/pom.xml +++ b/plugins/portlet/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-portlet-plugin diff --git a/plugins/rest/pom.xml b/plugins/rest/pom.xml index ef9792d55..7d1755652 100644 --- a/plugins/rest/pom.xml +++ b/plugins/rest/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-rest-plugin diff --git a/plugins/sitemesh/pom.xml b/plugins/sitemesh/pom.xml index e0492252f..3e2b232fa 100644 --- a/plugins/sitemesh/pom.xml +++ b/plugins/sitemesh/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-sitemesh-plugin diff --git a/plugins/spring/pom.xml b/plugins/spring/pom.xml index b2b0d5662..6572707f0 100644 --- a/plugins/spring/pom.xml +++ b/plugins/spring/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-spring-plugin diff --git a/plugins/testng/pom.xml b/plugins/testng/pom.xml index 823941ba1..c86993f61 100644 --- a/plugins/testng/pom.xml +++ b/plugins/testng/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-testng-plugin diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index 21eb1a95f..67f76d6d3 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-tiles-plugin diff --git a/plugins/velocity/pom.xml b/plugins/velocity/pom.xml index 4edd24379..002cf0575 100644 --- a/plugins/velocity/pom.xml +++ b/plugins/velocity/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.1.0-SNAPSHOT + 6.0.3 struts2-velocity-plugin diff --git a/pom.xml b/pom.xml index 993c3cfdd..8a471cd8b 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 4.0.0 struts2-parent - 6.1.0-SNAPSHOT + 6.0.3 pom Struts 2 http://struts.apache.org/ @@ -51,7 +51,7 @@ scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ - HEAD + STRUTS_6_0_3 @@ -104,7 +104,7 @@ UTF-8 - 2022-08-25T05:39:47Z + 2022-09-02T12:37:45Z 1.8 1.8 From 49240c50a285edaa4e9652215ed0bbcbebcb43f3 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 2 Sep 2022 14:41:56 +0200 Subject: [PATCH 022/143] [maven-release-plugin] prepare for next development iteration --- apps/pom.xml | 2 +- apps/rest-showcase/pom.xml | 4 ++-- apps/showcase/pom.xml | 2 +- assembly/pom.xml | 2 +- bom/pom.xml | 6 +++--- bundles/admin/pom.xml | 2 +- bundles/demo/pom.xml | 2 +- bundles/pom.xml | 2 +- core/pom.xml | 2 +- plugins/async/pom.xml | 2 +- plugins/bean-validation/pom.xml | 2 +- plugins/cdi/pom.xml | 2 +- plugins/config-browser/pom.xml | 2 +- plugins/convention/pom.xml | 2 +- plugins/dwr/pom.xml | 2 +- plugins/embeddedjsp/pom.xml | 2 +- plugins/gxp/pom.xml | 2 +- plugins/jasperreports/pom.xml | 2 +- plugins/javatemplates/pom.xml | 2 +- plugins/jfreechart/pom.xml | 2 +- plugins/json/pom.xml | 2 +- plugins/junit/pom.xml | 2 +- plugins/osgi/pom.xml | 2 +- plugins/oval/pom.xml | 2 +- plugins/pell-multipart/pom.xml | 2 +- plugins/plexus/pom.xml | 2 +- plugins/pom.xml | 2 +- plugins/portlet-mocks/pom.xml | 2 +- plugins/portlet-tiles/pom.xml | 2 +- plugins/portlet/pom.xml | 2 +- plugins/rest/pom.xml | 2 +- plugins/sitemesh/pom.xml | 2 +- plugins/spring/pom.xml | 2 +- plugins/testng/pom.xml | 2 +- plugins/tiles/pom.xml | 2 +- plugins/velocity/pom.xml | 2 +- pom.xml | 6 +++--- 37 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apps/pom.xml b/apps/pom.xml index ec4fd09cc..ab8a81107 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.3 + 6.1.0-SNAPSHOT struts2-apps pom diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml index 92292612a..870683b81 100644 --- a/apps/rest-showcase/pom.xml +++ b/apps/rest-showcase/pom.xml @@ -24,12 +24,12 @@ org.apache.struts struts2-apps - 6.0.3 + 6.1.0-SNAPSHOT struts2-rest-showcase war - 6.0.3 + 6.1.0-SNAPSHOT Struts 2 Rest Showcase Webapp Struts 2 Rest Showcase Example diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index abc5d9f48..51b87ae26 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-apps - 6.0.3 + 6.1.0-SNAPSHOT struts2-showcase diff --git a/assembly/pom.xml b/assembly/pom.xml index b875c81b2..6773c74bd 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.3 + 6.1.0-SNAPSHOT struts2-assembly diff --git a/bom/pom.xml b/bom/pom.xml index 64e5c5be0..e25ca89dd 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -29,7 +29,7 @@ struts2-bom - 6.0.3 + 6.1.0-SNAPSHOT pom Struts 2 Bill of Materials @@ -44,7 +44,7 @@ - 6.0.3 + 6.1.0-SNAPSHOT true true @@ -185,7 +185,7 @@ - STRUTS_6_0_3 + HEAD scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ diff --git a/bundles/admin/pom.xml b/bundles/admin/pom.xml index 3bc51f0f8..395dcb80f 100644 --- a/bundles/admin/pom.xml +++ b/bundles/admin/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.0.3 + 6.1.0-SNAPSHOT struts2-osgi-admin-bundle diff --git a/bundles/demo/pom.xml b/bundles/demo/pom.xml index d48bcfc5e..7258e0dd7 100644 --- a/bundles/demo/pom.xml +++ b/bundles/demo/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-osgi-bundles - 6.0.3 + 6.1.0-SNAPSHOT struts2-osgi-demo-bundle diff --git a/bundles/pom.xml b/bundles/pom.xml index 2583e2c86..af4fd2d53 100755 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.3 + 6.1.0-SNAPSHOT struts2-osgi-bundles diff --git a/core/pom.xml b/core/pom.xml index 116b5ff50..d7cee0c16 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.3 + 6.1.0-SNAPSHOT struts2-core jar diff --git a/plugins/async/pom.xml b/plugins/async/pom.xml index 76d53520e..4135b3e35 100644 --- a/plugins/async/pom.xml +++ b/plugins/async/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-async-plugin diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml index cbe34f81e..56fe9b03d 100644 --- a/plugins/bean-validation/pom.xml +++ b/plugins/bean-validation/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/plugins/cdi/pom.xml b/plugins/cdi/pom.xml index e1b03a06d..c56349ee1 100644 --- a/plugins/cdi/pom.xml +++ b/plugins/cdi/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-cdi-plugin diff --git a/plugins/config-browser/pom.xml b/plugins/config-browser/pom.xml index 80486e83c..cef8a3f81 100644 --- a/plugins/config-browser/pom.xml +++ b/plugins/config-browser/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-config-browser-plugin diff --git a/plugins/convention/pom.xml b/plugins/convention/pom.xml index 93f0e5ec2..0157bc957 100644 --- a/plugins/convention/pom.xml +++ b/plugins/convention/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-convention-plugin diff --git a/plugins/dwr/pom.xml b/plugins/dwr/pom.xml index aa5f7f13f..9f94008f0 100644 --- a/plugins/dwr/pom.xml +++ b/plugins/dwr/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-dwr-plugin diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml index eadb8cb98..9da33bbc1 100644 --- a/plugins/embeddedjsp/pom.xml +++ b/plugins/embeddedjsp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-embeddedjsp-plugin diff --git a/plugins/gxp/pom.xml b/plugins/gxp/pom.xml index 9a5b945d6..d64ae471a 100644 --- a/plugins/gxp/pom.xml +++ b/plugins/gxp/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-gxp-plugin diff --git a/plugins/jasperreports/pom.xml b/plugins/jasperreports/pom.xml index 2c56be206..767d417ab 100644 --- a/plugins/jasperreports/pom.xml +++ b/plugins/jasperreports/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-jasperreports-plugin diff --git a/plugins/javatemplates/pom.xml b/plugins/javatemplates/pom.xml index 83f3b7386..7b68afa12 100644 --- a/plugins/javatemplates/pom.xml +++ b/plugins/javatemplates/pom.xml @@ -25,7 +25,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-javatemplates-plugin diff --git a/plugins/jfreechart/pom.xml b/plugins/jfreechart/pom.xml index 1fbffcb83..2a587272c 100644 --- a/plugins/jfreechart/pom.xml +++ b/plugins/jfreechart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-jfreechart-plugin diff --git a/plugins/json/pom.xml b/plugins/json/pom.xml index a8c6a1ad6..047ee5ff2 100644 --- a/plugins/json/pom.xml +++ b/plugins/json/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-json-plugin diff --git a/plugins/junit/pom.xml b/plugins/junit/pom.xml index 94bc58b34..9c43045a3 100644 --- a/plugins/junit/pom.xml +++ b/plugins/junit/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-junit-plugin diff --git a/plugins/osgi/pom.xml b/plugins/osgi/pom.xml index 2965d2a91..98a251676 100644 --- a/plugins/osgi/pom.xml +++ b/plugins/osgi/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-osgi-plugin diff --git a/plugins/oval/pom.xml b/plugins/oval/pom.xml index bd1f3d308..f981ae5dd 100644 --- a/plugins/oval/pom.xml +++ b/plugins/oval/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-oval-plugin diff --git a/plugins/pell-multipart/pom.xml b/plugins/pell-multipart/pom.xml index 4b557bac5..417199369 100644 --- a/plugins/pell-multipart/pom.xml +++ b/plugins/pell-multipart/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-pell-multipart-plugin diff --git a/plugins/plexus/pom.xml b/plugins/plexus/pom.xml index 3c1d7c653..ca58f500e 100644 --- a/plugins/plexus/pom.xml +++ b/plugins/plexus/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-plexus-plugin diff --git a/plugins/pom.xml b/plugins/pom.xml index 726865a5a..c26c1af41 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-parent - 6.0.3 + 6.1.0-SNAPSHOT struts2-plugins diff --git a/plugins/portlet-mocks/pom.xml b/plugins/portlet-mocks/pom.xml index a6072ef52..a3e42df93 100644 --- a/plugins/portlet-mocks/pom.xml +++ b/plugins/portlet-mocks/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-portlet-mocks-plugin diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml index cf3fda7a8..c13e058e5 100644 --- a/plugins/portlet-tiles/pom.xml +++ b/plugins/portlet-tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-portlet-tiles-plugin diff --git a/plugins/portlet/pom.xml b/plugins/portlet/pom.xml index 7b74cca9a..151dab478 100644 --- a/plugins/portlet/pom.xml +++ b/plugins/portlet/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-portlet-plugin diff --git a/plugins/rest/pom.xml b/plugins/rest/pom.xml index 7d1755652..ef9792d55 100644 --- a/plugins/rest/pom.xml +++ b/plugins/rest/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-rest-plugin diff --git a/plugins/sitemesh/pom.xml b/plugins/sitemesh/pom.xml index 3e2b232fa..e0492252f 100644 --- a/plugins/sitemesh/pom.xml +++ b/plugins/sitemesh/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-sitemesh-plugin diff --git a/plugins/spring/pom.xml b/plugins/spring/pom.xml index 6572707f0..b2b0d5662 100644 --- a/plugins/spring/pom.xml +++ b/plugins/spring/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-spring-plugin diff --git a/plugins/testng/pom.xml b/plugins/testng/pom.xml index c86993f61..823941ba1 100644 --- a/plugins/testng/pom.xml +++ b/plugins/testng/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-testng-plugin diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index 67f76d6d3..21eb1a95f 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-tiles-plugin diff --git a/plugins/velocity/pom.xml b/plugins/velocity/pom.xml index 002cf0575..4edd24379 100644 --- a/plugins/velocity/pom.xml +++ b/plugins/velocity/pom.xml @@ -24,7 +24,7 @@ org.apache.struts struts2-plugins - 6.0.3 + 6.1.0-SNAPSHOT struts2-velocity-plugin diff --git a/pom.xml b/pom.xml index 8a471cd8b..cdd13feda 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 4.0.0 struts2-parent - 6.0.3 + 6.1.0-SNAPSHOT pom Struts 2 http://struts.apache.org/ @@ -51,7 +51,7 @@ scm:git:https://gitbox.apache.org/repos/asf/struts.git scm:git:https://gitbox.apache.org/repos/asf/struts.git https://github.com/apache/struts/ - STRUTS_6_0_3 + HEAD @@ -104,7 +104,7 @@ UTF-8 - 2022-09-02T12:37:45Z + 2022-09-02T12:41:56Z 1.8 1.8 From ce2975e2f0605868a5c37067c1a206e1570115d6 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sat, 3 Sep 2022 08:47:41 +0200 Subject: [PATCH 023/143] Updates supported versions --- SECURITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 393fe23d4..eca65f01b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,8 +7,8 @@ and what potential vulnerability it can have: | Version | Supported | | ------- | ------------------ | -| 2.5.20 | :white_check_mark: | -| 2.3.37 | :white_check_mark: | +| 6.0.0 | :white_check_mark: | +| 2.5.30 | :white_check_mark: | ## Reporting New Security Issues with thr Apache Struts From bbb5b6bb3721560c5dca2863ea48b1c931de1ce1 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 4 Sep 2022 10:58:58 +0200 Subject: [PATCH 024/143] Adds OpenSSF Scorecard badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 04ecf1d57..262888244 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ The Apache Struts web framework [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/) [![Javadocs](https://javadoc.io/badge/org.apache.struts/struts2-core.svg)](https://javadoc.io/doc/org.apache.struts/struts2-core) [![Coverage Status](https://coveralls.io/repos/github/apache/struts/badge.svg)](https://coveralls.io/github/apache/struts) +[![Coverage Status](https://coveralls.io/repos/github/apache/struts/badge.svg)](https://coveralls.io/github/apache/struts) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/struts/badge)](https://deps.dev/maven/org.apache.struts%3Astruts2-core) [![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) The Apache Struts web framework is a free open-source solution for creating Java web applications. From 85144061422325a84bc11e48fdadc4fb7987db5f Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 4 Sep 2022 10:59:52 +0200 Subject: [PATCH 025/143] Removes duplicated code coverage badge --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 262888244..136a290dd 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ The Apache Struts web framework [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/) [![Javadocs](https://javadoc.io/badge/org.apache.struts/struts2-core.svg)](https://javadoc.io/doc/org.apache.struts/struts2-core) [![Coverage Status](https://coveralls.io/repos/github/apache/struts/badge.svg)](https://coveralls.io/github/apache/struts) -[![Coverage Status](https://coveralls.io/repos/github/apache/struts/badge.svg)](https://coveralls.io/github/apache/struts) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/struts/badge)](https://deps.dev/maven/org.apache.struts%3Astruts2-core) [![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) From 5a3d2c4eb9c8cf9ed74c53ab2c79c05868dc70c6 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 4 Sep 2022 11:15:28 +0200 Subject: [PATCH 026/143] WW-5219 Moves TestNG related classes into TestNG plugin Also moves test classes under testng package --- core/pom.xml | 3 +- .../JakartaStreamMultiPartRequestTest.java | 43 +++++++++---------- plugins/testng/pom.xml | 1 - .../struts2/{ => testng}/StrutsTestCase.java | 6 +-- .../struts2/testng}/TestNGXWorkTestCase.java | 3 +- .../TestNGStrutsTestCaseTest.java | 9 ++-- .../testng}/TestNGXWorkTestCaseTest.java | 7 +-- pom.xml | 4 +- 8 files changed, 35 insertions(+), 41 deletions(-) rename plugins/testng/src/main/java/org/apache/struts2/{ => testng}/StrutsTestCase.java (96%) rename {core/src/main/java/com/opensymphony/xwork2 => plugins/testng/src/main/java/org/apache/struts2/testng}/TestNGXWorkTestCase.java (96%) rename plugins/testng/src/test/java/org/apache/struts2/{ => testng}/TestNGStrutsTestCaseTest.java (95%) rename {core/src/test/java/com/opensymphony/xwork2 => plugins/testng/src/test/java/org/apache/struts2/testng}/TestNGXWorkTestCaseTest.java (95%) diff --git a/core/pom.xml b/core/pom.xml index d7cee0c16..71a3f777b 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -339,8 +339,7 @@ org.testng testng - compile - true + test diff --git a/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequestTest.java b/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequestTest.java index cf453acac..59861e2ed 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequestTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/multipart/JakartaStreamMultiPartRequestTest.java @@ -18,53 +18,50 @@ */ package org.apache.struts2.dispatcher.multipart; +import org.apache.struts2.dispatcher.LocalizedMessage; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.mock.web.DelegatingServletInputStream; + +import javax.servlet.http.HttpServletRequest; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; -import javax.servlet.http.HttpServletRequest; - -import org.apache.struts2.dispatcher.LocalizedMessage; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; -import org.springframework.mock.web.DelegatingServletInputStream; -import org.testng.Assert; - public class JakartaStreamMultiPartRequestTest { private JakartaStreamMultiPartRequest multiPart; private Path tempDir; - + @Before public void initialize() { multiPart = new JakartaStreamMultiPartRequest(); tempDir = Paths.get("target", "multi-part-test"); } - + /** * Number of bytes in files greater than 2GB overflow the {@code int} primative. - * The {@link HttpServletRequest#getContentLength()} returns {@literal -1} + * The {@link HttpServletRequest#getContentLength()} returns {@literal -1} * when the header is not present or the size is greater than {@link Integer#MAX_VALUE}. - * @throws IOException */ @Test public void unknownContentLength() throws IOException { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); Mockito.when(request.getContentType()).thenReturn("multipart/form-data; charset=utf-8; boundary=__X_BOUNDARY__"); Mockito.when(request.getMethod()).thenReturn("POST"); - Mockito.when(request.getContentLength()).thenReturn(Integer.valueOf(-1)); - StringBuilder entity = new StringBuilder(); - entity.append("\r\n--__X_BOUNDARY__\r\n"); - entity.append("Content-Disposition: form-data; name=\"upload\"; filename=\"test.csv\"\r\n"); - entity.append("Content-Type: text/csv\r\n\r\n1,2\r\n\r\n"); - entity.append("--__X_BOUNDARY__\r\n"); - entity.append("Content-Disposition: form-data; name=\"upload2\"; filename=\"test2.csv\"\r\n"); - entity.append("Content-Type: text/csv\r\n\r\n3,4\r\n\r\n"); - entity.append("--__X_BOUNDARY__--\r\n"); - Mockito.when(request.getInputStream()).thenReturn(new DelegatingServletInputStream(new ByteArrayInputStream(entity.toString().getBytes(StandardCharsets.UTF_8)))); + Mockito.when(request.getContentLength()).thenReturn(-1); + String entity = "\r\n--__X_BOUNDARY__\r\n" + + "Content-Disposition: form-data; name=\"upload\"; filename=\"test.csv\"\r\n" + + "Content-Type: text/csv\r\n\r\n1,2\r\n\r\n" + + "--__X_BOUNDARY__\r\n" + + "Content-Disposition: form-data; name=\"upload2\"; filename=\"test2.csv\"\r\n" + + "Content-Type: text/csv\r\n\r\n3,4\r\n\r\n" + + "--__X_BOUNDARY__--\r\n"; + Mockito.when(request.getInputStream()).thenReturn(new DelegatingServletInputStream(new ByteArrayInputStream(entity.getBytes(StandardCharsets.UTF_8)))); multiPart.setMaxSize("4"); multiPart.parse(request, tempDir.toString()); LocalizedMessage next = multiPart.getErrors().iterator().next(); diff --git a/plugins/testng/pom.xml b/plugins/testng/pom.xml index 823941ba1..cc4d2ba51 100644 --- a/plugins/testng/pom.xml +++ b/plugins/testng/pom.xml @@ -35,7 +35,6 @@ org.testng testng - 6.9.10 org.springframework diff --git a/plugins/testng/src/main/java/org/apache/struts2/StrutsTestCase.java b/plugins/testng/src/main/java/org/apache/struts2/testng/StrutsTestCase.java similarity index 96% rename from plugins/testng/src/main/java/org/apache/struts2/StrutsTestCase.java rename to plugins/testng/src/main/java/org/apache/struts2/testng/StrutsTestCase.java index 193f14220..630eb2df6 100644 --- a/plugins/testng/src/main/java/org/apache/struts2/StrutsTestCase.java +++ b/plugins/testng/src/main/java/org/apache/struts2/testng/StrutsTestCase.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.testng; import java.util.Map; @@ -26,8 +26,6 @@ import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.springframework.mock.web.MockServletContext; -import com.opensymphony.xwork2.TestNGXWorkTestCase; - /** * Base test class for TestNG unit tests. Provides common Struts variables * and performs Struts setup and teardown processes @@ -39,7 +37,7 @@ public class StrutsTestCase extends TestNGXWorkTestCase { super.setUp(); initDispatcher(null); } - + protected Dispatcher initDispatcher(Map params) { Dispatcher du = StrutsTestCaseHelper.initDispatcher(new MockServletContext(), params); configurationManager = du.getConfigurationManager(); diff --git a/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java b/plugins/testng/src/main/java/org/apache/struts2/testng/TestNGXWorkTestCase.java similarity index 96% rename from core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java rename to plugins/testng/src/main/java/org/apache/struts2/testng/TestNGXWorkTestCase.java index 3f34dfec1..3d3519b3d 100644 --- a/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java +++ b/plugins/testng/src/main/java/org/apache/struts2/testng/TestNGXWorkTestCase.java @@ -16,8 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -package com.opensymphony.xwork2; +package org.apache.struts2.testng; +import com.opensymphony.xwork2.ActionProxyFactory; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.ConfigurationManager; import com.opensymphony.xwork2.config.ConfigurationProvider; diff --git a/plugins/testng/src/test/java/org/apache/struts2/TestNGStrutsTestCaseTest.java b/plugins/testng/src/test/java/org/apache/struts2/testng/TestNGStrutsTestCaseTest.java similarity index 95% rename from plugins/testng/src/test/java/org/apache/struts2/TestNGStrutsTestCaseTest.java rename to plugins/testng/src/test/java/org/apache/struts2/testng/TestNGStrutsTestCaseTest.java index dd4ab6a7a..cd86bf99c 100644 --- a/plugins/testng/src/test/java/org/apache/struts2/TestNGStrutsTestCaseTest.java +++ b/plugins/testng/src/test/java/org/apache/struts2/testng/TestNGStrutsTestCaseTest.java @@ -16,11 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.testng; import junit.framework.TestCase; import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.testng.StrutsTestCase; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; @@ -46,13 +47,13 @@ public class TestNGStrutsTestCaseTest extends TestCase { RunTest.mgr = null; } } - + public static class RunTest extends StrutsTestCase { public static boolean ran = false; public static ConfigurationManager mgr; public static Dispatcher du; - - @Test + + @Test public void testRun() { ran = true; mgr = this.configurationManager; diff --git a/core/src/test/java/com/opensymphony/xwork2/TestNGXWorkTestCaseTest.java b/plugins/testng/src/test/java/org/apache/struts2/testng/TestNGXWorkTestCaseTest.java similarity index 95% rename from core/src/test/java/com/opensymphony/xwork2/TestNGXWorkTestCaseTest.java rename to plugins/testng/src/test/java/org/apache/struts2/testng/TestNGXWorkTestCaseTest.java index 0b543a6a0..dcc7a8c9c 100644 --- a/core/src/test/java/com/opensymphony/xwork2/TestNGXWorkTestCaseTest.java +++ b/plugins/testng/src/test/java/org/apache/struts2/testng/TestNGXWorkTestCaseTest.java @@ -16,10 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package com.opensymphony.xwork2; +package org.apache.struts2.testng; import com.opensymphony.xwork2.config.ConfigurationManager; import junit.framework.TestCase; +import org.apache.struts2.testng.TestNGXWorkTestCase; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; @@ -42,12 +43,12 @@ public class TestNGXWorkTestCaseTest extends TestCase { RunTest.mgr = null; } } - + @Test public static class RunTest extends TestNGXWorkTestCase { public static boolean ran = false; public static ConfigurationManager mgr; - + public void testRun() { ran = true; mgr = this.configurationManager; diff --git a/pom.xml b/pom.xml index cdd13feda..1899ed558 100644 --- a/pom.xml +++ b/pom.xml @@ -1112,9 +1112,7 @@ org.testng testng - 7.1.0 - compile - true + 7.4.0 From 980387e91cba413e2648d91c4206c8e411147b40 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 4 Sep 2022 11:59:01 +0200 Subject: [PATCH 027/143] WW-5220 Moves JUnit related test into the JUnit plugin Also moves all the plugin classes under junit package --- .../JasperReportsResultTest.java | 14 +- .../struts2/dispatcher/ChartResultTest.java | 17 +- .../struts2/json/DefaultJSONWriterTest.java | 16 +- .../json/JSONActionRedirectResultTest.java | 15 +- .../struts2/json/JSONInterceptorTest.java | 25 +- .../struts2/json/JSONPopulatorTest.java | 2 +- .../apache/struts2/json/JSONResultTest.java | 42 +- .../json/JSONValidationInterceptorTest.java | 28 +- .../ConventionPluginResourceLoader.java | 2 +- .../{ => junit}/StrutsJUnit4TestCase.java | 504 +++++++++--------- .../{ => junit}/StrutsPortletTestCase.java | 12 +- .../{ => junit}/StrutsRestTestCase.java | 3 +- .../StrutsSpringJUnit4TestCase.java | 2 +- .../{ => junit}/StrutsSpringTestCase.java | 94 ++-- .../struts2/{ => junit}/StrutsTestCase.java | 5 +- .../struts2/junit}/XWorkJUnit4TestCase.java | 9 +- .../struts2/{ => junit}/util/TestUtils.java | 2 +- .../struts2/{ => junit}/JUnitTestAction.java | 78 +-- .../struts2/{ => junit}/MySessionBean.java | 2 +- .../{ => junit}/StrutsJUnit4TestCaseTest.java | 6 +- .../StrutsSpringJUnit4TestCaseTest.java | 16 +- .../{ => junit}/StrutsSpringTestCaseTest.java | 54 +- .../{ => junit}/StrutsTestCaseTest.java | 201 +++---- .../StrutsJUnit4ConventionTestCaseTest.java | 4 +- .../{ => junit}/session/SessionGetAction.java | 2 +- .../{ => junit}/session/SessionSetAction.java | 2 +- .../StrutsJUnit4SessionTestCaseTest.java | 10 +- .../src/test/resources/applicationContext.xml | 6 +- .../resources/struts-session-values-test.xml | 8 +- .../junit/src/test/resources/struts-test.xml | 6 +- plugins/junit/src/test/resources/struts.xml | 8 +- 31 files changed, 601 insertions(+), 594 deletions(-) rename plugins/junit/src/main/java/org/apache/struts2/{ => junit}/ConventionPluginResourceLoader.java (98%) rename plugins/junit/src/main/java/org/apache/struts2/{ => junit}/StrutsJUnit4TestCase.java (92%) rename plugins/junit/src/main/java/org/apache/struts2/{ => junit}/StrutsPortletTestCase.java (98%) rename plugins/junit/src/main/java/org/apache/struts2/{ => junit}/StrutsRestTestCase.java (98%) rename plugins/junit/src/main/java/org/apache/struts2/{ => junit}/StrutsSpringJUnit4TestCase.java (97%) rename plugins/junit/src/main/java/org/apache/struts2/{ => junit}/StrutsSpringTestCase.java (93%) rename plugins/junit/src/main/java/org/apache/struts2/{ => junit}/StrutsTestCase.java (98%) rename {core/src/main/java/com/opensymphony/xwork2 => plugins/junit/src/main/java/org/apache/struts2/junit}/XWorkJUnit4TestCase.java (91%) rename plugins/junit/src/main/java/org/apache/struts2/{ => junit}/util/TestUtils.java (98%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/JUnitTestAction.java (94%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/MySessionBean.java (96%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/StrutsJUnit4TestCaseTest.java (92%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/StrutsSpringJUnit4TestCaseTest.java (93%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/StrutsSpringTestCaseTest.java (95%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/StrutsTestCaseTest.java (96%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/convention/StrutsJUnit4ConventionTestCaseTest.java (95%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/session/SessionGetAction.java (96%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/session/SessionSetAction.java (96%) rename plugins/junit/src/test/java/org/apache/struts2/{ => junit}/session/StrutsJUnit4SessionTestCaseTest.java (90%) diff --git a/plugins/jasperreports/src/test/java/org/apache/struts2/views/jasperreports/JasperReportsResultTest.java b/plugins/jasperreports/src/test/java/org/apache/struts2/views/jasperreports/JasperReportsResultTest.java index 02c1eb43a..4a563df94 100644 --- a/plugins/jasperreports/src/test/java/org/apache/struts2/views/jasperreports/JasperReportsResultTest.java +++ b/plugins/jasperreports/src/test/java/org/apache/struts2/views/jasperreports/JasperReportsResultTest.java @@ -25,7 +25,7 @@ import com.opensymphony.xwork2.util.ClassLoaderUtil; import com.opensymphony.xwork2.util.ValueStack; import net.sf.jasperreports.engine.JasperCompileManager; import org.apache.struts2.StrutsStatics; -import org.apache.struts2.StrutsTestCase; +import org.apache.struts2.junit.StrutsTestCase; import javax.servlet.ServletException; import java.net.URL; @@ -82,7 +82,7 @@ public class JasperReportsResultTest extends StrutsTestCase { result.execute(this.invocation); } catch (ServletException e) { assertEquals("Error building dataSource for excluded or not accepted [getDatasource()]", - e.getMessage()); + e.getMessage()); } // verify that above test has really effect @@ -242,14 +242,14 @@ public class JasperReportsResultTest extends StrutsTestCase { private static final Map[] JR_MAP_ARRAY_DATA_SOURCE = new Map[]{ - new HashMap() {{ - put("firstName", "Foo"); - put("lastName", "Bar"); - }} + new HashMap() {{ + put("firstName", "Foo"); + put("lastName", "Bar"); + }} }; private static final NotExcludedAcceptedPatternsChecker NO_EXCLUSION_ACCEPT_ALL_PATTERNS_CHECKER - = new NotExcludedAcceptedPatternsChecker() { + = new NotExcludedAcceptedPatternsChecker() { @Override public IsAllowed isAllowed(String value) { return IsAllowed.yes("*"); diff --git a/plugins/jfreechart/src/test/java/org/apache/struts2/dispatcher/ChartResultTest.java b/plugins/jfreechart/src/test/java/org/apache/struts2/dispatcher/ChartResultTest.java index 0dda1732e..5a8cb3f7c 100644 --- a/plugins/jfreechart/src/test/java/org/apache/struts2/dispatcher/ChartResultTest.java +++ b/plugins/jfreechart/src/test/java/org/apache/struts2/dispatcher/ChartResultTest.java @@ -23,7 +23,7 @@ import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.util.ValueStack; import org.apache.struts2.ServletActionContext; -import org.apache.struts2.StrutsTestCase; +import org.apache.struts2.junit.StrutsTestCase; import org.easymock.EasyMock; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; @@ -36,6 +36,7 @@ import java.io.IOException; /** + * */ public class ChartResultTest extends StrutsTestCase { @@ -50,7 +51,7 @@ public class ChartResultTest extends StrutsTestCase { public void testChart() throws Exception { EasyMock.expect(responseMock.getOutputStream()).andReturn(os); EasyMock.replay(responseMock, mockActionProxy, actionInvocation); - + ChartResult result = new ChartResult(); result.setChart(mockChart); @@ -62,7 +63,7 @@ public class ChartResultTest extends StrutsTestCase { EasyMock.verify(responseMock); assertTrue(os.isWritten()); } - + public void testContentTypePng() throws Exception { EasyMock.expect(responseMock.getOutputStream()).andReturn(os); responseMock.setContentType("image/png"); @@ -79,7 +80,7 @@ public class ChartResultTest extends StrutsTestCase { EasyMock.verify(responseMock); assertTrue(os.isWritten()); } - + public void testContentTypeJpg() throws Exception { EasyMock.expect(responseMock.getOutputStream()).andReturn(os); responseMock.setContentType("image/jpg"); @@ -101,7 +102,7 @@ public class ChartResultTest extends StrutsTestCase { public void testChartNotSet() { ChartResult result = new ChartResult(); EasyMock.replay(responseMock, mockActionProxy, actionInvocation); - + // expect exception if chart not set. result.setChart(null); @@ -141,7 +142,7 @@ public class ChartResultTest extends StrutsTestCase { assertEquals("150", result.getWidth().toString()); assertTrue(os.isWritten()); } - + protected void setUp() throws Exception { super.setUp(); @@ -160,8 +161,8 @@ public class ChartResultTest extends StrutsTestCase { actionInvocation = EasyMock.createMock(ActionInvocation.class); EasyMock.expect(actionInvocation.getStack()).andReturn(stack).anyTimes(); - - + + os = new MockServletOutputStream(); responseMock = EasyMock.createNiceMock(HttpServletResponse.class); diff --git a/plugins/json/src/test/java/org/apache/struts2/json/DefaultJSONWriterTest.java b/plugins/json/src/test/java/org/apache/struts2/json/DefaultJSONWriterTest.java index 05e32807b..1f25cabbc 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/DefaultJSONWriterTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/DefaultJSONWriterTest.java @@ -18,10 +18,10 @@ */ package org.apache.struts2.json; -import org.apache.struts2.StrutsTestCase; import org.apache.struts2.json.annotations.JSONFieldBridge; import org.apache.struts2.json.bridge.StringBridge; -import org.apache.struts2.util.TestUtils; +import org.apache.struts2.junit.StrutsTestCase; +import org.apache.struts2.junit.util.TestUtils; import org.junit.Test; import java.net.URL; @@ -32,10 +32,10 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; -public class DefaultJSONWriterTest extends StrutsTestCase{ +public class DefaultJSONWriterTest extends StrutsTestCase { @Test public void testWrite() throws Exception { - Bean bean1=new Bean(); + Bean bean1 = new Bean(); bean1.setStringField("str"); bean1.setBooleanField(true); bean1.setCharField('s'); @@ -54,7 +54,7 @@ public class DefaultJSONWriterTest extends StrutsTestCase{ @Test public void testWriteExcludeNull() throws Exception { - BeanWithMap bean1=new BeanWithMap(); + BeanWithMap bean1 = new BeanWithMap(); bean1.setStringField("str"); bean1.setBooleanField(true); bean1.setCharField('s'); @@ -78,7 +78,7 @@ public class DefaultJSONWriterTest extends StrutsTestCase{ TestUtils.assertEquals(DefaultJSONWriter.class.getResource("jsonwriter-write-bean-03.txt"), json); } - private class BeanWithMap extends Bean{ + private class BeanWithMap extends Bean { private Map map; public Map getMap() { @@ -92,7 +92,7 @@ public class DefaultJSONWriterTest extends StrutsTestCase{ @Test public void testWriteAnnotatedBean() throws Exception { - AnnotatedBean bean1=new AnnotatedBean(); + AnnotatedBean bean1 = new AnnotatedBean(); bean1.setStringField("str"); bean1.setBooleanField(true); bean1.setCharField('s'); @@ -146,7 +146,7 @@ public class DefaultJSONWriterTest extends StrutsTestCase{ } } - private class AnnotatedBean extends Bean{ + private class AnnotatedBean extends Bean { private URL url; @JSONFieldBridge(impl = StringBridge.class) diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONActionRedirectResultTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONActionRedirectResultTest.java index 383b119e1..9e93fc5d1 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/JSONActionRedirectResultTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONActionRedirectResultTest.java @@ -18,19 +18,18 @@ */ package org.apache.struts2.json; -import org.apache.struts2.StrutsStatics; -import org.apache.struts2.StrutsTestCase; -import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; -import org.apache.struts2.views.util.DefaultUrlHelper; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.mock.web.MockServletContext; - import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.config.entities.ActionConfig; import com.opensymphony.xwork2.mock.MockActionInvocation; import com.opensymphony.xwork2.mock.MockActionProxy; import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.StrutsStatics; +import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; +import org.apache.struts2.junit.StrutsTestCase; +import org.apache.struts2.views.util.DefaultUrlHelper; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockServletContext; public class JSONActionRedirectResultTest extends StrutsTestCase { diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java index 20fdad73d..8fadec272 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java @@ -18,19 +18,18 @@ */ package org.apache.struts2.json; -import java.util.Calendar; -import java.util.List; -import java.util.Map; - -import org.apache.struts2.StrutsTestCase; -import org.apache.struts2.util.TestUtils; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.mock.MockActionInvocation; +import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.junit.StrutsTestCase; +import org.apache.struts2.junit.util.TestUtils; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.mock.MockActionInvocation; -import com.opensymphony.xwork2.util.ValueStack; +import java.util.Calendar; +import java.util.List; +import java.util.Map; public class JSONInterceptorTest extends StrutsTestCase { private MockActionInvocationEx invocation; @@ -294,7 +293,7 @@ public class JSONInterceptorTest extends StrutsTestCase { assertEquals("application/json;charset=UTF-8", response.getContentType()); } - @SuppressWarnings( { "unchecked", "unchecked" }) + @SuppressWarnings({"unchecked", "unchecked"}) public void testReadEmpty() throws Exception { // request setRequestContent("json-6.txt"); @@ -309,7 +308,7 @@ public class JSONInterceptorTest extends StrutsTestCase { interceptor.intercept(this.invocation); } - @SuppressWarnings( { "unchecked", "unchecked" }) + @SuppressWarnings({"unchecked", "unchecked"}) public void test() throws Exception { // request setRequestContent("json-1.txt"); @@ -457,7 +456,7 @@ public class JSONInterceptorTest extends StrutsTestCase { assertEquals(bean2.getDoubleField(), 10.1); assertEquals(bean2.getByteField(), 3); } - + public void testJSONArray() throws Exception { setRequestContent("json-12.txt"); this.request.addHeader("Content-Type", "application/json"); @@ -509,7 +508,7 @@ public class JSONInterceptorTest extends StrutsTestCase { assertEquals(beans.get(0).getDoubleField(), 10.1); assertEquals(beans.get(0).getByteField(), 3); } - + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONPopulatorTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONPopulatorTest.java index dd6fa7235..c3a2a3bfe 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/JSONPopulatorTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONPopulatorTest.java @@ -27,7 +27,7 @@ import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; -import org.apache.struts2.util.TestUtils; +import org.apache.struts2.junit.util.TestUtils; public class JSONPopulatorTest extends TestCase { diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONResultTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONResultTest.java index 531f7ef26..c346729eb 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/JSONResultTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONResultTest.java @@ -18,6 +18,19 @@ */ package org.apache.struts2.json; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.Result; +import com.opensymphony.xwork2.mock.MockActionInvocation; +import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.StrutsStatics; +import org.apache.struts2.junit.StrutsTestCase; +import org.apache.struts2.junit.util.TestUtils; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockServletContext; + +import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.math.BigInteger; import java.text.SimpleDateFormat; @@ -33,21 +46,6 @@ import java.util.Map; import java.util.Set; import java.util.regex.Pattern; -import javax.servlet.http.HttpServletResponse; - -import com.opensymphony.xwork2.Result; -import org.apache.struts2.StrutsStatics; -import org.apache.struts2.StrutsTestCase; -import org.apache.struts2.util.TestUtils; -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.mock.web.MockServletContext; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.mock.MockActionInvocation; -import com.opensymphony.xwork2.util.ValueStack; - /** * JSONResultTest */ @@ -298,13 +296,13 @@ public class JSONResultTest extends StrutsTestCase { stack.push(action); // test scape characters - action.setArray(new String[] { "a", "a", "\"", "\\", "/", "\b", "\f", "\n", "\r", "\t" }); + action.setArray(new String[]{"a", "a", "\"", "\\", "/", "\b", "\f", "\n", "\r", "\t"}); List list = new ArrayList(); list.add("b"); list.add(1); - list.add(new int[] { 10, 12 }); + list.add(new int[]{10, 12}); action.setCollection(list); // beans @@ -343,7 +341,7 @@ public class JSONResultTest extends StrutsTestCase { Map map = new LinkedHashMap(); map.put("a", 1); - map.put("c", new float[] { 1.0f, 2.0f }); + map.put("c", new float[]{1.0f, 2.0f}); action.setMap(map); action.setFoo("foo"); @@ -403,13 +401,13 @@ public class JSONResultTest extends StrutsTestCase { stack.push(action); // test scape characters - action.setArray(new String[] { "a", "a", "\"", "\\", "/", "\b", "\f", "\n", "\r", "\t" }); + action.setArray(new String[]{"a", "a", "\"", "\\", "/", "\b", "\f", "\n", "\r", "\t"}); List list = new ArrayList(); list.add("b"); list.add(1); - list.add(new int[] { 10, 12 }); + list.add(new int[]{10, 12}); action.setCollection(list); // beans @@ -446,7 +444,7 @@ public class JSONResultTest extends StrutsTestCase { Map map = new LinkedHashMap(); map.put("a", 1); - map.put("c", new float[] { 1.0f, 2.0f }); + map.put("c", new float[]{1.0f, 2.0f}); action.setMap(map); action.setFoo("foo"); @@ -714,7 +712,7 @@ public class JSONResultTest extends StrutsTestCase { assertEquals("UTF-8", encoding); } - public void testPassingNullInvocation() throws Exception{ + public void testPassingNullInvocation() throws Exception { Result result = new JSONResult(); try { result.execute(null); diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONValidationInterceptorTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONValidationInterceptorTest.java index 7a27bebb3..8cf3dcef1 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/JSONValidationInterceptorTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONValidationInterceptorTest.java @@ -26,13 +26,13 @@ import com.opensymphony.xwork2.mock.MockActionInvocation; import com.opensymphony.xwork2.mock.MockActionProxy; import com.opensymphony.xwork2.validator.annotations.EmailValidator; import com.opensymphony.xwork2.validator.annotations.IntRangeFieldValidator; -import com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator; import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; +import com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator; import org.apache.struts2.StrutsStatics; -import org.apache.struts2.StrutsTestCase; import org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor; import org.apache.struts2.interceptor.validation.SkipValidation; -import org.apache.struts2.util.TestUtils; +import org.apache.struts2.junit.StrutsTestCase; +import org.apache.struts2.junit.util.TestUtils; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; @@ -53,13 +53,13 @@ public class JSONValidationInterceptorTest extends StrutsTestCase { private AnnotationValidationInterceptor validationInterceptor; public void testValidationFails() throws Exception { - + action.addActionError("General error"); - + Map parameters = new HashMap(); parameters.put("struts.enableJSONValidation", "true"); request.setParameterMap(parameters); - + validationInterceptor.intercept(invocation); interceptor.intercept(invocation); @@ -69,11 +69,11 @@ public class JSONValidationInterceptorTest extends StrutsTestCase { //json assertThat(normalizedActual) - .contains("\"errors\":[\"Generalerror\"]") - .contains("\"fieldErrors\":{") - .contains("\"value\":[\"Minvalueis-1\"]") - .contains("\"text\":[\"Tooshort\",\"Thisisnoemail\"]") - .contains("\"password\":[\"Passwordisn'tcorrect\"]"); + .contains("\"errors\":[\"Generalerror\"]") + .contains("\"fieldErrors\":{") + .contains("\"value\":[\"Minvalueis-1\"]") + .contains("\"text\":[\"Tooshort\",\"Thisisnoemail\"]") + .contains("\"password\":[\"Passwordisn'tcorrect\"]"); //execution assertFalse(action.isExecuted()); @@ -89,7 +89,7 @@ public class JSONValidationInterceptorTest extends StrutsTestCase { action.setText("abcd@ggg.com"); action.setPassword("apassword"); action.setValue(10); - + Map parameters = new HashMap(); parameters.put("struts.enableJSONValidation", "true"); request.setParameterMap(parameters); @@ -102,7 +102,7 @@ public class JSONValidationInterceptorTest extends StrutsTestCase { String normalizedActual = TestUtils.normalize(json, true); assertEquals("", normalizedActual); } - + public void testValidationSucceedsValidateOnly() throws Exception { JSONValidationInterceptor interceptor = new JSONValidationInterceptor(); @@ -115,7 +115,7 @@ public class JSONValidationInterceptorTest extends StrutsTestCase { parameters.put("struts.validateOnly", "true"); parameters.put("struts.enableJSONValidation", "true"); request.setParameterMap(parameters); - + validationInterceptor.intercept(invocation); interceptor.intercept(invocation); diff --git a/plugins/junit/src/main/java/org/apache/struts2/ConventionPluginResourceLoader.java b/plugins/junit/src/main/java/org/apache/struts2/junit/ConventionPluginResourceLoader.java similarity index 98% rename from plugins/junit/src/main/java/org/apache/struts2/ConventionPluginResourceLoader.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/ConventionPluginResourceLoader.java index 060ea0f0a..caf9f1056 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/ConventionPluginResourceLoader.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/ConventionPluginResourceLoader.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.junit; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; diff --git a/plugins/junit/src/main/java/org/apache/struts2/StrutsJUnit4TestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsJUnit4TestCase.java similarity index 92% rename from plugins/junit/src/main/java/org/apache/struts2/StrutsJUnit4TestCase.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/StrutsJUnit4TestCase.java index 25fade262..e7df6476d 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/StrutsJUnit4TestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsJUnit4TestCase.java @@ -1,252 +1,252 @@ -/* - * 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; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionProxy; -import com.opensymphony.xwork2.ActionProxyFactory; -import com.opensymphony.xwork2.XWorkJUnit4TestCase; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.interceptor.ValidationAware; -import com.opensymphony.xwork2.interceptor.annotations.After; -import com.opensymphony.xwork2.interceptor.annotations.Before; -import org.apache.commons.lang3.StringUtils; -import org.apache.struts2.dispatcher.Dispatcher; -import org.apache.struts2.dispatcher.HttpParameters; -import org.apache.struts2.dispatcher.mapper.ActionMapper; -import org.apache.struts2.dispatcher.mapper.ActionMapping; -import org.apache.struts2.util.StrutsTestCaseHelper; -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.mock.web.MockHttpSession; -import org.springframework.mock.web.MockPageContext; -import org.springframework.mock.web.MockServletContext; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.UnsupportedEncodingException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertNotNull; - - -public abstract class StrutsJUnit4TestCase extends XWorkJUnit4TestCase { - - protected MockHttpServletResponse response; - protected MockHttpServletRequest request; - protected MockPageContext pageContext; - protected MockServletContext servletContext; - protected Map dispatcherInitParams; - protected Dispatcher dispatcher; - - protected DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); - - /** - * gets an object from the stack after an action is executed - */ - protected Object findValueAfterExecute(String key) { - return ServletActionContext.getValueStack(request).findValue(key); - } - - /** - * gets an object from the stack after an action is executed - * - * @return The executed action - */ - @SuppressWarnings("unchecked") - protected T getAction() { - return (T) findValueAfterExecute("action"); - } - - protected boolean containsErrors() { - T action = this.getAction(); - if (action instanceof ValidationAware) { - return ((ValidationAware) action).hasActionErrors(); - } - throw new UnsupportedOperationException("Current action does not implement ValidationAware interface"); - } - - /** - * Executes an action and returns it's output (not the result returned from - * execute()), but the actual output that would be written to the response. - * For this to work the configured result for the action needs to be - * FreeMarker, or Velocity (JSPs can be used with the Embedded JSP plugin) - */ - protected String executeAction(String uri) throws ServletException, UnsupportedEncodingException { - request.setRequestURI(uri); - ActionMapping mapping = getActionMapping(request); - - assertNotNull(mapping); - Dispatcher.getInstance().serviceAction(request, response, mapping); - - if (response.getStatus() != HttpServletResponse.SC_OK) - throw new ServletException("Error code [" + response.getStatus() + "], Error: [" - + response.getErrorMessage() + "]"); - - return response.getContentAsString(); - } - - /** - * Creates an action proxy for a request, and sets parameters of the ActionInvocation to the passed - * parameters. Make sure to set the request parameters in the protected "request" object before calling this method. - */ - protected ActionProxy getActionProxy(String uri) { - request.setRequestURI(uri); - ActionMapping mapping = getActionMapping(request); - String namespace = mapping.getNamespace(); - String name = mapping.getName(); - String method = mapping.getMethod(); - - Configuration config = configurationManager.getConfiguration(); - ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( - namespace, name, method, new HashMap(), true, false); - - initActionContext(proxy.getInvocation().getInvocationContext()); - - // this is normally done in onSetUp(), but we are using Struts internal - // objects (proxy and action invocation) - // so we have to hack around so it works - ServletActionContext.setServletContext(servletContext); - ServletActionContext.setRequest(request); - ServletActionContext.setResponse(response); - - ServletActionContext.getContext().put(ServletActionContext.ACTION_MAPPING, mapping); - - return proxy; - } - - protected void initActionContext(ActionContext actionContext) { - actionContext.setParameters(HttpParameters.create(request.getParameterMap()).build()); - initSession(actionContext); - // set the action context to the one used by the proxy - ActionContext.bind(actionContext); - } - - protected void initSession(ActionContext actionContext) { - if (actionContext.getSession() == null) { - actionContext.withSession(new HashMap<>()); - request.setSession(new MockHttpSession(servletContext)); - } - } - - /** - * Finds an ActionMapping for a given request - */ - protected ActionMapping getActionMapping(HttpServletRequest request) { - return container.getInstance(ActionMapper.class).getMapping(request, configurationManager); - } - - /** - * Finds an ActionMapping for a given url - */ - protected ActionMapping getActionMapping(String url) { - MockHttpServletRequest req = new MockHttpServletRequest(); - req.setRequestURI(url); - return getActionMapping(req); - } - - /** - * Injects dependencies on an Object using Struts internal IoC container - */ - protected void injectStrutsDependencies(Object object) { - container.inject(object); - } - - protected void setupBeforeInitDispatcher() throws Exception { - } - - protected void initServletMockObjects() { - servletContext = new MockServletContext(resourceLoader); - response = new MockHttpServletResponse(); - request = new MockHttpServletRequest(); - pageContext = new MockPageContext(servletContext, request, response); - } - - public void finishExecution() { - HttpSession session = this.request.getSession(); - Enumeration attributeNames = session.getAttributeNames(); - - MockHttpServletRequest nextRequest = new MockHttpServletRequest(); - - while (attributeNames.hasMoreElements()) { - String key = (String) attributeNames.nextElement(); - Object attribute = session.getAttribute(key); - nextRequest.getSession().setAttribute(key, attribute); - } - - this.response = new MockHttpServletResponse(); - this.request = nextRequest; - this.pageContext = new MockPageContext(servletContext, request, response); - } - - /** - * Sets up the configuration settings, XWork configuration, and - * message resources - */ - @Before - public void setUp() throws Exception { - super.setUp(); - initServletMockObjects(); - setupBeforeInitDispatcher(); - initDispatcherParams(); - initDispatcher(dispatcherInitParams); - } - - protected void initDispatcherParams() { - if (StringUtils.isNotBlank(getConfigPath())) { - dispatcherInitParams = new HashMap<>(); - dispatcherInitParams.put("config", "struts-default.xml," + getConfigPath()); - } - } - - protected Dispatcher initDispatcher(Map params) { - dispatcher = StrutsTestCaseHelper.initDispatcher(servletContext, params); - configurationManager = dispatcher.getConfigurationManager(); - configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - container.inject(dispatcher); - return dispatcher; - } - - /** - * Override this method to return a comma separated list of paths to a configuration - * file. - *

The default implementation simply returns null. - * @return a comma separated list of config locations - */ - protected String getConfigPath() { - return null; - } - - @After - public void tearDown() throws Exception { - super.tearDown(); - if (dispatcher != null && dispatcher.getConfigurationManager() != null) { - dispatcher.cleanup(); - dispatcher = null; - } - StrutsTestCaseHelper.tearDown(); - } - -} +/* + * 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.junit; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionProxy; +import com.opensymphony.xwork2.ActionProxyFactory; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.interceptor.ValidationAware; +import com.opensymphony.xwork2.interceptor.annotations.After; +import com.opensymphony.xwork2.interceptor.annotations.Before; +import org.apache.commons.lang3.StringUtils; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.dispatcher.HttpParameters; +import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.ActionMapping; +import org.apache.struts2.util.StrutsTestCaseHelper; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.mock.web.MockPageContext; +import org.springframework.mock.web.MockServletContext; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.UnsupportedEncodingException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertNotNull; + +public abstract class StrutsJUnit4TestCase extends XWorkJUnit4TestCase { + + protected MockHttpServletResponse response; + protected MockHttpServletRequest request; + protected MockPageContext pageContext; + protected MockServletContext servletContext; + protected Map dispatcherInitParams; + protected Dispatcher dispatcher; + + protected DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); + + /** + * gets an object from the stack after an action is executed + */ + protected Object findValueAfterExecute(String key) { + return ServletActionContext.getValueStack(request).findValue(key); + } + + /** + * gets an object from the stack after an action is executed + * + * @return The executed action + */ + @SuppressWarnings("unchecked") + protected T getAction() { + return (T) findValueAfterExecute("action"); + } + + protected boolean containsErrors() { + T action = this.getAction(); + if (action instanceof ValidationAware) { + return ((ValidationAware) action).hasActionErrors(); + } + throw new UnsupportedOperationException("Current action does not implement ValidationAware interface"); + } + + /** + * Executes an action and returns it's output (not the result returned from + * execute()), but the actual output that would be written to the response. + * For this to work the configured result for the action needs to be + * FreeMarker, or Velocity (JSPs can be used with the Embedded JSP plugin) + */ + protected String executeAction(String uri) throws ServletException, UnsupportedEncodingException { + request.setRequestURI(uri); + ActionMapping mapping = getActionMapping(request); + + assertNotNull(mapping); + Dispatcher.getInstance().serviceAction(request, response, mapping); + + if (response.getStatus() != HttpServletResponse.SC_OK) + throw new ServletException("Error code [" + response.getStatus() + "], Error: [" + + response.getErrorMessage() + "]"); + + return response.getContentAsString(); + } + + /** + * Creates an action proxy for a request, and sets parameters of the ActionInvocation to the passed + * parameters. Make sure to set the request parameters in the protected "request" object before calling this method. + */ + protected ActionProxy getActionProxy(String uri) { + request.setRequestURI(uri); + ActionMapping mapping = getActionMapping(request); + String namespace = mapping.getNamespace(); + String name = mapping.getName(); + String method = mapping.getMethod(); + + Configuration config = configurationManager.getConfiguration(); + ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( + namespace, name, method, new HashMap(), true, false); + + initActionContext(proxy.getInvocation().getInvocationContext()); + + // this is normally done in onSetUp(), but we are using Struts internal + // objects (proxy and action invocation) + // so we have to hack around so it works + ServletActionContext.setServletContext(servletContext); + ServletActionContext.setRequest(request); + ServletActionContext.setResponse(response); + + ServletActionContext.getContext().put(ServletActionContext.ACTION_MAPPING, mapping); + + return proxy; + } + + protected void initActionContext(ActionContext actionContext) { + actionContext.setParameters(HttpParameters.create(request.getParameterMap()).build()); + initSession(actionContext); + // set the action context to the one used by the proxy + ActionContext.bind(actionContext); + } + + protected void initSession(ActionContext actionContext) { + if (actionContext.getSession() == null) { + actionContext.withSession(new HashMap<>()); + request.setSession(new MockHttpSession(servletContext)); + } + } + + /** + * Finds an ActionMapping for a given request + */ + protected ActionMapping getActionMapping(HttpServletRequest request) { + return container.getInstance(ActionMapper.class).getMapping(request, configurationManager); + } + + /** + * Finds an ActionMapping for a given url + */ + protected ActionMapping getActionMapping(String url) { + MockHttpServletRequest req = new MockHttpServletRequest(); + req.setRequestURI(url); + return getActionMapping(req); + } + + /** + * Injects dependencies on an Object using Struts internal IoC container + */ + protected void injectStrutsDependencies(Object object) { + container.inject(object); + } + + protected void setupBeforeInitDispatcher() throws Exception { + } + + protected void initServletMockObjects() { + servletContext = new MockServletContext(resourceLoader); + response = new MockHttpServletResponse(); + request = new MockHttpServletRequest(); + pageContext = new MockPageContext(servletContext, request, response); + } + + public void finishExecution() { + HttpSession session = this.request.getSession(); + Enumeration attributeNames = session.getAttributeNames(); + + MockHttpServletRequest nextRequest = new MockHttpServletRequest(); + + while (attributeNames.hasMoreElements()) { + String key = (String) attributeNames.nextElement(); + Object attribute = session.getAttribute(key); + nextRequest.getSession().setAttribute(key, attribute); + } + + this.response = new MockHttpServletResponse(); + this.request = nextRequest; + this.pageContext = new MockPageContext(servletContext, request, response); + } + + /** + * Sets up the configuration settings, XWork configuration, and + * message resources + */ + @Before + public void setUp() throws Exception { + super.setUp(); + initServletMockObjects(); + setupBeforeInitDispatcher(); + initDispatcherParams(); + initDispatcher(dispatcherInitParams); + } + + protected void initDispatcherParams() { + if (StringUtils.isNotBlank(getConfigPath())) { + dispatcherInitParams = new HashMap<>(); + dispatcherInitParams.put("config", "struts-default.xml," + getConfigPath()); + } + } + + protected Dispatcher initDispatcher(Map params) { + dispatcher = StrutsTestCaseHelper.initDispatcher(servletContext, params); + configurationManager = dispatcher.getConfigurationManager(); + configuration = configurationManager.getConfiguration(); + container = configuration.getContainer(); + container.inject(dispatcher); + return dispatcher; + } + + /** + * Override this method to return a comma separated list of paths to a configuration + * file. + *

The default implementation simply returns null. + * + * @return a comma separated list of config locations + */ + protected String getConfigPath() { + return null; + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + if (dispatcher != null && dispatcher.getConfigurationManager() != null) { + dispatcher.cleanup(); + dispatcher = null; + } + StrutsTestCaseHelper.tearDown(); + } + +} diff --git a/plugins/junit/src/main/java/org/apache/struts2/StrutsPortletTestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsPortletTestCase.java similarity index 98% rename from plugins/junit/src/main/java/org/apache/struts2/StrutsPortletTestCase.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/StrutsPortletTestCase.java index b5b430945..de7d8da91 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/StrutsPortletTestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsPortletTestCase.java @@ -16,15 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.junit; import com.opensymphony.xwork2.ActionContext; -import java.util.HashMap; -import java.util.Map; -import javax.portlet.PortletMode; -import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.struts2.StrutsStatics; import org.apache.struts2.mock.web.portlet.MockPortletContext; import org.apache.struts2.mock.web.portlet.MockPortletRequest; import org.apache.struts2.mock.web.portlet.MockPortletResponse; @@ -33,6 +31,10 @@ import org.apache.struts2.mock.web.portlet.MockStateAwareResponse; import org.apache.struts2.portlet.PortletConstants; import org.apache.struts2.portlet.PortletPhase; +import javax.portlet.PortletMode; +import java.util.HashMap; +import java.util.Map; + /* * Changes: This is a copy of org.apache.struts2.StrutsPortletTestCase from the Struts 2 portlet-plugin, moved * into the junit-plugin (same package org.apache.struts2). diff --git a/plugins/junit/src/main/java/org/apache/struts2/StrutsRestTestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java similarity index 98% rename from plugins/junit/src/main/java/org/apache/struts2/StrutsRestTestCase.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java index b4f84a6bb..6e7c5f93c 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/StrutsRestTestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java @@ -16,12 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.junit; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.ActionProxyFactory; import com.opensymphony.xwork2.config.Configuration; +import org.apache.struts2.ServletActionContext; import org.apache.struts2.dispatcher.Dispatcher; import org.apache.struts2.dispatcher.HttpParameters; import org.apache.struts2.dispatcher.mapper.ActionMapping; diff --git a/plugins/junit/src/main/java/org/apache/struts2/StrutsSpringJUnit4TestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsSpringJUnit4TestCase.java similarity index 97% rename from plugins/junit/src/main/java/org/apache/struts2/StrutsSpringJUnit4TestCase.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/StrutsSpringJUnit4TestCase.java index 30c2281c9..6ddeb94a0 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/StrutsSpringJUnit4TestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsSpringJUnit4TestCase.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.junit; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; diff --git a/plugins/junit/src/main/java/org/apache/struts2/StrutsSpringTestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsSpringTestCase.java similarity index 93% rename from plugins/junit/src/main/java/org/apache/struts2/StrutsSpringTestCase.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/StrutsSpringTestCase.java index 59635f35b..13a92ed64 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/StrutsSpringTestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsSpringTestCase.java @@ -1,47 +1,47 @@ -/* - * 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; - -import org.springframework.context.ApplicationContext; -import org.springframework.test.context.support.GenericXmlContextLoader; -import org.springframework.web.context.WebApplicationContext; - -/** - * Base class for Spring JUnit actions - */ -public abstract class StrutsSpringTestCase extends StrutsTestCase { - - private static final String DEFAULT_CONTEXT_LOCATION = "classpath*:applicationContext.xml"; - protected static ApplicationContext applicationContext; - - protected void setupBeforeInitDispatcher() throws Exception { - // only load beans from spring once - if (applicationContext == null) { - GenericXmlContextLoader xmlContextLoader = new GenericXmlContextLoader(); - applicationContext = xmlContextLoader.loadContext(getContextLocations()); - } - - servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext); - } - - protected String[] getContextLocations() { - return new String[] {DEFAULT_CONTEXT_LOCATION}; - } - -} +/* + * 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.junit; + +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.support.GenericXmlContextLoader; +import org.springframework.web.context.WebApplicationContext; + +/** + * Base class for Spring JUnit actions + */ +public abstract class StrutsSpringTestCase extends StrutsTestCase { + + private static final String DEFAULT_CONTEXT_LOCATION = "classpath*:applicationContext.xml"; + protected static ApplicationContext applicationContext; + + protected void setupBeforeInitDispatcher() throws Exception { + // only load beans from spring once + if (applicationContext == null) { + GenericXmlContextLoader xmlContextLoader = new GenericXmlContextLoader(); + applicationContext = xmlContextLoader.loadContext(getContextLocations()); + } + + servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext); + } + + protected String[] getContextLocations() { + return new String[]{DEFAULT_CONTEXT_LOCATION}; + } + +} diff --git a/plugins/junit/src/main/java/org/apache/struts2/StrutsTestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsTestCase.java similarity index 98% rename from plugins/junit/src/main/java/org/apache/struts2/StrutsTestCase.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/StrutsTestCase.java index 8451515f9..f0d9e7ea6 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/StrutsTestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsTestCase.java @@ -16,13 +16,14 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.junit; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.ActionProxyFactory; import com.opensymphony.xwork2.XWorkTestCase; import com.opensymphony.xwork2.config.Configuration; +import org.apache.struts2.ServletActionContext; import org.apache.struts2.dispatcher.Dispatcher; import org.apache.struts2.dispatcher.HttpParameters; import org.apache.struts2.dispatcher.mapper.ActionMapper; @@ -94,7 +95,7 @@ public abstract class StrutsTestCase extends XWorkTestCase { Configuration config = configurationManager.getConfiguration(); ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( - namespace, name, method, new HashMap(), true, false); + namespace, name, method, new HashMap(), true, false); initActionContext(proxy.getInvocation().getInvocationContext()); diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/XWorkJUnit4TestCase.java similarity index 91% rename from core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/XWorkJUnit4TestCase.java index ebec23fa2..d36c3b0ad 100644 --- a/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/XWorkJUnit4TestCase.java @@ -16,13 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -package com.opensymphony.xwork2; +package org.apache.struts2.junit; +import com.opensymphony.xwork2.ActionProxyFactory; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.ConfigurationException; import com.opensymphony.xwork2.config.ConfigurationManager; import com.opensymphony.xwork2.config.ConfigurationProvider; -import com.opensymphony.xwork2.inject.*; +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.inject.ContainerBuilder; +import com.opensymphony.xwork2.inject.Context; +import com.opensymphony.xwork2.inject.Factory; +import com.opensymphony.xwork2.inject.Scope; import com.opensymphony.xwork2.test.StubConfigurationProvider; import com.opensymphony.xwork2.util.XWorkTestCaseHelper; import com.opensymphony.xwork2.util.location.LocatableProperties; diff --git a/plugins/junit/src/main/java/org/apache/struts2/util/TestUtils.java b/plugins/junit/src/main/java/org/apache/struts2/junit/util/TestUtils.java similarity index 98% rename from plugins/junit/src/main/java/org/apache/struts2/util/TestUtils.java rename to plugins/junit/src/main/java/org/apache/struts2/junit/util/TestUtils.java index 205381353..32923fc24 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/util/TestUtils.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/util/TestUtils.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2.util; +package org.apache.struts2.junit.util; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; diff --git a/plugins/junit/src/test/java/org/apache/struts2/JUnitTestAction.java b/plugins/junit/src/test/java/org/apache/struts2/junit/JUnitTestAction.java similarity index 94% rename from plugins/junit/src/test/java/org/apache/struts2/JUnitTestAction.java rename to plugins/junit/src/test/java/org/apache/struts2/junit/JUnitTestAction.java index 428adfe52..f09c34144 100644 --- a/plugins/junit/src/test/java/org/apache/struts2/JUnitTestAction.java +++ b/plugins/junit/src/test/java/org/apache/struts2/junit/JUnitTestAction.java @@ -1,39 +1,39 @@ -/* - * 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; - -import com.opensymphony.xwork2.ActionSupport; -import org.springframework.beans.factory.annotation.Autowired; - -public class JUnitTestAction extends ActionSupport { - private static final long serialVersionUID = 1629266238339053546L; - - private String name; - - @Autowired - private MySessionBean mySessionBean; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} +/* + * 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.junit; + +import com.opensymphony.xwork2.ActionSupport; +import org.springframework.beans.factory.annotation.Autowired; + +public class JUnitTestAction extends ActionSupport { + private static final long serialVersionUID = 1629266238339053546L; + + private String name; + + @Autowired + private MySessionBean mySessionBean; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/plugins/junit/src/test/java/org/apache/struts2/MySessionBean.java b/plugins/junit/src/test/java/org/apache/struts2/junit/MySessionBean.java similarity index 96% rename from plugins/junit/src/test/java/org/apache/struts2/MySessionBean.java rename to plugins/junit/src/test/java/org/apache/struts2/junit/MySessionBean.java index 1c90a800a..4cf8364c3 100644 --- a/plugins/junit/src/test/java/org/apache/struts2/MySessionBean.java +++ b/plugins/junit/src/test/java/org/apache/struts2/junit/MySessionBean.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.junit; public class MySessionBean { diff --git a/plugins/junit/src/test/java/org/apache/struts2/StrutsJUnit4TestCaseTest.java b/plugins/junit/src/test/java/org/apache/struts2/junit/StrutsJUnit4TestCaseTest.java similarity index 92% rename from plugins/junit/src/test/java/org/apache/struts2/StrutsJUnit4TestCaseTest.java rename to plugins/junit/src/test/java/org/apache/struts2/junit/StrutsJUnit4TestCaseTest.java index 8bc691522..64b0f9bac 100644 --- a/plugins/junit/src/test/java/org/apache/struts2/StrutsJUnit4TestCaseTest.java +++ b/plugins/junit/src/test/java/org/apache/struts2/junit/StrutsJUnit4TestCaseTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2; +package org.apache.struts2.junit; import com.opensymphony.xwork2.ActionProxy; import org.junit.Assert; @@ -27,7 +27,7 @@ import org.junit.Test; * Date: 8/15/11 * Time: 7:04 PM */ -public class StrutsJUnit4TestCaseTest extends StrutsJUnit4TestCase{ +public class StrutsJUnit4TestCaseTest extends StrutsJUnit4TestCase { @Test public void testExecuteActionAgainstCustomStrutsConfigFile() throws Exception { String output = executeAction("/test/testAction-2.action"); @@ -38,7 +38,7 @@ public class StrutsJUnit4TestCaseTest extends StrutsJUnit4TestCase { - @Test + @Test public void getActionMapping() { ActionMapping mapping = getActionMapping("/test/testAction.action"); Assert.assertNotNull(mapping); @@ -42,11 +42,11 @@ public class StrutsSpringJUnit4TestCaseTest extends StrutsSpringJUnit4TestCase * In prior versions only one executeAction() call could happen in a single test case, because * either the session values were deleted or the wrong result would be returned (always the result of * the first action execution). */ -public class StrutsJUnit4SessionTestCaseTest extends StrutsJUnit4TestCase{ +public class StrutsJUnit4SessionTestCaseTest extends StrutsJUnit4TestCase { @Test public void testPersistingSessionValues() throws Exception { String output = executeAction("/sessiontest/sessionSet.action"); diff --git a/plugins/junit/src/test/resources/applicationContext.xml b/plugins/junit/src/test/resources/applicationContext.xml index feec52c87..91d9017f5 100644 --- a/plugins/junit/src/test/resources/applicationContext.xml +++ b/plugins/junit/src/test/resources/applicationContext.xml @@ -33,6 +33,6 @@ - - - \ No newline at end of file + + + diff --git a/plugins/junit/src/test/resources/struts-session-values-test.xml b/plugins/junit/src/test/resources/struts-session-values-test.xml index d49b8d272..8030f80b0 100644 --- a/plugins/junit/src/test/resources/struts-session-values-test.xml +++ b/plugins/junit/src/test/resources/struts-session-values-test.xml @@ -21,15 +21,15 @@ --> + "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" + "http://struts.apache.org/dtds/struts-2.1.dtd"> - + /template-session.ftl - + /template-session.ftl diff --git a/plugins/junit/src/test/resources/struts-test.xml b/plugins/junit/src/test/resources/struts-test.xml index f01637495..9eed684ea 100644 --- a/plugins/junit/src/test/resources/struts-test.xml +++ b/plugins/junit/src/test/resources/struts-test.xml @@ -20,12 +20,12 @@ */ --> + "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" + "http://struts.apache.org/dtds/struts-2.1.dtd"> - + /template-2.ftl diff --git a/plugins/junit/src/test/resources/struts.xml b/plugins/junit/src/test/resources/struts.xml index f99b8421c..04b00af94 100644 --- a/plugins/junit/src/test/resources/struts.xml +++ b/plugins/junit/src/test/resources/struts.xml @@ -20,14 +20,14 @@ */ --> + "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" + "http://struts.apache.org/dtds/struts-2.1.dtd"> - + /template-1.ftl - \ No newline at end of file + From 22a80f9c51f87cd95a5a9a46861f4a8b552ef836 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 14 Sep 2022 16:49:50 +0200 Subject: [PATCH 028/143] WW-5213 Upgrades javax.el to 3.0.1-b12 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1899ed558..f36e4b92c 100644 --- a/pom.xml +++ b/pom.xml @@ -818,7 +818,7 @@ org.glassfish javax.el - 3.0.1-b11 + 3.0.1-b12 From c9c39130f6f11adaaedf15aa584c2a5f76c47661 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sat, 17 Sep 2022 09:40:38 +0200 Subject: [PATCH 029/143] WW-5226 Upgrades Weld to version 2.4.8.Final --- .../struts2/cdi/CdiObjectFactoryTest.java | 31 ++++++++++--------- pom.xml | 4 +-- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/plugins/cdi/src/test/java/org/apache/struts2/cdi/CdiObjectFactoryTest.java b/plugins/cdi/src/test/java/org/apache/struts2/cdi/CdiObjectFactoryTest.java index 7bee7629a..bae580cd4 100644 --- a/plugins/cdi/src/test/java/org/apache/struts2/cdi/CdiObjectFactoryTest.java +++ b/plugins/cdi/src/test/java/org/apache/struts2/cdi/CdiObjectFactoryTest.java @@ -18,33 +18,33 @@ */ package org.apache.struts2.cdi; -import org.jboss.weld.environment.se.StartMain; -import static org.junit.Assert.*; - +import org.jboss.weld.bootstrap.api.helpers.RegistrySingletonProvider; +import org.jboss.weld.environment.se.Weld; import org.jboss.weld.environment.se.WeldContainer; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.springframework.mock.jndi.SimpleNamingContextBuilder; import javax.enterprise.inject.spi.InjectionTarget; -/** - * CdiObjectFactoryTest. - */ +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + public class CdiObjectFactoryTest { - @Before - public void setUp() throws Exception { + @BeforeClass + public static void setup() throws Exception { + Weld weld = new Weld().containerId(RegistrySingletonProvider.STATIC_INSTANCE); + WeldContainer container = weld.initialize(); + SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); builder.activate(); - - StartMain sm = new StartMain(new String[0]); - WeldContainer weldContainer = sm.go(); - builder.bind(CdiObjectFactory.CDI_JNDIKEY_BEANMANAGER_COMP, weldContainer.getBeanManager()); + builder.bind(CdiObjectFactory.CDI_JNDIKEY_BEANMANAGER_COMP, container.getBeanManager()); } @Test - public void testFindBeanManager() throws Exception { + public void testFindBeanManager() { assertNotNull(new CdiObjectFactory().findBeanManager()); } @@ -56,7 +56,8 @@ public class CdiObjectFactoryTest { assertNotNull(fooConsumer.fooService); } - @Test public void testGetInjectionTarget() throws Exception { + @Test + public void testGetInjectionTarget() { final CdiObjectFactory cdiObjectFactory = new CdiObjectFactory(); final InjectionTarget injectionTarget = cdiObjectFactory.getInjectionTarget(FooConsumer.class); assertNotNull(injectionTarget); diff --git a/pom.xml b/pom.xml index f36e4b92c..fe0e45379 100644 --- a/pom.xml +++ b/pom.xml @@ -1202,13 +1202,13 @@ org.jboss.weld weld-core - 2.2.16.SP1 + 2.4.8.Final org.jboss.weld.se weld-se - 2.2.16.SP1 + 2.4.8.Final From 7b655207ec8de281e5c53320de4f83eab59df2d1 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sat, 17 Sep 2022 09:40:54 +0200 Subject: [PATCH 030/143] Includes commons-text in minimal library set --- assembly/src/main/assembly/min-lib.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/assembly/src/main/assembly/min-lib.xml b/assembly/src/main/assembly/min-lib.xml index 3e6e4a176..3cae96356 100644 --- a/assembly/src/main/assembly/min-lib.xml +++ b/assembly/src/main/assembly/min-lib.xml @@ -36,6 +36,7 @@ org.apache.struts:struts2-core org.freemarker:freemarker org.apache.commons:commons-lang3 + org.apache.commons:commons-text org.apache.logging.log4j:log4j-api ognl:ognl commons-fileupload:commons-fileupload From f04b68db03dd56bfac94186c0d62978fe7ac7d1b Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sat, 17 Sep 2022 10:02:31 +0200 Subject: [PATCH 031/143] Blocks force pushes to the master branch --- .asf.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.asf.yaml b/.asf.yaml index 379309b9a..dad75e1ef 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -12,3 +12,5 @@ notifications: github: del_branch_on_merge: true + protected_branches: + master: { } From 03edeee0d8480a0a7ba51d1ef4fad5864a2b2bf6 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 18 Sep 2022 15:43:37 +0200 Subject: [PATCH 032/143] WW-5227 Upgrades Log4j to version 2.19.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f36e4b92c..dd72022dd 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ 9.2 2.13.2 2.13.2.1 - 2.18.0 + 2.19.0 3.3.3 1.7.32 5.3.22 From 858f19557d6c694411b791868734120186ebb0e1 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 20 Sep 2022 11:13:18 +0200 Subject: [PATCH 033/143] WW-5229 Upgrades Spring to version 5.3.23 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 14795803c..50d7ce699 100644 --- a/pom.xml +++ b/pom.xml @@ -115,7 +115,7 @@ 2.19.0 3.3.3 1.7.32 - 5.3.22 + 5.3.23 3.0.8 1.0.7 3.0.0-M7 From dc5dac7be21dda4d9292dbcbb1ca64d802ab63f4 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 20 Sep 2022 15:27:39 +0200 Subject: [PATCH 034/143] WW-5228 Upgrades OWASP dependency-check-maven to version 7.2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 50d7ce699..e60455fbd 100644 --- a/pom.xml +++ b/pom.xml @@ -379,7 +379,7 @@ org.owasp dependency-check-maven - 7.0.1 + 7.2.0 src/etc/project-suppression.xml From 062b76718b09c423c3b6b7af8fdada5dad95e33d Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 20 Sep 2022 15:33:11 +0200 Subject: [PATCH 035/143] WW-5231 Upgrades apache-rat-plugin to version 0.15 --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 50d7ce699..e7a56b202 100644 --- a/pom.xml +++ b/pom.xml @@ -340,6 +340,7 @@ org.apache.rat apache-rat-plugin + 0.15 true true From ab22c7377d39df735715b64f09f21f6c9161c6c0 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 20 Sep 2022 15:48:21 +0200 Subject: [PATCH 036/143] WW-5232 Introduces GH Actions build instead of using Travis --- .github/workflows/maven.yml | 53 ++++++++++++++++++++++++++++++++++ .travis.yml | 29 ------------------- pom.xml | 57 +++++++++---------------------------- 3 files changed, 66 insertions(+), 73 deletions(-) create mode 100644 .github/workflows/maven.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 000000000..9e40783c7 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,53 @@ +# 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. + +name: Java Build + +on: + pull_request: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + java: [ '8', '11', '17' ] + steps: + - name: Checkout code + uses: actions/checkout@v3.0.2 + - name: Set up cache + uses: actions/cache@v3.0.8 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v3 + with: + distribution: adopt + java-version: ${{ matrix.java }} + - name: Build with Maven on Java ${{ matrix.java }} + if: matrix.java != '11' + run: mvn -B -V -DskipAssembly test --no-transfer-progress + - name: Code coverage on Java ${{ matrix.java }} + if: matrix.java == '11' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} + run: mvn -B -V -Pcoverage verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e86980e60..000000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -dist: jammy -language: java -sudo: false - -jdk: - - openjdk11 - - openjdk17 - -install: true - -env: -global: - - secure: iI7IpfDtS+LUyS2yNuRCR3KelNyvBHuoMQ3gb1UNmR5SSL7jO/p3olQWrQROs28FJ+dpE3lHyIjoHrebKQGJHHAgTG2XWxn+G3fDsf+wSSFSLoDGj0o2SgGXooBbR2dccnNZHCyQaOyE2cIPWaOxrQZFE4No70LQB4mrP/gdkoc= -matrix: - include: - - jdk: openjdk8 - env: STRUTS_IT=true # do integration tests and coverage reports when jdk 11 and 17 tests prospered - -script: - - if [ "$STRUTS_IT" == "true" ]; then - ./mvnw clean install -DskipTests -DskipAssembly -B; - ./mvnw test org.jacoco:jacoco-maven-plugin:report org.jacoco:jacoco-maven-plugin:report-integration org.eluder.coveralls:coveralls-maven-plugin:report -Ptravis-coveralls -DskipAssembly -B; - else - ./mvnw clean package test -DskipAssembly -B; - fi; - -cache: - directories: - - $HOME/.m2 diff --git a/pom.xml b/pom.xml index 50d7ce699..da4ee7a64 100644 --- a/pom.xml +++ b/pom.xml @@ -182,17 +182,6 @@ - - jdk9 - - [9,) - - - - - true - - jdk17 @@ -218,33 +207,13 @@ - travis-coveralls + coverage + + https://sonarcloud.io + apache + apache_struts + - - - - org.apache.maven.plugins - maven-surefire-plugin - - ${argLine} - - - - org.apache.maven.plugins - maven-failsafe-plugin - - ${argLine} - - - - org.eclipse.jetty - jetty-maven-plugin - - ${argLine} - - - - org.jacoco @@ -258,18 +227,18 @@ - prepare-agent-integration + report - prepare-agent-integration + report + + + XML + + - - io.jsonwebtoken.coveralls - coveralls-maven-plugin - 4.4.1 - From 6b2cc20b2dc8957c670305f67bffad37963b3cbd Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 20 Sep 2022 16:08:32 +0200 Subject: [PATCH 037/143] WW-5232 Defines default ENV settings --- .github/workflows/maven.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9e40783c7..2f8ae774e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -21,6 +21,10 @@ on: branches: - master +env: + MAVEN_OPTS: -Xmx2048m -Xms1024m + LANG: en_US.utf8 + jobs: build: runs-on: ubuntu-latest From 36ac23acf58eb6cf43f04b3a817d87e8d8c9c33c Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 20 Sep 2022 16:18:17 +0200 Subject: [PATCH 038/143] WW-5232 Uses Sonar Coverage badge instead of Travis on --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 136a290dd..e416a56dd 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The Apache Struts web framework [![Build Status @ Travis](https://travis-ci.com/apache/struts.svg?branch=master)](https://app.travis-ci.com/apache/struts) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/) [![Javadocs](https://javadoc.io/badge/org.apache.struts/struts2-core.svg)](https://javadoc.io/doc/org.apache.struts/struts2-core) -[![Coverage Status](https://coveralls.io/repos/github/apache/struts/badge.svg)](https://coveralls.io/github/apache/struts) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=apache_struts&metric=coverage)](https://sonarcloud.io/summary/new_code?id=apache_struts) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/struts/badge)](https://deps.dev/maven/org.apache.struts%3Astruts2-core) [![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) From dc1a663d69e2c2d84b32b5d8ce5fd514603ffb12 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 20 Sep 2022 16:22:59 +0200 Subject: [PATCH 039/143] WW-5232 Uses default SONAR_TOKEN name --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2f8ae774e..06601e4da 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -53,5 +53,5 @@ jobs: if: matrix.java == '11' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: mvn -B -V -Pcoverage verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress From 0fc71949ca3ee316174235dc7864f1d672051124 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 21 Sep 2022 15:44:47 +0200 Subject: [PATCH 040/143] WW-5232 Uses Apache specific SONARCLOUD_TOKEN secret --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 06601e4da..2f8ae774e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -53,5 +53,5 @@ jobs: if: matrix.java == '11' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} run: mvn -B -V -Pcoverage verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress From 9fb86054bbebcc1fc40b0a652ee9857ac489c53d Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 21 Sep 2022 17:17:07 +0200 Subject: [PATCH 041/143] Reverts back to SONAR_TOKEN --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2f8ae774e..06601e4da 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -53,5 +53,5 @@ jobs: if: matrix.java == '11' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: mvn -B -V -Pcoverage verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress From 296b3cc89c9b9be5bc67de0ba6b5db78f60cbe5d Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 21 Sep 2022 17:27:20 +0200 Subject: [PATCH 042/143] Uses SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 06601e4da..2f8ae774e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -53,5 +53,5 @@ jobs: if: matrix.java == '11' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} run: mvn -B -V -Pcoverage verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress From eb6836828088fb06ff927465a0fa4e1d05e8b07b Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 21 Sep 2022 22:29:14 +0200 Subject: [PATCH 043/143] WW-5232 Avoids building assemblies --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2f8ae774e..9a0d796aa 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -54,4 +54,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} - run: mvn -B -V -Pcoverage verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress + run: mvn -B -V -Pcoverage -DskipAssembly verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress From 7183d32caf7b14af71aeabe00d3e1c7a56abb835 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 25 Sep 2022 10:09:02 +0200 Subject: [PATCH 044/143] Replaces Travis badge with GH Actions badge --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e416a56dd..289cfd2a0 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ The Apache Struts web framework ------------------------------- -[![Build Status @ Jenkins](https://builds.apache.org/buildStatus/icon?job=Struts%2FStruts+Core%2Fmaster)](https://ci-builds.apache.org/job/Struts/job/Struts%20Core/job/master/) -[![Build Status @ Travis](https://travis-ci.com/apache/struts.svg?branch=master)](https://app.travis-ci.com/apache/struts) +[![Jenkins Build](https://builds.apache.org/buildStatus/icon?job=Struts%2FStruts+Core%2Fmaster)](https://ci-builds.apache.org/job/Struts/job/Struts%20Core/job/master/) +[![Java Build](https://github.com/apache/struts/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/struts/actions/workflows/maven.yml) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/) [![Javadocs](https://javadoc.io/badge/org.apache.struts/struts2-core.svg)](https://javadoc.io/doc/org.apache.struts/struts2-core) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=apache_struts&metric=coverage)](https://sonarcloud.io/summary/new_code?id=apache_struts) From 3774ffa7c3010cd9a6ffbb5e16080351e5408645 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 27 Sep 2022 09:21:03 +0200 Subject: [PATCH 045/143] WW-5234 Improves DTD definitions to use proper URL --- .../src/main/resources/struts.xml | 4 +- ...-lotsOfRichtexteditorSubmit-validation.xml | 14 +- .../action/EmployeeAction-validation.xml | 2 +- .../action/SkillAction-validation.xml | 2 +- .../FileUploadAction-validation.xml | 5 +- .../person/NewPersonAction-validation.xml | 2 +- .../showcase/person/Person-validation.xml | 2 +- .../IteratorGeneratorTagDemo-validation.xml | 12 +- ...ClientSideValidationExample-validation.xml | 8 +- ...bmitFieldValidatorsExamples-validation.xml | 10 +- ...tNonFieldValidatorsExamples-validation.xml | 12 +- .../validation/QuizAction-validation.xml | 4 +- ...plication-submitApplication-validation.xml | 2 +- .../User-userContext-validation.xml | 10 +- ...itVisitorValidatorsExamples-validation.xml | 6 +- .../main/resources/struts-actionchaining.xml | 6 +- .../src/main/resources/struts-async.xml | 2 +- .../src/main/resources/struts-conversion.xml | 22 +- .../src/main/resources/struts-dispatcher.xml | 2 +- .../main/resources/struts-filedownload.xml | 2 +- .../src/main/resources/struts-fileupload.xml | 8 +- .../src/main/resources/struts-freemarker.xml | 6 +- .../src/main/resources/struts-hangman.xml | 10 +- .../src/main/resources/struts-interactive.xml | 4 +- .../main/resources/struts-model-driven.xml | 7 +- .../src/main/resources/struts-person.xml | 2 +- .../src/main/resources/struts-tags-non-ui.xml | 28 +- .../src/main/resources/struts-tags-ui.xml | 2 +- .../src/main/resources/struts-tags.xml | 2 +- .../src/main/resources/struts-tiles.xml | 2 +- .../src/main/resources/struts-token.xml | 2 +- .../src/main/resources/struts-validation.xml | 40 +-- .../src/main/resources/struts-wait.xml | 2 +- .../src/main/resources/struts-xslt.xml | 4 +- apps/showcase/src/main/resources/struts.xml | 2 +- bundles/admin/src/main/resources/struts.xml | 4 +- bundles/demo/src/main/resources/struts.xml | 8 +- .../xwork2/validator/Validator.java | 2 +- .../xwork2/validator/ValidatorFactory.java | 2 +- .../xwork2/validator/validators/default.xml | 2 +- core/src/main/resources/struts-2.0.dtd | 8 +- core/src/main/resources/struts-2.1.7.dtd | 2 +- core/src/main/resources/struts-2.1.dtd | 2 +- core/src/main/resources/struts-2.3.dtd | 2 +- core/src/main/resources/struts-2.5.dtd | 2 +- core/src/main/resources/struts-6.0.dtd | 2 +- core/src/main/resources/struts-default.xml | 310 +++++++++++------- core/src/main/resources/xwork-default.xml | 2 +- .../main/resources/xwork-validator-1.0.2.dtd | 6 +- .../main/resources/xwork-validator-1.0.3.dtd | 2 +- .../main/resources/xwork-validator-1.0.dtd | 6 +- .../resources/xwork-validator-config-1.0.dtd | 2 +- .../xwork-validator-definition-1.0.dtd | 2 +- .../xwork2/ModelDrivenAction-validation.xml | 2 +- .../SimpleAction-some-alias-validation.xml | 2 +- .../SimpleAction-subproperty-validation.xml | 2 +- .../xwork2/SimpleAction-validation.xml | 2 +- ...impleAction-validationAlias-validation.xml | 2 +- .../TestBean-anotherContext-validation.xml | 2 +- .../xwork2/TestBean-badtest-validation.xml | 2 +- .../TestBean-beanMessageBundle-validation.xml | 2 +- ...stBean-expressionValidation-validation.xml | 2 +- .../xwork2/TestBean-validation.xml | 2 +- ...Bean-visitorChildValidation-validation.xml | 2 +- .../TestBean-visitorValidation-validation.xml | 2 +- .../xwork2/TestChildBean-validation.xml | 4 +- .../ValidationOrderAction-validation.xml | 18 +- .../loadorder1/xwork-test-load-order.xml | 2 +- .../loadorder2/xwork-test-load-order.xml | 2 +- .../loadorder3/xwork-test-load-order.xml | 2 +- .../xwork2/config/providers/xwork- test.xml | 2 +- .../xwork-include-after-package-2.xml | 2 +- .../providers/xwork-include-after-package.xml | 2 +- .../xwork-include-before-package-2.xml | 2 +- .../xwork-include-before-package.xml | 2 +- .../config/providers/xwork-include-parent.xml | 2 +- .../providers/xwork-test-action-invalid.xml | 2 +- ...rk-test-actions-packagedefaultclassref.xml | 2 +- .../config/providers/xwork-test-actions.xml | 2 +- .../providers/xwork-test-allowed-methods.xml | 2 +- .../providers/xwork-test-bad-inheritance.xml | 4 +- .../providers/xwork-test-basic-packages.xml | 2 +- .../providers/xwork-test-default-package.xml | 2 +- .../xwork-test-defaultclassref-package.xml | 4 +- .../xwork-test-envs-substitution.xml | 2 +- .../xwork-test-exception-mappings.xml | 2 +- .../xwork-test-global-result-inheritence.xml | 2 +- .../providers/xwork-test-include-wildcard.xml | 2 +- .../xwork-test-interceptor-defaultref.xml | 2 +- .../xwork-test-interceptor-inheritance.xml | 2 +- ...work-test-interceptor-param-overriding.xml | 11 +- .../xwork-test-interceptor-params.xml | 2 +- ...est-interceptor-stack-param-overriding.xml | 2 +- .../xwork-test-interceptors-basic.xml | 2 +- .../xwork-test-interceptors-spring.xml | 2 +- .../providers/xwork-test-multilevel.xml | 2 +- .../xwork-test-package-inheritance.xml | 4 +- .../config/providers/xwork-test-reload.xml | 2 +- .../xwork-test-result-inheritance.xml | 2 +- .../providers/xwork-test-result-names.xml | 2 +- .../providers/xwork-test-result-types.xml | 2 +- .../config/providers/xwork-test-results.xml | 2 +- .../providers/xwork-test-wildcard-1.xml | 2 +- .../providers/xwork-test-wildcard-2.xml | 2 +- .../providers/xwork-test-wildcard-include.xml | 4 +- .../xwork-unknownhandler-stack-empty.xml | 2 +- .../providers/xwork-unknownhandler-stack.xml | 2 +- .../xwork2/test/DataAware-validation.xml | 2 +- .../DataAware-validationAlias-validation.xml | 2 +- .../xwork2/test/DataAware2-validation.xml | 2 +- .../xwork2/test/Equidae-validation.xml | 2 +- .../xwork2/test/SimpleAction2-validation.xml | 2 +- ...mpleAction2-validationAlias-validation.xml | 2 +- .../xwork2/test/User-validation.xml | 2 +- .../xwork2/test/UserMarker-validation.xml | 2 +- ...VisitorValidatorModelAction-validation.xml | 2 +- ...estAction-beanMessageBundle-validation.xml | 2 +- ...torTestAction-validateArray-validation.xml | 2 +- ...atorTestAction-validateList-validation.xml | 2 +- .../VisitorValidatorTestAction-validation.xml | 2 +- ...tion-visitorChildValidation-validation.xml | 2 +- ...estAction-visitorValidation-validation.xml | 2 +- ...tion-visitorValidationAlias-validation.xml | 2 +- .../validator/validator-parser-test.xml | 2 +- .../validator/validator-parser-test2.xml | 10 +- .../validator/validator-parser-test3.xml | 2 +- .../validator/validator-parser-test4.xml | 2 +- .../validator/validator-parser-test5.xml | 2 +- .../validator/validator-parser-test6.xml | 2 +- .../xwork2/validator/validators-fail.xml | 2 +- core/src/test/resources/includeTest.xml | 2 +- core/src/test/resources/my-validators.xml | 2 +- .../src/test/resources/myOther-validators.xml | 2 +- .../apache/struts2/TestAction-validation.xml | 2 +- .../struts2/dispatcher/ng/struts-no-op.xml | 2 +- .../struts2/views/jsp/WW3090-struts.xml | 2 +- .../ui/DoubleValidationAction-validation.xml | 4 +- .../jsp/ui/IntValidationAction-validation.xml | 2 +- .../struts2/views/jsp/ui/User-validation.xml | 2 +- .../src/test/resources/struts-escape-body.xml | 2 +- .../struts-object-factory-result-builder.xml | 2 +- core/src/test/resources/struts-testing.xml | 2 +- core/src/test/resources/struts.xml | 2 +- core/src/test/resources/validators.xml | 2 +- .../test/resources/xwork-class-param-test.xml | 2 +- core/src/test/resources/xwork-param-test.xml | 2 +- core/src/test/resources/xwork-proxyinvoke.xml | 2 +- core/src/test/resources/xwork-sample.xml | 14 +- core/src/test/resources/xwork-test-beans.xml | 2 +- .../src/test/resources/xwork-test-default.xml | 2 +- .../test/resources/xwork-test-validation.xml | 4 +- .../src/main/resources/struts-plugin.xml | 2 +- .../src/main/resources/struts-plugin.xml | 2 +- .../test/resources/bean-validation-test.xml | 2 +- .../cdi/src/main/resources/struts-plugin.xml | 4 +- .../src/main/resources/struts-plugin.xml | 12 +- .../src/main/resources/struts-plugin.xml | 2 +- .../src/main/resources/struts-plugin.xml | 2 +- .../gxp/src/main/resources/struts-plugin.xml | 4 +- .../src/main/resources/struts-plugin.xml | 6 +- .../src/main/resources/struts-plugin.xml | 4 +- .../src/main/resources/struts-plugin.xml | 6 +- .../json/src/main/resources/struts-plugin.xml | 2 +- .../struts-convention-configuration.xml | 2 +- .../resources/struts-session-values-test.xml | 2 +- .../junit/src/test/resources/struts-test.xml | 2 +- plugins/junit/src/test/resources/struts.xml | 2 +- .../osgi/src/main/resources/struts-plugin.xml | 6 +- .../oval/src/main/resources/struts-plugin.xml | 2 +- plugins/oval/src/test/resources/oval-test.xml | 2 +- .../src/main/resources/struts-plugin.xml | 4 +- .../src/main/resources/struts-plugin.xml | 4 +- .../src/main/resources/struts-plugin.xml | 2 +- .../src/main/resources/struts-plugin.xml | 2 +- plugins/portlet/src/test/resources/struts.xml | 2 +- .../rest/src/main/resources/struts-plugin.xml | 2 +- .../src/main/resources/struts-plugin.xml | 2 +- .../src/main/resources/struts-plugin.xml | 8 +- .../xwork2/spring/actionContext-xwork.xml | 4 +- .../src/main/resources/struts-plugin.xml | 2 +- .../src/main/resources/struts-plugin.xml | 2 +- 181 files changed, 527 insertions(+), 444 deletions(-) diff --git a/apps/rest-showcase/src/main/resources/struts.xml b/apps/rest-showcase/src/main/resources/struts.xml index a8991da66..b4515186f 100644 --- a/apps/rest-showcase/src/main/resources/struts.xml +++ b/apps/rest-showcase/src/main/resources/struts.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> @@ -41,4 +41,4 @@ index,show,create,update,destroy,deleteConfirm,edit,editNew - \ No newline at end of file + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml index 07a7e5d7b..1c63b912f 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml @@ -21,31 +21,31 @@ --> - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + Description1 Is Required !!! - + Description2 Is Required !!! - + Description3 Is Required !!! - + Description4 Is Required !!! - - + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml index 2fb09bc77..a19d0449d 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml @@ -19,7 +19,7 @@ * under the License. */ --> - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml index 0c0929ff2..5c2574a4d 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml @@ -19,7 +19,7 @@ * under the License. */ --> - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml index cfd41786e..e15b2506f 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> @@ -35,5 +35,4 @@ Caption cannot be empty - - \ No newline at end of file + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml index a3f63fc5d..0bd8abe33 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml @@ -19,7 +19,7 @@ * under the License. */ --> - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml index 8cdef7094..425d4154f 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml @@ -19,7 +19,7 @@ * under the License. */ --> - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml index 44eb0032f..07f1ea9ad 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml @@ -21,8 +21,8 @@ --> - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + @@ -30,13 +30,13 @@ Value must not be empty - - + + Count must be an integer - + - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml index 0beb7e3a9..2d732c0ab 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml @@ -21,10 +21,10 @@ --> - - - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml index 5d23023bb..4def409bb 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml @@ -19,12 +19,12 @@ * under the License. */ --> - - - - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml index 92fb2313e..a94a9e2ff 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml @@ -19,13 +19,13 @@ * under the License. */ --> - - - - - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + + + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml index 411612fd1..8f7a48604 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml @@ -19,11 +19,11 @@ * under the License. */ --> - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml index d6ef55067..492475df6 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml index 1020aa60a..1e3dd4c6c 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml @@ -19,17 +19,17 @@ * under the License. */ --> - - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + Name Required - + 1 100 @@ -41,6 +41,6 @@ Birthday Required - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml index 7e24f4bb2..cb4a8138f 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml @@ -19,10 +19,10 @@ * under the License. */ --> - - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + diff --git a/apps/showcase/src/main/resources/struts-actionchaining.xml b/apps/showcase/src/main/resources/struts-actionchaining.xml index f140f9e96..2b187dd72 100644 --- a/apps/showcase/src/main/resources/struts-actionchaining.xml +++ b/apps/showcase/src/main/resources/struts-actionchaining.xml @@ -21,12 +21,12 @@ --> - + "https://struts.apache.org/dtds/struts-2.5.dtd"> + - actionChain2 + actionChain2 actionChain3 diff --git a/apps/showcase/src/main/resources/struts-async.xml b/apps/showcase/src/main/resources/struts-async.xml index faa38656c..0921e6832 100644 --- a/apps/showcase/src/main/resources/struts-async.xml +++ b/apps/showcase/src/main/resources/struts-async.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-conversion.xml b/apps/showcase/src/main/resources/struts-conversion.xml index a3c147bd6..4c4c1658a 100644 --- a/apps/showcase/src/main/resources/struts-conversion.xml +++ b/apps/showcase/src/main/resources/struts-conversion.xml @@ -21,15 +21,15 @@ --> - + "https://struts.apache.org/dtds/struts-2.5.dtd"> + - + /WEB-INF/conversion/index.jsp - + @@ -49,8 +49,8 @@ /WEB-INF/conversion/Person.java.txt - - + + /WEB-INF/conversion/enterAddressInfo.jsp @@ -68,9 +68,9 @@ /WEB-INF/conversion/Address.java.txt - - - + + + /WEB-INF/conversion/enterOperations.jsp @@ -93,6 +93,6 @@ /WEB-INF/conversion/OperationsEnumActionConversion.txt - + - + diff --git a/apps/showcase/src/main/resources/struts-dispatcher.xml b/apps/showcase/src/main/resources/struts-dispatcher.xml index 0a89502fe..7051b1f3c 100644 --- a/apps/showcase/src/main/resources/struts-dispatcher.xml +++ b/apps/showcase/src/main/resources/struts-dispatcher.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-filedownload.xml b/apps/showcase/src/main/resources/struts-filedownload.xml index 56d083f0a..335777bd4 100644 --- a/apps/showcase/src/main/resources/struts-filedownload.xml +++ b/apps/showcase/src/main/resources/struts-filedownload.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-fileupload.xml b/apps/showcase/src/main/resources/struts-fileupload.xml index 33be370ba..4efcad89f 100644 --- a/apps/showcase/src/main/resources/struts-fileupload.xml +++ b/apps/showcase/src/main/resources/struts-fileupload.xml @@ -21,11 +21,11 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> - + /WEB-INF/fileupload/upload.jsp @@ -34,11 +34,11 @@ /WEB-INF/fileupload/upload.jsp /WEB-INF/fileupload/upload-success.jsp - + /WEB-INF/fileupload/multipleUploadUsingList.jsp - + /WEB-INF/fileupload/multipleUploadUsingList.jsp /WEB-INF/fileupload/multiple-success.jsp diff --git a/apps/showcase/src/main/resources/struts-freemarker.xml b/apps/showcase/src/main/resources/struts-freemarker.xml index 26ee8aedc..c0de0a92a 100644 --- a/apps/showcase/src/main/resources/struts-freemarker.xml +++ b/apps/showcase/src/main/resources/struts-freemarker.xml @@ -21,16 +21,16 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> /WEB-INF/freemarker/customFreemarkerManagerUsage.ftl - + /WEB-INF/freemarker/standardTags.ftl - + diff --git a/apps/showcase/src/main/resources/struts-hangman.xml b/apps/showcase/src/main/resources/struts-hangman.xml index ee1f4f6a1..d81f4b368 100644 --- a/apps/showcase/src/main/resources/struts-hangman.xml +++ b/apps/showcase/src/main/resources/struts-hangman.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> @@ -41,9 +41,9 @@ /WEB-INF/hangman/hangmanNonAjax.ftl - - - + + + /WEB-INF/hangman/blank.ftl @@ -61,4 +61,4 @@ /WEB-INF/hangman/updateGuessLeft.ftl - + diff --git a/apps/showcase/src/main/resources/struts-interactive.xml b/apps/showcase/src/main/resources/struts-interactive.xml index ad584a17a..cda563df5 100644 --- a/apps/showcase/src/main/resources/struts-interactive.xml +++ b/apps/showcase/src/main/resources/struts-interactive.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> @@ -38,4 +38,4 @@ - \ No newline at end of file + diff --git a/apps/showcase/src/main/resources/struts-model-driven.xml b/apps/showcase/src/main/resources/struts-model-driven.xml index c8731e980..da01d922e 100644 --- a/apps/showcase/src/main/resources/struts-model-driven.xml +++ b/apps/showcase/src/main/resources/struts-model-driven.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> @@ -29,11 +29,10 @@ /WEB-INF/modelDriven/modelDriven.jsp - + /WEB-INF/modelDriven/modelDrivenResult.jsp - - \ No newline at end of file + diff --git a/apps/showcase/src/main/resources/struts-person.xml b/apps/showcase/src/main/resources/struts-person.xml index 946c4c104..a1500888d 100644 --- a/apps/showcase/src/main/resources/struts-person.xml +++ b/apps/showcase/src/main/resources/struts-person.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-tags-non-ui.xml b/apps/showcase/src/main/resources/struts-tags-non-ui.xml index 42d0506ae..f445da037 100644 --- a/apps/showcase/src/main/resources/struts-tags-non-ui.xml +++ b/apps/showcase/src/main/resources/struts-tags-non-ui.xml @@ -21,14 +21,14 @@ --> - + "https://struts.apache.org/dtds/struts-2.5.dtd"> + - + - + /WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp @@ -46,11 +46,11 @@ /WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp - + - + /WEB-INF/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp @@ -60,8 +60,8 @@ /WEB-INF/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp - - + + @@ -74,8 +74,8 @@ /WEB-INF/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp - - + + @@ -88,7 +88,7 @@ /WEB-INF/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp - + @@ -101,14 +101,14 @@ /WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp - + /WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl - + /WEB-INF/tags/non-ui/actionPrefix/normalSubmit.ftl @@ -131,7 +131,7 @@ /WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl - + diff --git a/apps/showcase/src/main/resources/struts-tags-ui.xml b/apps/showcase/src/main/resources/struts-tags-ui.xml index 13e33d65b..1055678ad 100644 --- a/apps/showcase/src/main/resources/struts-tags-ui.xml +++ b/apps/showcase/src/main/resources/struts-tags-ui.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-tags.xml b/apps/showcase/src/main/resources/struts-tags.xml index b2896dace..c9482f10f 100644 --- a/apps/showcase/src/main/resources/struts-tags.xml +++ b/apps/showcase/src/main/resources/struts-tags.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-tiles.xml b/apps/showcase/src/main/resources/struts-tiles.xml index 6845710dc..5fa2f8071 100644 --- a/apps/showcase/src/main/resources/struts-tiles.xml +++ b/apps/showcase/src/main/resources/struts-tiles.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-token.xml b/apps/showcase/src/main/resources/struts-token.xml index 5f41d1a31..db6704168 100644 --- a/apps/showcase/src/main/resources/struts-token.xml +++ b/apps/showcase/src/main/resources/struts-token.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-validation.xml b/apps/showcase/src/main/resources/struts-validation.xml index 23d662f55..31bcab48f 100755 --- a/apps/showcase/src/main/resources/struts-validation.xml +++ b/apps/showcase/src/main/resources/struts-validation.xml @@ -21,8 +21,8 @@ --> - + "https://struts.apache.org/dtds/struts-2.5.dtd"> + @@ -74,7 +74,7 @@ /WEB-INF/validation/ajaxFormSubmitSuccess.jsp - + @@ -83,46 +83,46 @@ index.jsp - - + + - + /WEB-INF/validation/fieldValidatorsExample.jsp - + /WEB-INF/validation/fieldValidatorsExample.jsp /WEB-INF/validation/successFieldValidatorsExample.jsp - - - + + + - + /WEB-INF/validation/nonFieldValidatorsExample.jsp - + /WEB-INF/validation/nonFieldValidatorsExample.jsp /WEB-INF/validation/successNonFieldValidatorsExample.jsp - - - + + + - + /WEB-INF/validation/visitorValidatorsExample.jsp - + /WEB-INF/validation/visitorValidatorsExample.jsp /WEB-INF/validation/successVisitorValidatorsExample.jsp @@ -146,7 +146,7 @@ - + STORE @@ -173,7 +173,7 @@ /WEB-INF/validation/storeErrorsAcrossRequestCancel.jsp - + - + diff --git a/apps/showcase/src/main/resources/struts-wait.xml b/apps/showcase/src/main/resources/struts-wait.xml index 273e8e550..8ede40d74 100644 --- a/apps/showcase/src/main/resources/struts-wait.xml +++ b/apps/showcase/src/main/resources/struts-wait.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/apps/showcase/src/main/resources/struts-xslt.xml b/apps/showcase/src/main/resources/struts-xslt.xml index 5bbdc55b5..261b367e4 100644 --- a/apps/showcase/src/main/resources/struts-xslt.xml +++ b/apps/showcase/src/main/resources/struts-xslt.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> @@ -36,7 +36,7 @@ info.classpath - + info diff --git a/apps/showcase/src/main/resources/struts.xml b/apps/showcase/src/main/resources/struts.xml index cfdac4b39..cb47af8bf 100644 --- a/apps/showcase/src/main/resources/struts.xml +++ b/apps/showcase/src/main/resources/struts.xml @@ -21,7 +21,7 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> diff --git a/bundles/admin/src/main/resources/struts.xml b/bundles/admin/src/main/resources/struts.xml index e106e8bdf..2bb1bf134 100644 --- a/bundles/admin/src/main/resources/struts.xml +++ b/bundles/admin/src/main/resources/struts.xml @@ -22,13 +22,13 @@ + "https://struts.apache.org/dtds/struts-2.5.dtd"> - + {1} viewBundle.ftl diff --git a/bundles/demo/src/main/resources/struts.xml b/bundles/demo/src/main/resources/struts.xml index 0e4d78967..003635f16 100644 --- a/bundles/demo/src/main/resources/struts.xml +++ b/bundles/demo/src/main/resources/struts.xml @@ -21,11 +21,11 @@ --> + "https://struts.apache.org/dtds/struts-2.5.dtd"> - @@ -52,4 +52,4 @@ - \ No newline at end of file + diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/Validator.java b/core/src/main/java/com/opensymphony/xwork2/validator/Validator.java index 4a8c87333..6550e513a 100644 --- a/core/src/main/java/com/opensymphony/xwork2/validator/Validator.java +++ b/core/src/main/java/com/opensymphony/xwork2/validator/Validator.java @@ -222,7 +222,7 @@ import com.opensymphony.xwork2.util.ValueStack; * <!-- START SNIPPET: exShortCircuitingValidators --> * <!DOCTYPE validators PUBLIC * "-//Apache Struts//XWork Validator 1.0.3//EN" - * "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> + * "https://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> * <validators> * <!-- Field Validators for email field --> * <field name="email"> diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java b/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java index 8510fe6bb..f085d1b12 100644 --- a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java +++ b/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java @@ -115,7 +115,7 @@ package com.opensymphony.xwork2.validator; *

  * 
  * <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
-   		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
+   		"https://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
  * <validators>
  *   <field name="bar">
  *       <field-validator type="required">
diff --git a/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml b/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml
index f3972e4e6..b0e6ed4f8 100644
--- a/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml
+++ b/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">
 
 
 
diff --git a/core/src/main/resources/struts-2.0.dtd b/core/src/main/resources/struts-2.0.dtd
index b71a8539a..0f4ffa9cb 100644
--- a/core/src/main/resources/struts-2.0.dtd
+++ b/core/src/main/resources/struts-2.0.dtd
@@ -24,10 +24,10 @@
 
 
 
@@ -131,7 +131,7 @@
 
 
 
 
diff --git a/core/src/main/resources/struts-2.1.7.dtd b/core/src/main/resources/struts-2.1.7.dtd
index 790202cf6..6af002e93 100644
--- a/core/src/main/resources/struts-2.1.7.dtd
+++ b/core/src/main/resources/struts-2.1.7.dtd
@@ -27,7 +27,7 @@
 
    
+	"https://struts.apache.org/dtds/struts-2.1.7.dtd">
 -->
 
 
diff --git a/core/src/main/resources/struts-2.1.dtd b/core/src/main/resources/struts-2.1.dtd
index e6ad908c7..760ab3143 100644
--- a/core/src/main/resources/struts-2.1.dtd
+++ b/core/src/main/resources/struts-2.1.dtd
@@ -27,7 +27,7 @@
 
    
+	"https://struts.apache.org/dtds/struts-2.1.dtd">
 -->
 
 
diff --git a/core/src/main/resources/struts-2.3.dtd b/core/src/main/resources/struts-2.3.dtd
index 4a1eeb9cb..67ab3c65a 100644
--- a/core/src/main/resources/struts-2.3.dtd
+++ b/core/src/main/resources/struts-2.3.dtd
@@ -27,7 +27,7 @@
 
    
+	"https://struts.apache.org/dtds/struts-2.3.dtd">
 -->
 
 
diff --git a/core/src/main/resources/struts-2.5.dtd b/core/src/main/resources/struts-2.5.dtd
index d0ee064d9..5bdf627a2 100644
--- a/core/src/main/resources/struts-2.5.dtd
+++ b/core/src/main/resources/struts-2.5.dtd
@@ -27,7 +27,7 @@
 
    
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 -->
 
 
diff --git a/core/src/main/resources/struts-6.0.dtd b/core/src/main/resources/struts-6.0.dtd
index 3df027de9..3741c445d 100644
--- a/core/src/main/resources/struts-6.0.dtd
+++ b/core/src/main/resources/struts-6.0.dtd
@@ -27,7 +27,7 @@
 
    
+    "https://struts.apache.org/dtds/struts-6.0.dtd">
 -->
 
 
diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml
index a75c14ec0..467b9007c 100644
--- a/core/src/main/resources/struts-default.xml
+++ b/core/src/main/resources/struts-default.xml
@@ -31,8 +31,8 @@
     and {@link com.opensymphony.xwork2.inject.Inject}
 -->
 
+        "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
+        "https://struts.apache.org/dtds/struts-6.0.dtd">
 
 
 
@@ -47,7 +47,7 @@
                 java.lang.ProcessBuilder,
                 java.lang.Thread,
                 sun.misc.Unsafe,
-                com.opensymphony.xwork2.ActionContext" />
+                com.opensymphony.xwork2.ActionContext"/>
 
     
+                sun.misc.Unsafe"/>
 
     
     
@@ -89,7 +89,7 @@
                 com.opensymphony.xwork2.util.,
                 org.apache.tomcat.,
                 org.apache.catalina.core.,
-                org.wildfly.extension.undertow.deployment." />
+                org.wildfly.extension.undertow.deployment."/>
 
     
+                com.opensymphony.xwork2.util."/>
 
     
-    
-    
-    
-    
-    
-    
+    
+    
+    
+    
+    
+    
 
-    
-    
+    
+    
 
-    
-    
+    
+    
 
-    
+    
 
-    
-    
-    
+    
+    
+    
 
-    
+    
 
-    
-    
-    
-    
-    
+    
+    
+    
+    
+    
 
-    
-    
+    
+    
 
-    
+    
 
-    
-    
+    
+    
 
-    
-    
-    
+    
+    
+    
 
-    
+    
 
-    
-    
-    
-    
-    
+    
+    
+    
+    
+    
 
-    
+    
 
-    
-    
-    
-    
-    
+    
+    
+    
+    
+    
 
-    
-    
+    
+    
 
-    
-    
-    
+    
+    
+    
 
-    
-    
+    
+    
 
-    
-    
-    
+    
+    
+    
 
-    
+    
 
-    
-    
+    
+    
 
-    
-    
+    
+    
 
-    
+    
 
-    
+    
 
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
 
-    
-    
+    
+    
 
-    
+    
 
-    
-    
+    
+    
 
-    
+    
 
     
-    
-    
-    
+    
+    
+    
 
-    
-    
-    
+    
+    
+    
 
-    
+    
 
-    
-    
+    
+    
 
-    
-    
+    
+    
 
     
         
@@ -244,50 +323,57 @@
             
             
             
-            
-            
+            
+            
         
 
         
             
-            
+            
             
             
-            
+            
             
             
-            
+            
             
-            
+            
             
-            
+            
             
             
             
             
             
             
-            
+            
             
             
-            
+            
             
             
             
             
             
             
-            
+            
             
-            
-            
-            
-            
-            
-            
-            
-            
-            
+            
+            
+            
+            
+            
+            
+            
+            
+            
 
             
             
@@ -448,11 +534,11 @@
                 
             
 
-       
+        
 
         
 
-        
+        
 
         execute,input,back,cancel,browse,save,delete,list,index
 
diff --git a/core/src/main/resources/xwork-default.xml b/core/src/main/resources/xwork-default.xml
index fcdcb5f43..b4dce657b 100644
--- a/core/src/main/resources/xwork-default.xml
+++ b/core/src/main/resources/xwork-default.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
 
diff --git a/core/src/main/resources/xwork-validator-1.0.2.dtd b/core/src/main/resources/xwork-validator-1.0.2.dtd
index a54734033..aa7713800 100644
--- a/core/src/main/resources/xwork-validator-1.0.2.dtd
+++ b/core/src/main/resources/xwork-validator-1.0.2.dtd
@@ -22,10 +22,10 @@
 
 
 
diff --git a/core/src/main/resources/xwork-validator-1.0.3.dtd b/core/src/main/resources/xwork-validator-1.0.3.dtd
index 5a056887e..7ebc36285 100644
--- a/core/src/main/resources/xwork-validator-1.0.3.dtd
+++ b/core/src/main/resources/xwork-validator-1.0.3.dtd
@@ -25,7 +25,7 @@
 
   
+  		"https://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
 -->
 
 
diff --git a/core/src/main/resources/xwork-validator-1.0.dtd b/core/src/main/resources/xwork-validator-1.0.dtd
index 7be377f14..278770612 100644
--- a/core/src/main/resources/xwork-validator-1.0.dtd
+++ b/core/src/main/resources/xwork-validator-1.0.dtd
@@ -22,10 +22,10 @@
 
 
 
diff --git a/core/src/main/resources/xwork-validator-config-1.0.dtd b/core/src/main/resources/xwork-validator-config-1.0.dtd
index 8714b75ae..e98dcf966 100644
--- a/core/src/main/resources/xwork-validator-config-1.0.dtd
+++ b/core/src/main/resources/xwork-validator-config-1.0.dtd
@@ -25,7 +25,7 @@
 
   
+  		"https://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
 -->
 
 
diff --git a/core/src/main/resources/xwork-validator-definition-1.0.dtd b/core/src/main/resources/xwork-validator-definition-1.0.dtd
index 801f7594e..e93bd7887 100644
--- a/core/src/main/resources/xwork-validator-definition-1.0.dtd
+++ b/core/src/main/resources/xwork-validator-definition-1.0.dtd
@@ -25,7 +25,7 @@
 
   
+  		"https://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">
 -->
 
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/ModelDrivenAction-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/ModelDrivenAction-validation.xml
index 1a777b9c1..6ef6dc27a 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/ModelDrivenAction-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/ModelDrivenAction-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-some-alias-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-some-alias-validation.xml
index 9bc2cf0b8..5aa306686 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-some-alias-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-some-alias-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-subproperty-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-subproperty-validation.xml
index 8682377a9..8304c0b0c 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-subproperty-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-subproperty-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-validation.xml
index 9d5f9f5a1..229c25789 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-validationAlias-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-validationAlias-validation.xml
index 9bc2cf0b8..5aa306686 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-validationAlias-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction-validationAlias-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/TestBean-anotherContext-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/TestBean-anotherContext-validation.xml
index f6af52390..4a9187f99 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/TestBean-anotherContext-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/TestBean-anotherContext-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/TestBean-badtest-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/TestBean-badtest-validation.xml
index 0c5f26fa1..c51dd3f77 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/TestBean-badtest-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/TestBean-badtest-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/TestBean-beanMessageBundle-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/TestBean-beanMessageBundle-validation.xml
index ca388b594..74921d6fd 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/TestBean-beanMessageBundle-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/TestBean-beanMessageBundle-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/TestBean-expressionValidation-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/TestBean-expressionValidation-validation.xml
index 39894eac1..8fd7044f6 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/TestBean-expressionValidation-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/TestBean-expressionValidation-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/TestBean-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/TestBean-validation.xml
index 0437eb27b..4e620947f 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/TestBean-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/TestBean-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/TestBean-visitorChildValidation-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/TestBean-visitorChildValidation-validation.xml
index 11655bb1f..b7a554612 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/TestBean-visitorChildValidation-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/TestBean-visitorChildValidation-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/TestBean-visitorValidation-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/TestBean-visitorValidation-validation.xml
index 05adfb1a3..de417db12 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/TestBean-visitorValidation-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/TestBean-visitorValidation-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/TestChildBean-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/TestChildBean-validation.xml
index ec7fc715b..0cb7401f0 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/TestChildBean-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/TestChildBean-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
@@ -28,7 +28,7 @@
     
         name == 'test'
         Name is invalid
-     
+    
     
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/ValidationOrderAction-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/ValidationOrderAction-validation.xml
index ddb2ce12c..a16765297 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/ValidationOrderAction-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/ValidationOrderAction-validation.xml
@@ -19,9 +19,9 @@
  * under the License.
  */
 -->
-
+  		"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 
 	
@@ -47,13 +47,13 @@
 			confirmed password must match password
 		
 	
-	
+
 	
 		
 			first name required
 		
 	
-	
+
 	
 		
 			last name required
@@ -65,25 +65,25 @@
 			city is required
 		
 	
-	
+
 	
 		
 			province is required
 		
 	
-	
+
 	
 		
 			country is required
 		
 	
-	
+
 	
 		
 			postal code is required
 		
 	
-	
+
 	
 		
 			email is required
@@ -98,7 +98,7 @@
 			website is required
 		
 	
-	
+
 	
 		
 			password hint is required
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder1/xwork-test-load-order.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder1/xwork-test-load-order.xml
index e66737355..805c5b60b 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder1/xwork-test-load-order.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder1/xwork-test-load-order.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder2/xwork-test-load-order.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder2/xwork-test-load-order.xml
index 8cbf2d7ae..602d778ef 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder2/xwork-test-load-order.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder2/xwork-test-load-order.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder3/xwork-test-load-order.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder3/xwork-test-load-order.xml
index 03d16f94b..c54e17fb3 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder3/xwork-test-load-order.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/loadorder3/xwork-test-load-order.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork- test.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork- test.xml
index 456a725fb..e832300df 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork- test.xml	
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork- test.xml	
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-after-package-2.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-after-package-2.xml
index bf6df3e2e..f29ce17b6 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-after-package-2.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-after-package-2.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-after-package.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-after-package.xml
index 06d213d82..d9f87ec67 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-after-package.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-after-package.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-before-package-2.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-before-package-2.xml
index aeae5a6da..59ef1e9cb 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-before-package-2.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-before-package-2.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-before-package.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-before-package.xml
index c68115b83..2ccff3a8f 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-before-package.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-before-package.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-parent.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-parent.xml
index dbd77959d..758b55f0e 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-parent.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-include-parent.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-action-invalid.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-action-invalid.xml
index 53b9a2fcf..8fa336915 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-action-invalid.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-action-invalid.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-actions-packagedefaultclassref.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-actions-packagedefaultclassref.xml
index c2717befc..42d2d5b64 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-actions-packagedefaultclassref.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-actions-packagedefaultclassref.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-actions.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-actions.xml
index 456a725fb..e832300df 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-actions.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-actions.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml
index 17b33ab38..85ada7e4e 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
         input,cancel
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-bad-inheritance.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-bad-inheritance.xml
index d271a1c42..5f6b1f070 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-bad-inheritance.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-bad-inheritance.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
@@ -31,6 +31,6 @@
     
 
     
-    
+
     
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-basic-packages.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-basic-packages.xml
index ccd8aed7a..e6b3a7fbd 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-basic-packages.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-basic-packages.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-default-package.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-default-package.xml
index 2c566d20b..d5869ca23 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-default-package.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-default-package.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-defaultclassref-package.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-defaultclassref-package.xml
index adc41eb11..ae9c254c3 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-defaultclassref-package.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-defaultclassref-package.xml
@@ -21,10 +21,10 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
         
     
     
-
\ No newline at end of file
+
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-envs-substitution.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-envs-substitution.xml
index 03fe2b715..a328c721e 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-envs-substitution.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-envs-substitution.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-exception-mappings.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-exception-mappings.xml
index 71f607012..bb7a3454b 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-exception-mappings.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-exception-mappings.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-global-result-inheritence.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-global-result-inheritence.xml
index 461c2e17a..4852fae82 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-global-result-inheritence.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-global-result-inheritence.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-include-wildcard.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-include-wildcard.xml
index a9ef73178..afc333416 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-include-wildcard.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-include-wildcard.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
   
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-defaultref.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-defaultref.xml
index 7cde9bcd1..955c12348 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-defaultref.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-defaultref.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-inheritance.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-inheritance.xml
index 929a0181f..5226d0a6c 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-inheritance.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-inheritance.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-param-overriding.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-param-overriding.xml
index 660f6dcdd..af8c52d82 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-param-overriding.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-param-overriding.xml
@@ -21,26 +21,26 @@
 -->
 
+		"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
 	
 		
 			
 		
-	
+
 		
 			
 			
 			
-			
+
 			
 				
 				
 				
 			
 		
-		
+
 		
 			
 				i1p1
@@ -49,7 +49,7 @@
 			
 			test1
 		
-		
+
 		
 			
 				i3p1
@@ -60,4 +60,3 @@
 		
 	
 
-    
\ No newline at end of file
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-params.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-params.xml
index 32c4099a6..e74d5320c 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-params.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-params.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-stack-param-overriding.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-stack-param-overriding.xml
index d94e4f263..7a54fcd83 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-stack-param-overriding.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptor-stack-param-overriding.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptors-basic.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptors-basic.xml
index 6ed804d26..dec118da5 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptors-basic.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptors-basic.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptors-spring.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptors-spring.xml
index 431926d9f..1adf5edf8 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptors-spring.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-interceptors-spring.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-multilevel.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-multilevel.xml
index 7e3f99baf..2852fb656 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-multilevel.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-multilevel.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-package-inheritance.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-package-inheritance.xml
index b57b54624..c728ac8fb 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-package-inheritance.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-package-inheritance.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
@@ -35,7 +35,7 @@
     
         
     
-    
+
     
     	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-reload.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-reload.xml
index 142b8eb38..c71e8b5de 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-reload.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-reload.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-inheritance.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-inheritance.xml
index b526aabc4..5e0f97cfc 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-inheritance.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-inheritance.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml
index e239161ba..e00fd3cbc 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-types.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-types.xml
index 6763ea62e..569488e3a 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-types.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-types.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-results.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-results.xml
index 91ab55548..76363a7ba 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-results.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-results.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-1.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-1.xml
index a889f0ff7..b447dd65c 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-1.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-1.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-2.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-2.xml
index c84108d90..3ffb56b57 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-2.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-2.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-include.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-include.xml
index d3525473c..60a69c277 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-include.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-wildcard-include.xml
@@ -21,11 +21,11 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
     
     
     
-
\ No newline at end of file
+
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-unknownhandler-stack-empty.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-unknownhandler-stack-empty.xml
index 313507cf3..4ec37d69b 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-unknownhandler-stack-empty.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-unknownhandler-stack-empty.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-unknownhandler-stack.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-unknownhandler-stack.xml
index 886ae18c6..6cf80101c 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-unknownhandler-stack.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-unknownhandler-stack.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/test/DataAware-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/test/DataAware-validation.xml
index 822366f14..9d02543c7 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/test/DataAware-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/test/DataAware-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/test/DataAware-validationAlias-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/test/DataAware-validationAlias-validation.xml
index 72d598fef..faad9758e 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/test/DataAware-validationAlias-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/test/DataAware-validationAlias-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/test/DataAware2-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/test/DataAware2-validation.xml
index 92183e658..3fd057047 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/test/DataAware2-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/test/DataAware2-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/test/Equidae-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/test/Equidae-validation.xml
index 7a5f47a70..e65c5a377 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/test/Equidae-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/test/Equidae-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/test/SimpleAction2-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/test/SimpleAction2-validation.xml
index 2ff8331f4..ca7887caa 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/test/SimpleAction2-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/test/SimpleAction2-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/test/SimpleAction2-validationAlias-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/test/SimpleAction2-validationAlias-validation.xml
index 9bc2cf0b8..5aa306686 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/test/SimpleAction2-validationAlias-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/test/SimpleAction2-validationAlias-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/test/User-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/test/User-validation.xml
index c29c8c900..267de6424 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/test/User-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/test/User-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/test/UserMarker-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/test/UserMarker-validation.xml
index 953376c2b..e94c26323 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/test/UserMarker-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/test/UserMarker-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorModelAction-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorModelAction-validation.xml
index 3579cb961..203b92062 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorModelAction-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorModelAction-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-beanMessageBundle-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-beanMessageBundle-validation.xml
index d2a9ba14c..501ada4f6 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-beanMessageBundle-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-beanMessageBundle-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validateArray-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validateArray-validation.xml
index c77736822..77bfabbd9 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validateArray-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validateArray-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validateList-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validateList-validation.xml
index 7e350152b..f928368be 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validateList-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validateList-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validation.xml
index 38728076b..a8de9f705 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorChildValidation-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorChildValidation-validation.xml
index d2a9ba14c..501ada4f6 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorChildValidation-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorChildValidation-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorValidation-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorValidation-validation.xml
index d2a9ba14c..501ada4f6 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorValidation-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorValidation-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorValidationAlias-validation.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorValidationAlias-validation.xml
index d7112c567..37ae57de0 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorValidationAlias-validation.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/VisitorValidatorTestAction-visitorValidationAlias-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test.xml
index ebc161aee..14b2bf376 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test2.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test2.xml
index 0e43abf20..17a7759d7 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test2.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test2.xml
@@ -21,18 +21,18 @@
 -->
 
-       
+       "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
+
 
    
       
          a field error message
-         
+      
    
    
       
       an expression error message
    
 
-              
-       
+
+
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test3.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test3.xml
index f6825fbd6..93851e6bd 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test3.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test3.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         email.equals(email2)
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test4.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test4.xml
index 642c3b74f..effa71fb0 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test4.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test4.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
 
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test5.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test5.xml
index ea9bc7805..88b3514c2 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test5.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test5.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
 
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test6.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test6.xml
index 3e8d84a08..68a9dfa75 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test6.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/validator-parser-test6.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
 
 
     
diff --git a/core/src/test/resources/com/opensymphony/xwork2/validator/validators-fail.xml b/core/src/test/resources/com/opensymphony/xwork2/validator/validators-fail.xml
index eaf9f381d..03c5dd072 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/validator/validators-fail.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/validator/validators-fail.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
 
 
     
diff --git a/core/src/test/resources/includeTest.xml b/core/src/test/resources/includeTest.xml
index 018c3ba30..16ff28092 100644
--- a/core/src/test/resources/includeTest.xml
+++ b/core/src/test/resources/includeTest.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
         
diff --git a/core/src/test/resources/my-validators.xml b/core/src/test/resources/my-validators.xml
index bc4543e40..431fac151 100644
--- a/core/src/test/resources/my-validators.xml
+++ b/core/src/test/resources/my-validators.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
 
     
 
diff --git a/core/src/test/resources/myOther-validators.xml b/core/src/test/resources/myOther-validators.xml
index 128c186de..198cc6822 100644
--- a/core/src/test/resources/myOther-validators.xml
+++ b/core/src/test/resources/myOther-validators.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
 
     
 
diff --git a/core/src/test/resources/org/apache/struts2/TestAction-validation.xml b/core/src/test/resources/org/apache/struts2/TestAction-validation.xml
index cfcdf4367..e40b22826 100644
--- a/core/src/test/resources/org/apache/struts2/TestAction-validation.xml
+++ b/core/src/test/resources/org/apache/struts2/TestAction-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/org/apache/struts2/dispatcher/ng/struts-no-op.xml b/core/src/test/resources/org/apache/struts2/dispatcher/ng/struts-no-op.xml
index e9cf3be11..00393612f 100644
--- a/core/src/test/resources/org/apache/struts2/dispatcher/ng/struts-no-op.xml
+++ b/core/src/test/resources/org/apache/struts2/dispatcher/ng/struts-no-op.xml
@@ -21,5 +21,5 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-6.0.dtd">
 
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/WW3090-struts.xml b/core/src/test/resources/org/apache/struts2/views/jsp/WW3090-struts.xml
index 974d4bfab..1542a41c2 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/WW3090-struts.xml
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/WW3090-struts.xml
@@ -22,7 +22,7 @@
 
 
+        "https://struts.apache.org/dtds/struts-6.0.dtd">
 
 
 
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleValidationAction-validation.xml b/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleValidationAction-validation.xml
index f1ab64e6b..3c2a0c941 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleValidationAction-validation.xml
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleValidationAction-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
@@ -28,4 +28,4 @@
             bar must be between ${minInclusive} and ${maxInclusive}.
         
     
-
\ No newline at end of file
+
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/IntValidationAction-validation.xml b/core/src/test/resources/org/apache/struts2/views/jsp/ui/IntValidationAction-validation.xml
index 8ab34b89d..f200cb396 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/IntValidationAction-validation.xml
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/IntValidationAction-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/User-validation.xml b/core/src/test/resources/org/apache/struts2/views/jsp/ui/User-validation.xml
index 5bf827fe0..7ca3158bb 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/User-validation.xml
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/User-validation.xml
@@ -19,7 +19,7 @@
  * under the License.
  */
 -->
-
+
 
     
         
diff --git a/core/src/test/resources/struts-escape-body.xml b/core/src/test/resources/struts-escape-body.xml
index 186ba9760..fda3f1010 100644
--- a/core/src/test/resources/struts-escape-body.xml
+++ b/core/src/test/resources/struts-escape-body.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-6.0.dtd">
 
     
 
diff --git a/core/src/test/resources/struts-object-factory-result-builder.xml b/core/src/test/resources/struts-object-factory-result-builder.xml
index f5988785d..a76b6f703 100644
--- a/core/src/test/resources/struts-object-factory-result-builder.xml
+++ b/core/src/test/resources/struts-object-factory-result-builder.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/core/src/test/resources/struts-testing.xml b/core/src/test/resources/struts-testing.xml
index 5d9c5b21f..62023b2e6 100644
--- a/core/src/test/resources/struts-testing.xml
+++ b/core/src/test/resources/struts-testing.xml
@@ -21,7 +21,7 @@
 -->
 
+          "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/struts.xml b/core/src/test/resources/struts.xml
index 59197aab3..55b6805e4 100644
--- a/core/src/test/resources/struts.xml
+++ b/core/src/test/resources/struts.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-6.0.dtd">
 
     
         
diff --git a/core/src/test/resources/validators.xml b/core/src/test/resources/validators.xml
index 883bd433d..dc99a4e8c 100644
--- a/core/src/test/resources/validators.xml
+++ b/core/src/test/resources/validators.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
 
     
     
diff --git a/core/src/test/resources/xwork-class-param-test.xml b/core/src/test/resources/xwork-class-param-test.xml
index 451b9f7bc..74161eadf 100644
--- a/core/src/test/resources/xwork-class-param-test.xml
+++ b/core/src/test/resources/xwork-class-param-test.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
diff --git a/core/src/test/resources/xwork-param-test.xml b/core/src/test/resources/xwork-param-test.xml
index ba6386dbe..8eed0b55d 100644
--- a/core/src/test/resources/xwork-param-test.xml
+++ b/core/src/test/resources/xwork-param-test.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/core/src/test/resources/xwork-proxyinvoke.xml b/core/src/test/resources/xwork-proxyinvoke.xml
index 109907cee..3e95e62cf 100644
--- a/core/src/test/resources/xwork-proxyinvoke.xml
+++ b/core/src/test/resources/xwork-proxyinvoke.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
 
diff --git a/core/src/test/resources/xwork-sample.xml b/core/src/test/resources/xwork-sample.xml
index 0a4c0aacd..c31023456 100644
--- a/core/src/test/resources/xwork-sample.xml
+++ b/core/src/test/resources/xwork-sample.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
@@ -84,8 +84,8 @@
             
             
         
-		
-		
             {1}
             {2}
@@ -136,7 +136,7 @@
             
             
         
-	
+
         
             
             
@@ -275,7 +275,7 @@
                 
 
         
-       
+
         
                  
         
@@ -289,8 +289,8 @@
 
         
                 
-         
-        
+        
+
         
  			
         
diff --git a/core/src/test/resources/xwork-test-beans.xml b/core/src/test/resources/xwork-test-beans.xml
index 92e673d6b..c88a34917 100644
--- a/core/src/test/resources/xwork-test-beans.xml
+++ b/core/src/test/resources/xwork-test-beans.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
diff --git a/core/src/test/resources/xwork-test-default.xml b/core/src/test/resources/xwork-test-default.xml
index f805aa3cb..d9f6dddd4 100644
--- a/core/src/test/resources/xwork-test-default.xml
+++ b/core/src/test/resources/xwork-test-default.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
         
diff --git a/core/src/test/resources/xwork-test-validation.xml b/core/src/test/resources/xwork-test-validation.xml
index fe71c26b8..b58c66193 100644
--- a/core/src/test/resources/xwork-test-validation.xml
+++ b/core/src/test/resources/xwork-test-validation.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
     
@@ -70,7 +70,7 @@
             
             
         
-        
+
         
             
             
diff --git a/plugins/async/src/main/resources/struts-plugin.xml b/plugins/async/src/main/resources/struts-plugin.xml
index fb71372d9..da2aee816 100644
--- a/plugins/async/src/main/resources/struts-plugin.xml
+++ b/plugins/async/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
diff --git a/plugins/bean-validation/src/test/resources/bean-validation-test.xml b/plugins/bean-validation/src/test/resources/bean-validation-test.xml
index 360e10eb6..bd5716cee 100644
--- a/plugins/bean-validation/src/test/resources/bean-validation-test.xml
+++ b/plugins/bean-validation/src/test/resources/bean-validation-test.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
     
diff --git a/plugins/cdi/src/main/resources/struts-plugin.xml b/plugins/cdi/src/main/resources/struts-plugin.xml
index 9c79a3326..b969296fa 100644
--- a/plugins/cdi/src/main/resources/struts-plugin.xml
+++ b/plugins/cdi/src/main/resources/struts-plugin.xml
@@ -21,10 +21,10 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
-    
+
     
 
     
diff --git a/plugins/config-browser/src/main/resources/struts-plugin.xml b/plugins/config-browser/src/main/resources/struts-plugin.xml
index 46c51e48d..b2187d4e2 100644
--- a/plugins/config-browser/src/main/resources/struts-plugin.xml
+++ b/plugins/config-browser/src/main/resources/struts-plugin.xml
@@ -21,12 +21,12 @@
 -->
 
-    
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
+
 
 
     
-    
+
     
 
         
@@ -56,15 +56,15 @@
         
             /config-browser/showConfig.ftl
         
-        
+
         
             /config-browser/showConstants.ftl
         
-        
+
         
             /config-browser/showBeans.ftl
         
-        
+
         
             /config-browser/showJars.ftl
         
diff --git a/plugins/convention/src/main/resources/struts-plugin.xml b/plugins/convention/src/main/resources/struts-plugin.xml
index fed289a74..6cd8b04a8 100644
--- a/plugins/convention/src/main/resources/struts-plugin.xml
+++ b/plugins/convention/src/main/resources/struts-plugin.xml
@@ -22,7 +22,7 @@
 
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
   
diff --git a/plugins/embeddedjsp/src/main/resources/struts-plugin.xml b/plugins/embeddedjsp/src/main/resources/struts-plugin.xml
index 2f7b5565c..1651b3fa3 100644
--- a/plugins/embeddedjsp/src/main/resources/struts-plugin.xml
+++ b/plugins/embeddedjsp/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
diff --git a/plugins/gxp/src/main/resources/struts-plugin.xml b/plugins/gxp/src/main/resources/struts-plugin.xml
index b6d9c8ffb..dd39530e5 100644
--- a/plugins/gxp/src/main/resources/struts-plugin.xml
+++ b/plugins/gxp/src/main/resources/struts-plugin.xml
@@ -21,10 +21,10 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
-     
+    
     
         
             
diff --git a/plugins/jasperreports/src/main/resources/struts-plugin.xml b/plugins/jasperreports/src/main/resources/struts-plugin.xml
index f9417990b..e99209135 100644
--- a/plugins/jasperreports/src/main/resources/struts-plugin.xml
+++ b/plugins/jasperreports/src/main/resources/struts-plugin.xml
@@ -21,11 +21,11 @@
 -->
 
-    
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
+
 
     
-    
+
     	
     		
     	
diff --git a/plugins/javatemplates/src/main/resources/struts-plugin.xml b/plugins/javatemplates/src/main/resources/struts-plugin.xml
index 537095792..5ca258c4f 100644
--- a/plugins/javatemplates/src/main/resources/struts-plugin.xml
+++ b/plugins/javatemplates/src/main/resources/struts-plugin.xml
@@ -21,8 +21,8 @@
 -->
 
-    
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
+
 
 
     
diff --git a/plugins/jfreechart/src/main/resources/struts-plugin.xml b/plugins/jfreechart/src/main/resources/struts-plugin.xml
index dbb411465..68506aba4 100644
--- a/plugins/jfreechart/src/main/resources/struts-plugin.xml
+++ b/plugins/jfreechart/src/main/resources/struts-plugin.xml
@@ -21,11 +21,11 @@
 -->
 
-    
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
+
 
     
-    
+
     	
     		
     			150
diff --git a/plugins/json/src/main/resources/struts-plugin.xml b/plugins/json/src/main/resources/struts-plugin.xml
index 44b035a35..a20a5924a 100644
--- a/plugins/json/src/main/resources/struts-plugin.xml
+++ b/plugins/json/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/plugins/junit/src/test/resources/struts-session-values-test.xml b/plugins/junit/src/test/resources/struts-session-values-test.xml
index 8030f80b0..ea6e1f415 100644
--- a/plugins/junit/src/test/resources/struts-session-values-test.xml
+++ b/plugins/junit/src/test/resources/struts-session-values-test.xml
@@ -22,7 +22,7 @@
 
 
+        "https://struts.apache.org/dtds/struts-2.1.dtd">
 
 
     
diff --git a/plugins/junit/src/test/resources/struts-test.xml b/plugins/junit/src/test/resources/struts-test.xml
index 9eed684ea..c0943a71c 100644
--- a/plugins/junit/src/test/resources/struts-test.xml
+++ b/plugins/junit/src/test/resources/struts-test.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.1.dtd">
 
 
     
diff --git a/plugins/junit/src/test/resources/struts.xml b/plugins/junit/src/test/resources/struts.xml
index 04b00af94..6d2210687 100644
--- a/plugins/junit/src/test/resources/struts.xml
+++ b/plugins/junit/src/test/resources/struts.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.1.dtd">
 
 
     
diff --git a/plugins/osgi/src/main/resources/struts-plugin.xml b/plugins/osgi/src/main/resources/struts-plugin.xml
index 8e529244f..22c1cd4a8 100644
--- a/plugins/osgi/src/main/resources/struts-plugin.xml
+++ b/plugins/osgi/src/main/resources/struts-plugin.xml
@@ -21,8 +21,8 @@
 -->
 
-    
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
+
 
     
     
@@ -33,7 +33,7 @@
 
     
     
-    
+
     
     
     
diff --git a/plugins/oval/src/main/resources/struts-plugin.xml b/plugins/oval/src/main/resources/struts-plugin.xml
index 8b205a75d..da2108820 100644
--- a/plugins/oval/src/main/resources/struts-plugin.xml
+++ b/plugins/oval/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/plugins/oval/src/test/resources/oval-test.xml b/plugins/oval/src/test/resources/oval-test.xml
index 522e92fbe..e4a69b506 100644
--- a/plugins/oval/src/test/resources/oval-test.xml
+++ b/plugins/oval/src/test/resources/oval-test.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
     
diff --git a/plugins/pell-multipart/src/main/resources/struts-plugin.xml b/plugins/pell-multipart/src/main/resources/struts-plugin.xml
index 0569fa8ba..a9fc10b4e 100644
--- a/plugins/pell-multipart/src/main/resources/struts-plugin.xml
+++ b/plugins/pell-multipart/src/main/resources/struts-plugin.xml
@@ -21,8 +21,8 @@
 -->
 
-    
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
+
 
     
 
diff --git a/plugins/plexus/src/main/resources/struts-plugin.xml b/plugins/plexus/src/main/resources/struts-plugin.xml
index 8d596b364..43e20350c 100644
--- a/plugins/plexus/src/main/resources/struts-plugin.xml
+++ b/plugins/plexus/src/main/resources/struts-plugin.xml
@@ -21,11 +21,11 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
-    
+
     
     
 
diff --git a/plugins/portlet-tiles/src/main/resources/struts-plugin.xml b/plugins/portlet-tiles/src/main/resources/struts-plugin.xml
index dc9aa022e..b7ad6ce78 100644
--- a/plugins/portlet-tiles/src/main/resources/struts-plugin.xml
+++ b/plugins/portlet-tiles/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/plugins/portlet/src/main/resources/struts-plugin.xml b/plugins/portlet/src/main/resources/struts-plugin.xml
index 7b9144767..a66479793 100644
--- a/plugins/portlet/src/main/resources/struts-plugin.xml
+++ b/plugins/portlet/src/main/resources/struts-plugin.xml
@@ -22,7 +22,7 @@
 
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/plugins/portlet/src/test/resources/struts.xml b/plugins/portlet/src/test/resources/struts.xml
index d8c52875b..afd0d9a81 100644
--- a/plugins/portlet/src/test/resources/struts.xml
+++ b/plugins/portlet/src/test/resources/struts.xml
@@ -21,7 +21,7 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/plugins/rest/src/main/resources/struts-plugin.xml b/plugins/rest/src/main/resources/struts-plugin.xml
index 1dd8d9dcb..589d12ca7 100644
--- a/plugins/rest/src/main/resources/struts-plugin.xml
+++ b/plugins/rest/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
 
diff --git a/plugins/sitemesh/src/main/resources/struts-plugin.xml b/plugins/sitemesh/src/main/resources/struts-plugin.xml
index 406a73a0f..bad62b8e2 100644
--- a/plugins/sitemesh/src/main/resources/struts-plugin.xml
+++ b/plugins/sitemesh/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
diff --git a/plugins/spring/src/main/resources/struts-plugin.xml b/plugins/spring/src/main/resources/struts-plugin.xml
index 51fb37c2e..7a5462037 100644
--- a/plugins/spring/src/main/resources/struts-plugin.xml
+++ b/plugins/spring/src/main/resources/struts-plugin.xml
@@ -21,11 +21,11 @@
 -->
 
-    
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
+
 
     
-    
+
     
     
 
@@ -40,5 +40,5 @@
         
             
         
-        
+    
 
diff --git a/plugins/spring/src/test/resources/com/opensymphony/xwork2/spring/actionContext-xwork.xml b/plugins/spring/src/test/resources/com/opensymphony/xwork2/spring/actionContext-xwork.xml
index d44f41d00..63647477b 100644
--- a/plugins/spring/src/test/resources/com/opensymphony/xwork2/spring/actionContext-xwork.xml
+++ b/plugins/spring/src/test/resources/com/opensymphony/xwork2/spring/actionContext-xwork.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-2.5.dtd">
 
 	
 	
@@ -48,7 +48,7 @@
         
 
         
-        
+
         
 			
 		
diff --git a/plugins/tiles/src/main/resources/struts-plugin.xml b/plugins/tiles/src/main/resources/struts-plugin.xml
index 7bd133d49..9ae060a3d 100644
--- a/plugins/tiles/src/main/resources/struts-plugin.xml
+++ b/plugins/tiles/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
     
diff --git a/plugins/velocity/src/main/resources/struts-plugin.xml b/plugins/velocity/src/main/resources/struts-plugin.xml
index 30084ed3d..48ae45bdd 100644
--- a/plugins/velocity/src/main/resources/struts-plugin.xml
+++ b/plugins/velocity/src/main/resources/struts-plugin.xml
@@ -21,7 +21,7 @@
 -->
 
+        "https://struts.apache.org/dtds/struts-6.0.dtd">
 
 
 

From 32201b2ef2cdfe3eccd57e0029aa935d55d9c3ce Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Tue, 27 Sep 2022 19:41:20 +0200
Subject: [PATCH 046/143] WW-5232 Applies proper coverage settings for Jacoco
 plugin and Sonar

---
 apps/rest-showcase/pom.xml  | 1 +
 apps/showcase/pom.xml       | 1 +
 core/pom.xml                | 4 +---
 plugins/embeddedjsp/pom.xml | 1 +
 pom.xml                     | 5 ++++-
 5 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml
index 870683b81..95bbbbf02 100644
--- a/apps/rest-showcase/pom.xml
+++ b/apps/rest-showcase/pom.xml
@@ -125,6 +125,7 @@
             
                 maven-surefire-plugin
                 
+                    @{argLine}
                     
                         it/**
                         **/*$*
diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml
index 51b87ae26..18a7febc0 100644
--- a/apps/showcase/pom.xml
+++ b/apps/showcase/pom.xml
@@ -237,6 +237,7 @@
             
                 maven-surefire-plugin
                 
+                    @{argLine}
                     
                         it/**
                         **/*$*
diff --git a/core/pom.xml b/core/pom.xml
index 71a3f777b..e8b92fbf2 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -41,6 +41,7 @@
                 org.apache.maven.plugins
                 maven-surefire-plugin
                 
+                    @{argLine}
                     
                         
                             maven.testng.output.dir
@@ -54,9 +55,6 @@
                         ${project.build.testOutputDirectory}/xwork - jar.jar
                         ${project.build.testOutputDirectory}/xwork - zip.zip
                     
-                    
-                        **/*Test.java
-                    
                     
                         **/XWorkTestCase.java
                         **/TestBean.java
diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml
index 9da33bbc1..f76297bcc 100644
--- a/plugins/embeddedjsp/pom.xml
+++ b/plugins/embeddedjsp/pom.xml
@@ -97,6 +97,7 @@
                 org.apache.maven.plugins
                 maven-surefire-plugin
                 
+                    @{argLine}
                     
                         ${project.build.testOutputDirectory}/jsps.jar
                     
diff --git a/pom.xml b/pom.xml
index 3ab070020..ff48f95f1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -130,6 +130,8 @@
         apache
         https://sonarcloud.io
         apps/**
+
+        -Duser.language=en -Duser.country=US -Duser.region=US
     
 
     
@@ -199,6 +201,7 @@
                                     --add-opens java.base/java.lang=ALL-UNNAMED
                                     --add-opens java.base/java.util=ALL-UNNAMED
                                     -Dillegal-access=permit
+                                    @{argLine}
                                 
                             
                         
@@ -264,7 +267,7 @@
                         
                     
                     
-                        -Duser.language=en -Duser.region=US
+                        @{argLine}
                         
                             **/*Test.java
                         

From 6887ef900b585e74f4611345bc1c648c3ef64ace Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Wed, 28 Sep 2022 10:58:26 +0200
Subject: [PATCH 047/143] WW-5235 Uses debug log level when setting expression
 max length to avoid cluttering logs

---
 core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
index 49be23790..c5430491b 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
@@ -268,10 +268,10 @@ public class OgnlUtil {
         try {
             if (maxLength == null || maxLength.isEmpty()) {
                 Ognl.applyExpressionMaxLength(null);
-                LOG.info("OGNL Expression Max Length disabled.");
+                LOG.warn("OGNL Expression Max Length disabled.");
             } else {
                 Ognl.applyExpressionMaxLength(Integer.parseInt(maxLength));
-                LOG.info("OGNL Expression Max Length enabled with {}.", maxLength);
+                LOG.debug("OGNL Expression Max Length enabled with {}.", maxLength);
             }
         } catch (Exception ex) {
             LOG.error("Unable to set OGNL Expression Max Length {}.", maxLength);  // Help configuration debugging.

From ddbd02e6bb4c00b647e1a8f89610d5ff3165aeb6 Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Wed, 28 Sep 2022 11:09:16 +0200
Subject: [PATCH 048/143] WW-5184 Uses debug log level when parameter value was
 not accepted

---
 .../interceptor/ParametersInterceptor.java    | 31 +++++++++++--------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
index f81ba15fd..ff962c895 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
@@ -272,7 +272,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
         ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware) ? (ParameterNameAware) action : null;
         return acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name));
     }
-    
+
     /**
      * Checks if parameter value can be accepted or thrown away
      *
@@ -316,13 +316,13 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
 
         return logEntry.toString();
     }
-    
+
     /**
      * Validates the name passed is:
      * * Within the max length of a parameter name
      * * Is not excluded
      * * Is accepted
-     * 
+     *
      * @param name - Name to check
      * @return true if accepted
      */
@@ -351,19 +351,24 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
      * * Value is null/blank
      * * Value is not excluded
      * * Value is accepted
-     * 
+     *
      * @param name - Param name (for logging)
      * @param value - value to check
      * @return true if accepted
      */
     protected boolean acceptableValue(String name, String value) {
-    	boolean accepted = (value == null || value.isEmpty() || (!isParamValueExcluded(value) && isParamValueAccepted(value)));
+        boolean accepted = (value == null || value.isEmpty() || (!isParamValueExcluded(value) && isParamValueAccepted(value)));
         if (!accepted) {
-            LOG.warn("Parameter [{}] was not accepted with value [{}] and will be dropped!", name, value);
+            String message = "Value [{}] of parameter [{}] was not accepted and will be dropped!";
+            if (devMode) {
+                LOG.warn(message, value, name);
+            } else {
+                LOG.debug(message, value, name);
+            }
         }
         return accepted;
     }
-    
+
     protected boolean isWithinLengthLimit(String name) {
         boolean matchLength = name.length() <= paramNameMaxLength;
         if (!matchLength) {
@@ -407,7 +412,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
         }
         return false;
     }
-    
+
 
     public void setAcceptedValuePatterns(String commaDelimitedPatterns) {
     	Set patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
@@ -427,7 +432,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
         	acceptedValuePatterns = Collections.unmodifiableSet(acceptedValuePatterns);
         }
     }
-    
+
     public void setExcludeValuePatterns(String commaDelimitedPatterns) {
     	Set patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
         if (excludedValuePatterns == null) {
@@ -446,7 +451,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
         	excludedValuePatterns = Collections.unmodifiableSet(excludedValuePatterns);
         }
     }
-    
+
 	protected boolean isParamValueExcluded(String value) {
 		if (hasParamValuesToExclude()) {
 			for (Pattern excludedPattern : excludedValuePatterns) {
@@ -478,15 +483,15 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
 		LOG.warn("Parameter value [{}] did not match any acceptedValuePattern pattern and will be dropped.", value);
 		return false;
 	}
-    
+
     private boolean hasParamValuesToExclude() {
     	return excludedValuePatterns != null && excludedValuePatterns.size() > 0;
     }
-    
+
     private boolean hasParamValuesToAccept() {
     	return acceptedValuePatterns != null && acceptedValuePatterns.size() > 0;
     }
-    
+
     /**
      * Whether to order the parameters or not
      *

From 097297affdbfb788f21aff0dc97707f0576ec01d Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Wed, 28 Sep 2022 11:32:01 +0200
Subject: [PATCH 049/143] WW-5232 Stop generating Jacoco reports which are not
 used

---
 pom.xml | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/pom.xml b/pom.xml
index ff48f95f1..a7e7728b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -227,19 +227,9 @@
                                 prepare-agent
                                 
                                     prepare-agent
+                                    prepare-agent-integration
                                 
                             
-                            
-                                report
-                                
-                                    report
-                                
-                                
-                                    
-                                        XML
-                                    
-                                
-                            
                         
                     
                 

From cbfd3a7ab94b1fda96536a88eee56a1e9e63fc64 Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Wed, 28 Sep 2022 11:35:12 +0200
Subject: [PATCH 050/143] WW-5184 Improves logging around excluding/accepting
 values of incoming parameters

---
 .../interceptor/ParametersInterceptor.java    | 191 ++++++++++--------
 .../ParametersInterceptorTest.java            |  33 ++-
 2 files changed, 121 insertions(+), 103 deletions(-)

diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
index ff962c895..73f650442 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
@@ -26,6 +26,7 @@ import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
 import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
 import com.opensymphony.xwork2.util.ClearableValueStack;
 import com.opensymphony.xwork2.util.MemberAccessValueStack;
+import com.opensymphony.xwork2.util.TextParseUtil;
 import com.opensymphony.xwork2.util.ValueStack;
 import com.opensymphony.xwork2.util.ValueStackFactory;
 import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
@@ -33,8 +34,8 @@ import org.apache.commons.lang3.BooleanUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.struts2.StrutsConstants;
-import org.apache.struts2.dispatcher.Parameter;
 import org.apache.struts2.dispatcher.HttpParameters;
+import org.apache.struts2.dispatcher.Parameter;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -44,7 +45,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.regex.Pattern;
-import com.opensymphony.xwork2.util.TextParseUtil;
 
 /**
  * This interceptor sets all parameters on the value stack.
@@ -69,7 +69,6 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
     private Set excludedValuePatterns = null;
     private Set acceptedValuePatterns = null;
 
-
     @Inject
     public void setValueStackFactory(ValueStackFactory valueStackFactory) {
         this.valueStackFactory = valueStackFactory;
@@ -246,8 +245,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
         if (action instanceof TextProvider) {
             TextProvider tp = (TextProvider) action;
             developerNotification = tp.getText("devmode.notification",
-                    "Developer Notification:\n{0}",
-                    new String[]{developerNotification}
+                "Developer Notification:\n{0}",
+                new String[]{developerNotification}
             );
         }
 
@@ -281,13 +280,13 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
      * @return true if parameter is accepted
      */
     protected boolean isAcceptableParameterValue(Parameter param, Object action) {
-    	ParameterValueAware parameterValueAware = (action instanceof ParameterValueAware) ? (ParameterValueAware) action : null;
-    	boolean acceptableParmValue = (parameterValueAware == null || parameterValueAware.acceptableParameterValue(param.getValue()));
-    	if(hasParamValuesToExclude() || hasParamValuesToAccept()) {
-    		// Additional validations to process
-    		acceptableParmValue &= acceptableValue(param.getName(), param.getValue());
-    	}
-    	return acceptableParmValue;
+        ParameterValueAware parameterValueAware = (action instanceof ParameterValueAware) ? (ParameterValueAware) action : null;
+        boolean acceptableParamValue = (parameterValueAware == null || parameterValueAware.acceptableParameterValue(param.getValue()));
+        if (hasParamValuesToExclude() || hasParamValuesToAccept()) {
+            // Additional validations to process
+            acceptableParamValue &= acceptableValue(param.getName(), param.getValue());
+        }
+        return acceptableParamValue;
     }
 
     /**
@@ -352,7 +351,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
      * * Value is not excluded
      * * Value is accepted
      *
-     * @param name - Param name (for logging)
+     * @param name  - Param name (for logging)
      * @param value - value to check
      * @return true if accepted
      */
@@ -374,9 +373,9 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
         if (!matchLength) {
             if (devMode) { // warn only when in devMode
                 LOG.warn("Parameter [{}] is too long, allowed length is [{}]. Use Interceptor Parameter Overriding " +
-                                "to override the limit, see more at\n" +
-                                "https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding",
-                        name, paramNameMaxLength);
+                        "to override the limit, see more at\n" +
+                        "https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding",
+                    name, paramNameMaxLength);
             } else {
                 LOG.warn("Parameter [{}] is too long, allowed length is [{}]", name, paramNameMaxLength);
             }
@@ -390,8 +389,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
             return true;
         } else if (devMode) { // warn only when in devMode
             LOG.warn("Parameter [{}] didn't match accepted pattern [{}]! See Accepted / Excluded patterns at\n" +
-                            "https://struts.apache.org/security/#accepted--excluded-patterns",
-                    paramName, result.getAcceptedPattern());
+                    "https://struts.apache.org/security/#accepted--excluded-patterns",
+                paramName, result.getAcceptedPattern());
         } else {
             LOG.debug("Parameter [{}] didn't match accepted pattern [{}]!", paramName, result.getAcceptedPattern());
         }
@@ -403,8 +402,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
         if (result.isExcluded()) {
             if (devMode) { // warn only when in devMode
                 LOG.warn("Parameter [{}] matches excluded pattern [{}]! See Accepted / Excluded patterns at\n" +
-                                "https://struts.apache.org/security/#accepted--excluded-patterns",
-                        paramName, result.getExcludedPattern());
+                        "https://struts.apache.org/security/#accepted--excluded-patterns",
+                    paramName, result.getExcludedPattern());
             } else {
                 LOG.debug("Parameter [{}] matches excluded pattern [{}]!", paramName, result.getExcludedPattern());
             }
@@ -413,83 +412,55 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
         return false;
     }
 
-
-    public void setAcceptedValuePatterns(String commaDelimitedPatterns) {
-    	Set patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
-        if (acceptedValuePatterns == null) {
-            // Limit unwanted log entries (for 1st call, acceptedValuePatterns null)
-            LOG.debug("Sets accepted value patterns to [{}], note this may impact the safety of your application!", patterns);
-        } else {
-            LOG.warn("Replacing accepted patterns [{}] with [{}], be aware that this affects all instances and may impact the safety of your application!",
-            		acceptedValuePatterns, patterns);
-        }
-        acceptedValuePatterns = new HashSet<>(patterns.size());
-        try {
-            for (String pattern : patterns) {
-            	acceptedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
+    protected boolean isParamValueExcluded(String value) {
+        if (hasParamValuesToExclude()) {
+            for (Pattern excludedPattern : excludedValuePatterns) {
+                if (value != null) {
+                    if (excludedPattern.matcher(value).matches()) {
+                        if (devMode) {
+                            LOG.warn("Parameter value [{}] matches excluded pattern [{}]! See Accepting/Excluding parameter values at\n" +
+                                    "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",
+                                value, excludedValuePatterns);
+                        } else {
+                            LOG.debug("Parameter value [{}] matches excluded pattern [{}]", value, excludedPattern);
+                        }
+                        return true;
+                    }
+                }
             }
-        } finally {
-        	acceptedValuePatterns = Collections.unmodifiableSet(acceptedValuePatterns);
         }
+        return false;
     }
 
-    public void setExcludeValuePatterns(String commaDelimitedPatterns) {
-    	Set patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
-        if (excludedValuePatterns == null) {
-            // Limit unwanted log entries (for 1st call, excludedValuePatterns null)
-            LOG.debug("Setting excluded value patterns to [{}]", patterns);
-        } else {
-            LOG.warn("Replacing accepted patterns [{}] with [{}], be aware that this affects all instances and may impact safety of your application!",
-            		excludedValuePatterns, patterns);
-        }
-        excludedValuePatterns = new HashSet<>(patterns.size());
-        try {
-            for (String pattern : patterns) {
-            	excludedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
+    protected boolean isParamValueAccepted(String value) {
+        if (hasParamValuesToAccept()) {
+            for (Pattern excludedPattern : acceptedValuePatterns) {
+                if (value != null) {
+                    if (excludedPattern.matcher(value).matches()) {
+                        return true;
+                    }
+                }
             }
-        } finally {
-        	excludedValuePatterns = Collections.unmodifiableSet(excludedValuePatterns);
+        } else {
+            // acceptedValuePatterns not defined so anything is allowed
+            return true;
         }
+        if (devMode) {
+            LOG.warn("Parameter value [{}] didn't match accepted pattern [{}]! See Accepting/Excluding parameter values at\n" +
+                    "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",
+                value, acceptedValuePatterns);
+        } else {
+            LOG.debug("Parameter value [{}] was not accepted!", value);
+        }
+        return false;
     }
 
-	protected boolean isParamValueExcluded(String value) {
-		if (hasParamValuesToExclude()) {
-			for (Pattern excludedPattern : excludedValuePatterns) {
-				if (value != null) {
-					if (excludedPattern.matcher(value).matches()) {
-						LOG.warn("Parameter value [{}] matches excluded pattern [{}] and will be dropped.", value,
-								excludedPattern);
-						return true;
-					}
-				}
-			}
-		}
-		return false;
-	}
-
-	protected boolean isParamValueAccepted(String value) {
-		if (hasParamValuesToAccept()) {
-			for (Pattern excludedPattern : acceptedValuePatterns) {
-				if (value != null) {
-					if (excludedPattern.matcher(value).matches()) {
-						return true;
-					}
-				}
-			}
-		} else {
-			// acceptedValuePatterns not defined so anything is allowed
-			return true;
-		}
-		LOG.warn("Parameter value [{}] did not match any acceptedValuePattern pattern and will be dropped.", value);
-		return false;
-	}
-
     private boolean hasParamValuesToExclude() {
-    	return excludedValuePatterns != null && excludedValuePatterns.size() > 0;
+        return excludedValuePatterns != null && excludedValuePatterns.size() > 0;
     }
 
     private boolean hasParamValuesToAccept() {
-    	return acceptedValuePatterns != null && acceptedValuePatterns.size() > 0;
+        return acceptedValuePatterns != null && acceptedValuePatterns.size() > 0;
     }
 
     /**
@@ -533,4 +504,54 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
     public void setExcludeParams(String commaDelim) {
         excludedPatterns.setExcludedPatterns(commaDelim);
     }
+
+    /**
+     * Sets a comma-delimited list of regular expressions to match
+     * values of parameters that should be accepted and included in the parameter map.
+     *
+     * @param commaDelimitedPatterns A comma-delimited set of regular expressions
+     */
+    public void setAcceptedValuePatterns(String commaDelimitedPatterns) {
+        Set patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
+        if (acceptedValuePatterns == null) {
+            // Limit unwanted log entries (for 1st call, acceptedValuePatterns null)
+            LOG.debug("Sets accepted value patterns to [{}], note this may impact the safety of your application!", patterns);
+        } else {
+            LOG.warn("Replacing accepted patterns [{}] with [{}], be aware that this may impact safety of your application!",
+                acceptedValuePatterns, patterns);
+        }
+        acceptedValuePatterns = new HashSet<>(patterns.size());
+        try {
+            for (String pattern : patterns) {
+                acceptedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
+            }
+        } finally {
+            acceptedValuePatterns = Collections.unmodifiableSet(acceptedValuePatterns);
+        }
+    }
+
+    /**
+     * Sets a comma-delimited list of regular expressions to match
+     * values of parameters that should be removed from the parameter map.
+     *
+     * @param commaDelimitedPatterns A comma-delimited set of regular expressions
+     */
+    public void setExcludedValuePatterns(String commaDelimitedPatterns) {
+        Set patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
+        if (excludedValuePatterns == null) {
+            // Limit unwanted log entries (for 1st call, excludedValuePatterns null)
+            LOG.debug("Setting excluded value patterns to [{}]", patterns);
+        } else {
+            LOG.warn("Replacing excluded value patterns [{}] with [{}], be aware that this may impact safety of your application!",
+                excludedValuePatterns, patterns);
+        }
+        excludedValuePatterns = new HashSet<>(patterns.size());
+        try {
+            for (String pattern : patterns) {
+                excludedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
+            }
+        } finally {
+            excludedValuePatterns = Collections.unmodifiableSet(excludedValuePatterns);
+        }
+    }
 }
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java
index ce8fe8498..245e868ad 100644
--- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java
@@ -34,7 +34,6 @@ import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
 import com.opensymphony.xwork2.mock.MockActionInvocation;
 import com.opensymphony.xwork2.ognl.OgnlValueStack;
 import com.opensymphony.xwork2.ognl.OgnlValueStackFactory;
-import com.opensymphony.xwork2.ognl.SecurityMemberAccess;
 import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
 import com.opensymphony.xwork2.util.CompoundRoot;
 import com.opensymphony.xwork2.util.ValueStack;
@@ -45,11 +44,9 @@ import ognl.PropertyAccessor;
 import org.apache.struts2.config.StrutsXmlConfigurationProvider;
 import org.apache.struts2.dispatcher.HttpParameters;
 import org.junit.Assert;
-import org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean;
 
 import java.io.File;
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -781,10 +778,10 @@ public class ParametersInterceptorTest extends XWorkTestCase {
     public void testExcludedParametersValuesAreIgnored() throws Exception {
         ParametersInterceptor pi = createParametersInterceptor();
         // Contains (based on pattern)
-        pi.setExcludeValuePatterns(".*\\$\\{.*?\\}.*,.*%\\{.*?\\}.*");
-        
+        pi.setExcludedValuePatterns(".*\\$\\{.*?\\}.*,.*%\\{.*?\\}.*");
+
         assertTrue("${2*2} was excluded by isParamValueExcluded", pi.isParamValueExcluded("${2*2}"));
-        
+
         final Map actual = injectValueStackFactory(pi);
         ValueStack stack = injectValueStack(actual);
 
@@ -812,14 +809,14 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
         assertEquals(expected, actual);
     }
-    
+
     public void testAcceptedParametersValuesAreIgnored() throws Exception {
         ParametersInterceptor pi = createParametersInterceptor();
         // Starts with (based on pattern)
         pi.setAcceptedValuePatterns("^\\$\\{foo\\}.*,^%\\{bar\\}.*,^fooValue");
 
         assertTrue("${foo} was allowed by isParamValueAccepted", pi.isParamValueAccepted("${foo}"));
-        
+
         final Map actual = injectValueStackFactory(pi);
         ValueStack stack = injectValueStack(actual);
 
@@ -849,16 +846,16 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
         assertEquals(expected, actual);
     }
-    
+
     public void testAcceptedAndExcludedParametersValuesAreIgnored() throws Exception {
         ParametersInterceptor pi = createParametersInterceptor();
         // Starts with (based on pattern)
         pi.setAcceptedValuePatterns("^\\$\\{foo\\}.*,^%\\{bar\\}.*,^fooValue");
-        pi.setExcludeValuePatterns(".*\\$\\{2.*2\\}.*,.*\\%\\{2.*2\\}.*");
-        
+        pi.setExcludedValuePatterns(".*\\$\\{2.*2\\}.*,.*\\%\\{2.*2\\}.*");
+
         assertTrue("${foo} was allowed by isParamValueAccepted", pi.isParamValueAccepted("${foo}"));
         assertTrue("${2*2} was excluded by isParamValueExcluded", pi.isParamValueExcluded("${2*2}"));
-        
+
         final Map actual = injectValueStackFactory(pi);
         ValueStack stack = injectValueStack(actual);
 
@@ -878,7 +875,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
                 put("barKey%", "%{2+2}");
                 put("barKey2%", "foo%{2+2}");
                 put("barKey3", "nothing");
-                
+
                 put("allowedKey", "${foo}");
                 put("allowedKey2", "%{bar}");
                 put("fooKey", "fooValue");
@@ -888,14 +885,14 @@ public class ParametersInterceptorTest extends XWorkTestCase {
         pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
         assertEquals(expected, actual);
     }
-    
+
     public void testExcludedParametersValuesAreIgnoredWithParameterValueAware() throws Exception {
         ParametersInterceptor pi = createParametersInterceptor();
         // Contains (based on pattern)
-        pi.setExcludeValuePatterns(".*\\$\\{.*?\\}.*,.*%\\{.*?\\}.*");
-        
+        pi.setExcludedValuePatterns(".*\\$\\{.*?\\}.*,.*%\\{.*?\\}.*");
+
         assertTrue("${2*2} was excluded by isParamValueExcluded", pi.isParamValueExcluded("${2*2}"));
-                
+
         final Map actual = injectValueStackFactory(pi);
         ValueStack stack = injectValueStack(actual);
 
@@ -905,7 +902,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
                 put("fooKey", "fooValue");
             }
         };
-        
+
         Object a = new ParameterValueAware() {
 			@Override
 			public boolean acceptableParameterValue(String parameterValue) {

From 2217e2c1ca96760cba59950efe06194f05a10604 Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Fri, 30 Sep 2022 08:19:09 +0200
Subject: [PATCH 051/143] Disables Code quality step in Jenkins pipeline to
 avoid overriding GH Actions results

---
 Jenkinsfile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Jenkinsfile b/Jenkinsfile
index 233ade32d..762d88240 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -88,6 +88,7 @@ pipeline {
             }
           }
         }
+/*
         stage('Code Quality') {
           when {
             branch 'master'
@@ -98,6 +99,7 @@ pipeline {
             }
           }
         }
+*/
       }
       post {
         always {

From 5338b44c233dbc7a26a5b0c6b0993d770fa5340e Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Fri, 30 Sep 2022 08:25:44 +0200
Subject: [PATCH 052/143] WW-5184 Reduces code complexity when handling
 excluded/accepted values patterns

---
 .../interceptor/ParametersInterceptor.java    | 43 +++++++++----------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
index 73f650442..3fa04220a 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java
@@ -413,38 +413,35 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
     }
 
     protected boolean isParamValueExcluded(String value) {
-        if (hasParamValuesToExclude()) {
-            for (Pattern excludedPattern : excludedValuePatterns) {
-                if (value != null) {
-                    if (excludedPattern.matcher(value).matches()) {
-                        if (devMode) {
-                            LOG.warn("Parameter value [{}] matches excluded pattern [{}]! See Accepting/Excluding parameter values at\n" +
-                                    "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",
-                                value, excludedValuePatterns);
-                        } else {
-                            LOG.debug("Parameter value [{}] matches excluded pattern [{}]", value, excludedPattern);
-                        }
-                        return true;
-                    }
+        if (!hasParamValuesToExclude()) {
+            LOG.debug("'excludedValuePatterns' not defined so anything is allowed");
+            return false;
+        }
+        for (Pattern excludedValuePattern : excludedValuePatterns) {
+            if (excludedValuePattern.matcher(value).matches()) {
+                if (devMode) {
+                    LOG.warn("Parameter value [{}] matches excluded pattern [{}]! See Accepting/Excluding parameter values at\n" +
+                            "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",
+                        value, excludedValuePatterns);
+                } else {
+                    LOG.debug("Parameter value [{}] matches excluded pattern [{}]", value, excludedValuePattern);
                 }
+                return true;
             }
         }
         return false;
     }
 
     protected boolean isParamValueAccepted(String value) {
-        if (hasParamValuesToAccept()) {
-            for (Pattern excludedPattern : acceptedValuePatterns) {
-                if (value != null) {
-                    if (excludedPattern.matcher(value).matches()) {
-                        return true;
-                    }
-                }
-            }
-        } else {
-            // acceptedValuePatterns not defined so anything is allowed
+        if (!hasParamValuesToAccept()) {
+            LOG.debug("'acceptedValuePatterns' not defined so anything is allowed");
             return true;
         }
+        for (Pattern acceptedValuePattern : acceptedValuePatterns) {
+            if (acceptedValuePattern.matcher(value).matches()) {
+                return true;
+            }
+        }
         if (devMode) {
             LOG.warn("Parameter value [{}] didn't match accepted pattern [{}]! See Accepting/Excluding parameter values at\n" +
                     "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",

From 04cf1dae5fc0e6b5bb9f5b1ad1fc70c72ece1a60 Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Fri, 30 Sep 2022 09:50:51 +0200
Subject: [PATCH 053/143] Puts back JaCoCo report generation

---
 pom.xml | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/pom.xml b/pom.xml
index a7e7728b1..174ce6802 100644
--- a/pom.xml
+++ b/pom.xml
@@ -230,6 +230,18 @@
                                     prepare-agent-integration
                                 
                             
+                            
+                                report
+                                
+                                    report
+                                    report-integration
+                                
+                                
+                                    
+                                        XML
+                                    
+                                
+                            
                         
                     
                 

From e0da03c2627530c0e77eca94ee5351c733be795c Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Fri, 30 Sep 2022 10:38:15 +0200
Subject: [PATCH 054/143] Sets proper Sonar options in Jenkins pipeline and
 removes duplicated sonar properties

---
 Jenkinsfile | 6 ++----
 pom.xml     | 4 +---
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 762d88240..2adf56ac9 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -79,7 +79,7 @@ pipeline {
         }
         stage('Test') {
           steps {
-            sh './mvnw -B test'
+            sh './mvnw -B verify -Pcoverage -DskipAssembly'
           }
           post {
             always {
@@ -88,18 +88,16 @@ pipeline {
             }
           }
         }
-/*
         stage('Code Quality') {
           when {
             branch 'master'
           }
           steps {
             withCredentials([string(credentialsId: 'asf-struts-sonarcloud', variable: 'SONARCLOUD_TOKEN')]) {
-              sh './mvnw sonar:sonar -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN}'
+              sh './mvnw -B -Pcoverage -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN} sonar:sonar'
             }
           }
         }
-*/
       }
       post {
         always {
diff --git a/pom.xml b/pom.xml
index ff48f95f1..b80a4b2f6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,9 +125,9 @@
         1.9
 
         
+        apache
         apache_struts
         ${project.artifactId}
-        apache
         https://sonarcloud.io
         apps/**
 
@@ -213,8 +213,6 @@
             coverage
             
                 https://sonarcloud.io
-                apache
-                apache_struts
             
             
                 

From 8f0db1d22a5cbfaf43d19628ea548387088f781a Mon Sep 17 00:00:00 2001
From: Lukasz Lenart 
Date: Tue, 4 Oct 2022 10:12:52 +0200
Subject: [PATCH 055/143] WW-3691 Converts BackgroundProcess into interface and
 uses Executor to execute BackgroundProcess

---
 .../wait/ThreadPoolExecutorProvider.java      |  56 ++++++
 .../src/main/resources/struts-wait.xml        |   3 +
 .../ExecuteAndWaitInterceptor.java            |  66 +++++--
 .../interceptor/exec/BackgroundProcess.java   |  41 ++++
 .../interceptor/exec/ExecutorProvider.java    |  38 ++++
 .../StrutsBackgroundProcess.java}             |  80 +++++---
 .../exec/StrutsExecutorProvider.java          |  53 ++++++
 .../interceptor/BackgroundProcessTest.java    | 104 ----------
 .../ExecuteAndWaitInterceptorTest.java        |  46 ++++-
 .../exec/StrutsBackgroundProcessTest.java     | 179 ++++++++++++++++++
 10 files changed, 513 insertions(+), 153 deletions(-)
 create mode 100644 apps/showcase/src/main/java/org/apache/struts2/showcase/wait/ThreadPoolExecutorProvider.java
 create mode 100644 core/src/main/java/org/apache/struts2/interceptor/exec/BackgroundProcess.java
 create mode 100644 core/src/main/java/org/apache/struts2/interceptor/exec/ExecutorProvider.java
 rename core/src/main/java/org/apache/struts2/interceptor/{BackgroundProcess.java => exec/StrutsBackgroundProcess.java} (63%)
 create mode 100644 core/src/main/java/org/apache/struts2/interceptor/exec/StrutsExecutorProvider.java
 delete mode 100644 core/src/test/java/org/apache/struts2/interceptor/BackgroundProcessTest.java
 create mode 100644 core/src/test/java/org/apache/struts2/interceptor/exec/StrutsBackgroundProcessTest.java

diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/ThreadPoolExecutorProvider.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/ThreadPoolExecutorProvider.java
new file mode 100644
index 000000000..ffffc7a1d
--- /dev/null
+++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/ThreadPoolExecutorProvider.java
@@ -0,0 +1,56 @@
+/*
+ * 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.showcase.wait;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.interceptor.exec.ExecutorProvider;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class ThreadPoolExecutorProvider implements ExecutorProvider {
+
+    private static final Logger LOG = LogManager.getLogger(ThreadPoolExecutorProvider.class);
+
+    private final ExecutorService executor;
+
+    public ThreadPoolExecutorProvider() {
+        this.executor = new ThreadPoolExecutor(1, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>());
+    }
+
+    @Override
+    public void execute(Runnable task) {
+        LOG.info("Executing task: {}", task);
+        executor.execute(task);
+    }
+
+    @Override
+    public boolean isShutdown() {
+        return executor.isShutdown();
+    }
+
+    @Override
+    public void shutdown() {
+        LOG.info("Shutting down executor");
+        executor.shutdown();
+    }
+}
diff --git a/apps/showcase/src/main/resources/struts-wait.xml b/apps/showcase/src/main/resources/struts-wait.xml
index 8ede40d74..7b6a204a6 100644
--- a/apps/showcase/src/main/resources/struts-wait.xml
+++ b/apps/showcase/src/main/resources/struts-wait.xml
@@ -24,6 +24,9 @@
 	"https://struts.apache.org/dtds/struts-2.5.dtd">
 
 
+
+    
+
     
 
         
diff --git a/core/src/main/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptor.java
index b49ebcae7..4a5cb91b4 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptor.java
@@ -22,12 +22,17 @@ import com.opensymphony.xwork2.Action;
 import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
 import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.interceptor.exec.BackgroundProcess;
+import org.apache.struts2.interceptor.exec.ExecutorProvider;
+import org.apache.struts2.interceptor.exec.StrutsBackgroundProcess;
+import org.apache.struts2.interceptor.exec.StrutsExecutorProvider;
 import org.apache.struts2.util.TokenHelper;
 import org.apache.struts2.views.freemarker.FreemarkerResult;
 
@@ -84,7 +89,7 @@ import java.util.Map;
  * 
  *
  * 

Interceptor parameters:

- * + *

* * *

    @@ -94,11 +99,11 @@ import java.util.Map; *
  • delaySleepInterval (optional) - only used with delay. Used for waking up at certain intervals to check if the background process is already done. Default is 100 millis.
  • * *
- * + *

* * *

Extending the interceptor:

- * + *

* *

* If you wish to make special preparations before and/or after the invocation of the background thread, you can extend @@ -167,9 +172,8 @@ import java.util.Map; * <result name="success">longRunningAction-success.jsp</result> * </action> *

- * + *

* - * */ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor { @@ -186,22 +190,28 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor { private int threadPriority = Thread.NORM_PRIORITY; private Container container; + private ExecutorProvider executor; @Inject public void setContainer(Container container) { this.container = container; } + @Inject(required = false) + public void setExecutorProvider(ExecutorProvider executorProvider) { + this.executor = executorProvider; + } + /** * Creates a new background process * - * @param name The process name + * @param name The process name * @param actionInvocation The action invocation - * @param threadPriority The thread priority + * @param threadPriority The thread priority * @return The new process */ protected BackgroundProcess getNewBackgroundProcess(String name, ActionInvocation actionInvocation, int threadPriority) { - return new BackgroundProcess(name + "BackgroundThread", actionInvocation, threadPriority); + return new StrutsBackgroundProcess(actionInvocation, name + "_background-process", threadPriority); } /** @@ -209,7 +219,6 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor { * are mapped to requests. * * @param proxy action proxy - * * @return the name of the background thread */ protected String getBackgroundProcessName(ActionProxy proxy) { @@ -223,10 +232,10 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor { ActionProxy proxy = actionInvocation.getProxy(); String name = getBackgroundProcessName(proxy); ActionContext context = actionInvocation.getInvocationContext(); - Map session = context.getSession(); + Map session = context.getSession(); HttpSession httpSession = ServletActionContext.getRequest().getSession(true); - Boolean secondTime = true; + Boolean secondTime = true; if (executeAfterValidationPass) { secondTime = (Boolean) context.get(KEY); if (secondTime == null) { @@ -250,8 +259,13 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor { } if ((!executeAfterValidationPass || secondTime) && bp == null) { - bp = getNewBackgroundProcess(name, actionInvocation, threadPriority); + bp = getNewBackgroundProcess(name, actionInvocation, threadPriority).prepare(); session.put(KEY + name, bp); + if (executor.isShutdown()) { + LOG.warn("Executor is shutting down, cannot execute a new process"); + return actionInvocation.invoke(); + } + executor.execute(bp); performInitialDelay(bp); // first time let some time pass before showing wait page secondTime = false; } @@ -259,16 +273,16 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor { if ((!executeAfterValidationPass || !secondTime) && bp != null && !bp.isDone()) { actionInvocation.getStack().push(bp.getAction()); - final String token = TokenHelper.getToken(); - if (token != null) { - TokenHelper.setSessionToken(TokenHelper.getTokenName(), token); + final String token = TokenHelper.getToken(); + if (token != null) { + TokenHelper.setSessionToken(TokenHelper.getTokenName(), token); } - Map results = proxy.getConfig().getResults(); + Map results = proxy.getConfig().getResults(); if (!results.containsKey(WAIT)) { - LOG.warn("ExecuteAndWait interceptor has detected that no result named 'wait' is available. " + - "Defaulting to a plain built-in wait page. It is highly recommend you " + - "provide an action-specific or global result named '{}'.", WAIT); + LOG.warn("ExecuteAndWait interceptor has detected that no result named 'wait' is available. " + + "Defaulting to a plain built-in wait page. It is highly recommend you " + + "provide an action-specific or global result named '{}'.", WAIT); // no wait result? hmm -- let's try to do dynamically put it in for you! //we used to add a fake "wait" result here, since the configuration is unmodifiable, that is no longer @@ -286,7 +300,7 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor { session.remove(KEY + name); actionInvocation.getStack().push(bp.getAction()); - // if an exception occured during action execution, throw it here + // if an exception occurred during action execution, throw it here if (bp.getException() != null) { throw bp.getException(); } @@ -369,5 +383,17 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor { this.executeAfterValidationPass = executeAfterValidationPass; } + @Override + public void init() { + super.init(); + if (executor == null) { + executor = new StrutsExecutorProvider(); + } + } + @Override + public void destroy() { + super.destroy(); + executor.shutdown(); + } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/exec/BackgroundProcess.java b/core/src/main/java/org/apache/struts2/interceptor/exec/BackgroundProcess.java new file mode 100644 index 000000000..732c3d0af --- /dev/null +++ b/core/src/main/java/org/apache/struts2/interceptor/exec/BackgroundProcess.java @@ -0,0 +1,41 @@ +/* + * 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.interceptor.exec; + +import com.opensymphony.xwork2.ActionInvocation; +import org.apache.struts2.interceptor.ExecuteAndWaitInterceptor; + +/** + * Interface used to create a background process which will be executed by + * {@link ExecuteAndWaitInterceptor} + */ +public interface BackgroundProcess extends Runnable { + + BackgroundProcess prepare(); + + Object getAction(); + + ActionInvocation getInvocation(); + + String getResult(); + + Exception getException(); + + boolean isDone(); +} diff --git a/core/src/main/java/org/apache/struts2/interceptor/exec/ExecutorProvider.java b/core/src/main/java/org/apache/struts2/interceptor/exec/ExecutorProvider.java new file mode 100644 index 000000000..a6b06bde9 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/interceptor/exec/ExecutorProvider.java @@ -0,0 +1,38 @@ +/* + * 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.interceptor.exec; + +import java.util.concurrent.ExecutorService; + +/** + * Interface mimics {@link ExecutorService} to be used with + * {@link org.apache.struts2.interceptor.ExecuteAndWaitInterceptor} + * to execute {@link BackgroundProcess} + * + * @since 6.1.0 + */ +public interface ExecutorProvider { + + void execute(Runnable task); + + boolean isShutdown(); + + void shutdown(); + +} diff --git a/core/src/main/java/org/apache/struts2/interceptor/BackgroundProcess.java b/core/src/main/java/org/apache/struts2/interceptor/exec/StrutsBackgroundProcess.java similarity index 63% rename from core/src/main/java/org/apache/struts2/interceptor/BackgroundProcess.java rename to core/src/main/java/org/apache/struts2/interceptor/exec/StrutsBackgroundProcess.java index eed1811e0..8f563912b 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/BackgroundProcess.java +++ b/core/src/main/java/org/apache/struts2/interceptor/exec/StrutsBackgroundProcess.java @@ -16,24 +16,27 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2.interceptor; - -import java.io.Serializable; +package org.apache.struts2.interceptor.exec; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; +import java.io.Serializable; + /** * Background thread to be executed by the ExecuteAndWaitInterceptor. - * */ -public class BackgroundProcess implements Serializable { +public class StrutsBackgroundProcess implements BackgroundProcess, Serializable { private static final long serialVersionUID = 3884464776311686443L; + private final String threadName; + private final int threadPriority; + + private transient Thread processThread; //WW-4900 transient since 2.5.15 - transient protected ActionInvocation invocation; - transient protected Exception exception; + protected transient ActionInvocation invocation; + protected transient Exception exception; protected String result; protected boolean done; @@ -41,32 +44,47 @@ public class BackgroundProcess implements Serializable { /** * Constructs a background process * - * @param threadName The thread name * @param invocation The action invocation - * @param threadPriority The thread priority + * @param threadName The name of background thread + * @param threadPriority The priority of background thread */ - public BackgroundProcess(String threadName, final ActionInvocation invocation, int threadPriority) { + public StrutsBackgroundProcess(ActionInvocation invocation, String threadName, int threadPriority) { this.invocation = invocation; - try { - final Thread t = new Thread(new Runnable() { - public void run() { - try { - beforeInvocation(); - result = invocation.invokeActionOnly(); - afterInvocation(); - } catch (Exception e) { - exception = e; - } + this.threadName = threadName; + this.threadPriority = threadPriority; + } - done = true; + @Override + public BackgroundProcess prepare() { + try { + processThread = new Thread(() -> { + try { + beforeInvocation(); + result = invocation.invokeActionOnly(); + afterInvocation(); + } catch (Exception e) { + exception = e; } + + done = true; }); - t.setName(threadName); - t.setPriority(threadPriority); - t.start(); + processThread.setName(threadName); + processThread.setPriority(threadPriority); } catch (Exception e) { + done = true; exception = e; } + return this; + } + + @Override + public void run() { + if (processThread == null) { + done = true; + exception = new IllegalStateException("Background thread " + threadName + " has not been prepared!"); + return; + } + processThread.start(); } /** @@ -93,8 +111,9 @@ public class BackgroundProcess implements Serializable { /** * Retrieves the action. * - * @return the action. + * @return the action. */ + @Override public Object getAction() { return invocation.getAction(); } @@ -104,6 +123,7 @@ public class BackgroundProcess implements Serializable { * * @return the action invocation */ + @Override public ActionInvocation getInvocation() { return invocation; } @@ -111,8 +131,9 @@ public class BackgroundProcess implements Serializable { /** * Gets the result of the background process. * - * @return the result; null if not done. + * @return the result; null if not done. */ + @Override public String getResult() { return result; } @@ -122,6 +143,7 @@ public class BackgroundProcess implements Serializable { * * @return the exception or null if no exception was thrown. */ + @Override public Exception getException() { return exception; } @@ -131,7 +153,13 @@ public class BackgroundProcess implements Serializable { * * @return true if finished, false otherwise */ + @Override public boolean isDone() { return done; } + + @Override + public String toString() { + return "StrutsBackgroundProcess { name = " + processThread.getName() + " }"; + } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/exec/StrutsExecutorProvider.java b/core/src/main/java/org/apache/struts2/interceptor/exec/StrutsExecutorProvider.java new file mode 100644 index 000000000..7370f318a --- /dev/null +++ b/core/src/main/java/org/apache/struts2/interceptor/exec/StrutsExecutorProvider.java @@ -0,0 +1,53 @@ +/* + * 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.interceptor.exec; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class StrutsExecutorProvider implements ExecutorProvider { + + private static final Logger LOG = LogManager.getLogger(StrutsExecutorProvider.class); + + private final ExecutorService executor; + + public StrutsExecutorProvider() { + this.executor = Executors.newSingleThreadExecutor(); + } + + @Override + public void execute(Runnable task) { + LOG.debug("Executing task: {}", task); + executor.execute(task); + } + + @Override + public boolean isShutdown() { + return executor.isShutdown(); + } + + @Override + public void shutdown() { + LOG.debug("Shutting down executor"); + executor.shutdown(); + } +} diff --git a/core/src/test/java/org/apache/struts2/interceptor/BackgroundProcessTest.java b/core/src/test/java/org/apache/struts2/interceptor/BackgroundProcessTest.java deleted file mode 100644 index b811b1dd5..000000000 --- a/core/src/test/java/org/apache/struts2/interceptor/BackgroundProcessTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.interceptor; - -import com.mockobjects.servlet.MockHttpServletRequest; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.mock.MockActionInvocation; -import org.apache.struts2.StrutsInternalTestCase; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.concurrent.Callable; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -/** - * Test case for BackgroundProcessTest. - */ -public class BackgroundProcessTest extends StrutsInternalTestCase { - - public void testSerializeDeserialize() throws Exception { - final NotSerializableException expectedException = new NotSerializableException(new MockHttpServletRequest()); - final Semaphore lock = new Semaphore(1); - lock.acquire(); - MockActionInvocationWithActionInvoker invocation = new MockActionInvocationWithActionInvoker(new Callable() { - @Override - public String call() throws Exception { - lock.release(); - throw expectedException; - } - }); - invocation.setInvocationContext(ActionContext.getContext()); - - BackgroundProcess bp = new BackgroundProcess("BackgroundProcessTest.testSerializeDeserialize", invocation - , Thread.MIN_PRIORITY); - if(!lock.tryAcquire(1500L, TimeUnit.MILLISECONDS)) { - lock.release(); - fail("background thread did not release lock on timeout"); - } - lock.release(); - - bp.result = "BackgroundProcessTest.testSerializeDeserialize"; - bp.done = true; - Thread.sleep(1000);//give a chance to background thread to set exception - assertEquals(expectedException, bp.exception); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(bp); - oos.close(); - byte b[] = baos.toByteArray(); - baos.close(); - - ByteArrayInputStream bais = new ByteArrayInputStream(b); - ObjectInputStream ois = new ObjectInputStream(bais); - BackgroundProcess deserializedBp = (BackgroundProcess) ois.readObject(); - ois.close(); - bais.close(); - - assertNull("invocation should not be serialized", deserializedBp.invocation); - assertNull("exception should not be serialized", deserializedBp.exception); - assertEquals(bp.result, deserializedBp.result); - assertEquals(bp.done, deserializedBp.done); - } - - - private class MockActionInvocationWithActionInvoker extends MockActionInvocation { - private Callable actionInvoker; - - MockActionInvocationWithActionInvoker(Callable actionInvoker){ - this.actionInvoker = actionInvoker; - } - - @Override - public String invokeActionOnly() throws Exception { - return actionInvoker.call(); - } - } - - private class NotSerializableException extends Exception { - private MockHttpServletRequest notSerializableField; - NotSerializableException(MockHttpServletRequest notSerializableField) { - this.notSerializableField = notSerializableField; - } - } -} \ No newline at end of file diff --git a/core/src/test/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptorTest.java index 08c034b9b..87595d9b5 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptorTest.java @@ -36,9 +36,9 @@ import com.opensymphony.xwork2.interceptor.ParametersInterceptor; import com.opensymphony.xwork2.mock.MockResult; import com.opensymphony.xwork2.ognl.OgnlUtil; import com.opensymphony.xwork2.util.location.LocatableProperties; -import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsInternalTestCase; import org.apache.struts2.dispatcher.HttpParameters; +import org.apache.struts2.interceptor.exec.ExecutorProvider; import org.apache.struts2.views.jsp.StrutsMockHttpServletRequest; import org.apache.struts2.views.jsp.StrutsMockHttpSession; @@ -49,6 +49,8 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * Test case for ExecuteAndWaitInterceptor. @@ -78,6 +80,20 @@ public class ExecuteAndWaitInterceptorTest extends StrutsInternalTestCase { assertEquals("success", result2); } + public void testExecutorProvider() throws Exception { + waitInterceptor.setExecutorProvider(new TestExecutorProvider()); + + ActionProxy proxy = buildProxy("action1"); + String result = proxy.execute(); + assertEquals("wait", result); + + Thread.sleep(1000); + + ActionProxy proxy2 = buildProxy("action1"); + String result2 = proxy2.execute(); + assertEquals("success", result2); + } + public void testTwoWait() throws Exception { waitInterceptor.setDelay(0); waitInterceptor.setDelaySleepInterval(0); @@ -226,7 +242,11 @@ public class ExecuteAndWaitInterceptorTest extends StrutsInternalTestCase { .withServletRequest(request) .getContextMap(); + container.inject(waitInterceptor); container.inject(parametersInterceptor); + + waitInterceptor.init(); + parametersInterceptor.init(); } protected void tearDown() throws Exception { @@ -250,8 +270,6 @@ public class ExecuteAndWaitInterceptorTest extends StrutsInternalTestCase { } public void loadPackages() throws ConfigurationException { - - // interceptors waitInterceptor = new ExecuteAndWaitInterceptor(); parametersInterceptor = new ParametersInterceptor(); @@ -273,5 +291,27 @@ public class ExecuteAndWaitInterceptorTest extends StrutsInternalTestCase { } } + } +class TestExecutorProvider implements ExecutorProvider { + + private final ExecutorService executor = Executors.newSingleThreadExecutor(); + + @Override + public void execute(Runnable task) { + executor.execute(task); + } + + @Override + public boolean isShutdown() { + return executor.isShutdown(); + } + + @Override + public void shutdown() { + executor.shutdown(); + } +} + + diff --git a/core/src/test/java/org/apache/struts2/interceptor/exec/StrutsBackgroundProcessTest.java b/core/src/test/java/org/apache/struts2/interceptor/exec/StrutsBackgroundProcessTest.java new file mode 100644 index 000000000..64ae48771 --- /dev/null +++ b/core/src/test/java/org/apache/struts2/interceptor/exec/StrutsBackgroundProcessTest.java @@ -0,0 +1,179 @@ +/* + * 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.interceptor.exec; + +import com.mockobjects.servlet.MockHttpServletRequest; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.mock.MockActionInvocation; +import org.apache.struts2.StrutsInternalTestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Test case for BackgroundProcessTest. + */ +public class StrutsBackgroundProcessTest extends StrutsInternalTestCase { + + private final ExecutorService executor = Executors.newSingleThreadExecutor(); + + public void testSerializeDeserialize() throws Exception { + final NotSerializableException expectedException = new NotSerializableException(new MockHttpServletRequest()); + final Semaphore lock = new Semaphore(1); + lock.acquire(); + MockActionInvocationWithActionInvoker invocation = new MockActionInvocationWithActionInvoker(() -> { + lock.release(); + throw expectedException; + }); + invocation.setInvocationContext(ActionContext.getContext()); + + StrutsBackgroundProcess bp = (StrutsBackgroundProcess) new StrutsBackgroundProcess( + invocation, + "BackgroundProcessTest.testSerializeDeserialize", + Thread.MIN_PRIORITY + ).prepare(); + executor.execute(bp); + + if (!lock.tryAcquire(1500L, TimeUnit.MILLISECONDS)) { + lock.release(); + fail("background thread did not release lock on timeout"); + } + lock.release(); + + bp.result = "BackgroundProcessTest.testSerializeDeserialize"; + bp.done = true; + Thread.sleep(1000);//give a chance to background thread to set exception + assertEquals(expectedException, bp.exception); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(bp); + oos.close(); + byte[] b = baos.toByteArray(); + baos.close(); + + ByteArrayInputStream bais = new ByteArrayInputStream(b); + ObjectInputStream ois = new ObjectInputStream(bais); + StrutsBackgroundProcess deserializedBp = (StrutsBackgroundProcess) ois.readObject(); + ois.close(); + bais.close(); + + assertNull("invocation should not be serialized", deserializedBp.invocation); + assertNull("exception should not be serialized", deserializedBp.exception); + assertEquals(bp.result, deserializedBp.result); + assertEquals(bp.done, deserializedBp.done); + } + + public void testMultipleProcesses() throws InterruptedException { + Random random = new SecureRandom(); + AtomicInteger mutableState = new AtomicInteger(0); + MockActionInvocationWithActionInvoker invocation = new MockActionInvocationWithActionInvoker(() -> { + Thread.sleep(Math.max(50, random.nextInt(150))); + mutableState.getAndIncrement(); + return "done"; + }); + + List bps = new ArrayList<>(); + for (int i = 0; i < 100; i++) { + String name = String.format("Order: %s", i); + BackgroundProcess bp = new LockBackgroundProcess(invocation, name).prepare(); + bps.add(bp); + executor.execute(bp); + } + + Thread.sleep(300); + + for (BackgroundProcess bp : bps) { + assertTrue("Process is still active: " + bp, bp.isDone()); + } + assertEquals(100, mutableState.get()); + } + + public void testUnpreparedProcess() throws ExecutionException, InterruptedException, TimeoutException { + // given + MockActionInvocationWithActionInvoker invocation = new MockActionInvocationWithActionInvoker(() -> "done"); + BackgroundProcess bp = new StrutsBackgroundProcess(invocation, "Unprepared", Thread.NORM_PRIORITY); + + // when + executor.submit(bp).get(1000, TimeUnit.MILLISECONDS); + + // then + assertTrue(bp.isDone()); + assertEquals("Background thread Unprepared has not been prepared!", bp.getException().getMessage()); + } + + private static class MockActionInvocationWithActionInvoker extends MockActionInvocation { + private final Callable actionInvoker; + + MockActionInvocationWithActionInvoker(Callable actionInvoker) { + this.actionInvoker = actionInvoker; + } + + @Override + public String invokeActionOnly() throws Exception { + return actionInvoker.call(); + } + } + + private static class NotSerializableException extends Exception { + private MockHttpServletRequest notSerializableField; + + NotSerializableException(MockHttpServletRequest notSerializableField) { + this.notSerializableField = notSerializableField; + } + } + +} + +class LockBackgroundProcess extends StrutsBackgroundProcess { + + private final Object lock = LockBackgroundProcess.class; + + public LockBackgroundProcess(ActionInvocation invocation, String name) { + super(invocation, name, Thread.NORM_PRIORITY); + } + + @Override + public void run() { + synchronized (lock) { + super.run(); + } + } + + @Override + protected void afterInvocation() throws Exception { + super.afterInvocation(); + lock.notify(); + } +} From a21bd994eb56bf734f25e4a4590833a3258aa1b8 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 6 Oct 2022 08:54:14 +0200 Subject: [PATCH 056/143] WW-5238 Uses proper order of mapping functions to support action: prefix --- .../xwork2/config/entities/PackageConfig.java | 14 +- .../mapper/DefaultActionMapper.java | 2 +- .../mapper/DefaultActionMapperTest.java | 123 ++++++++---------- 3 files changed, 54 insertions(+), 85 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java index 4d16ee81f..9174e651b 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java @@ -20,26 +20,18 @@ package com.opensymphony.xwork2.config.entities; import com.opensymphony.xwork2.util.location.Located; import com.opensymphony.xwork2.util.location.Location; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import java.io.Serializable; import java.util.*; - /** * Configuration for Package. * *

* In the xml configuration file this is defined as the package tag. *

- * - * @author Rainer Hermanns - * @version $Revision$ */ -public class PackageConfig extends Located implements Comparable, Serializable, InterceptorLocator { - - private static final Logger LOG = LogManager.getLogger(PackageConfig.class); +public class PackageConfig extends Located implements Comparable, Serializable, InterceptorLocator { protected Map actionConfigs; protected Map globalResultConfigs; @@ -422,8 +414,7 @@ public class PackageConfig extends Located implements Comparable, Serializable, return "PackageConfig: [" + name + "] for namespace [" + namespace + "] with parents [" + parents + "]"; } - public int compareTo(Object o) { - PackageConfig other = (PackageConfig) o; + public int compareTo(PackageConfig other) { String full = namespace + "!" + name; String otherFull = other.namespace + "!" + other.name; @@ -443,7 +434,6 @@ public class PackageConfig extends Located implements Comparable, Serializable, public static class Builder implements InterceptorLocator { protected PackageConfig target; - private boolean strictDMI = true; public Builder(String name) { target = new PackageConfig(name); diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java index 9c09e187e..98fec5316 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java @@ -289,8 +289,8 @@ public class DefaultActionMapper implements ActionMapper { } parseNameAndNamespace(uri, mapping, configManager); - extractMethodName(mapping, configManager); handleSpecialParameters(request, mapping); + extractMethodName(mapping, configManager); return parseActionName(mapping); } diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java index 479494b16..a9d01eec7 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java @@ -20,15 +20,15 @@ package org.apache.struts2.dispatcher.mapper; import com.mockobjects.servlet.MockHttpServletRequest; import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.Result; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.ConfigurationManager; +import com.opensymphony.xwork2.config.entities.ActionConfig; import com.opensymphony.xwork2.config.entities.PackageConfig; +import com.opensymphony.xwork2.config.entities.ResultConfig; import com.opensymphony.xwork2.config.impl.DefaultConfiguration; import com.opensymphony.xwork2.inject.Container; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsInternalTestCase; -import org.apache.struts2.result.StrutsResultSupport; import org.apache.struts2.views.jsp.StrutsMockHttpServletRequest; import java.util.Arrays; @@ -38,7 +38,6 @@ import java.util.Map; /** * DefaultActionMapper test case. - * */ public class DefaultActionMapperTest extends StrutsInternalTestCase { @@ -46,6 +45,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { private ConfigurationManager configManager; private Configuration config; + @SuppressWarnings("rawtypes") protected void setUp() throws Exception { super.setUp(); req = new MockHttpServletRequest(); @@ -79,6 +79,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertNull(mapping.getMethod()); } + @SuppressWarnings("rawtypes") public void testGetMappingWithMethod() { req.setupGetParameterMap(new HashMap()); req.setupGetRequestURI("/my/namespace/actionName!add.action"); @@ -157,7 +158,6 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { } - public void testGetMappingWithNamespaceSlash() { req.setupGetRequestURI("/my-hh/abc.action"); @@ -256,6 +256,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertNull(mapping); } + @SuppressWarnings("rawtypes") public void testGetUri() { req.setupGetParameterMap(new HashMap()); req.setupGetRequestURI("/my/namespace/actionName.action"); @@ -268,6 +269,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals("/my/namespace/actionName.action", mapper.getUriFromActionMapping(mapping)); } + @SuppressWarnings("rawtypes") public void testGetUriWithSemicolonPresent() { req.setupGetParameterMap(new HashMap()); req.setupGetRequestURI("/my/namespace/actionName.action;abc=123rty56"); @@ -280,6 +282,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals("/my/namespace/actionName.action", mapper.getUriFromActionMapping(mapping)); } + @SuppressWarnings("rawtypes") public void testGetUriWithMethod() { req.setupGetParameterMap(new HashMap()); req.setupGetRequestURI("/my/namespace/actionName!add.action"); @@ -294,7 +297,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { } public void testGetUriWithOriginalExtension() { - ActionMapping mapping = new ActionMapping("actionName", "/ns", null, new HashMap()); + ActionMapping mapping = new ActionMapping("actionName", "/ns", null, new HashMap<>()); ActionMapping orig = new ActionMapping(); orig.setExtension("foo"); @@ -304,6 +307,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals("/ns/actionName.foo", mapper.getUriFromActionMapping(mapping)); } + @SuppressWarnings("rawtypes") public void testGetMappingWithNoExtension() { req.setupGetParameterMap(new HashMap()); req.setupGetRequestURI("/my/namespace/actionName"); @@ -320,6 +324,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertNull(mapping.getMethod()); } + @SuppressWarnings("rawtypes") public void testGetMappingWithNoExtensionButUriHasExtension() { req.setupGetParameterMap(new HashMap()); req.setupGetRequestURI("/my/namespace/actionName.html"); @@ -524,88 +529,66 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals("myAction", actionMapping.getName()); } - public void testRedirectPrefix() { + public void testActionPrefix() { Map parameterMap = new HashMap<>(); - parameterMap.put("redirect:" + "http://www.google.com", ""); + parameterMap.put("action:" + "next", ""); StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); - request.setupGetServletPath("/someServletPath.action"); + request.setupGetServletPath("/index.action"); request.setParameterMap(parameterMap); DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); defaultActionMapper.setContainer(container); ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); - Result result = actionMapping.getResult(); - assertNull(result); + assertNotNull(actionMapping); + assertEquals("/", actionMapping.getNamespace()); + assertEquals("index", actionMapping.getName()); + assertNull(actionMapping.getMethod()); } - public void testUnsafeRedirectPrefix() { + public void testActionPrefixWhenAllowed() { + config = new DefaultConfiguration(); + PackageConfig pkg = new PackageConfig.Builder("test") + .namespace("/test") + .addActionConfig("execute", new ActionConfig.Builder("test", "index", "org.test.TestAction") + .methodName("execute") + .addAllowedMethod("execute") + .build()) + .addActionConfig("next", new ActionConfig.Builder("test", "next", "org.test.TestAction") + .methodName("next") + .addAllowedMethod("next") + .addResultConfig(new ResultConfig.Builder("next", "org.test.TestResult") + .build()) + .build()) + .build(); + + config.addPackageConfig("test", pkg); + + + configManager = new ConfigurationManager(Container.DEFAULT_NAME) { + public Configuration getConfiguration() { + return config; + } + }; + Map parameterMap = new HashMap<>(); - parameterMap.put("redirect:" + "http://%{3*4}", ""); + parameterMap.put("action:" + "next", ""); StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); - request.setupGetServletPath("/someServletPath.action"); + request.setupGetServletPath("/test/index.action"); request.setParameterMap(parameterMap); DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); defaultActionMapper.setContainer(container); + defaultActionMapper.setAllowActionPrefix("true"); + ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); - Result result = actionMapping.getResult(); - assertNull(result); - } - - public void testRedirectActionPrefix() { - Map parameterMap = new HashMap<>(); - parameterMap.put("redirectAction:" + "myAction", ""); - - StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); - request.setupGetServletPath("/someServletPath.action"); - request.setParameterMap(parameterMap); - - DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); - defaultActionMapper.setContainer(container); - ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); - - - StrutsResultSupport result = (StrutsResultSupport) actionMapping.getResult(); - assertNull(result); - } - - public void testUnsafeRedirectActionPrefix() { - Map parameterMap = new HashMap<>(); - parameterMap.put("redirectAction:" + "%{3*4}", ""); - - StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); - request.setupGetServletPath("/someServletPath.action"); - request.setParameterMap(parameterMap); - - DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); - defaultActionMapper.setContainer(container); - ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); - - - StrutsResultSupport result = (StrutsResultSupport) actionMapping.getResult(); - assertNull(result); - } - - public void testRedirectActionPrefixWithEmptyExtension() { - Map parameterMap = new HashMap<>(); - parameterMap.put("redirectAction:" + "myAction", ""); - - StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); - request.setupGetServletPath("/someServletPath"); - request.setParameterMap(parameterMap); - - DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); - defaultActionMapper.setContainer(container); - defaultActionMapper.setExtensions(",,"); - ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); - - - StrutsResultSupport result = (StrutsResultSupport) actionMapping.getResult(); - assertNull(result); + assertNotNull(actionMapping); + assertEquals("/test", actionMapping.getNamespace()); + assertEquals("next", actionMapping.getName()); + assertEquals("next", actionMapping.getMethod()); } public void testCustomActionPrefix() { @@ -617,11 +600,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { request.setupGetServletPath("/someServletPath.action"); DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); - defaultActionMapper.addParameterAction("foo", new ParameterAction() { - public void execute(String key, ActionMapping mapping) { - mapping.setName("myAction"); - } - }); + defaultActionMapper.addParameterAction("foo", (key, mapping) -> mapping.setName("myAction")); ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); assertEquals(actionMapping.getName(), "myAction"); From 26effbf05de95ff9188b6cfe2ef930908bb6ba96 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 13 Oct 2022 15:39:07 +0200 Subject: [PATCH 057/143] WW-5241 Improves Exec&Wait example in Showcase app --- .../src/main/resources/struts-wait.xml | 4 + .../main/webapp/WEB-INF/decorators/main.jsp | 2 +- .../src/main/webapp/WEB-INF/wait/complete.jsp | 29 ++++---- .../src/main/webapp/WEB-INF/wait/index.jsp | 53 +++++++++++++ .../src/main/webapp/WEB-INF/wait/wait.jsp | 74 +++++++------------ apps/showcase/src/main/webapp/wait/index.html | 53 ------------- 6 files changed, 100 insertions(+), 115 deletions(-) create mode 100644 apps/showcase/src/main/webapp/WEB-INF/wait/index.jsp delete mode 100644 apps/showcase/src/main/webapp/wait/index.html diff --git a/apps/showcase/src/main/resources/struts-wait.xml b/apps/showcase/src/main/resources/struts-wait.xml index 7b6a204a6..b237dac68 100644 --- a/apps/showcase/src/main/resources/struts-wait.xml +++ b/apps/showcase/src/main/resources/struts-wait.xml @@ -28,6 +28,10 @@ + + + /WEB-INF/wait/index.jsp + /WEB-INF/wait/example1.jsp diff --git a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp index d63f61f9a..ff1353032 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp @@ -239,7 +239,7 @@
  • Person Manager
  • CRUD
  • -
  • Execute & Wait
  • +
  • Execute & Wait
  • Token
  • Model Driven
  • diff --git a/apps/showcase/src/main/webapp/WEB-INF/wait/complete.jsp b/apps/showcase/src/main/webapp/WEB-INF/wait/complete.jsp index 74c97c74c..47cbb0674 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/wait/complete.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/wait/complete.jsp @@ -1,19 +1,19 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Struts2 Showcase - Execute and Wait Examples + + + + + +
    +
    +
    + +

    + These examples illustrate Struts build in support for execute and wait. +

    +

    + When you have a process that takes a long time your users can be impatient and starts to submit/click + again. +
    A good solution is to show the user a progress page (wait page) while the process takes it time. +

    + +
    +
    Example 1 (no delay) +
    Example 2 (with delay) +
    Example 3 (with longer check delay) +

    +
    +
    + + diff --git a/apps/showcase/src/main/webapp/WEB-INF/wait/wait.jsp b/apps/showcase/src/main/webapp/WEB-INF/wait/wait.jsp index e4b467968..57f169d87 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/wait/wait.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/wait/wait.jsp @@ -1,19 +1,19 @@ - - - Struts2 Showcase - Execute and Wait Examples - - - - - - - -
    -
    -
    - -

    - These examples illustrate Struts build in support for execute and wait. -

    -

    - When you have a process that takes a long time your users can be impatient and starts to submit/click again. -
    A good solution is to show the user a progress page (wait page) while the process takes it time. -

    - -
    -
    Example 1 (no delay) -
    Example 2 (with delay) -
    Example 3 (with longer check delay) -

    -
    -
    - - From 415e0fbd44bea04fc3c6566d38fbe60d22680c55 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 14 Oct 2022 11:32:10 +0200 Subject: [PATCH 058/143] WW-5241 Ignores calls to append !method when DMI is disabled --- .../mapper/DefaultActionMapper.java | 33 +++++++++++-------- .../mapper/DefaultActionMapperTest.java | 22 +++++++++++-- .../struts2/result/PostbackResultTest.java | 5 ++- .../ServletActionRedirectResultTest.java | 7 ++-- .../struts2/views/jsp/AbstractUITagTest.java | 6 ++-- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java index 98fec5316..ff16adfbf 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java @@ -34,7 +34,12 @@ import org.apache.struts2.StrutsConstants; import org.apache.struts2.util.PrefixTrie; import javax.servlet.http.HttpServletRequest; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; /** @@ -344,8 +349,8 @@ public class DefaultActionMapper implements ActionMapper { /** * Parses the name and namespace from the uri * - * @param uri The uri - * @param mapping The action mapping to populate + * @param uri The uri + * @param mapping The action mapping to populate * @param configManager configuration manager */ protected void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) { @@ -453,7 +458,7 @@ public class DefaultActionMapper implements ActionMapper { /** * Reads defined method name for a given action from configuration * - * @param mapping current instance of {@link ActionMapping} + * @param mapping current instance of {@link ActionMapping} * @param configurationManager current instance of {@link ConfigurationManager} */ protected void extractMethodName(ActionMapping mapping, ConfigurationManager configurationManager) { @@ -507,7 +512,7 @@ public class DefaultActionMapper implements ActionMapper { } /** - * @return null if no extension is specified. + * @return null if no extension is specified. */ protected String getDefaultExtension() { if (extensions == null) { @@ -552,17 +557,19 @@ public class DefaultActionMapper implements ActionMapper { } protected void handleDynamicMethod(ActionMapping mapping, StringBuilder uri) { + if (!allowDynamicMethodCalls) { + LOG.debug("DMI is disabled, ignoring appending !method to the URI"); + return; + } // See WW-3965 if (StringUtils.isNotEmpty(mapping.getMethod())) { - if (allowDynamicMethodCalls) { - // handle "name!method" convention. - String name = mapping.getName(); - if (!name.contains("!")) { - // Append the method as no bang found - uri.append("!").append(mapping.getMethod()); - } - } else { + // handle "name!method" convention. + String name = mapping.getName(); + if (!name.contains("!")) { + // Append the method as no bang found uri.append("!").append(mapping.getMethod()); + } else if (name.endsWith("!")) { + uri.append(mapping.getMethod()); } } } diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java index a9d01eec7..289e92751 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java @@ -640,6 +640,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { public void testGetUriFromActionMapper1() { DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping actionMapping = new ActionMapping(); actionMapping.setMethod("myMethod"); actionMapping.setName("myActionName"); @@ -651,6 +652,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { public void testGetUriFromActionMapper2() { DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping actionMapping = new ActionMapping(); actionMapping.setMethod("myMethod"); actionMapping.setName("myActionName"); @@ -662,6 +664,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { public void testGetUriFromActionMapper3() { DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping actionMapping = new ActionMapping(); actionMapping.setMethod("myMethod"); actionMapping.setName("myActionName"); @@ -671,7 +674,6 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals("/myActionName!myMethod.action", uri); } - public void testGetUriFromActionMapper4() { DefaultActionMapper mapper = new DefaultActionMapper(); ActionMapping actionMapping = new ActionMapping(); @@ -692,9 +694,9 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals("/myActionName.action", uri); } - // public void testGetUriFromActionMapper6() { DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping actionMapping = new ActionMapping(); actionMapping.setMethod("myMethod"); actionMapping.setName("myActionName?test=bla"); @@ -706,6 +708,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { public void testGetUriFromActionMapper7() { DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping actionMapping = new ActionMapping(); actionMapping.setMethod("myMethod"); actionMapping.setName("myActionName?test=bla"); @@ -717,6 +720,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { public void testGetUriFromActionMapper8() { DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping actionMapping = new ActionMapping(); actionMapping.setMethod("myMethod"); actionMapping.setName("myActionName?test=bla"); @@ -726,6 +730,16 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals("/myActionName!myMethod.action?test=bla", uri); } + public void testGetUriFromActionMapperWithDisabledDMI() { + DefaultActionMapper mapper = new DefaultActionMapper(); + ActionMapping actionMapping = new ActionMapping(); + actionMapping.setMethod("myMethod"); + actionMapping.setName("myActionName?test=bla"); + actionMapping.setNamespace(""); + String uri = mapper.getUriFromActionMapping(actionMapping); + + assertEquals("/myActionName.action?test=bla", uri); + } public void testGetUriFromActionMapper9() { DefaultActionMapper mapper = new DefaultActionMapper(); @@ -769,6 +783,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { public void testGetUriFromActionMapper_justActionAndMethod() { DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping actionMapping = new ActionMapping(); actionMapping.setMethod("myMethod"); actionMapping.setName("myActionName"); @@ -780,7 +795,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { public void testGetUriFromActionMapperWhenBlankExtension() { DefaultActionMapper mapper = new DefaultActionMapper(); - mapper.setExtensions(",,"); + mapper.setExtensions(","); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping actionMapping = new ActionMapping(); actionMapping.setMethod("myMethod"); actionMapping.setName("myActionName"); diff --git a/core/src/test/java/org/apache/struts2/result/PostbackResultTest.java b/core/src/test/java/org/apache/struts2/result/PostbackResultTest.java index 42d9330fa..f019436f7 100644 --- a/core/src/test/java/org/apache/struts2/result/PostbackResultTest.java +++ b/core/src/test/java/org/apache/struts2/result/PostbackResultTest.java @@ -26,6 +26,7 @@ import com.opensymphony.xwork2.util.ValueStack; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsInternalTestCase; import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; import org.easymock.IMocksControl; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -117,7 +118,9 @@ public class PostbackResultTest extends StrutsInternalTestCase { expect(mockInvocation.getStack()).andReturn(stack).anyTimes(); control.replay(); - result.setActionMapper(container.getInstance(ActionMapper.class)); + DefaultActionMapper mapper = (DefaultActionMapper) container.getInstance(ActionMapper.class); + mapper.setAllowDynamicMethodCalls("true"); + result.setActionMapper(mapper); result.execute(mockInvocation); assertEquals("
    " + "", res.getContentAsString()); diff --git a/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java b/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java index 19136bf16..216bb98e0 100644 --- a/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java +++ b/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java @@ -28,6 +28,7 @@ import com.opensymphony.xwork2.util.ValueStack; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsInternalTestCase; import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; import org.apache.struts2.views.util.DefaultUrlHelper; import org.easymock.IMocksControl; import org.springframework.mock.web.MockHttpServletRequest; @@ -163,7 +164,9 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { expect(mockInvocation.getStack()).andReturn(stack).anyTimes(); control.replay(); - result.setActionMapper(container.getInstance(ActionMapper.class)); + DefaultActionMapper mapper = (DefaultActionMapper) container.getInstance(ActionMapper.class); + mapper.setAllowDynamicMethodCalls("true"); + result.setActionMapper(mapper); result.execute(mockInvocation); assertEquals("/myNamespace${1-1}/myAction${1-1}!myMethod${1-1}.action?param1=value+1¶m2=value+2¶m3=value+3#fragment", res.getRedirectedUrl()); @@ -313,5 +316,5 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { ServletActionRedirectResult result = (ServletActionRedirectResult) factory.buildResult(resultConfig, ActionContext.getContext().getContextMap()); assertNotNull(result); } - + } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java index 79603acfd..c0fad07bd 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java @@ -23,6 +23,8 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.apache.commons.beanutils.BeanUtils; import org.apache.struts2.ServletActionContext; +import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; import org.apache.struts2.views.jsp.ui.AbstractUITag; import java.io.InputStream; @@ -227,7 +229,7 @@ public abstract class AbstractUITagTest extends AbstractTagTest { try (InputStream in = url.openStream()) { byte[] buf = new byte[4096]; int nbytes; - + while ((nbytes = in.read(buf)) > 0) { buffer.append(new String(buf, 0, nbytes)); } @@ -245,7 +247,7 @@ public abstract class AbstractUITagTest extends AbstractTagTest { protected void setUp() throws Exception { super.setUp(); - + ((DefaultActionMapper) container.getInstance(ActionMapper.class)).setAllowDynamicMethodCalls("true"); ServletActionContext.setServletContext(pageContext.getServletContext()); } From 9dd2560172c377ce182c47ef11a0c4529f4347c9 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 14 Oct 2022 12:03:02 +0200 Subject: [PATCH 059/143] WW-5241 Adds test cases to cover checking namespace, action and method names --- .../mapper/DefaultActionMapperTest.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java index 289e92751..0c3a592d2 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java @@ -896,4 +896,78 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals(mapper.defaultMethodName, mapper.cleanupMethodName("${#foo='method',#foo}")); } + public void testTestAllowedNamespaceName() { + // give + DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowedNamespaceNames("[a-z/]*"); + + // when + String result = mapper.cleanupNamespaceName("/ns"); + + // then + assertEquals("/ns", result); + } + + public void testTestAllowedNamespaceNameAndFallbackToDefault() { + // give + DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowedNamespaceNames("[a-z/]*"); + mapper.setDefaultNamespaceName("/ns"); + + // when + String result = mapper.cleanupNamespaceName("/ns2"); + + // then + assertEquals("/ns", result); + } + + public void testTestAllowedActionName() { + // give + DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowedActionNames("[a-z]*"); + + // when + String result = mapper.cleanupActionName("action"); + + // then + assertEquals("action", result); + } + + public void testTestAllowedActionNameAndFallbackToDefault() { + // give + DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowedActionNames("[a-z]*"); + mapper.setDefaultActionName("error"); + + // when + String result = mapper.cleanupActionName("action2"); + + // then + assertEquals("error", result); + } + + public void testTestAllowedMethodName() { + // give + DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowedMethodNames("[a-z]*"); + + // when + String result = mapper.cleanupMethodName("execute"); + + // then + assertEquals("execute", result); + } + + public void testTestAllowedMethodNameAndFallbackToDefault() { + // give + DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowedMethodNames("[a-z]*"); + mapper.setDefaultMethodName("error"); + + // when + String result = mapper.cleanupMethodName("execute2"); + + // then + assertEquals("error", result); + } } From 864f513365e954581973862178f86b9fd3cfb8c5 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 14 Oct 2022 12:29:40 +0200 Subject: [PATCH 060/143] WW-5241 Adds test cases to cover DMI when mapping action --- .../mapper/DefaultActionMapper.java | 4 ++ .../mapper/DefaultActionMapperTest.java | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java index ff16adfbf..70e1e874f 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java @@ -462,6 +462,10 @@ public class DefaultActionMapper implements ActionMapper { * @param configurationManager current instance of {@link ConfigurationManager} */ protected void extractMethodName(ActionMapping mapping, ConfigurationManager configurationManager) { + if (mapping.getMethod() != null && allowDynamicMethodCalls) { + LOG.debug("DMI is enabled and method has been already mapped based on bang operator"); + return; + } String methodName = null; for (PackageConfig cfg : configurationManager.getConfiguration().getPackageConfigs().values()) { if (cfg.getNamespace().equals(mapping.getNamespace())) { diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java index 0c3a592d2..097517e21 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java @@ -591,6 +591,47 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase { assertEquals("next", actionMapping.getMethod()); } + public void testActionPrefixWithBangWhenAllowed() { + Map parameterMap = new HashMap<>(); + parameterMap.put("action:" + "next!another", ""); + + StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); + request.setupGetServletPath("/index.action"); + request.setParameterMap(parameterMap); + + DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); + defaultActionMapper.setContainer(container); + defaultActionMapper.setAllowActionPrefix("true"); + defaultActionMapper.setAllowDynamicMethodCalls("true"); + + ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); + + assertNotNull(actionMapping); + assertEquals("/", actionMapping.getNamespace()); + assertEquals("next", actionMapping.getName()); + assertEquals("another", actionMapping.getMethod()); + } + + public void testMethodPrefixWhenAllowed() { + Map parameterMap = new HashMap<>(); + parameterMap.put("method:" + "another", ""); + + StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); + request.setupGetServletPath("/index.action"); + request.setParameterMap(parameterMap); + + DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); + defaultActionMapper.setContainer(container); + defaultActionMapper.setAllowDynamicMethodCalls("true"); + + ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); + + assertNotNull(actionMapping); + assertEquals("/", actionMapping.getNamespace()); + assertEquals("index", actionMapping.getName()); + assertEquals("another", actionMapping.getMethod()); + } + public void testCustomActionPrefix() { Map parameterMap = new HashMap<>(); parameterMap.put("foo:myAction", ""); From e783d1871598629840c50ba95edc983e9de26f93 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 14 Oct 2022 12:49:22 +0200 Subject: [PATCH 061/143] WW-5242 Marks struts.mapper.action.prefix.crossNamespaces as deprecated --- .../struts2/dispatcher/mapper/DefaultActionMapper.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java index 98fec5316..7ab98a7d8 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java @@ -236,6 +236,11 @@ public class DefaultActionMapper implements ActionMapper { this.allowActionPrefix = BooleanUtils.toBoolean(allowActionPrefix); } + /** + * @deprecated since 6.1.0 - please refactor your application to avoid using this functionality + * @param allowActionCrossNamespaceAccess true to enable cross namespace action access + */ + @Deprecated @Inject(value = StrutsConstants.STRUTS_MAPPER_ACTION_PREFIX_CROSSNAMESPACES) public void setAllowActionCrossNamespaceAccess(String allowActionCrossNamespaceAccess) { this.allowActionCrossNamespaceAccess = BooleanUtils.toBoolean(allowActionCrossNamespaceAccess); From 2cb0d28960bd9ef71fc8fc27e1b23f40bc7d87aa Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 16 Oct 2022 08:51:09 +0200 Subject: [PATCH 062/143] WW-5244 Upgrades commons-text to version 1.10.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 68c478c02..e3eb123ed 100644 --- a/pom.xml +++ b/pom.xml @@ -927,7 +927,7 @@ org.apache.commons commons-text - 1.8 + 1.10.0 commons-digester From 50842e8d1935797c222437fb46c12dab1a72fd1c Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 16 Oct 2022 08:55:27 +0200 Subject: [PATCH 063/143] WW-5242 Marks constant definition as deprecated --- core/src/main/java/org/apache/struts2/StrutsConstants.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java index 710062269..18ccfbc93 100644 --- a/core/src/main/java/org/apache/struts2/StrutsConstants.java +++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java @@ -398,7 +398,11 @@ public final class StrutsConstants { /** Enables action: prefix */ public static final String STRUTS_MAPPER_ACTION_PREFIX_ENABLED = "struts.mapper.action.prefix.enabled"; - /** Enables access to actions in other namespaces than current with action: prefix */ + /** + * Enables access to actions in other namespaces than current with action: prefix + * @deprecated it will be removed soon, please refactor your application + */ + @Deprecated public static final String STRUTS_MAPPER_ACTION_PREFIX_CROSSNAMESPACES = "struts.mapper.action.prefix.crossNamespaces"; public static final String DEFAULT_TEMPLATE_TYPE_CONFIG_KEY = "struts.ui.templateSuffix"; From bb7161029669b6d2055ac42ff17de315ef1272f0 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 17 Oct 2022 08:54:03 +0200 Subject: [PATCH 064/143] WW-2815 Refactors XStreamHandler to allow to provide a custom configuration --- .../struts2/rest/handler/XStreamHandler.java | 33 ++-- .../XStreamAllowedClassNames.java} | 4 +- .../XStreamAllowedClasses.java} | 4 +- .../XStreamPermissionProvider.java | 2 +- .../rest/handler/xstream/XStreamProvider.java | 29 ++++ .../rest/handler/XStreamHandlerTest.java | 160 ++++++++++++++++++ 6 files changed, 216 insertions(+), 16 deletions(-) rename plugins/rest/src/main/java/org/apache/struts2/rest/handler/{AllowedClassNames.java => xstream/XStreamAllowedClassNames.java} (90%) rename plugins/rest/src/main/java/org/apache/struts2/rest/handler/{AllowedClasses.java => xstream/XStreamAllowedClasses.java} (90%) rename plugins/rest/src/main/java/org/apache/struts2/rest/handler/{ => xstream}/XStreamPermissionProvider.java (95%) create mode 100644 plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamProvider.java create mode 100644 plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java index 22e597561..d3534e32b 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java @@ -21,6 +21,7 @@ package org.apache.struts2.rest.handler; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ModelDriven; import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.StaxDriver; import com.thoughtworks.xstream.security.ArrayTypePermission; import com.thoughtworks.xstream.security.ExplicitTypePermission; import com.thoughtworks.xstream.security.NoTypePermission; @@ -29,12 +30,15 @@ import com.thoughtworks.xstream.security.PrimitiveTypePermission; import com.thoughtworks.xstream.security.TypePermission; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.rest.handler.xstream.XStreamAllowedClassNames; +import org.apache.struts2.rest.handler.xstream.XStreamAllowedClasses; +import org.apache.struts2.rest.handler.xstream.XStreamPermissionProvider; +import org.apache.struts2.rest.handler.xstream.XStreamProvider; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.Collection; -import java.util.Date; import java.util.Map; import java.util.Set; @@ -68,7 +72,15 @@ public class XStreamHandler extends AbstractContentTypeHandler { } protected XStream createXStream(ActionInvocation invocation) { - XStream stream = new XStream(); + XStream stream; + if (invocation.getAction() instanceof XStreamProvider) { + LOG.debug("Using provider {} to create instance of XStream", invocation.getAction().getClass().getSimpleName()); + stream = ((XStreamProvider) invocation.getAction()).createXStream(); + } else { + LOG.debug("Creating default XStream instance using Stax driver: {}", StaxDriver.class.getSimpleName()); + stream = new XStream(new StaxDriver()); + } + LOG.debug("Clears existing permissions"); stream.addPermission(NoTypePermission.NONE); @@ -82,13 +94,13 @@ public class XStreamHandler extends AbstractContentTypeHandler { private void addPerActionPermission(ActionInvocation invocation, XStream stream) { Object action = invocation.getAction(); - if (action instanceof AllowedClasses) { - Set> allowedClasses = ((AllowedClasses) action).allowedClasses(); - stream.addPermission(new ExplicitTypePermission(allowedClasses.toArray(new Class[allowedClasses.size()]))); + if (action instanceof XStreamAllowedClasses) { + Set> allowedClasses = ((XStreamAllowedClasses) action).allowedClasses(); + stream.addPermission(new ExplicitTypePermission(allowedClasses.toArray(new Class[0]))); } - if (action instanceof AllowedClassNames) { - Set allowedClassNames = ((AllowedClassNames) action).allowedClassNames(); - stream.addPermission(new ExplicitTypePermission(allowedClassNames.toArray(new String[allowedClassNames.size()]))); + if (action instanceof XStreamAllowedClassNames) { + Set allowedClassNames = ((XStreamAllowedClassNames) action).allowedClassNames(); + stream.addPermission(new ExplicitTypePermission(allowedClassNames.toArray(new String[0]))); } if (action instanceof XStreamPermissionProvider) { Collection permissions = ((XStreamPermissionProvider) action).getTypePermissions(); @@ -101,13 +113,12 @@ public class XStreamHandler extends AbstractContentTypeHandler { protected void addDefaultPermissions(ActionInvocation invocation, XStream stream) { stream.addPermission(new ExplicitTypePermission(new Class[]{invocation.getAction().getClass()})); if (invocation.getAction() instanceof ModelDriven) { - stream.addPermission(new ExplicitTypePermission(new Class[]{((ModelDriven) invocation.getAction()).getModel().getClass()})); + stream.addPermission(new ExplicitTypePermission(new Class[]{((ModelDriven) invocation.getAction()).getModel().getClass()})); } stream.addPermission(NullPermission.NULL); stream.addPermission(PrimitiveTypePermission.PRIMITIVES); stream.addPermission(ArrayTypePermission.ARRAYS); stream.addPermission(CollectionTypePermission.COLLECTIONS); - stream.addPermission(new ExplicitTypePermission(new Class[]{Date.class})); } public String getContentType() { @@ -125,7 +136,7 @@ public class XStreamHandler extends AbstractContentTypeHandler { @Override public boolean allows(Class type) { return type != null && type.isInterface() && - (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)); + (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)); } } diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClassNames.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamAllowedClassNames.java similarity index 90% rename from plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClassNames.java rename to plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamAllowedClassNames.java index c7c23ba58..340ac9c9b 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClassNames.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamAllowedClassNames.java @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2.rest.handler; +package org.apache.struts2.rest.handler.xstream; import java.util.Set; -public interface AllowedClassNames { +public interface XStreamAllowedClassNames { Set allowedClassNames(); } diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClasses.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamAllowedClasses.java similarity index 90% rename from plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClasses.java rename to plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamAllowedClasses.java index 149a32c90..504c35f89 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClasses.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamAllowedClasses.java @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2.rest.handler; +package org.apache.struts2.rest.handler.xstream; import java.util.Set; -public interface AllowedClasses { +public interface XStreamAllowedClasses { Set> allowedClasses(); } diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamPermissionProvider.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamPermissionProvider.java similarity index 95% rename from plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamPermissionProvider.java rename to plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamPermissionProvider.java index b58bf91db..f163912cf 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamPermissionProvider.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamPermissionProvider.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2.rest.handler; +package org.apache.struts2.rest.handler.xstream; import com.thoughtworks.xstream.security.TypePermission; diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamProvider.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamProvider.java new file mode 100644 index 000000000..517029d74 --- /dev/null +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/xstream/XStreamProvider.java @@ -0,0 +1,29 @@ +/* + * 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.rest.handler.xstream; + +import com.thoughtworks.xstream.XStream; + +/** + * An interface to be implemented by an action to create/provide an instance + * of XStream - it allows customisation per action + */ +public interface XStreamProvider { + XStream createXStream(); +} diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java new file mode 100644 index 000000000..3510634ed --- /dev/null +++ b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java @@ -0,0 +1,160 @@ +/* + * 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.rest.handler; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.XWorkTestCase; +import com.opensymphony.xwork2.mock.MockActionInvocation; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.StaxDriver; +import com.thoughtworks.xstream.security.ExplicitTypePermission; +import com.thoughtworks.xstream.security.TypePermission; +import org.apache.struts2.rest.handler.xstream.XStreamAllowedClassNames; +import org.apache.struts2.rest.handler.xstream.XStreamAllowedClasses; +import org.apache.struts2.rest.handler.xstream.XStreamPermissionProvider; +import org.apache.struts2.rest.handler.xstream.XStreamProvider; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +public class XStreamHandlerTest extends XWorkTestCase { + + private XStreamHandler handler; + private MockActionInvocation ai; + + public void setUp() throws Exception { + super.setUp(); + handler = new XStreamHandler(); + ai = new MockActionInvocation(); + ActionSupport action = new ActionSupport(); + ActionContext context = ActionContext.of(new HashMap<>()).withLocale(Locale.US); + ai.setInvocationContext(context); + ai.setAction(action); + } + + public void testObjectToXml() throws Exception { + // given + SimpleBean obj = new SimpleBean(); + obj.setName("Jan"); + obj.setAge(12L); + obj.setParents(Arrays.asList("Adam", "Ewa")); + + // when + Writer stream = new StringWriter(); + handler.fromObject(ai, obj, null, stream); + + // then + stream.flush(); + assertThat(stream.toString()) + .contains("") + .contains("Jan") + .contains("12") + .contains("") + .contains("Adam") + .contains("Ewa") + .contains(""); + } + + public void testXmlToObject() { + // given + String xml = "Jan12AdamEwa"; + + SimpleBean obj = new SimpleBean(); + ai.setAction(new SimpleAction()); + + // when + Reader in = new StringReader(xml); + handler.toObject(ai, in, obj); + + // then + assertNotNull(obj); + assertEquals("Jan", obj.getName()); + assertEquals(12L, obj.getAge().longValue()); + assertNotNull(obj.getParents()); + assertThat(obj.getParents()) + .hasSize(2) + .containsExactly("Adam", "Ewa"); + } + + public void testXmlToObjectWithAliases() { + // given + String xml = "Jan12AdamEwa"; + + SimpleBean obj = new SimpleBean(); + ai.setAction(new SimpleAliasAction()); + + // when + Reader in = new StringReader(xml); + handler.toObject(ai, in, obj); + + // then + assertNotNull(obj); + assertEquals("Jan", obj.getName()); + assertEquals(12L, obj.getAge().longValue()); + assertNotNull(obj.getParents()); + assertThat(obj.getParents()) + .hasSize(2) + .containsExactly("Adam", "Ewa"); + } + + private static class SimpleAction implements XStreamAllowedClasses, XStreamAllowedClassNames, XStreamPermissionProvider { + @Override + public Set> allowedClasses() { + Set> classes = new HashSet<>(); + classes.add(SimpleBean.class); + return classes; + } + + @Override + public Set allowedClassNames() { + HashSet strings = new HashSet<>(); + strings.add(ArrayList.class.getName()); + return strings; + } + + @Override + public Collection getTypePermissions() { + ArrayList permissions = new ArrayList<>(); + permissions.add(new ExplicitTypePermission(new Class[]{String.class})); + return permissions; + } + } + + private static class SimpleAliasAction extends SimpleAction implements XStreamProvider { + @Override + public XStream createXStream() { + XStream stream = new XStream(new StaxDriver()); + stream.alias("parents", ArrayList.class); + stream.alias("data", SimpleBean.class); + return stream; + } + } +} From ac13c32bdb9fc5a16fe9b1e0fb1d2769a13f0740 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 17 Oct 2022 09:47:37 +0200 Subject: [PATCH 065/143] WW-2815 Drops deprecated API --- .../org/apache/struts2/rest/handler/XStreamHandler.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java index d3534e32b..70ea810eb 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java @@ -62,15 +62,6 @@ public class XStreamHandler extends AbstractContentTypeHandler { xstream.fromXML(in, target); } - /** - * @deprecated use version with {@link ActionInvocation} - */ - @Deprecated - protected XStream createXStream() { - LOG.warn("You are using a deprecated API!"); - return new XStream(); - } - protected XStream createXStream(ActionInvocation invocation) { XStream stream; if (invocation.getAction() instanceof XStreamProvider) { From a562f8f8065223e71777b1931a736c9ac980e913 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 17 Oct 2022 09:52:07 +0200 Subject: [PATCH 066/143] WW-2815 Fixes support for Collections and String --- .../org/apache/struts2/rest/handler/XStreamHandler.java | 4 ++-- .../apache/struts2/rest/handler/XStreamHandlerTest.java | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java index 70ea810eb..5958ff5c9 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java @@ -107,6 +107,7 @@ public class XStreamHandler extends AbstractContentTypeHandler { stream.addPermission(new ExplicitTypePermission(new Class[]{((ModelDriven) invocation.getAction()).getModel().getClass()})); } stream.addPermission(NullPermission.NULL); + stream.addPermission(new ExplicitTypePermission(new Class[]{String.class})); stream.addPermission(PrimitiveTypePermission.PRIMITIVES); stream.addPermission(ArrayTypePermission.ARRAYS); stream.addPermission(CollectionTypePermission.COLLECTIONS); @@ -126,8 +127,7 @@ public class XStreamHandler extends AbstractContentTypeHandler { @Override public boolean allows(Class type) { - return type != null && type.isInterface() && - (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)); + return type != null && (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)); } } diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java index 3510634ed..732643bdc 100644 --- a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java +++ b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/XStreamHandlerTest.java @@ -38,6 +38,7 @@ import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; @@ -135,16 +136,12 @@ public class XStreamHandlerTest extends XWorkTestCase { @Override public Set allowedClassNames() { - HashSet strings = new HashSet<>(); - strings.add(ArrayList.class.getName()); - return strings; + return Collections.emptySet(); } @Override public Collection getTypePermissions() { - ArrayList permissions = new ArrayList<>(); - permissions.add(new ExplicitTypePermission(new Class[]{String.class})); - return permissions; + return Collections.emptyList(); } } From 339c30320af03e80c36dd878c53cce0a946865b2 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 17 Oct 2022 10:14:51 +0200 Subject: [PATCH 067/143] WW-2815 Drops clearing existing permissions to avoid messing with user provided configuration --- .../java/org/apache/struts2/rest/handler/XStreamHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java index 5958ff5c9..d4d40221d 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java @@ -72,9 +72,6 @@ public class XStreamHandler extends AbstractContentTypeHandler { stream = new XStream(new StaxDriver()); } - LOG.debug("Clears existing permissions"); - stream.addPermission(NoTypePermission.NONE); - LOG.debug("Adds per action permissions"); addPerActionPermission(invocation, stream); From 802afb0cc0df878a55584a9a5dc9d0f61bbfd1f0 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 17 Oct 2022 10:55:46 +0200 Subject: [PATCH 068/143] WW-2815 Drops unused import --- .../java/org/apache/struts2/rest/handler/XStreamHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java index d4d40221d..13831093f 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java @@ -24,7 +24,6 @@ import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.StaxDriver; import com.thoughtworks.xstream.security.ArrayTypePermission; import com.thoughtworks.xstream.security.ExplicitTypePermission; -import com.thoughtworks.xstream.security.NoTypePermission; import com.thoughtworks.xstream.security.NullPermission; import com.thoughtworks.xstream.security.PrimitiveTypePermission; import com.thoughtworks.xstream.security.TypePermission; From 984f8eff2e0f02c74b36f531d45518d58dd4a56e Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 19 Oct 2022 08:49:37 +0200 Subject: [PATCH 069/143] WW-5245 Upgrades Jackson Databind to version 2.13.4.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e3eb123ed..944b1ed2a 100644 --- a/pom.xml +++ b/pom.xml @@ -110,8 +110,8 @@ 9.2 - 2.13.2 - 2.13.2.1 + 2.13.4 + 2.13.4.2 2.19.0 3.3.3 1.7.32 From 01164c4d7461d4b42b49aec84762f7b8562638fe Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 19 Oct 2022 11:38:50 +0200 Subject: [PATCH 070/143] WW-5230 Upgrades OGNL to version 3.3.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 944b1ed2a..5a8fa9af7 100644 --- a/pom.xml +++ b/pom.xml @@ -113,7 +113,7 @@ 2.13.4 2.13.4.2 2.19.0 - 3.3.3 + 3.3.4 1.7.32 5.3.23 3.0.8 From 993c4c4cab21ace8970d094da03291b21547ab83 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 19 Oct 2022 12:22:31 +0200 Subject: [PATCH 071/143] WW-3529 Fixes using RegEx related characters in named pattern --- .../util/NamedVariablePatternMatcher.java | 71 +++++++++++-------- .../util/NamedVariablePatternMatcherTest.java | 27 +++++-- 2 files changed, 63 insertions(+), 35 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java b/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java index cb848868d..24e5e9b35 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java @@ -18,6 +18,8 @@ */ package com.opensymphony.xwork2.util; +import org.apache.commons.lang3.StringUtils; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -57,7 +59,7 @@ import java.util.regex.Pattern; * * *

    - * Excaping hasn't been implemented since the intended use of these patterns will be in matching URLs. + * Escaping hasn't been implemented since the intended use of these patterns will be in matching URLs. *

    * * @since 2.1 @@ -75,38 +77,47 @@ public class NamedVariablePatternMatcher implements PatternMatcher 0) { - List varNames = new ArrayList<>(); - StringBuilder varName = null; - for (int x=0; x varNames = new ArrayList<>(); + int s = 0; + while (s < len) { + int e = data.indexOf('{', s); + if (e < 0 && data.indexOf('}') > -1) { + throw new IllegalArgumentException("Missing openning '{' in [" + data + "]!"); + } + if (e < 0) { + regex.append(Pattern.quote(data.substring(s))); + break; + } + if (e > s) { + regex.append(Pattern.quote(data.substring(s, e))); + } + s = e + 1; + e = data.indexOf('}', s); + if (e < 0) { + return null; + } + String varName = data.substring(s, e); + if (StringUtils.isEmpty(varName)) { + throw new IllegalArgumentException("Missing variable name in [" + data + "]!"); + } + varNames.add(varName); + regex.append("([^/]+)"); + s = e + 1; + } + return new CompiledPattern(Pattern.compile(regex.toString()), varNames); } /** * Tries to process the data against the compiled expression. If successful, the map will contain * the matched data, using the specified variable names in the original pattern. * - * @param map The map of variables + * @param map The map of variables * @param data The data to match * @param expr The compiled pattern * @return True if matched, false if not matched, the data was null, or the data was an empty string @@ -116,8 +127,8 @@ public class NamedVariablePatternMatcher implements PatternMatcher 0) { Matcher matcher = expr.getPattern().matcher(data); if (matcher.matches()) { - for (int x=0; x variableNames; + private final Pattern pattern; + private final List variableNames; public CompiledPattern(Pattern pattern, List variableNames) { diff --git a/core/src/test/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcherTest.java b/core/src/test/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcherTest.java index e11fb6870..b5eda4f0a 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcherTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcherTest.java @@ -37,15 +37,18 @@ public class NamedVariablePatternMatcherTest { assertNull(matcher.compilePattern(null)); assertNull(matcher.compilePattern("")); - CompiledPattern pattern = matcher.compilePattern("foo"); - assertEquals("foo", pattern.getPattern().pattern()); + CompiledPattern pattern = matcher.compilePattern("action.{format}"); + assertEquals("\\Qaction.\\E([^/]+)", pattern.getPattern().pattern()); + + pattern = matcher.compilePattern("foo"); + assertEquals("\\Qfoo\\E", pattern.getPattern().pattern()); pattern = matcher.compilePattern("foo{jim}"); - assertEquals("foo([^/]+)", pattern.getPattern().pattern()); + assertEquals("\\Qfoo\\E([^/]+)", pattern.getPattern().pattern()); assertEquals("jim", pattern.getVariableNames().get(0)); pattern = matcher.compilePattern("foo{jim}/{bob}"); - assertEquals("foo([^/]+)/([^/]+)", pattern.getPattern().pattern()); + assertEquals("\\Qfoo\\E([^/]+)\\Q/\\E([^/]+)", pattern.getPattern().pattern()); assertEquals("jim", pattern.getVariableNames().get(0)); assertEquals("bob", pattern.getVariableNames().get(1)); assertTrue(pattern.getPattern().matcher("foostar/jie").matches()); @@ -53,12 +56,26 @@ public class NamedVariablePatternMatcherTest { } @Test(expected = IllegalArgumentException.class) - public void testCompileWithMismatchedBracketsParses() { + public void testCompileWithMissingVariableName() { + NamedVariablePatternMatcher matcher = new NamedVariablePatternMatcher(); + + matcher.compilePattern("{}"); + } + + @Test(expected = IllegalArgumentException.class) + public void testCompileWithMissingOpeningBracket1() { NamedVariablePatternMatcher matcher = new NamedVariablePatternMatcher(); matcher.compilePattern("}"); } + @Test(expected = IllegalArgumentException.class) + public void testCompileWithMissingOpeningBracket2() { + NamedVariablePatternMatcher matcher = new NamedVariablePatternMatcher(); + + matcher.compilePattern("test}"); + } + @Test public void testMatch() { NamedVariablePatternMatcher matcher = new NamedVariablePatternMatcher(); From c41f05fe68c4f89ba5042747a43bb74e108ce550 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 19 Oct 2022 13:57:59 +0200 Subject: [PATCH 072/143] WW-3737 Allows to define a custom separator used to split patterns --- .../opensymphony/xwork2/XWorkTestCase.java | 31 ++-- .../xwork2/inject/ContainerImpl.java | 175 ++++++++---------- .../org/apache/struts2/StrutsConstants.java | 3 + .../struts2/dispatcher/InitOperations.java | 37 ++-- .../dispatcher/InitOperationsTest.java | 86 +++++++++ 5 files changed, 202 insertions(+), 130 deletions(-) create mode 100644 core/src/test/java/org/apache/struts2/dispatcher/InitOperationsTest.java diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java index 330e96412..ec7a8d755 100644 --- a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java +++ b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java @@ -34,22 +34,22 @@ import java.util.Locale; import java.util.Map; /** - * Base JUnit TestCase to extend for XWork specific JUnit tests. Uses + * Base JUnit TestCase to extend for XWork specific JUnit tests. Uses * the generic test setup for logic. * * @author plightbo */ public abstract class XWorkTestCase extends TestCase { - + protected ConfigurationManager configurationManager; protected Configuration configuration; protected Container container; protected ActionProxyFactory actionProxyFactory; - + public XWorkTestCase() { super(); } - + @Override protected void setUp() throws Exception { configurationManager = XWorkTestCaseHelper.setUp(); @@ -57,7 +57,7 @@ public abstract class XWorkTestCase extends TestCase { container = configuration.getContainer(); actionProxyFactory = container.getInstance(ActionProxyFactory.class); } - + @Override protected void tearDown() throws Exception { XWorkTestCaseHelper.tearDown(configurationManager); @@ -66,34 +66,33 @@ public abstract class XWorkTestCase extends TestCase { container = null; actionProxyFactory = null; } - + protected void loadConfigurationProviders(ConfigurationProvider... providers) { configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers); configuration = configurationManager.getConfiguration(); container = configuration.getContainer(); actionProxyFactory = container.getInstance(ActionProxyFactory.class); } - - protected void loadButAdd(final Class type, final Object impl) { + + protected void loadButAdd(final Class type, final T impl) { loadButAdd(type, Container.DEFAULT_NAME, impl); } - - protected void loadButAdd(final Class type, final String name, final Object impl) { + + protected void loadButAdd(final Class type, final String name, final T impl) { loadConfigurationProviders(new StubConfigurationProvider() { @Override - public void register(ContainerBuilder builder, - LocatableProperties props) throws ConfigurationException { + public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { if (impl instanceof String || ClassUtils.isPrimitiveOrWrapper(impl.getClass())) { props.setProperty(name, "" + impl); } else { - builder.factory(type, name, new Factory() { - public Object create(Context context) throws Exception { + builder.factory(type, name, new Factory() { + public T create(Context context) throws Exception { return impl; } @Override - public Class type() { - return impl.getClass(); + public Class type() { + return (Class) impl.getClass(); } }, Scope.SINGLETON); } diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java index ad3d43c2f..455f8a449 100644 --- a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java +++ b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java @@ -19,10 +19,26 @@ import com.opensymphony.xwork2.inject.util.ReferenceCache; import java.io.Serializable; import java.lang.annotation.Annotation; -import java.lang.reflect.*; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ReflectPermission; import java.security.AccessControlException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Set; /** * Default {@link Container} implementation. @@ -39,11 +55,7 @@ class ContainerImpl implements Container { this.factories = factories; final Map, Set> map = new HashMap<>(); for (Key key : factories.keySet()) { - Set names = map.get(key.getType()); - if (names == null) { - names = new HashSet<>(); - map.put(key.getType(), names); - } + Set names = map.computeIfAbsent(key.getType(), k -> new HashSet<>()); names.add(key.getName()); } @@ -63,20 +75,20 @@ class ContainerImpl implements Container { * Field and method injectors. */ final Map, List> injectors = - new ReferenceCache, List>() { - @Override - protected List create(Class key) { - List injectors = new ArrayList<>(); - addInjectors(key, injectors); - return injectors; - } - }; + new ReferenceCache, List>() { + @Override + protected List create(Class key) { + List injectors = new ArrayList<>(); + addInjectors(key, injectors); + return injectors; + } + }; /** * Recursively adds injectors for fields and methods from the given class to the given list. Injects parent classes * before sub classes. */ - void addInjectors(Class clazz, List injectors) { + void addInjectors(Class clazz, List injectors) { if (clazz == Object.class) { return; } @@ -97,38 +109,24 @@ class ContainerImpl implements Container { addInjectorsForMethods(clazz.getDeclaredMethods(), true, injectors); } - callInContext(new ContextualCallable() { - public Void call(InternalContext context) { - for (Injector injector : injectors) { - injector.inject(context, null); - } - return null; + callInContext((ContextualCallable) context -> { + for (Injector injector : injectors) { + injector.inject(context, null); } + return null; }); } void addInjectorsForMethods(Method[] methods, boolean statics, List injectors) { - addInjectorsForMembers(Arrays.asList(methods), statics, injectors, - new InjectorFactory() { - public Injector create(ContainerImpl container, Method method, - String name) throws MissingDependencyException { - return new MethodInjector(container, method, name); - } - }); + addInjectorsForMembers(Arrays.asList(methods), statics, injectors, MethodInjector::new); } void addInjectorsForFields(Field[] fields, boolean statics, List injectors) { - addInjectorsForMembers(Arrays.asList(fields), statics, injectors, - new InjectorFactory() { - public Injector create(ContainerImpl container, Field field, - String name) throws MissingDependencyException { - return new FieldInjector(container, field, name); - } - }); + addInjectorsForMembers(Arrays.asList(fields), statics, injectors, FieldInjector::new); } void addInjectorsForMembers( - List members, boolean statics, List injectors, InjectorFactory injectorFactory) { + List members, boolean statics, List injectors, InjectorFactory injectorFactory) { for (M member : members) { if (isStatic(member) == statics) { Inject inject = member.getAnnotation(Inject.class); @@ -148,12 +146,12 @@ class ContainerImpl implements Container { interface InjectorFactory { Injector create(ContainerImpl container, M member, String name) - throws MissingDependencyException; + throws MissingDependencyException; } /** * Determines if a given {@link Member} is static or not. - * + * * @param member checked for the static modifier. * @return true if member is static, false otherwise. */ @@ -163,13 +161,13 @@ class ContainerImpl implements Container { /** * Determines if a given {@link Member} is considered to be public for reflection usage or not. - * + * * @param member checked to see if it is public for reflection usage. * @return true if member is public for reflection usage, false otherwise. */ private static boolean isPublicForReflection(Member member) { return Modifier.isPublic(member.getModifiers()) && - Modifier.isPublic(member.getDeclaringClass().getModifiers()); + Modifier.isPublic(member.getDeclaringClass().getModifiers()); } static class FieldInjector implements Injector { @@ -179,7 +177,7 @@ class ContainerImpl implements Container { final ExternalContext externalContext; public FieldInjector(ContainerImpl container, Field field, String name) - throws MissingDependencyException { + throws MissingDependencyException { this.field = field; if (!isPublicForReflection(field) && !field.isAccessible()) { SecurityManager sm = System.getSecurityManager(); @@ -190,7 +188,7 @@ class ContainerImpl implements Container { field.setAccessible(true); } catch (AccessControlException e) { throw new DependencyException("Security manager in use, could not access field: " - + field.getDeclaringClass().getName() + "(" + field.getName() + ")", e); + + field.getDeclaringClass().getName() + "(" + field.getName() + ")", e); } } @@ -225,8 +223,12 @@ class ContainerImpl implements Container { * @param parameterTypes parameter types * @return injections */ - ParameterInjector[] - getParametersInjectors(M member, Annotation[][] annotations, Class[] parameterTypes, String defaultName) throws MissingDependencyException { + ParameterInjector[] getParametersInjectors( + M member, + Annotation[][] annotations, + Class[] parameterTypes, + String defaultName + ) throws MissingDependencyException { final List> parameterInjectors = new ArrayList<>(); final Iterator annotationsIterator = Arrays.asList(annotations).iterator(); @@ -247,12 +249,11 @@ class ContainerImpl implements Container { } final ExternalContext externalContext = ExternalContext.newInstance(member, key, this); - return new ParameterInjector(externalContext, factory); + return new ParameterInjector<>(externalContext, factory); } - @SuppressWarnings("unchecked") private ParameterInjector[] toArray(List> parameterInjections) { - return parameterInjections.toArray(new ParameterInjector[parameterInjections.size()]); + return parameterInjections.toArray(new ParameterInjector[0]); } /** @@ -261,7 +262,7 @@ class ContainerImpl implements Container { Inject findInject(Annotation[] annotations) { for (Annotation annotation : annotations) { if (annotation.annotationType() == Inject.class) { - return Inject.class.cast(annotation); + return (Inject) annotation; } } return null; @@ -283,7 +284,7 @@ class ContainerImpl implements Container { method.setAccessible(true); } catch (AccessControlException e) { throw new DependencyException("Security manager in use, could not access method: " - + name + "(" + method.getName() + ")", e); + + name + "(" + method.getName() + ")", e); } } @@ -292,7 +293,7 @@ class ContainerImpl implements Container { throw new DependencyException(method + " has no parameters to inject."); } parameterInjectors = container.getParametersInjectors( - method, method.getParameterAnnotations(), parameterTypes, name); + method, method.getParameterAnnotations(), parameterTypes, name); } @Override @@ -305,14 +306,12 @@ class ContainerImpl implements Container { } } - Map, ConstructorInjector> constructors = - new ReferenceCache, ConstructorInjector>() { - @Override - @SuppressWarnings("unchecked") - protected ConstructorInjector create(Class implementation) { - return new ConstructorInjector(ContainerImpl.this, implementation); - } - }; + Map, ConstructorInjector> constructors = new ReferenceCache, ConstructorInjector>() { + @Override + protected ConstructorInjector create(Class implementation) { + return new ConstructorInjector<>(ContainerImpl.this, implementation); + } + }; static class ConstructorInjector { @@ -334,7 +333,7 @@ class ContainerImpl implements Container { constructor.setAccessible(true); } catch (AccessControlException e) { throw new DependencyException("Security manager in use, could not access constructor: " - + implementation.getName() + "(" + constructor.getName() + ")", e); + + implementation.getName() + "(" + constructor.getName() + ")", e); } } @@ -359,14 +358,14 @@ class ContainerImpl implements Container { } ParameterInjector[] constructParameterInjector( - Inject inject, ContainerImpl container, Constructor constructor) throws MissingDependencyException { + Inject inject, ContainerImpl container, Constructor constructor) throws MissingDependencyException { return constructor.getParameterTypes().length == 0 - ? null // default constructor. - : container.getParametersInjectors( - constructor, - constructor.getParameterAnnotations(), - constructor.getParameterTypes(), - inject.value() + ? null // default constructor. + : container.getParametersInjectors( + constructor, + constructor.getParameterAnnotations(), + constructor.getParameterTypes(), + inject.value() ); } @@ -378,7 +377,7 @@ class ContainerImpl implements Container { if (constructor.getAnnotation(Inject.class) != null) { if (found != null) { throw new DependencyException("More than one constructor annotated" - + " with @Inject found in " + implementation + "."); + + " with @Inject found in " + implementation + "."); } found = constructor; } @@ -466,7 +465,7 @@ class ContainerImpl implements Container { } } - private static Object[] getParameters(Member member, InternalContext context, ParameterInjector[] parameterInjectors) { + private static Object[] getParameters(Member member, InternalContext context, ParameterInjector[] parameterInjectors) { if (parameterInjectors == null) { return null; } @@ -494,13 +493,12 @@ class ContainerImpl implements Container { } } - @SuppressWarnings("unchecked") T getInstance(Class type, String name, InternalContext context) { final ExternalContext previous = context.getExternalContext(); final Key key = Key.newInstance(type, name); context.setExternalContext(ExternalContext.newInstance(null, key, this)); try { - final InternalFactory o = getFactory(key); + final InternalFactory o = getFactory(key); if (o != null) { return getFactory(key).create(context); } else { @@ -517,39 +515,25 @@ class ContainerImpl implements Container { @Override public void inject(final Object o) { - callInContext(new ContextualCallable() { - public Void call(InternalContext context) { - inject(o, context); - return null; - } + callInContext((ContextualCallable) context -> { + inject(o, context); + return null; }); } @Override public T inject(final Class implementation) { - return callInContext(new ContextualCallable() { - public T call(InternalContext context) { - return inject(implementation, context); - } - }); + return callInContext(context -> inject(implementation, context)); } @Override public T getInstance(final Class type, final String name) { - return callInContext(new ContextualCallable() { - public T call(InternalContext context) { - return getInstance(type, name, context); - } - }); + return callInContext(context -> getInstance(type, name, context)); } @Override public T getInstance(final Class type) { - return callInContext(new ContextualCallable() { - public T call(InternalContext context) { - return getInstance(type, context); - } - }); + return callInContext(context -> getInstance(type, context)); } @Override @@ -561,12 +545,7 @@ class ContainerImpl implements Container { return names; } - ThreadLocal localContext = new ThreadLocal() { - @Override - protected Object[] initialValue() { - return new Object[1]; - } - }; + ThreadLocal localContext = ThreadLocal.withInitial(() -> new Object[1]); /** * Looks up thread local context. Creates (and removes) a new context if necessary. @@ -598,7 +577,7 @@ class ContainerImpl implements Container { */ @SuppressWarnings("unchecked") ConstructorInjector getConstructor(Class implementation) { - return constructors.get(implementation); + return (ConstructorInjector) constructors.get(implementation); } final ThreadLocal localScopeStrategy = new ThreadLocal<>(); diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java index 18ccfbc93..f37a85078 100644 --- a/core/src/main/java/org/apache/struts2/StrutsConstants.java +++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java @@ -56,6 +56,9 @@ public final class StrutsConstants { /** Comma separated list of patterns (java.util.regex.Pattern) to be excluded from Struts2-processing */ public static final String STRUTS_ACTION_EXCLUDE_PATTERN = "struts.action.excludePattern"; + /** A custom separator used to split list of patterns (java.util.regex.Pattern) to be excluded from Struts2-processing */ + public static final String STRUTS_ACTION_EXCLUDE_PATTERN_SEPARATOR = "struts.action.excludePattern.separator"; + /** Whether to use the response encoding (JSP page encoding) for s:include tag processing (false - use STRUTS_I18N_ENCODING - by default) */ public static final String STRUTS_TAG_INCLUDETAG_USERESPONSEENCODING = "struts.tag.includetag.useResponseEncoding"; 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 7c6b7626f..819e7cdb9 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/InitOperations.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/InitOperations.java @@ -21,7 +21,12 @@ package org.apache.struts2.dispatcher; import com.opensymphony.xwork2.ActionContext; import org.apache.struts2.StrutsConstants; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.regex.Pattern; /** @@ -36,10 +41,9 @@ public class InitOperations { * Creates and initializes the dispatcher * * @param filterConfig host configuration - * * @return the dispatcher */ - public Dispatcher initDispatcher( HostConfig filterConfig ) { + public Dispatcher initDispatcher(HostConfig filterConfig) { Dispatcher dispatcher = createDispatcher(filterConfig); dispatcher.init(); return dispatcher; @@ -49,10 +53,10 @@ public class InitOperations { * Initializes the static content loader with the filter configuration * * @param filterConfig host configuration - * @param dispatcher the dispatcher + * @param dispatcher the dispatcher * @return the static content loader */ - public StaticContentLoader initStaticContentLoader( HostConfig filterConfig, Dispatcher dispatcher ) { + public StaticContentLoader initStaticContentLoader(HostConfig filterConfig, Dispatcher dispatcher) { StaticContentLoader loader = dispatcher.getContainer().getInstance(StaticContentLoader.class); loader.setHostConfig(filterConfig); return loader; @@ -60,7 +64,6 @@ public class InitOperations { /** * @return The dispatcher on the thread. - * * @throws IllegalStateException If there is no dispatcher available */ public Dispatcher findDispatcherOnThread() { @@ -75,12 +78,11 @@ public class InitOperations { * Create a {@link Dispatcher} * * @param filterConfig host configuration - * * @return The dispatcher on the thread. */ protected Dispatcher createDispatcher(HostConfig filterConfig) { Map params = new HashMap<>(); - for ( Iterator parameterNames = filterConfig.getInitParameterNames(); parameterNames.hasNext(); ) { + for (Iterator parameterNames = filterConfig.getInitParameterNames(); parameterNames.hasNext(); ) { String name = parameterNames.next(); String value = filterConfig.getInitParameter(name); params.put(name, value); @@ -96,20 +98,23 @@ public class InitOperations { * Extract a list of patterns to exclude from request filtering * * @param dispatcher The dispatcher to check for exclude pattern configuration - * * @return a List of Patterns for request to exclude if apply, or null - * * @see org.apache.struts2.StrutsConstants#STRUTS_ACTION_EXCLUDE_PATTERN */ - public List buildExcludedPatternsList( Dispatcher dispatcher ) { - return buildExcludedPatternsList(dispatcher.getContainer().getInstance(String.class, StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN)); + public List 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 buildExcludedPatternsList( String patterns ) { + + private List buildExcludedPatternsList(String patterns, String separator) { if (null != patterns && patterns.trim().length() != 0) { List list = new ArrayList<>(); - String[] tokens = patterns.split(","); - for ( String token : tokens ) { + String[] tokens = patterns.split(separator); + for (String token : tokens) { list.add(Pattern.compile(token.trim())); } return Collections.unmodifiableList(list); diff --git a/core/src/test/java/org/apache/struts2/dispatcher/InitOperationsTest.java b/core/src/test/java/org/apache/struts2/dispatcher/InitOperationsTest.java new file mode 100644 index 000000000..aa2aaeaa3 --- /dev/null +++ b/core/src/test/java/org/apache/struts2/dispatcher/InitOperationsTest.java @@ -0,0 +1,86 @@ +/* + * 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.dispatcher; + +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.inject.ContainerBuilder; +import com.opensymphony.xwork2.util.location.LocatableProperties; +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.StrutsInternalTestCase; +import org.apache.struts2.config.PropertiesConfigurationProvider; + +import java.util.List; +import java.util.regex.Pattern; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class InitOperationsTest extends StrutsInternalTestCase { + + public void testExcludePatterns() { + // given + loadConfigurationProviders(new PropertiesConfigurationProvider() { + @Override + public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { + props.setProperty(StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN, "/ns1/.*\\.json,/ns2/.*\\.json"); + } + }); + + Dispatcher mockDispatcher = mock(Dispatcher.class); + when(mockDispatcher.getContainer()).thenReturn(container); + + // when + InitOperations init = new InitOperations(); + List patterns = init.buildExcludedPatternsList(mockDispatcher); + + // then + assertThat(patterns).extracting(Pattern::toString).containsOnly( + "/ns1/.*\\.json", + "/ns2/.*\\.json" + ); + } + + public void testExcludePatternsUsingCustomSeparator() { + // given + loadConfigurationProviders(new PropertiesConfigurationProvider() { + @Override + public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { + props.setProperty(StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN, "/ns1/[a-z]{1,10}.json///ns2/[a-z]{1,10}.json"); + props.setProperty(StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN_SEPARATOR, "//"); + } + }); + + Dispatcher mockDispatcher = mock(Dispatcher.class); + when(mockDispatcher.getContainer()).thenReturn(container); + + // when + InitOperations init = new InitOperations(); + + String separator = container.getInstance(String.class, StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN_SEPARATOR); + List patterns = init.buildExcludedPatternsList(mockDispatcher); + + // then + assertThat(separator).isNotBlank().isEqualTo("//"); + assertThat(patterns).extracting(Pattern::toString).containsOnly( + "/ns1/[a-z]{1,10}.json", + "/ns2/[a-z]{1,10}.json" + ); + } +} From 943cb6295393a784719e00dc4a9d0465e3d150ca Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 21 Oct 2022 10:49:31 +0200 Subject: [PATCH 073/143] WW-5133 Drops labelposition attribute --- .../apache/struts2/components/Checkbox.java | 11 --------- .../org/apache/struts2/components/UIBean.java | 11 --------- .../struts2/views/jsp/ui/AbstractUITag.java | 9 ------- .../resources/template/xhtml/validation.js | 4 ++-- .../src/site/resources/tags/a-attributes.html | 8 ------- .../tags/actionerror-attributes.html | 8 ------- .../tags/actionmessage-attributes.html | 8 ------- .../resources/tags/checkbox-attributes.html | 8 ------- .../tags/checkboxlist-attributes.html | 8 ------- .../resources/tags/combobox-attributes.html | 8 ------- .../resources/tags/component-attributes.html | 8 ------- .../tags/datetextfield-attributes.html | 8 ------- .../site/resources/tags/debug-attributes.html | 8 ------- .../tags/doubleselect-attributes.html | 8 ------- .../resources/tags/fielderror-attributes.html | 8 ------- .../site/resources/tags/file-attributes.html | 8 ------- .../site/resources/tags/form-attributes.html | 8 ------- .../site/resources/tags/head-attributes.html | 8 ------- .../resources/tags/hidden-attributes.html | 8 ------- .../tags/inputtransferselect-attributes.html | 8 ------- .../site/resources/tags/label-attributes.html | 8 ------- .../site/resources/tags/link-attributes.html | 8 ------- .../tags/optiontransferselect-attributes.html | 8 ------- .../resources/tags/password-attributes.html | 8 ------- .../site/resources/tags/radio-attributes.html | 8 ------- .../site/resources/tags/reset-attributes.html | 8 ------- .../resources/tags/script-attributes.html | 8 ------- .../resources/tags/select-attributes.html | 8 ------- .../resources/tags/submit-attributes.html | 8 ------- .../resources/tags/textarea-attributes.html | 8 ------- .../resources/tags/textfield-attributes.html | 8 ------- .../site/resources/tags/token-attributes.html | 8 ------- .../tags/updownselect-attributes.html | 8 ------- .../struts2/views/jsp/ui/CheckboxTest.java | 8 +++---- .../struts2/views/jsp/ui/FormTagTest.java | 24 +++++++++---------- .../struts2/views/jsp/ui/LabelTest.java | 10 ++++---- 36 files changed, 23 insertions(+), 286 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/components/Checkbox.java b/core/src/main/java/org/apache/struts2/components/Checkbox.java index dd853caba..81ea73fa7 100644 --- a/core/src/main/java/org/apache/struts2/components/Checkbox.java +++ b/core/src/main/java/org/apache/struts2/components/Checkbox.java @@ -96,17 +96,6 @@ public class Checkbox extends UIBean { this.submitUnchecked = submitUnchecked; } - /** - * Deprecated since 2.5.27 - * @deprecated use {@link #setLabelPosition(String)} instead - */ - @Deprecated - @Override - @StrutsTagAttribute(description="(Deprecated) Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme") - public void setLabelposition(String labelPosition) { - super.setLabelPosition(labelPosition); - } - @Override @StrutsTagAttribute(description="Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme") public void setLabelPosition(String labelPosition) { diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java index 4a4b5eb2b..5455960d5 100644 --- a/core/src/main/java/org/apache/struts2/components/UIBean.java +++ b/core/src/main/java/org/apache/struts2/components/UIBean.java @@ -689,7 +689,6 @@ public abstract class UIBean extends Component { if (labelPosition != null) { String labelPosition = findString(this.labelPosition); - addParameter("labelposition", labelPosition); addParameter("labelPosition", labelPosition); } @@ -1119,16 +1118,6 @@ public abstract class UIBean extends Component { this.labelSeparator = labelseparator; } - /** - * Deprecated since 2.5.27 - * @deprecated use {@link #setLabelPosition(String)} instead - */ - @StrutsTagAttribute(description="(Deprecated) Define label position of form element (top/left)") - @Deprecated - public void setLabelposition(String labelPosition) { - this.labelPosition = labelPosition; - } - @StrutsTagAttribute(description="Define label position of form element (top/left)") public void setLabelPosition(String labelPosition) { this.labelPosition = labelPosition; diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java index 345d37254..cb2b0b075 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java @@ -173,15 +173,6 @@ public abstract class AbstractUITag extends ComponentTagSupport implements Dynam this.label = label; } - /** - * Deprecated since 2.5.27 - * @deprecated use {@link #setLabelPosition(String)} instead - */ - @Deprecated - public void setLabelposition(String labelPosition) { - this.labelPosition = labelPosition; - } - public void setLabelPosition(String labelPosition) { this.labelPosition = labelPosition; } diff --git a/core/src/main/resources/template/xhtml/validation.js b/core/src/main/resources/template/xhtml/validation.js index feb1a9d14..abeaa7011 100644 --- a/core/src/main/resources/template/xhtml/validation.js +++ b/core/src/main/resources/template/xhtml/validation.js @@ -76,7 +76,7 @@ function clearErrorLabelsXHTML(form) { parentEl = null; } - //if labelposition is 'top' the label is on the row above + //if labelPosition is 'top' the label is on the row above if(parentEl && parentEl.cells) { var labelRow = parentEl.cells.length > 1 ? parentEl : StrutsUtils.previousElement(parentEl, "tr"); if (labelRow) { @@ -120,7 +120,7 @@ function addErrorXHTML(e, errorText) { table.insertBefore(tr, row); // update the label too - //if labelposition is 'top' the label is on the row above + //if labelPosition is 'top' the label is on the row above var labelRow = row.cells.length > 1 ? row : StrutsUtils.previousElement(tr, "tr"); var label = labelRow.cells[0].getElementsByTagName("label")[0]; if (label) { diff --git a/core/src/site/resources/tags/a-attributes.html b/core/src/site/resources/tags/a-attributes.html index e9fd9089c..dc26f4acb 100644 --- a/core/src/site/resources/tags/a-attributes.html +++ b/core/src/site/resources/tags/a-attributes.html @@ -197,14 +197,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - method false diff --git a/core/src/site/resources/tags/actionerror-attributes.html b/core/src/site/resources/tags/actionerror-attributes.html index 4d59c5fe1..4bde23efb 100644 --- a/core/src/site/resources/tags/actionerror-attributes.html +++ b/core/src/site/resources/tags/actionerror-attributes.html @@ -133,14 +133,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/actionmessage-attributes.html b/core/src/site/resources/tags/actionmessage-attributes.html index c00042bc1..1b8e70654 100644 --- a/core/src/site/resources/tags/actionmessage-attributes.html +++ b/core/src/site/resources/tags/actionmessage-attributes.html @@ -133,14 +133,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/checkbox-attributes.html b/core/src/site/resources/tags/checkbox-attributes.html index 23bc4b205..ca70c0528 100644 --- a/core/src/site/resources/tags/checkbox-attributes.html +++ b/core/src/site/resources/tags/checkbox-attributes.html @@ -133,14 +133,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme - name false diff --git a/core/src/site/resources/tags/checkboxlist-attributes.html b/core/src/site/resources/tags/checkboxlist-attributes.html index e75143e02..00eb35f80 100644 --- a/core/src/site/resources/tags/checkboxlist-attributes.html +++ b/core/src/site/resources/tags/checkboxlist-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - list true diff --git a/core/src/site/resources/tags/combobox-attributes.html b/core/src/site/resources/tags/combobox-attributes.html index c1c6454b3..d81412d76 100644 --- a/core/src/site/resources/tags/combobox-attributes.html +++ b/core/src/site/resources/tags/combobox-attributes.html @@ -149,14 +149,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - list true diff --git a/core/src/site/resources/tags/component-attributes.html b/core/src/site/resources/tags/component-attributes.html index d11ee7ece..b1c5caf56 100644 --- a/core/src/site/resources/tags/component-attributes.html +++ b/core/src/site/resources/tags/component-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/datetextfield-attributes.html b/core/src/site/resources/tags/datetextfield-attributes.html index 066ab75db..0e9d618f5 100644 --- a/core/src/site/resources/tags/datetextfield-attributes.html +++ b/core/src/site/resources/tags/datetextfield-attributes.html @@ -133,14 +133,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/debug-attributes.html b/core/src/site/resources/tags/debug-attributes.html index d11ee7ece..b1c5caf56 100644 --- a/core/src/site/resources/tags/debug-attributes.html +++ b/core/src/site/resources/tags/debug-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/doubleselect-attributes.html b/core/src/site/resources/tags/doubleselect-attributes.html index de13fdd73..7ddbe2f0e 100644 --- a/core/src/site/resources/tags/doubleselect-attributes.html +++ b/core/src/site/resources/tags/doubleselect-attributes.html @@ -413,14 +413,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - list true diff --git a/core/src/site/resources/tags/fielderror-attributes.html b/core/src/site/resources/tags/fielderror-attributes.html index 8e1b52154..7f0b4fae2 100644 --- a/core/src/site/resources/tags/fielderror-attributes.html +++ b/core/src/site/resources/tags/fielderror-attributes.html @@ -141,14 +141,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/file-attributes.html b/core/src/site/resources/tags/file-attributes.html index f456771ea..66a193d1b 100644 --- a/core/src/site/resources/tags/file-attributes.html +++ b/core/src/site/resources/tags/file-attributes.html @@ -133,14 +133,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/form-attributes.html b/core/src/site/resources/tags/form-attributes.html index 46784d5e3..73734a1c6 100644 --- a/core/src/site/resources/tags/form-attributes.html +++ b/core/src/site/resources/tags/form-attributes.html @@ -165,14 +165,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - method false diff --git a/core/src/site/resources/tags/head-attributes.html b/core/src/site/resources/tags/head-attributes.html index 4a93dab0f..e69d09195 100644 --- a/core/src/site/resources/tags/head-attributes.html +++ b/core/src/site/resources/tags/head-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/hidden-attributes.html b/core/src/site/resources/tags/hidden-attributes.html index 4a93dab0f..e69d09195 100644 --- a/core/src/site/resources/tags/hidden-attributes.html +++ b/core/src/site/resources/tags/hidden-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/inputtransferselect-attributes.html b/core/src/site/resources/tags/inputtransferselect-attributes.html index 1160bc9f5..d2f68a88d 100644 --- a/core/src/site/resources/tags/inputtransferselect-attributes.html +++ b/core/src/site/resources/tags/inputtransferselect-attributes.html @@ -189,14 +189,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - leftTitle false diff --git a/core/src/site/resources/tags/label-attributes.html b/core/src/site/resources/tags/label-attributes.html index 440ce9b72..b118c807b 100644 --- a/core/src/site/resources/tags/label-attributes.html +++ b/core/src/site/resources/tags/label-attributes.html @@ -133,14 +133,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/link-attributes.html b/core/src/site/resources/tags/link-attributes.html index 668f893e4..f340117f4 100644 --- a/core/src/site/resources/tags/link-attributes.html +++ b/core/src/site/resources/tags/link-attributes.html @@ -157,14 +157,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - media false diff --git a/core/src/site/resources/tags/optiontransferselect-attributes.html b/core/src/site/resources/tags/optiontransferselect-attributes.html index 074624e1e..78f12211e 100644 --- a/core/src/site/resources/tags/optiontransferselect-attributes.html +++ b/core/src/site/resources/tags/optiontransferselect-attributes.html @@ -549,14 +549,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - leftDownLabel false diff --git a/core/src/site/resources/tags/password-attributes.html b/core/src/site/resources/tags/password-attributes.html index 7fd3e771d..c3fb4ce77 100644 --- a/core/src/site/resources/tags/password-attributes.html +++ b/core/src/site/resources/tags/password-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - maxLength false diff --git a/core/src/site/resources/tags/radio-attributes.html b/core/src/site/resources/tags/radio-attributes.html index e75143e02..00eb35f80 100644 --- a/core/src/site/resources/tags/radio-attributes.html +++ b/core/src/site/resources/tags/radio-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - list true diff --git a/core/src/site/resources/tags/reset-attributes.html b/core/src/site/resources/tags/reset-attributes.html index e002708da..b2b742a08 100644 --- a/core/src/site/resources/tags/reset-attributes.html +++ b/core/src/site/resources/tags/reset-attributes.html @@ -133,14 +133,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - method false diff --git a/core/src/site/resources/tags/script-attributes.html b/core/src/site/resources/tags/script-attributes.html index 452acb390..aa9d22ba9 100644 --- a/core/src/site/resources/tags/script-attributes.html +++ b/core/src/site/resources/tags/script-attributes.html @@ -165,14 +165,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/select-attributes.html b/core/src/site/resources/tags/select-attributes.html index 75cbba6cb..b25f92ffc 100644 --- a/core/src/site/resources/tags/select-attributes.html +++ b/core/src/site/resources/tags/select-attributes.html @@ -149,14 +149,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - list true diff --git a/core/src/site/resources/tags/submit-attributes.html b/core/src/site/resources/tags/submit-attributes.html index 52ed55ad0..0d6ef2a8f 100644 --- a/core/src/site/resources/tags/submit-attributes.html +++ b/core/src/site/resources/tags/submit-attributes.html @@ -141,14 +141,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - method false diff --git a/core/src/site/resources/tags/textarea-attributes.html b/core/src/site/resources/tags/textarea-attributes.html index 60119551d..3b75f3045 100644 --- a/core/src/site/resources/tags/textarea-attributes.html +++ b/core/src/site/resources/tags/textarea-attributes.html @@ -133,14 +133,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - maxlength false diff --git a/core/src/site/resources/tags/textfield-attributes.html b/core/src/site/resources/tags/textfield-attributes.html index 194e76874..72fe987f4 100644 --- a/core/src/site/resources/tags/textfield-attributes.html +++ b/core/src/site/resources/tags/textfield-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - maxLength false diff --git a/core/src/site/resources/tags/token-attributes.html b/core/src/site/resources/tags/token-attributes.html index d11ee7ece..b1c5caf56 100644 --- a/core/src/site/resources/tags/token-attributes.html +++ b/core/src/site/resources/tags/token-attributes.html @@ -125,14 +125,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - name false diff --git a/core/src/site/resources/tags/updownselect-attributes.html b/core/src/site/resources/tags/updownselect-attributes.html index 94b2d3099..b827b514e 100644 --- a/core/src/site/resources/tags/updownselect-attributes.html +++ b/core/src/site/resources/tags/updownselect-attributes.html @@ -173,14 +173,6 @@ String String that will be appended to the label - - labelposition - false - - false - String - (Deprecated) Define label position of form element (top/left) - list true diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java index 783d5aefd..7bed748c2 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java @@ -123,7 +123,7 @@ public class CheckboxTest extends AbstractUITagTest { tag.setFieldValue("baz"); tag.setOnfocus("test();"); tag.setTitle("mytitle"); - tag.setLabelposition("top"); + tag.setLabelPosition("top"); tag.doStartTag(); tag.doEndTag(); @@ -151,7 +151,7 @@ public class CheckboxTest extends AbstractUITagTest { tag.setFieldValue("baz"); tag.setOnfocus("test();"); tag.setTitle("mytitle"); - tag.setLabelposition("top"); + tag.setLabelPosition("top"); tag.doStartTag(); setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). @@ -180,7 +180,7 @@ public class CheckboxTest extends AbstractUITagTest { tag.setFieldValue("baz"); tag.setOnfocus("test();"); tag.setTitle("mytitle"); - tag.setLabelposition("left"); + tag.setLabelPosition("left"); tag.doStartTag(); tag.doEndTag(); @@ -208,7 +208,7 @@ public class CheckboxTest extends AbstractUITagTest { tag.setFieldValue("baz"); tag.setOnfocus("test();"); tag.setTitle("mytitle"); - tag.setLabelposition("left"); + tag.setLabelPosition("left"); tag.doStartTag(); setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java index e9fba3ee6..6aa273574 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java @@ -1800,7 +1800,7 @@ public class FormTagTest extends AbstractUITagTest { form.setAction("testAction"); form.setPageContext(pageContext); form.setIncludeContext(false); - form.setLabelposition("top"); + form.setLabelPosition("top"); TextFieldTag text = new TextFieldTag(); text.setPageContext(pageContext); @@ -1835,7 +1835,7 @@ public class FormTagTest extends AbstractUITagTest { form.setAction("testAction"); form.setPageContext(pageContext); form.setIncludeContext(false); - form.setLabelposition("top"); + form.setLabelPosition("top"); TextFieldTag text = new TextFieldTag(); text.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. @@ -1874,12 +1874,12 @@ public class FormTagTest extends AbstractUITagTest { form.setAction("testAction"); form.setPageContext(pageContext); form.setIncludeContext(false); - form.setLabelposition("left"); + form.setLabelPosition("left"); TextFieldTag text = new TextFieldTag(); text.setPageContext(pageContext); text.setLabel("label"); - text.setLabelposition("top"); + text.setLabelPosition("top"); form.doStartTag(); text.doStartTag(); @@ -1910,13 +1910,13 @@ public class FormTagTest extends AbstractUITagTest { form.setAction("testAction"); form.setPageContext(pageContext); form.setIncludeContext(false); - form.setLabelposition("left"); + form.setLabelPosition("left"); TextFieldTag text = new TextFieldTag(); text.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. text.setPageContext(pageContext); text.setLabel("label"); - text.setLabelposition("top"); + text.setLabelPosition("top"); form.doStartTag(); setComponentTagClearTagState(form, true); // Ensure component tag state clearing is set true (to match tag). @@ -1950,7 +1950,7 @@ public class FormTagTest extends AbstractUITagTest { form.setAction("testAction"); form.setPageContext(pageContext); form.setIncludeContext(false); - form.setLabelposition("top"); + form.setLabelPosition("top"); TextFieldTag text = new TextFieldTag(); text.setPageContext(pageContext); @@ -1985,7 +1985,7 @@ public class FormTagTest extends AbstractUITagTest { form.setAction("testAction"); form.setPageContext(pageContext); form.setIncludeContext(false); - form.setLabelposition("top"); + form.setLabelPosition("top"); TextFieldTag text = new TextFieldTag(); text.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. @@ -2024,12 +2024,12 @@ public class FormTagTest extends AbstractUITagTest { form.setAction("testAction"); form.setPageContext(pageContext); form.setIncludeContext(false); - form.setLabelposition("left"); + form.setLabelPosition("left"); TextFieldTag text = new TextFieldTag(); text.setPageContext(pageContext); text.setLabel("label"); - text.setLabelposition("top"); + text.setLabelPosition("top"); form.doStartTag(); text.doStartTag(); @@ -2060,13 +2060,13 @@ public class FormTagTest extends AbstractUITagTest { form.setAction("testAction"); form.setPageContext(pageContext); form.setIncludeContext(false); - form.setLabelposition("left"); + form.setLabelPosition("left"); TextFieldTag text = new TextFieldTag(); text.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. text.setPageContext(pageContext); text.setLabel("label"); - text.setLabelposition("top"); + text.setLabelPosition("top"); form.doStartTag(); setComponentTagClearTagState(form, true); // Ensure component tag state clearing is set true (to match tag). diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java index c277ef9ee..7bc5a7c54 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java @@ -80,7 +80,7 @@ public class LabelTest extends AbstractUITagTest { strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - public void testSimpleWithLabelposition() throws Exception { + public void testSimpleWithLabelPosition() throws Exception { TestAction testAction = (TestAction) action; testAction.setFoo("bar"); @@ -89,7 +89,7 @@ public class LabelTest extends AbstractUITagTest { tag.setLabel("mylabel"); tag.setName("myname"); tag.setValue("%{foo}"); - tag.setLabelposition("top"); + tag.setLabelPosition("top"); tag.doStartTag(); tag.doEndTag(); @@ -104,7 +104,7 @@ public class LabelTest extends AbstractUITagTest { strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - public void testSimpleWithLabelposition_clearTagStateSet() throws Exception { + public void testSimpleWithLabelPosition_clearTagStateSet() throws Exception { TestAction testAction = (TestAction) action; testAction.setFoo("bar"); @@ -114,7 +114,7 @@ public class LabelTest extends AbstractUITagTest { tag.setLabel("mylabel"); tag.setName("myname"); tag.setValue("%{foo}"); - tag.setLabelposition("top"); + tag.setLabelPosition("top"); tag.doStartTag(); setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). @@ -398,7 +398,7 @@ public class LabelTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); - + verify(LabelTest.class.getResource("Label-7.txt")); // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). From 9568888700133a2ba114a3a749fe1a5b22214a7c Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 21 Oct 2022 11:36:54 +0200 Subject: [PATCH 074/143] WW-3725 Removes unused template --- .../template/archive/xhtml/controlheader.vm | 47 ------------------- 1 file changed, 47 deletions(-) delete mode 100644 core/src/main/resources/template/archive/xhtml/controlheader.vm diff --git a/core/src/main/resources/template/archive/xhtml/controlheader.vm b/core/src/main/resources/template/archive/xhtml/controlheader.vm deleted file mode 100644 index 95a289b1b..000000000 --- a/core/src/main/resources/template/archive/xhtml/controlheader.vm +++ /dev/null @@ -1,47 +0,0 @@ -#* - * $Id$ - * - * 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. - *# -## Only show message if errors are available. -## This will be done if ActionSupport is used. -#if( $fieldErrors.get($parameters.name) ) - #set ($hasFieldErrors = $fieldErrors.get($parameters.name)) - #foreach ($error in $fieldErrors.get($parameters.name)) - - #if ($parameters.labelPosition == 'top')#else#end$!struts.htmlEncode($error) - - #end -#end -## if the label position is top, -## then give the label it's own row in the table - -#if ($parameters.labelPosition && $parameters.labelPosition == 'top')#else#end#if ($parameters.label)#end -## add the extra row -#if ($parameters.labelPosition && $parameters.labelPosition == 'top') - - -#end -#if ($parameters.form.validate && $parameters.form.validate == true) - #if ($parameters.onblur) - #set ($parameters.onblur = "validate(this);${parameters.onblur}") - #else - #set ($parameters.onblur = "validate(this)") - #end -#end - From 3e30d0c375b17b817abfa329c2f88976e8ddbba1 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 21 Oct 2022 13:33:11 +0200 Subject: [PATCH 075/143] WW-5137 Removes deprecated class attribute --- .../main/java/org/apache/struts2/components/UIBean.java | 6 ------ core/src/site/resources/tags/a-attributes.html | 8 -------- core/src/site/resources/tags/actionerror-attributes.html | 8 -------- .../src/site/resources/tags/actionmessage-attributes.html | 8 -------- core/src/site/resources/tags/checkbox-attributes.html | 8 -------- core/src/site/resources/tags/checkboxlist-attributes.html | 8 -------- core/src/site/resources/tags/combobox-attributes.html | 8 -------- core/src/site/resources/tags/component-attributes.html | 8 -------- .../src/site/resources/tags/datetextfield-attributes.html | 8 -------- core/src/site/resources/tags/debug-attributes.html | 8 -------- core/src/site/resources/tags/doubleselect-attributes.html | 8 -------- core/src/site/resources/tags/fielderror-attributes.html | 8 -------- core/src/site/resources/tags/file-attributes.html | 8 -------- core/src/site/resources/tags/form-attributes.html | 8 -------- core/src/site/resources/tags/head-attributes.html | 8 -------- core/src/site/resources/tags/hidden-attributes.html | 8 -------- .../resources/tags/inputtransferselect-attributes.html | 8 -------- core/src/site/resources/tags/label-attributes.html | 8 -------- core/src/site/resources/tags/link-attributes.html | 8 -------- .../resources/tags/optiontransferselect-attributes.html | 8 -------- core/src/site/resources/tags/password-attributes.html | 8 -------- core/src/site/resources/tags/radio-attributes.html | 8 -------- core/src/site/resources/tags/reset-attributes.html | 8 -------- core/src/site/resources/tags/script-attributes.html | 8 -------- core/src/site/resources/tags/select-attributes.html | 8 -------- core/src/site/resources/tags/submit-attributes.html | 8 -------- core/src/site/resources/tags/textarea-attributes.html | 8 -------- core/src/site/resources/tags/textfield-attributes.html | 8 -------- core/src/site/resources/tags/token-attributes.html | 8 -------- core/src/site/resources/tags/updownselect-attributes.html | 8 -------- .../java/org/apache/struts2/components/UIBeanTest.java | 4 ++-- 31 files changed, 2 insertions(+), 240 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java index 4a4b5eb2b..057a64f90 100644 --- a/core/src/main/java/org/apache/struts2/components/UIBean.java +++ b/core/src/main/java/org/apache/struts2/components/UIBean.java @@ -1073,12 +1073,6 @@ public abstract class UIBean extends Component { this.cssClass = cssClass; } - @Deprecated - @StrutsTagAttribute(description="(Deprecated) The css class to use for element - it's an alias of cssClass attribute.") - public void setClass(String cssClass) { - this.cssClass = cssClass; - } - @StrutsTagAttribute(description="The css style definitions for element to use") public void setCssStyle(String cssStyle) { this.cssStyle = cssStyle; diff --git a/core/src/site/resources/tags/a-attributes.html b/core/src/site/resources/tags/a-attributes.html index e9fd9089c..904f9f6e8 100644 --- a/core/src/site/resources/tags/a-attributes.html +++ b/core/src/site/resources/tags/a-attributes.html @@ -37,14 +37,6 @@ String The anchor for this URL - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/actionerror-attributes.html b/core/src/site/resources/tags/actionerror-attributes.html index 4d59c5fe1..4024c1a6f 100644 --- a/core/src/site/resources/tags/actionerror-attributes.html +++ b/core/src/site/resources/tags/actionerror-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/actionmessage-attributes.html b/core/src/site/resources/tags/actionmessage-attributes.html index c00042bc1..f63c149ee 100644 --- a/core/src/site/resources/tags/actionmessage-attributes.html +++ b/core/src/site/resources/tags/actionmessage-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/checkbox-attributes.html b/core/src/site/resources/tags/checkbox-attributes.html index 23bc4b205..a5ea75d57 100644 --- a/core/src/site/resources/tags/checkbox-attributes.html +++ b/core/src/site/resources/tags/checkbox-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/checkboxlist-attributes.html b/core/src/site/resources/tags/checkboxlist-attributes.html index e75143e02..4de7aae95 100644 --- a/core/src/site/resources/tags/checkboxlist-attributes.html +++ b/core/src/site/resources/tags/checkboxlist-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/combobox-attributes.html b/core/src/site/resources/tags/combobox-attributes.html index c1c6454b3..fee13f3b9 100644 --- a/core/src/site/resources/tags/combobox-attributes.html +++ b/core/src/site/resources/tags/combobox-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/component-attributes.html b/core/src/site/resources/tags/component-attributes.html index d11ee7ece..a878f240a 100644 --- a/core/src/site/resources/tags/component-attributes.html +++ b/core/src/site/resources/tags/component-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/datetextfield-attributes.html b/core/src/site/resources/tags/datetextfield-attributes.html index 066ab75db..d4f2f3e99 100644 --- a/core/src/site/resources/tags/datetextfield-attributes.html +++ b/core/src/site/resources/tags/datetextfield-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/debug-attributes.html b/core/src/site/resources/tags/debug-attributes.html index d11ee7ece..a878f240a 100644 --- a/core/src/site/resources/tags/debug-attributes.html +++ b/core/src/site/resources/tags/debug-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/doubleselect-attributes.html b/core/src/site/resources/tags/doubleselect-attributes.html index de13fdd73..11c7c62cc 100644 --- a/core/src/site/resources/tags/doubleselect-attributes.html +++ b/core/src/site/resources/tags/doubleselect-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/fielderror-attributes.html b/core/src/site/resources/tags/fielderror-attributes.html index 8e1b52154..46a2fa25e 100644 --- a/core/src/site/resources/tags/fielderror-attributes.html +++ b/core/src/site/resources/tags/fielderror-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/file-attributes.html b/core/src/site/resources/tags/file-attributes.html index f456771ea..a39bdda4f 100644 --- a/core/src/site/resources/tags/file-attributes.html +++ b/core/src/site/resources/tags/file-attributes.html @@ -29,14 +29,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/form-attributes.html b/core/src/site/resources/tags/form-attributes.html index 46784d5e3..45aeddd31 100644 --- a/core/src/site/resources/tags/form-attributes.html +++ b/core/src/site/resources/tags/form-attributes.html @@ -37,14 +37,6 @@ String Set action name to submit to, without .action suffix - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/head-attributes.html b/core/src/site/resources/tags/head-attributes.html index 4a93dab0f..fc840dd6d 100644 --- a/core/src/site/resources/tags/head-attributes.html +++ b/core/src/site/resources/tags/head-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/hidden-attributes.html b/core/src/site/resources/tags/hidden-attributes.html index 4a93dab0f..fc840dd6d 100644 --- a/core/src/site/resources/tags/hidden-attributes.html +++ b/core/src/site/resources/tags/hidden-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/inputtransferselect-attributes.html b/core/src/site/resources/tags/inputtransferselect-attributes.html index 1160bc9f5..2ca7df965 100644 --- a/core/src/site/resources/tags/inputtransferselect-attributes.html +++ b/core/src/site/resources/tags/inputtransferselect-attributes.html @@ -61,14 +61,6 @@ String the css style used for rendering buttons - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/label-attributes.html b/core/src/site/resources/tags/label-attributes.html index 440ce9b72..df79480ee 100644 --- a/core/src/site/resources/tags/label-attributes.html +++ b/core/src/site/resources/tags/label-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/link-attributes.html b/core/src/site/resources/tags/link-attributes.html index 668f893e4..7d52086e2 100644 --- a/core/src/site/resources/tags/link-attributes.html +++ b/core/src/site/resources/tags/link-attributes.html @@ -29,14 +29,6 @@ String HTML link as attribute - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - crossorigin false diff --git a/core/src/site/resources/tags/optiontransferselect-attributes.html b/core/src/site/resources/tags/optiontransferselect-attributes.html index 074624e1e..0f0284745 100644 --- a/core/src/site/resources/tags/optiontransferselect-attributes.html +++ b/core/src/site/resources/tags/optiontransferselect-attributes.html @@ -157,14 +157,6 @@ String Set button css style - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/password-attributes.html b/core/src/site/resources/tags/password-attributes.html index 7fd3e771d..d2a57c24f 100644 --- a/core/src/site/resources/tags/password-attributes.html +++ b/core/src/site/resources/tags/password-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/radio-attributes.html b/core/src/site/resources/tags/radio-attributes.html index e75143e02..4de7aae95 100644 --- a/core/src/site/resources/tags/radio-attributes.html +++ b/core/src/site/resources/tags/radio-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/reset-attributes.html b/core/src/site/resources/tags/reset-attributes.html index e002708da..4a6348a18 100644 --- a/core/src/site/resources/tags/reset-attributes.html +++ b/core/src/site/resources/tags/reset-attributes.html @@ -29,14 +29,6 @@ String Set action attribute. - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/script-attributes.html b/core/src/site/resources/tags/script-attributes.html index 452acb390..80a15c1e6 100644 --- a/core/src/site/resources/tags/script-attributes.html +++ b/core/src/site/resources/tags/script-attributes.html @@ -37,14 +37,6 @@ String HTML script charset attribute - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - crossorigin false diff --git a/core/src/site/resources/tags/select-attributes.html b/core/src/site/resources/tags/select-attributes.html index 75cbba6cb..09cf40fa8 100644 --- a/core/src/site/resources/tags/select-attributes.html +++ b/core/src/site/resources/tags/select-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/submit-attributes.html b/core/src/site/resources/tags/submit-attributes.html index 52ed55ad0..4e8cdb788 100644 --- a/core/src/site/resources/tags/submit-attributes.html +++ b/core/src/site/resources/tags/submit-attributes.html @@ -29,14 +29,6 @@ String Set action attribute. - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/textarea-attributes.html b/core/src/site/resources/tags/textarea-attributes.html index 60119551d..c92033d67 100644 --- a/core/src/site/resources/tags/textarea-attributes.html +++ b/core/src/site/resources/tags/textarea-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cols false diff --git a/core/src/site/resources/tags/textfield-attributes.html b/core/src/site/resources/tags/textfield-attributes.html index 194e76874..85a202ac4 100644 --- a/core/src/site/resources/tags/textfield-attributes.html +++ b/core/src/site/resources/tags/textfield-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/token-attributes.html b/core/src/site/resources/tags/token-attributes.html index d11ee7ece..a878f240a 100644 --- a/core/src/site/resources/tags/token-attributes.html +++ b/core/src/site/resources/tags/token-attributes.html @@ -21,14 +21,6 @@ String Set the html accesskey attribute on rendered html element - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/site/resources/tags/updownselect-attributes.html b/core/src/site/resources/tags/updownselect-attributes.html index 94b2d3099..13a9a5e7d 100644 --- a/core/src/site/resources/tags/updownselect-attributes.html +++ b/core/src/site/resources/tags/updownselect-attributes.html @@ -45,14 +45,6 @@ Boolean Whether or not select all button should be displayed - - class - false - - false - String - (Deprecated) The css class to use for element - it's an alias of cssClass attribute. - cssClass false diff --git a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java index 90575f341..b1f2bcc10 100644 --- a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java +++ b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java @@ -196,7 +196,7 @@ public class UIBeanTest extends StrutsInternalTestCase { MockHttpServletResponse res = new MockHttpServletResponse(); TextField txtFld = new TextField(stack, req, res); - + Template defaultTemplate = txtFld.buildTemplateName(null, defaultTemplateName); Template customTemplate = txtFld.buildTemplateName(customTemplateName, defaultTemplateName); @@ -360,7 +360,7 @@ public class UIBeanTest extends StrutsInternalTestCase { MockHttpServletResponse res = new MockHttpServletResponse(); TextField txtFld = new TextField(stack, req, res); - txtFld.setClass(cssClass); + txtFld.setCssClass(cssClass); txtFld.evaluateParams(); assertEquals(cssClass, txtFld.getParameters().get("cssClass")); From 94a0c6e4258c920be89e9bde4273fe06fec17fc6 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 21 Oct 2022 21:12:41 +0200 Subject: [PATCH 076/143] WW-4173 Adds support to disable processing a given interceptor --- .../xwork2/DefaultActionInvocation.java | 26 +- .../interceptor/AbstractInterceptor.java | 14 +- .../xwork2/interceptor/Interceptor.java | 7 + .../struts2/interceptor/CoepInterceptor.java | 9 +- .../struts2/interceptor/CoopInterceptor.java | 8 +- .../interceptor/FetchMetadataInterceptor.java | 7 +- .../interceptor/csp/CspInterceptor.java | 9 +- .../xwork2/DefaultActionInvocationTest.java | 62 +++- .../opensymphony/xwork2/TestInterceptor.java | 89 ------ .../providers/InterceptorBuilderTest.java | 270 +++++++----------- .../providers/InterceptorForTestPurpose.java | 45 ++- ...ervletDispatchedTestAssertInterceptor.java | 56 ---- 12 files changed, 223 insertions(+), 379 deletions(-) delete mode 100644 core/src/test/java/com/opensymphony/xwork2/TestInterceptor.java delete mode 100644 core/src/test/java/org/apache/struts2/dispatcher/ServletDispatchedTestAssertInterceptor.java diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java index ea2076d4a..8c388d469 100644 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java +++ b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java @@ -73,7 +73,7 @@ public class DefaultActionInvocation implements ActionInvocation { protected UnknownHandlerManager unknownHandlerManager; protected OgnlUtil ognlUtil; protected AsyncManager asyncManager; - protected Callable asyncAction; + protected Callable asyncAction; protected WithLazyParams.LazyParamInjector lazyParamInjector; public DefaultActionInvocation(final Map extraContext, final boolean pushAction) { @@ -101,7 +101,7 @@ public class DefaultActionInvocation implements ActionInvocation { this.container = cont; } - @Inject(required=false) + @Inject(required = false) public void setActionEventListener(ActionEventListener listener) { this.actionEventListener = listener; } @@ -111,7 +111,7 @@ public class DefaultActionInvocation implements ActionInvocation { this.ognlUtil = ognlUtil; } - @Inject(required=false) + @Inject(required = false) public void setAsyncManager(AsyncManager asyncManager) { this.asyncManager = asyncManager; } @@ -214,7 +214,7 @@ public class DefaultActionInvocation implements ActionInvocation { } catch (NullPointerException e) { LOG.debug("Got NPE trying to read result configuration for resultCode [{}]", resultCode); } - + if (resultConfig == null) { // If no result is found for the given resultCode, try to get a wildcard '*' match. resultConfig = results.get("*"); @@ -248,7 +248,12 @@ public class DefaultActionInvocation implements ActionInvocation { if (interceptor instanceof WithLazyParams) { interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext); } - resultCode = interceptor.intercept(DefaultActionInvocation.this); + if (interceptor.isDisabled()) { + LOG.debug("Interceptor: {} is disabled, skipping to next", interceptor.getClass().getSimpleName()); + resultCode = this.invoke(); + } else { + resultCode = interceptor.intercept(DefaultActionInvocation.this); + } } else { resultCode = invokeActionOnly(); } @@ -268,9 +273,7 @@ public class DefaultActionInvocation implements ActionInvocation { if (preResultListeners != null) { LOG.trace("Executing PreResultListeners for result [{}]", result); - for (Object preResultListener : preResultListeners) { - PreResultListener listener = (PreResultListener) preResultListener; - + for (PreResultListener listener : preResultListeners) { listener.beforeResult(this, resultCode); } } @@ -314,7 +317,7 @@ public class DefaultActionInvocation implements ActionInvocation { gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ", defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'"; } - gripe += (((" -- " + e.getMessage()) != null) ? e.getMessage() : " [no message in exception]"); + gripe += e.getMessage(); throw new StrutsException(gripe, e, proxy.getConfig()); } @@ -363,7 +366,7 @@ public class DefaultActionInvocation implements ActionInvocation { result.execute(this); } else if (resultCode != null && !Action.NONE.equals(resultCode)) { throw new ConfigurationException("No result defined for action " + getAction().getClass().getName() - + " and result " + getResultCode(), proxy.getConfig()); + + " and result " + getResultCode(), proxy.getConfig()); } else { if (LOG.isDebugEnabled()) { LOG.debug("No result returned for action {} at {}", getAction().getClass().getName(), proxy.getConfig().getLocation()); @@ -464,6 +467,7 @@ public class DefaultActionInvocation implements ActionInvocation { /** * Save the result to be used later. + * * @param actionConfig current ActionConfig * @param methodResult the result of the action. * @return the result code to process. @@ -476,7 +480,7 @@ public class DefaultActionInvocation implements ActionInvocation { container.inject(explicitResult); return null; } else if (methodResult instanceof Callable) { - asyncAction = (Callable) methodResult; + asyncAction = (Callable) methodResult; return null; } else { return (String) methodResult; diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java index 250d68098..2895bc0f0 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java @@ -25,21 +25,31 @@ import com.opensymphony.xwork2.ActionInvocation; */ public abstract class AbstractInterceptor implements Interceptor { + private boolean disabled; + /** * Does nothing */ public void init() { } - + /** * Does nothing */ public void destroy() { } - /** * Override to handle interception */ public abstract String intercept(ActionInvocation invocation) throws Exception; + + public void setDisabled(String disable) { + this.disabled = Boolean.parseBoolean(disable); + } + + @Override + public boolean isDisabled() { + return this.disabled; + } } diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java index cafa08fc0..c60c2f416 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java @@ -219,4 +219,11 @@ public interface Interceptor extends Serializable { */ String intercept(ActionInvocation invocation) throws Exception; + /** + * Allows to disable processing a given interceptor + * + * @return true if the given interceptor should be skipped + * @since 6.1.0 + */ + boolean isDisabled(); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java index 6f9df6e11..c887877dc 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java @@ -47,12 +47,11 @@ public class CoepInterceptor extends AbstractInterceptor implements PreResultLis private static final String COEP_REPORT_HEADER = "Cross-Origin-Embedder-Policy-Report-Only"; private final Set exemptedPaths = new HashSet<>(); - private boolean disabled = false; private String header = COEP_ENFORCING_HEADER; @Override public String intercept(ActionInvocation invocation) throws Exception { - if (disabled) { + if (this.isDisabled()) { LOG.trace("COEP interceptor has been disabled"); } else { invocation.addPreResultListener(this); @@ -62,7 +61,7 @@ public class CoepInterceptor extends AbstractInterceptor implements PreResultLis @Override public void beforeResult(ActionInvocation invocation, String resultCode) { - if (disabled) { + if (this.isDisabled()) { return; } @@ -92,8 +91,4 @@ public class CoepInterceptor extends AbstractInterceptor implements PreResultLis } } - public void setDisabled(String value) { - disabled = Boolean.parseBoolean(value); - } - } diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java index ed1af3a04..5590ca98f 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java @@ -49,12 +49,11 @@ public class CoopInterceptor extends AbstractInterceptor implements PreResultLis private static final String COOP_HEADER = "Cross-Origin-Opener-Policy"; private final Set exemptedPaths = new HashSet<>(); - private boolean disabled = false; private String mode = SAME_ORIGIN; @Override public String intercept(ActionInvocation invocation) throws Exception { - if (disabled) { + if (this.isDisabled()) { LOG.trace("COOP interceptor has been disabled"); } else { invocation.addPreResultListener(this); @@ -64,7 +63,7 @@ public class CoopInterceptor extends AbstractInterceptor implements PreResultLis @Override public void beforeResult(ActionInvocation invocation, String resultCode) { - if (disabled) { + if (this.isDisabled()) { return; } HttpServletRequest request = invocation.getInvocationContext().getServletRequest(); @@ -95,7 +94,4 @@ public class CoopInterceptor extends AbstractInterceptor implements PreResultLis this.mode = mode; } - public void setDisabled(String value) { - this.disabled = Boolean.parseBoolean(value); - } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java index 5c119dd84..0122d718b 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java @@ -55,8 +55,6 @@ public class FetchMetadataInterceptor extends AbstractInterceptor { private final Set exemptedPaths = new HashSet<>(); private final ResourceIsolationPolicy resourceIsolationPolicy = new StrutsResourceIsolationPolicy(); - private boolean disabled = false; - @Inject(required = false) public void setExemptedPaths(String paths) { this.exemptedPaths.addAll(TextParseUtil.commaDelimitedStringToSet(paths)); @@ -64,7 +62,7 @@ public class FetchMetadataInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation invocation) throws Exception { - if (disabled) { + if (this.isDisabled()) { LOG.trace("Fetch Metadata interceptor has been disabled"); return invocation.invoke(); } @@ -111,7 +109,4 @@ public class FetchMetadataInterceptor extends AbstractInterceptor { response.setHeader(VARY_HEADER, VARY_HEADER_VALUE); } - public void setDisabled(String value) { - this.disabled = Boolean.parseBoolean(value); - } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java index ecf9697a9..eb3ddb4a0 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java @@ -45,11 +45,9 @@ public final class CspInterceptor extends AbstractInterceptor implements PreResu private final CspSettings settings = new DefaultCspSettings(); - private boolean disabled = false; - @Override public String intercept(ActionInvocation invocation) throws Exception { - if (disabled) { + if (this.isDisabled()) { LOG.trace("CSP interceptor has been disabled"); } else { invocation.addPreResultListener(this); @@ -58,7 +56,7 @@ public final class CspInterceptor extends AbstractInterceptor implements PreResu } public void beforeResult(ActionInvocation invocation, String resultCode) { - if (disabled) { + if (this.isDisabled()) { return; } HttpServletRequest request = invocation.getInvocationContext().getServletRequest(); @@ -93,7 +91,4 @@ public final class CspInterceptor extends AbstractInterceptor implements PreResu settings.setEnforcingMode(enforcingMode); } - public void setDisabled(String value) { - this.disabled = Boolean.parseBoolean(value); - } } diff --git a/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java index a0d53c9b6..0d2ca8918 100644 --- a/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java @@ -26,6 +26,8 @@ import com.opensymphony.xwork2.interceptor.PreResultListener; import com.opensymphony.xwork2.mock.MockActionProxy; import com.opensymphony.xwork2.mock.MockInterceptor; import com.opensymphony.xwork2.mock.MockResult; +import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory; +import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory; import com.opensymphony.xwork2.ognl.OgnlUtil; import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.util.ValueStackFactory; @@ -90,6 +92,36 @@ public class DefaultActionInvocationTest extends XWorkTestCase { } } + public void testInvokeWithDisabledInterceptors() throws Exception { + // given + List interceptorMappings = new ArrayList<>(); + MockInterceptor mockInterceptor1 = new MockInterceptor(); + mockInterceptor1.setFoo("test1"); + mockInterceptor1.setExpectedFoo("test1"); + interceptorMappings.add(new InterceptorMapping("test1", mockInterceptor1)); + MockInterceptor mockInterceptor2 = new MockInterceptor(); + interceptorMappings.add(new InterceptorMapping("test2", mockInterceptor2)); + mockInterceptor2.setDisabled("true"); + MockInterceptor mockInterceptor3 = new MockInterceptor(); + interceptorMappings.add(new InterceptorMapping("test3", mockInterceptor3)); + mockInterceptor3.setFoo("test3"); + mockInterceptor3.setExpectedFoo("test3"); + + // when + DefaultActionInvocation defaultActionInvocation = new DefaultActionInvocationTester(interceptorMappings); + container.inject(defaultActionInvocation); + defaultActionInvocation.stack = container.getInstance(ValueStackFactory.class).createValueStack(); + + defaultActionInvocation.setResultCode(""); + defaultActionInvocation.invoke(); + + // then + assertTrue(mockInterceptor1.isExecuted()); + assertFalse(mockInterceptor2.isExecuted()); + assertTrue(mockInterceptor3.isExecuted()); + assertTrue(defaultActionInvocation.isExecuted()); + } + public void testInvokingExistingExecuteMethod() throws Exception { // given DefaultActionInvocation dai = new DefaultActionInvocation(ActionContext.getContext().getContextMap(), false); @@ -106,7 +138,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { dai.stack = container.getInstance(ValueStackFactory.class).createValueStack(); dai.proxy = proxy; - dai.ognlUtil = new OgnlUtil(); + dai.ognlUtil = createOgnlUtil(); // when String result = dai.invokeAction(action, null); @@ -138,7 +170,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { dai.stack = container.getInstance(ValueStackFactory.class).createValueStack(); dai.proxy = proxy; - dai.ognlUtil = new OgnlUtil(); + dai.ognlUtil = createOgnlUtil(); dai.unknownHandlerManager = uhm; // when @@ -154,7 +186,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { assertTrue(actual instanceof NoSuchMethodException); } - public void testInvokingExistingMethodThatThrowsException() throws Exception { + public void testInvokingExistingMethodThatThrowsException() { // given DefaultActionInvocation dai = new DefaultActionInvocation(ActionContext.getContext().getContextMap(), false); container.inject(dai); @@ -170,7 +202,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { dai.stack = container.getInstance(ValueStackFactory.class).createValueStack(); dai.proxy = proxy; - dai.ognlUtil = new OgnlUtil(); + dai.ognlUtil = createOgnlUtil(); // when Throwable actual = null; @@ -185,7 +217,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { assertTrue(actual instanceof IllegalArgumentException); } - public void testUnknownHandlerManagerThatThrowsException() throws Exception { + public void testUnknownHandlerManagerThatThrowsException() { // given DefaultActionInvocation dai = new DefaultActionInvocation(ActionContext.getContext().getContextMap(), false); container.inject(dai); @@ -207,7 +239,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { dai.stack = container.getInstance(ValueStackFactory.class).createValueStack(); dai.proxy = proxy; - dai.ognlUtil = new OgnlUtil(); + dai.ognlUtil = createOgnlUtil(); dai.unknownHandlerManager = uhm; // when @@ -224,7 +256,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { assertTrue(actual instanceof NoSuchMethodException); } - public void testUnknownHandlerManagerThatReturnsNull() throws Exception { + public void testUnknownHandlerManagerThatReturnsNull() { // given DefaultActionInvocation dai = new DefaultActionInvocation(ActionContext.getContext().getContextMap(), false); container.inject(dai); @@ -246,7 +278,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { dai.stack = container.getInstance(ValueStackFactory.class).createValueStack(); dai.proxy = proxy; - dai.ognlUtil = new OgnlUtil(); + dai.ognlUtil = createOgnlUtil(); dai.unknownHandlerManager = uhm; // when @@ -284,7 +316,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { dai.stack = container.getInstance(ValueStackFactory.class).createValueStack(); dai.proxy = proxy; - dai.ognlUtil = new OgnlUtil(); + dai.ognlUtil = createOgnlUtil(); dai.unknownHandlerManager = uhm; // when @@ -376,7 +408,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { interceptorMappings.add(new InterceptorMapping("test1", mockInterceptor1)); dai.interceptors = interceptorMappings.iterator(); - dai.ognlUtil = new OgnlUtil(); + dai.ognlUtil = createOgnlUtil(); dai.invoke(); @@ -480,8 +512,14 @@ public class DefaultActionInvocationTest extends XWorkTestCase { loadConfigurationProviders(configurationProvider); } + private OgnlUtil createOgnlUtil() { + return new OgnlUtil( + new DefaultOgnlExpressionCacheFactory<>(), + new DefaultOgnlBeanInfoCacheFactory<>() + ); + } - private class SimpleActionEventListener implements ActionEventListener { + private static class SimpleActionEventListener implements ActionEventListener { private final String name; private final String result; @@ -507,7 +545,7 @@ public class DefaultActionInvocationTest extends XWorkTestCase { class DefaultActionInvocationTester extends DefaultActionInvocation { DefaultActionInvocationTester(List interceptorMappings) { - super(new HashMap(), false); + super(new HashMap<>(), false); interceptors = interceptorMappings.iterator(); MockActionProxy actionProxy = new MockActionProxy(); actionProxy.setMethod("execute"); diff --git a/core/src/test/java/com/opensymphony/xwork2/TestInterceptor.java b/core/src/test/java/com/opensymphony/xwork2/TestInterceptor.java deleted file mode 100644 index 210cb7039..000000000 --- a/core/src/test/java/com/opensymphony/xwork2/TestInterceptor.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 com.opensymphony.xwork2; - -import com.opensymphony.xwork2.interceptor.Interceptor; -import org.junit.Assert; - - -/** - * TestInterceptor - * - * @author Jason Carreira - * Created Apr 21, 2003 9:04:06 PM - */ -public class TestInterceptor implements Interceptor { - - public static final String DEFAULT_FOO_VALUE = "fooDefault"; - - - private String expectedFoo = DEFAULT_FOO_VALUE; - private String foo = DEFAULT_FOO_VALUE; - private boolean executed = false; - - - public boolean isExecuted() { - return executed; - } - - public void setExpectedFoo(String expectedFoo) { - this.expectedFoo = expectedFoo; - } - - public String getExpectedFoo() { - return expectedFoo; - } - - public void setFoo(String foo) { - this.foo = foo; - } - - public String getFoo() { - return foo; - } - - /** - * Called to let an interceptor clean up any resources it has allocated. - */ - public void destroy() { - } - - /** - * Called after an Interceptor is created, but before any requests are processed using the intercept() methodName. This - * gives the Interceptor a chance to initialize any needed resources. - */ - public void init() { - } - - /** - * Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the - * request by the DefaultActionInvocation or to short-circuit the processing and just return a String return code. - * - * @param invocation - * @return - * @throws Exception - */ - public String intercept(ActionInvocation invocation) throws Exception { - executed = true; - Assert.assertNotSame(DEFAULT_FOO_VALUE, foo); - Assert.assertEquals(expectedFoo, foo); - - return invocation.invoke(); - } -} diff --git a/core/src/test/java/com/opensymphony/xwork2/config/providers/InterceptorBuilderTest.java b/core/src/test/java/com/opensymphony/xwork2/config/providers/InterceptorBuilderTest.java index a0ab50e86..d26b326c9 100644 --- a/core/src/test/java/com/opensymphony/xwork2/config/providers/InterceptorBuilderTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/config/providers/InterceptorBuilderTest.java @@ -25,7 +25,7 @@ import com.opensymphony.xwork2.config.entities.InterceptorConfig; import com.opensymphony.xwork2.config.entities.InterceptorMapping; import com.opensymphony.xwork2.config.entities.InterceptorStackConfig; import com.opensymphony.xwork2.config.entities.PackageConfig; -import com.opensymphony.xwork2.interceptor.Interceptor; +import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import java.util.Collections; import java.util.LinkedHashMap; @@ -33,9 +33,6 @@ import java.util.List; /** * InterceptorBuilderTest - * - * @author Rainer Hermanns - * @version $Id$ */ public class InterceptorBuilderTest extends XWorkTestCase { @@ -46,7 +43,7 @@ public class InterceptorBuilderTest extends XWorkTestCase { super.setUp(); objectFactory = container.getInstance(ObjectFactory.class); } - + /** * Try to test this * @@ -55,91 +52,84 @@ public class InterceptorBuilderTest extends XWorkTestCase { * interceptor2_value1 * interceptor2_value2 * - * - * @throws Exception */ - public void testBuildInterceptor_1() throws Exception { + public void testBuildInterceptor_1() { InterceptorStackConfig interceptorStackConfig1 = new InterceptorStackConfig.Builder("interceptorStack1").build(); InterceptorConfig interceptorConfig1 = new InterceptorConfig.Builder("interceptor1", "com.opensymphony.xwork2.config.providers.InterceptorBuilderTest$MockInterceptor1").build(); - InterceptorConfig interceptorConfig2 = new InterceptorConfig.Builder("interceptor2", "com.opensymphony.xwork2.config.providers.InterceptorBuilderTest$MockInterceptor2").build(); - PackageConfig packageConfig = new PackageConfig.Builder("package1").namespace("/namespace").addInterceptorConfig(interceptorConfig1).addInterceptorConfig(interceptorConfig2).addInterceptorStackConfig(interceptorStackConfig1).build(); - List - interceptorMappings = - InterceptorBuilder.constructInterceptorReference(packageConfig, "interceptorStack1", - new LinkedHashMap() { - private static final long serialVersionUID = -1358620486812957895L; - - { - put("interceptor1.param1", "interceptor1_value1"); - put("interceptor1.param2", "interceptor1_value2"); - put("interceptor2.param1", "interceptor2_value1"); - put("interceptor2.param2", "interceptor2_value2"); - } - },null, objectFactory); + List interceptorMappings = + InterceptorBuilder.constructInterceptorReference(packageConfig, "interceptorStack1", + new LinkedHashMap() { + { + put("interceptor1.param1", "interceptor1_value1"); + put("interceptor1.param2", "interceptor1_value2"); + put("interceptor2.param1", "interceptor2_value1"); + put("interceptor2.param2", "interceptor2_value2"); + } + }, null, objectFactory); assertEquals(interceptorMappings.size(), 2); - assertEquals(((InterceptorMapping) interceptorMappings.get(0)).getName(), "interceptor1"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(0)).getInterceptor().getClass(), MockInterceptor1.class); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()).getParam1(), "interceptor1_value1"); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()).getParam2(), "interceptor1_value2"); + assertEquals(interceptorMappings.get(0).getName(), "interceptor1"); + assertNotNull(interceptorMappings.get(0).getInterceptor()); + assertEquals(interceptorMappings.get(0).getInterceptor().getClass(), MockInterceptor1.class); + assertEquals(((MockInterceptor1) interceptorMappings.get(0).getInterceptor()).getParam1(), "interceptor1_value1"); + assertEquals(((MockInterceptor1) interceptorMappings.get(0).getInterceptor()).getParam2(), "interceptor1_value2"); - assertEquals(((InterceptorMapping) interceptorMappings.get(1)).getName(), "interceptor2"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(1)).getInterceptor().getClass(), MockInterceptor2.class); - assertEquals(((MockInterceptor2) ((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()).getParam1(), "interceptor2_value1"); - assertEquals(((MockInterceptor2) ((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()).getParam2(), "interceptor2_value2"); + assertEquals(interceptorMappings.get(1).getName(), "interceptor2"); + assertNotNull(interceptorMappings.get(1).getInterceptor()); + assertEquals(interceptorMappings.get(1).getInterceptor().getClass(), MockInterceptor2.class); + assertEquals(((MockInterceptor2) interceptorMappings.get(1).getInterceptor()).getParam1(), "interceptor2_value1"); + assertEquals(((MockInterceptor2) interceptorMappings.get(1).getInterceptor()).getParam2(), "interceptor2_value2"); } - public void testMultipleSameInterceptors() throws Exception { + public void testMultipleSameInterceptors() { InterceptorConfig interceptorConfig1 = new InterceptorConfig.Builder("interceptor1", "com.opensymphony.xwork2.config.providers.InterceptorBuilderTest$MockInterceptor1").build(); InterceptorConfig interceptorConfig2 = new InterceptorConfig.Builder("interceptor2", "com.opensymphony.xwork2.config.providers.InterceptorBuilderTest$MockInterceptor2").build(); InterceptorStackConfig interceptorStackConfig1 = new InterceptorStackConfig.Builder("multiStack") - .addInterceptor(new InterceptorMapping(interceptorConfig1.getName(), objectFactory.buildInterceptor(interceptorConfig1, Collections.emptyMap()))) - .addInterceptor(new InterceptorMapping(interceptorConfig2.getName(), objectFactory.buildInterceptor(interceptorConfig2, Collections.emptyMap()))) - .addInterceptor(new InterceptorMapping(interceptorConfig1.getName(), objectFactory.buildInterceptor(interceptorConfig1, Collections.emptyMap()))) - .build(); + .addInterceptor(new InterceptorMapping(interceptorConfig1.getName(), objectFactory.buildInterceptor(interceptorConfig1, Collections.emptyMap()))) + .addInterceptor(new InterceptorMapping(interceptorConfig2.getName(), objectFactory.buildInterceptor(interceptorConfig2, Collections.emptyMap()))) + .addInterceptor(new InterceptorMapping(interceptorConfig1.getName(), objectFactory.buildInterceptor(interceptorConfig1, Collections.emptyMap()))) + .build(); PackageConfig packageConfig = new PackageConfig.Builder("package1") - .namespace("/namespace") - .addInterceptorConfig(interceptorConfig1) - .addInterceptorConfig(interceptorConfig2) - .addInterceptorConfig(interceptorConfig1) - .addInterceptorStackConfig(interceptorStackConfig1) - .build(); + .namespace("/namespace") + .addInterceptorConfig(interceptorConfig1) + .addInterceptorConfig(interceptorConfig2) + .addInterceptorConfig(interceptorConfig1) + .addInterceptorStackConfig(interceptorStackConfig1) + .build(); - List interceptorMappings = InterceptorBuilder.constructInterceptorReference(packageConfig, "multiStack", - new LinkedHashMap() { - { - put("interceptor1.param1", "interceptor1_value1"); - put("interceptor1.param2", "interceptor1_value2"); - } - }, null, objectFactory); + List interceptorMappings = InterceptorBuilder.constructInterceptorReference(packageConfig, "multiStack", + new LinkedHashMap() { + { + put("interceptor1.param1", "interceptor1_value1"); + put("interceptor1.param2", "interceptor1_value2"); + } + }, null, objectFactory); assertEquals(interceptorMappings.size(), 3); - assertEquals(((InterceptorMapping) interceptorMappings.get(0)).getName(), "interceptor1"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(0)).getInterceptor().getClass(), MockInterceptor1.class); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()).getParam1(), "interceptor1_value1"); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()).getParam2(), "interceptor1_value2"); + assertEquals(interceptorMappings.get(0).getName(), "interceptor1"); + assertNotNull(interceptorMappings.get(0).getInterceptor()); + assertEquals(interceptorMappings.get(0).getInterceptor().getClass(), MockInterceptor1.class); + assertEquals(((MockInterceptor1) interceptorMappings.get(0).getInterceptor()).getParam1(), "interceptor1_value1"); + assertEquals(((MockInterceptor1) interceptorMappings.get(0).getInterceptor()).getParam2(), "interceptor1_value2"); - assertEquals(((InterceptorMapping) interceptorMappings.get(1)).getName(), "interceptor2"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(1)).getInterceptor().getClass(), MockInterceptor2.class); + assertEquals(interceptorMappings.get(1).getName(), "interceptor2"); + assertNotNull(interceptorMappings.get(1).getInterceptor()); + assertEquals(interceptorMappings.get(1).getInterceptor().getClass(), MockInterceptor2.class); - assertEquals(((InterceptorMapping) interceptorMappings.get(2)).getName(), "interceptor1"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(2)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(2)).getInterceptor().getClass(), MockInterceptor1.class); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(2)).getInterceptor()).getParam1(), "interceptor1_value1"); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(2)).getInterceptor()).getParam2(), "interceptor1_value2"); + assertEquals(interceptorMappings.get(2).getName(), "interceptor1"); + assertNotNull(interceptorMappings.get(2).getInterceptor()); + assertEquals(interceptorMappings.get(2).getInterceptor().getClass(), MockInterceptor1.class); + assertEquals(((MockInterceptor1) interceptorMappings.get(2).getInterceptor()).getParam1(), "interceptor1_value1"); + assertEquals(((MockInterceptor1) interceptorMappings.get(2).getInterceptor()).getParam2(), "interceptor1_value2"); } /** @@ -150,53 +140,45 @@ public class InterceptorBuilderTest extends XWorkTestCase { * interceptor2_value1 * interceptor2_value2 * - * - * @throws Exception */ - public void testBuildInterceptor_2() throws Exception { + public void testBuildInterceptor_2() { InterceptorStackConfig interceptorStackConfig1 = new InterceptorStackConfig.Builder("interceptorStack1").build(); - InterceptorStackConfig interceptorStackConfig2 = new InterceptorStackConfig.Builder("interceptorStack2").build(); - InterceptorStackConfig interceptorStackConfig3 = new InterceptorStackConfig.Builder("interceptorStack3").build(); InterceptorConfig interceptorConfig1 = new InterceptorConfig.Builder("interceptor1", "com.opensymphony.xwork2.config.providers.InterceptorBuilderTest$MockInterceptor1").build(); - InterceptorConfig interceptorConfig2 = new InterceptorConfig.Builder("interceptor2", "com.opensymphony.xwork2.config.providers.InterceptorBuilderTest$MockInterceptor2").build(); + PackageConfig packageConfig = new PackageConfig.Builder("package1").namespace("/namespace"). + addInterceptorConfig(interceptorConfig1). + addInterceptorConfig(interceptorConfig2). + addInterceptorStackConfig(interceptorStackConfig1). + addInterceptorStackConfig(interceptorStackConfig2). + addInterceptorStackConfig(interceptorStackConfig3).build(); - PackageConfig packageConfig = new PackageConfig.Builder("package1").namespace("/namspace"). - addInterceptorConfig(interceptorConfig1). - addInterceptorConfig(interceptorConfig2). - addInterceptorStackConfig(interceptorStackConfig1). - addInterceptorStackConfig(interceptorStackConfig2). - addInterceptorStackConfig(interceptorStackConfig3).build(); - - List interceptorMappings = InterceptorBuilder.constructInterceptorReference(packageConfig, "interceptorStack1", - new LinkedHashMap() { - private static final long serialVersionUID = -5819935102242042570L; - - { - put("interceptorStack2.interceptor1.param1", "interceptor1_value1"); - put("interceptorStack2.interceptor1.param2", "interceptor1_value2"); - put("interceptorStack3.interceptor2.param1", "interceptor2_value1"); - put("interceptorStack3.interceptor2.param2", "interceptor2_value2"); - } - }, null, objectFactory); + List interceptorMappings = InterceptorBuilder.constructInterceptorReference(packageConfig, "interceptorStack1", + new LinkedHashMap() { + { + put("interceptorStack2.interceptor1.param1", "interceptor1_value1"); + put("interceptorStack2.interceptor1.param2", "interceptor1_value2"); + put("interceptorStack3.interceptor2.param1", "interceptor2_value1"); + put("interceptorStack3.interceptor2.param2", "interceptor2_value2"); + } + }, null, objectFactory); assertEquals(interceptorMappings.size(), 2); - assertEquals(((InterceptorMapping) interceptorMappings.get(0)).getName(), "interceptor1"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(0)).getInterceptor().getClass(), MockInterceptor1.class); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()).getParam1(), "interceptor1_value1"); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()).getParam2(), "interceptor1_value2"); + assertEquals(interceptorMappings.get(0).getName(), "interceptor1"); + assertNotNull(interceptorMappings.get(0).getInterceptor()); + assertEquals(interceptorMappings.get(0).getInterceptor().getClass(), MockInterceptor1.class); + assertEquals(((MockInterceptor1) interceptorMappings.get(0).getInterceptor()).getParam1(), "interceptor1_value1"); + assertEquals(((MockInterceptor1) interceptorMappings.get(0).getInterceptor()).getParam2(), "interceptor1_value2"); - assertEquals(((InterceptorMapping) interceptorMappings.get(1)).getName(), "interceptor2"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(1)).getInterceptor().getClass(), MockInterceptor2.class); - assertEquals(((MockInterceptor2) ((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()).getParam1(), "interceptor2_value1"); - assertEquals(((MockInterceptor2) ((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()).getParam2(), "interceptor2_value2"); + assertEquals(interceptorMappings.get(1).getName(), "interceptor2"); + assertNotNull(interceptorMappings.get(1).getInterceptor()); + assertEquals(interceptorMappings.get(1).getInterceptor().getClass(), MockInterceptor2.class); + assertEquals(((MockInterceptor2) interceptorMappings.get(1).getInterceptor()).getParam1(), "interceptor2_value1"); + assertEquals(((MockInterceptor2) interceptorMappings.get(1).getInterceptor()).getParam2(), "interceptor2_value2"); } /** @@ -207,72 +189,53 @@ public class InterceptorBuilderTest extends XWorkTestCase { * interceptor2_value1 * interceptor2_value2 * - * - * @throws Exception */ - public void testBuildInterceptor_3() throws Exception { + public void testBuildInterceptor_3() { InterceptorConfig interceptorConfig1 = new InterceptorConfig.Builder("interceptor1", "com.opensymphony.xwork2.config.providers.InterceptorBuilderTest$MockInterceptor1").build(); - InterceptorConfig interceptorConfig2 = new InterceptorConfig.Builder("interceptor2", "com.opensymphony.xwork2.config.providers.InterceptorBuilderTest$MockInterceptor2").build(); - InterceptorStackConfig interceptorStackConfig1 = new InterceptorStackConfig.Builder("interceptorStack1").build(); - - InterceptorStackConfig interceptorStackConfig2 = new InterceptorStackConfig.Builder("interceptorStack2").build(); - - InterceptorStackConfig interceptorStackConfig3 = new InterceptorStackConfig.Builder("interceptorStack3").build(); - - InterceptorStackConfig interceptorStackConfig4 = new InterceptorStackConfig.Builder("interceptorStack4").build(); - - InterceptorStackConfig interceptorStackConfig5 = new InterceptorStackConfig.Builder("interceptorStack5").build(); - - PackageConfig packageConfig = new PackageConfig.Builder("package1"). - addInterceptorConfig(interceptorConfig1). - addInterceptorConfig(interceptorConfig2). - addInterceptorStackConfig(interceptorStackConfig1). - addInterceptorStackConfig(interceptorStackConfig2). - addInterceptorStackConfig(interceptorStackConfig3). - addInterceptorStackConfig(interceptorStackConfig4). - addInterceptorStackConfig(interceptorStackConfig5).build(); + addInterceptorConfig(interceptorConfig1). + addInterceptorConfig(interceptorConfig2). + addInterceptorStackConfig(interceptorStackConfig1). + addInterceptorStackConfig(interceptorStackConfig2). + addInterceptorStackConfig(interceptorStackConfig3). + addInterceptorStackConfig(interceptorStackConfig4). + addInterceptorStackConfig(interceptorStackConfig5).build(); - - List interceptorMappings = InterceptorBuilder.constructInterceptorReference( - packageConfig, "interceptorStack1", - new LinkedHashMap() { - private static final long serialVersionUID = 4675809753780875525L; - - { - put("interceptorStack2.interceptorStack3.interceptorStack4.interceptor1.param1", "interceptor1_value1"); - put("interceptorStack2.interceptorStack3.interceptorStack4.interceptor1.param2", "interceptor1_value2"); - put("interceptorStack5.interceptor2.param1", "interceptor2_value1"); - put("interceptorStack5.interceptor2.param2", "interceptor2_value2"); - } - }, null, objectFactory); + List interceptorMappings = InterceptorBuilder.constructInterceptorReference( + packageConfig, "interceptorStack1", + new LinkedHashMap() { + { + put("interceptorStack2.interceptorStack3.interceptorStack4.interceptor1.param1", "interceptor1_value1"); + put("interceptorStack2.interceptorStack3.interceptorStack4.interceptor1.param2", "interceptor1_value2"); + put("interceptorStack5.interceptor2.param1", "interceptor2_value1"); + put("interceptorStack5.interceptor2.param2", "interceptor2_value2"); + } + }, null, objectFactory); assertEquals(interceptorMappings.size(), 2); - assertEquals(((InterceptorMapping) interceptorMappings.get(0)).getName(), "interceptor1"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(0)).getInterceptor().getClass(), MockInterceptor1.class); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()).getParam1(), "interceptor1_value1"); - assertEquals(((MockInterceptor1) ((InterceptorMapping) interceptorMappings.get(0)).getInterceptor()).getParam2(), "interceptor1_value2"); + assertEquals(interceptorMappings.get(0).getName(), "interceptor1"); + assertNotNull(interceptorMappings.get(0).getInterceptor()); + assertEquals(interceptorMappings.get(0).getInterceptor().getClass(), MockInterceptor1.class); + assertEquals(((MockInterceptor1) interceptorMappings.get(0).getInterceptor()).getParam1(), "interceptor1_value1"); + assertEquals(((MockInterceptor1) interceptorMappings.get(0).getInterceptor()).getParam2(), "interceptor1_value2"); - assertEquals(((InterceptorMapping) interceptorMappings.get(1)).getName(), "interceptor2"); - assertNotNull(((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()); - assertEquals(((InterceptorMapping) interceptorMappings.get(1)).getInterceptor().getClass(), MockInterceptor2.class); - assertEquals(((MockInterceptor2) ((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()).getParam1(), "interceptor2_value1"); - assertEquals(((MockInterceptor2) ((InterceptorMapping) interceptorMappings.get(1)).getInterceptor()).getParam2(), "interceptor2_value2"); + assertEquals(interceptorMappings.get(1).getName(), "interceptor2"); + assertNotNull(interceptorMappings.get(1).getInterceptor()); + assertEquals(interceptorMappings.get(1).getInterceptor().getClass(), MockInterceptor2.class); + assertEquals(((MockInterceptor2) interceptorMappings.get(1).getInterceptor()).getParam1(), "interceptor2_value1"); + assertEquals(((MockInterceptor2) interceptorMappings.get(1).getInterceptor()).getParam2(), "interceptor2_value2"); } - - public static class MockInterceptor1 implements Interceptor { - private static final long serialVersionUID = 2939902550126175874L; + public static class MockInterceptor1 extends AbstractInterceptor { private String param1; private String param2; @@ -292,19 +255,12 @@ public class InterceptorBuilderTest extends XWorkTestCase { return this.param2; } - public void destroy() { - } - - public void init() { - } - public String intercept(ActionInvocation invocation) throws Exception { return invocation.invoke(); } } - public static class MockInterceptor2 implements Interceptor { - private static final long serialVersionUID = 267427973306989618L; + public static class MockInterceptor2 extends AbstractInterceptor { private String param1; private String param2; @@ -324,12 +280,6 @@ public class InterceptorBuilderTest extends XWorkTestCase { return this.param2; } - public void destroy() { - } - - public void init() { - } - public String intercept(ActionInvocation invocation) throws Exception { return invocation.invoke(); } diff --git a/core/src/test/java/com/opensymphony/xwork2/config/providers/InterceptorForTestPurpose.java b/core/src/test/java/com/opensymphony/xwork2/config/providers/InterceptorForTestPurpose.java index 6fb798c21..bca455bae 100644 --- a/core/src/test/java/com/opensymphony/xwork2/config/providers/InterceptorForTestPurpose.java +++ b/core/src/test/java/com/opensymphony/xwork2/config/providers/InterceptorForTestPurpose.java @@ -19,32 +19,31 @@ package com.opensymphony.xwork2.config.providers; import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.interceptor.Interceptor; +import com.opensymphony.xwork2.interceptor.AbstractInterceptor; -/** - * - * @author tm_jee - * @version $Date$ $Id$ - */ -public class InterceptorForTestPurpose implements Interceptor { +public class InterceptorForTestPurpose extends AbstractInterceptor { - private String paramOne; - private String paramTwo; - - public String getParamOne() { return paramOne; } - public void setParamOne(String paramOne) { this.paramOne = paramOne; } - - public String getParamTwo() { return paramTwo; } - public void setParamTwo(String paramTwo) { this.paramTwo = paramTwo; } - - public void destroy() { - } + private String paramOne; + private String paramTwo; - public void init() { - } + public String getParamOne() { + return paramOne; + } - public String intercept(ActionInvocation invocation) throws Exception { - return invocation.invoke(); - } + public void setParamOne(String paramOne) { + this.paramOne = paramOne; + } + + public String getParamTwo() { + return paramTwo; + } + + public void setParamTwo(String paramTwo) { + this.paramTwo = paramTwo; + } + + public String intercept(ActionInvocation invocation) throws Exception { + return invocation.invoke(); + } } diff --git a/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatchedTestAssertInterceptor.java b/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatchedTestAssertInterceptor.java deleted file mode 100644 index d3a24d281..000000000 --- a/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatchedTestAssertInterceptor.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.dispatcher; - -import org.junit.Assert; - -import org.apache.struts2.TestAction; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.interceptor.Interceptor; - - -/** - */ -public class ServletDispatchedTestAssertInterceptor implements Interceptor { - - private static final long serialVersionUID = 1980347231443329805L; - - public ServletDispatchedTestAssertInterceptor() { - super(); - } - - public void destroy() { - } - - public void init() { - } - - public String intercept(ActionInvocation invocation) throws Exception { - Assert.assertTrue(invocation.getAction() instanceof TestAction); - - TestAction testAction = (TestAction) invocation.getAction(); - - Assert.assertEquals("bar", testAction.getFoo()); - - String result = invocation.invoke(); - - return result; - } -} From 084c257d6e2e80d51ff152e0e8e75d13d4e7af40 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 24 Oct 2022 08:27:12 +0200 Subject: [PATCH 077/143] WW-4173 Passes current ActionInvocation to allow based disabling interceptor on it --- .../java/com/opensymphony/xwork2/DefaultActionInvocation.java | 4 ++-- .../opensymphony/xwork2/interceptor/AbstractInterceptor.java | 2 +- .../java/com/opensymphony/xwork2/interceptor/Interceptor.java | 3 ++- .../java/org/apache/struts2/interceptor/CoepInterceptor.java | 4 ++-- .../java/org/apache/struts2/interceptor/CoopInterceptor.java | 4 ++-- .../apache/struts2/interceptor/FetchMetadataInterceptor.java | 2 +- .../org/apache/struts2/interceptor/csp/CspInterceptor.java | 4 ++-- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java index 8c388d469..c1e049dfa 100644 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java +++ b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java @@ -248,11 +248,11 @@ public class DefaultActionInvocation implements ActionInvocation { if (interceptor instanceof WithLazyParams) { interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext); } - if (interceptor.isDisabled()) { + if (interceptor.isDisabled(this)) { LOG.debug("Interceptor: {} is disabled, skipping to next", interceptor.getClass().getSimpleName()); resultCode = this.invoke(); } else { - resultCode = interceptor.intercept(DefaultActionInvocation.this); + resultCode = interceptor.intercept(this); } } else { resultCode = invokeActionOnly(); diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java index 2895bc0f0..efa009052 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java @@ -49,7 +49,7 @@ public abstract class AbstractInterceptor implements Interceptor { } @Override - public boolean isDisabled() { + public boolean isDisabled(ActionInvocation invocation) { return this.disabled; } } diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java index c60c2f416..3488314d2 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java @@ -222,8 +222,9 @@ public interface Interceptor extends Serializable { /** * Allows to disable processing a given interceptor * + * @param invocation current {@link ActionInvocation} to determine if the interceptor should be executed * @return true if the given interceptor should be skipped * @since 6.1.0 */ - boolean isDisabled(); + boolean isDisabled(ActionInvocation invocation); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java index c887877dc..6d550c19f 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java @@ -51,7 +51,7 @@ public class CoepInterceptor extends AbstractInterceptor implements PreResultLis @Override public String intercept(ActionInvocation invocation) throws Exception { - if (this.isDisabled()) { + if (this.isDisabled(invocation)) { LOG.trace("COEP interceptor has been disabled"); } else { invocation.addPreResultListener(this); @@ -61,7 +61,7 @@ public class CoepInterceptor extends AbstractInterceptor implements PreResultLis @Override public void beforeResult(ActionInvocation invocation, String resultCode) { - if (this.isDisabled()) { + if (this.isDisabled(invocation)) { return; } diff --git a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java index 5590ca98f..9827ceb13 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java @@ -53,7 +53,7 @@ public class CoopInterceptor extends AbstractInterceptor implements PreResultLis @Override public String intercept(ActionInvocation invocation) throws Exception { - if (this.isDisabled()) { + if (this.isDisabled(invocation)) { LOG.trace("COOP interceptor has been disabled"); } else { invocation.addPreResultListener(this); @@ -63,7 +63,7 @@ public class CoopInterceptor extends AbstractInterceptor implements PreResultLis @Override public void beforeResult(ActionInvocation invocation, String resultCode) { - if (this.isDisabled()) { + if (this.isDisabled(invocation)) { return; } HttpServletRequest request = invocation.getInvocationContext().getServletRequest(); diff --git a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java index 0122d718b..9a3583607 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java @@ -62,7 +62,7 @@ public class FetchMetadataInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation invocation) throws Exception { - if (this.isDisabled()) { + if (this.isDisabled(invocation)) { LOG.trace("Fetch Metadata interceptor has been disabled"); return invocation.invoke(); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java index eb3ddb4a0..38b196514 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/csp/CspInterceptor.java @@ -47,7 +47,7 @@ public final class CspInterceptor extends AbstractInterceptor implements PreResu @Override public String intercept(ActionInvocation invocation) throws Exception { - if (this.isDisabled()) { + if (this.isDisabled(invocation)) { LOG.trace("CSP interceptor has been disabled"); } else { invocation.addPreResultListener(this); @@ -56,7 +56,7 @@ public final class CspInterceptor extends AbstractInterceptor implements PreResu } public void beforeResult(ActionInvocation invocation, String resultCode) { - if (this.isDisabled()) { + if (this.isDisabled(invocation)) { return; } HttpServletRequest request = invocation.getInvocationContext().getServletRequest(); From a02cc6507c9371196590d30809026b5c30f6987d Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 24 Oct 2022 08:30:09 +0200 Subject: [PATCH 078/143] Defines OSSF Scorecard action to perform analysis --- .github/workflows/scorecards-analysis.yaml | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 .github/workflows/scorecards-analysis.yaml diff --git a/.github/workflows/scorecards-analysis.yaml b/.github/workflows/scorecards-analysis.yaml new file mode 100644 index 000000000..c8b4c85cc --- /dev/null +++ b/.github/workflows/scorecards-analysis.yaml @@ -0,0 +1,69 @@ +# 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. + +name: "Scorecards supply-chain security" + +on: + branch_protection_rule: + schedule: + - cron: "30 1 * * 6" # Weekly on Saturdays + push: + branches: [ "master" ] + +permissions: read-all + +jobs: + + analysis: + + name: "Scorecards analysis" + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to the code-scanning dashboard. + security-events: write + actions: read + id-token: write # This is required for requesting the JWT + contents: read # This is required for actions/checkout + + steps: + + - name: "Checkout code" + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # 3.1.0 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # 2.0.6 + with: + results_file: results.sarif + results_format: sarif + # A read-only PAT token, which is sufficient for the action to function. + # The relevant discussion: https://github.com/ossf/scorecard-action/issues/188 + repo_token: ${{ secrets.GITHUB_TOKEN }} + # Publish the results for public repositories to enable scorecard badges. + # For more details: https://github.com/ossf/scorecard-action#publishing-results + publish_results: true + + - name: "Upload artifact" + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # 3.1.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@b398f525a5587552e573b247ac661067fafa920b # 2.1.22 + with: + sarif_file: results.sarif From 936481e7ea8c060314a19c5d862602ad4102240e Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 24 Oct 2022 09:33:47 +0200 Subject: [PATCH 079/143] Adds badge with OSSF CII best practises scoring --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 289cfd2a0..ca6366563 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ The Apache Struts web framework [![Javadocs](https://javadoc.io/badge/org.apache.struts/struts2-core.svg)](https://javadoc.io/doc/org.apache.struts/struts2-core) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=apache_struts&metric=coverage)](https://sonarcloud.io/summary/new_code?id=apache_struts) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/struts/badge)](https://deps.dev/maven/org.apache.struts%3Astruts2-core) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6618/badge)](https://bestpractices.coreinfrastructure.org/projects/6618) [![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) The Apache Struts web framework is a free open-source solution for creating Java web applications. From b536136191d589095911dfb89a5b0ff4e3810f47 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 25 Oct 2022 13:29:21 +0200 Subject: [PATCH 080/143] Introduces CodeQL analyses --- .github/workflows/codeql.yml | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..cc116d622 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,43 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" From eb51594ed3b7ad8c5ccaa3bd173b7a87ad2bf9a8 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 25 Oct 2022 13:40:35 +0200 Subject: [PATCH 081/143] Adds proper header with Apache 2.0 license --- .github/workflows/codeql.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index cc116d622..147129c17 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,14 +1,18 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. +# 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 # -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. +# 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. + name: "CodeQL" on: From 9c078aef148dcbc69f0ff18702f9223f27680ff8 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 27 Oct 2022 12:53:05 +0200 Subject: [PATCH 082/143] WW-4440 Adds basic README.md to all submodules --- apps/README.md | 12 ++++++++++++ assembly/README.md | 3 +++ bom/README.md | 20 ++++++++++++++++++++ core/README.md | 6 ++++++ plugins/README.md | 3 +++ plugins/async/README.md | 6 ++++++ plugins/bean-validation/README.md | 7 +++++++ plugins/cdi/README.md | 6 ++++++ plugins/config-browser/README.md | 6 ++++++ plugins/convention/README.md | 6 ++++++ plugins/dwr/README.md | 6 ++++++ plugins/embeddedjsp/README.md | 2 ++ plugins/gxp/README.md | 2 ++ plugins/jasperreports/README.md | 6 ++++++ plugins/javatemplates/README.md | 6 ++++++ plugins/jfreechart/README.md | 6 ++++++ plugins/json/README.md | 6 ++++++ plugins/junit/README.md | 7 +++++++ plugins/osgi/README.md | 2 ++ plugins/oval/README.md | 2 ++ plugins/pell-multipart/README.md | 2 ++ plugins/plexus/README.md | 2 ++ plugins/portlet-mocks/README.md | 2 ++ plugins/portlet-tiles/README.md | 2 ++ plugins/portlet/README.md | 2 ++ plugins/rest/README.md | 7 +++++++ plugins/sitemesh/README.md | 2 ++ plugins/spring/README.md | 6 ++++++ plugins/testng/README.md | 6 ++++++ plugins/tiles/README.md | 6 ++++++ plugins/velocity/README.md | 6 ++++++ 31 files changed, 163 insertions(+) create mode 100644 apps/README.md create mode 100644 assembly/README.md create mode 100644 bom/README.md create mode 100644 core/README.md create mode 100644 plugins/README.md create mode 100644 plugins/async/README.md create mode 100644 plugins/bean-validation/README.md create mode 100644 plugins/cdi/README.md create mode 100644 plugins/config-browser/README.md create mode 100644 plugins/convention/README.md create mode 100644 plugins/dwr/README.md create mode 100644 plugins/embeddedjsp/README.md create mode 100644 plugins/gxp/README.md create mode 100644 plugins/jasperreports/README.md create mode 100644 plugins/javatemplates/README.md create mode 100644 plugins/jfreechart/README.md create mode 100644 plugins/json/README.md create mode 100644 plugins/junit/README.md create mode 100644 plugins/osgi/README.md create mode 100644 plugins/oval/README.md create mode 100644 plugins/pell-multipart/README.md create mode 100644 plugins/plexus/README.md create mode 100644 plugins/portlet-mocks/README.md create mode 100644 plugins/portlet-tiles/README.md create mode 100644 plugins/portlet/README.md create mode 100644 plugins/rest/README.md create mode 100644 plugins/sitemesh/README.md create mode 100644 plugins/spring/README.md create mode 100644 plugins/testng/README.md create mode 100644 plugins/tiles/README.md create mode 100644 plugins/velocity/README.md diff --git a/apps/README.md b/apps/README.md new file mode 100644 index 000000000..0036a0d3a --- /dev/null +++ b/apps/README.md @@ -0,0 +1,12 @@ +# Struts 2 Apps +These module consists of two example applications, which were built using the Apache Struts project. +One is an old-fashioned Web application and another is a modern REST based single page app. + +## Installation +Enter a given folder, either `showcase/` or `rest-showcase/` and start the app using Maven: + +``` +mvn jetty:run +``` + +then open your browser at http://localhost:8080 and navigate to a proper context. diff --git a/assembly/README.md b/assembly/README.md new file mode 100644 index 000000000..2bcd93d08 --- /dev/null +++ b/assembly/README.md @@ -0,0 +1,3 @@ +# Struts 2 Assemblies +This module is used to prepare ZIP archives with different set of JARs, like code source, Javadocs, etc. +It's a part of the release process, it shouldn't be used directly by users. diff --git a/bom/README.md b/bom/README.md new file mode 100644 index 000000000..02bacfe8d --- /dev/null +++ b/bom/README.md @@ -0,0 +1,20 @@ +# Struts 2 BOM +This is a Bill-Of-Materials to be used with Maven based project. It allows to import all the Struts 2 +dependencies at once and used them in your project where needed. + +## Installation +You must add a proper import statement into your `pom.xml` as presented below: + +```xml + + + + org.apache.struts + struts2-bom + ${struts2.version} + pom + import + + + +``` diff --git a/core/README.md b/core/README.md new file mode 100644 index 000000000..0d10dcbc9 --- /dev/null +++ b/core/README.md @@ -0,0 +1,6 @@ +# Struts 2 Core +This is a core of the Apache Struts framework and all other modules depend on it. +It requires Java 8 at minimum and a Servlet container supporting Java Servlet API 3.1 at least. + +## Installation +Just drop this plugin into `WEB-INF/lib` folder or add it as Maven dependency diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 000000000..ac7306895 --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,3 @@ +# Struts 2 Plugins +A set of officially supported plugins which are provided with the framework, you can read more about them +in the [documentation](https://struts.apache.org/plugins/). diff --git a/plugins/async/README.md b/plugins/async/README.md new file mode 100644 index 000000000..19f91e70d --- /dev/null +++ b/plugins/async/README.md @@ -0,0 +1,6 @@ +# Struts 2 Async plugin +This plugin add support for async actions which can be used since Servlet API 3.0 +(lack of documentation!!!) + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency diff --git a/plugins/bean-validation/README.md b/plugins/bean-validation/README.md new file mode 100644 index 000000000..d1d532c25 --- /dev/null +++ b/plugins/bean-validation/README.md @@ -0,0 +1,7 @@ +# Struts 2 Bean Validation plugin +This plugin add support for using the Bean Validation API instead of the built-in native Struts 2 validation logic. +You will find more details in [documentation](https://struts.apache.org/plugins/bean-validation/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. You must also provide +a proper implementation of the Bean Validation API, eg.: [Hibernate Bean Validation](https://hibernate.org/validator/) diff --git a/plugins/cdi/README.md b/plugins/cdi/README.md new file mode 100644 index 000000000..2c6e33617 --- /dev/null +++ b/plugins/cdi/README.md @@ -0,0 +1,6 @@ +# Struts 2 CDI plugin +This plugin add support for using the Contexts and Dependency Injection (CDI) API with your Struts actions. +You will find more details in [documentation](https://struts.apache.org/plugins/cdi/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/config-browser/README.md b/plugins/config-browser/README.md new file mode 100644 index 000000000..b29539b38 --- /dev/null +++ b/plugins/config-browser/README.md @@ -0,0 +1,6 @@ +# Struts 2 Config Browser plugin +This plugin allows to browse configuration of Struts in your application. **It shouldn't be used in production**! +You will find more details in [documentation](https://struts.apache.org/plugins/config-browser/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/convention/README.md b/plugins/convention/README.md new file mode 100644 index 000000000..b9a6a7c19 --- /dev/null +++ b/plugins/convention/README.md @@ -0,0 +1,6 @@ +# Struts 2 Convention plugin +This plugin allows to use _convention over configuration_ approach instead of configuring everything using `struts.xml`. +You will find more details in [documentation](https://struts.apache.org/plugins/convention/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/dwr/README.md b/plugins/dwr/README.md new file mode 100644 index 000000000..dc0c30a37 --- /dev/null +++ b/plugins/dwr/README.md @@ -0,0 +1,6 @@ +# Struts 2 Direct Web Remoting (DWR) plugin +This plugin allows to use Struts validation via DWR as remote beans. +You will find more details in [documentation](https://struts.apache.org/plugins/dwr/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/embeddedjsp/README.md b/plugins/embeddedjsp/README.md new file mode 100644 index 000000000..7064762e2 --- /dev/null +++ b/plugins/embeddedjsp/README.md @@ -0,0 +1,2 @@ +# Struts 2 EmbeddedJSP plugin +This plugin is deprecated and it will be removed soon, **please do not use it**! diff --git a/plugins/gxp/README.md b/plugins/gxp/README.md new file mode 100644 index 000000000..42c813027 --- /dev/null +++ b/plugins/gxp/README.md @@ -0,0 +1,2 @@ +# Struts 2 GXP plugin +This plugin is deprecated and it will be removed soon, **please do not use it**! diff --git a/plugins/jasperreports/README.md b/plugins/jasperreports/README.md new file mode 100644 index 000000000..a43d9cf0d --- /dev/null +++ b/plugins/jasperreports/README.md @@ -0,0 +1,6 @@ +# Struts 2 Direct Web Remoting (DWR) plugin +This plugin allows to use Jasper reports as a one of the result types. +You will find more details in [documentation](https://struts.apache.org/plugins/jasperreports/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/javatemplates/README.md b/plugins/javatemplates/README.md new file mode 100644 index 000000000..9c670c56c --- /dev/null +++ b/plugins/javatemplates/README.md @@ -0,0 +1,6 @@ +# Struts 2 Java Templates plugin +This plugin provides a faster Java implementation of tags in the `simple` theme. +You will find more details in [documentation](https://struts.apache.org/plugins/javatemplates/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/jfreechart/README.md b/plugins/jfreechart/README.md new file mode 100644 index 000000000..92881663f --- /dev/null +++ b/plugins/jfreechart/README.md @@ -0,0 +1,6 @@ +# Struts 2 JFreeChart plugin +The JFreeChart plugin allows Actions to easily return generated charts and graphs. +You will find more details in [documentation](https://struts.apache.org/plugins/jfreechart/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/json/README.md b/plugins/json/README.md new file mode 100644 index 000000000..c384bedfe --- /dev/null +++ b/plugins/json/README.md @@ -0,0 +1,6 @@ +# Struts 2 JFreeChart plugin +The JSON plugin provides a json result type that serializes actions into JSON. +You will find more details in [documentation](https://struts.apache.org/plugins/json/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/junit/README.md b/plugins/junit/README.md new file mode 100644 index 000000000..d0d0e5464 --- /dev/null +++ b/plugins/junit/README.md @@ -0,0 +1,7 @@ +# Struts 2 JFreeChart plugin +The JUnit Plugin supports testing actions within a Struts invocation, meaning that a full request is simulated, +and the output of the action can be tested. +You will find more details in [documentation](https://struts.apache.org/plugins/junit/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/osgi/README.md b/plugins/osgi/README.md new file mode 100644 index 000000000..c99dbc39f --- /dev/null +++ b/plugins/osgi/README.md @@ -0,0 +1,2 @@ +# Struts 2 OSGi plugin +This plugin is deprecated and it will be removed soon, **please do not use it**! diff --git a/plugins/oval/README.md b/plugins/oval/README.md new file mode 100644 index 000000000..735e75e27 --- /dev/null +++ b/plugins/oval/README.md @@ -0,0 +1,2 @@ +# Struts 2 OVal plugin +This plugin is deprecated and it will be removed soon, **please do not use it**! diff --git a/plugins/pell-multipart/README.md b/plugins/pell-multipart/README.md new file mode 100644 index 000000000..0372995e8 --- /dev/null +++ b/plugins/pell-multipart/README.md @@ -0,0 +1,2 @@ +# Struts 2 Pell Multipart plugin +This plugin is deprecated and it will be removed soon, **please do not use it**! diff --git a/plugins/plexus/README.md b/plugins/plexus/README.md new file mode 100644 index 000000000..090ecb849 --- /dev/null +++ b/plugins/plexus/README.md @@ -0,0 +1,2 @@ +# Struts 2 Plexus plugin +This plugin is deprecated and it will be removed soon, **please do not use it**! diff --git a/plugins/portlet-mocks/README.md b/plugins/portlet-mocks/README.md new file mode 100644 index 000000000..550476204 --- /dev/null +++ b/plugins/portlet-mocks/README.md @@ -0,0 +1,2 @@ +# Struts 2 Portlet Mocks plugin +This plugin is deprecated, and it will be removed soon, **please do not use it**! diff --git a/plugins/portlet-tiles/README.md b/plugins/portlet-tiles/README.md new file mode 100644 index 000000000..5cff1590b --- /dev/null +++ b/plugins/portlet-tiles/README.md @@ -0,0 +1,2 @@ +# Struts 2 Portlet Tiles plugin +This plugin is deprecated, and it will be removed soon, **please do not use it**! diff --git a/plugins/portlet/README.md b/plugins/portlet/README.md new file mode 100644 index 000000000..69958edb0 --- /dev/null +++ b/plugins/portlet/README.md @@ -0,0 +1,2 @@ +# Struts 2 Portlet plugin +This plugin is deprecated, and it will be removed soon, **please do not use it**! diff --git a/plugins/rest/README.md b/plugins/rest/README.md new file mode 100644 index 000000000..8553dec90 --- /dev/null +++ b/plugins/rest/README.md @@ -0,0 +1,7 @@ +# Struts 2 REST plugin +The REST Plugin provides high level support for the implementation of RESTful resource based web applications +with the Convention Plugin. +You will find more details in [documentation](https://struts.apache.org/plugins/rest/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/sitemesh/README.md b/plugins/sitemesh/README.md new file mode 100644 index 000000000..b11ca91e9 --- /dev/null +++ b/plugins/sitemesh/README.md @@ -0,0 +1,2 @@ +# Struts 2 Sitemesh plugin +This plugin is deprecated, and it will be removed soon, **please do not use it**! diff --git a/plugins/spring/README.md b/plugins/spring/README.md new file mode 100644 index 000000000..fbaf2781e --- /dev/null +++ b/plugins/spring/README.md @@ -0,0 +1,6 @@ +# Struts 2 Spring plugin +The Spring Plugin works by overriding the Struts ObjectFactory to enhance the creation of core framework objects +You will find more details in [documentation](https://struts.apache.org/plugins/spring/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/testng/README.md b/plugins/testng/README.md new file mode 100644 index 000000000..ac8faa03f --- /dev/null +++ b/plugins/testng/README.md @@ -0,0 +1,6 @@ +# Struts 2 TestNG plugin +The TestNG plugin provides integration with the popular TestNG unit testing framework. +You will find more details in [documentation](https://struts.apache.org/plugins/testng/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/tiles/README.md b/plugins/tiles/README.md new file mode 100644 index 000000000..41a4fbe28 --- /dev/null +++ b/plugins/tiles/README.md @@ -0,0 +1,6 @@ +# Struts 2 Tiles plugin +The Tiles plugin allows actions to return Tiles pages. +You will find more details in [documentation](https://struts.apache.org/plugins/tiles/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. diff --git a/plugins/velocity/README.md b/plugins/velocity/README.md new file mode 100644 index 000000000..3b27875eb --- /dev/null +++ b/plugins/velocity/README.md @@ -0,0 +1,6 @@ +# Struts 2 Velocity plugin +The Tiles plugin allows actions to return Tiles pages. +You will find more details in [documentation](https://struts.apache.org/plugins/velocity/). + +## Installation +Just drop this plugin JAR into `WEB-INF/lib` folder or add it as a Maven dependency. From 6658c6360e771a793ab261e5b4d3ed9dfb6720d3 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 27 Oct 2022 13:35:10 +0200 Subject: [PATCH 083/143] WW-5252 Disables parsing external entities --- .../opensymphony/xwork2/util/DomHelper.java | 130 ++++++++++-------- .../apache/struts2/views/xslt/XSLTResult.java | 60 ++++++-- core/src/main/resources/author.dtd | 22 +++ .../xwork2/util/DomHelperTest.java | 56 ++++---- 4 files changed, 173 insertions(+), 95 deletions(-) create mode 100644 core/src/main/resources/author.dtd diff --git a/core/src/main/java/com/opensymphony/xwork2/util/DomHelper.java b/core/src/main/java/com/opensymphony/xwork2/util/DomHelper.java index f1021dc37..b79c3c03a 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/DomHelper.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/DomHelper.java @@ -28,9 +28,17 @@ import org.apache.struts2.StrutsException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; -import org.xml.sax.*; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.TransformerFactory; @@ -48,28 +56,24 @@ import java.util.Map; public class DomHelper { private static final Logger LOG = LogManager.getLogger(DomHelper.class); - - public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; public static Location getLocationObject(Element element) { return LocationAttributes.getLocation(element); } - /** * Creates a W3C Document that remembers the location of each element in * the source file. The location of element nodes can then be retrieved * using the {@link #getLocationObject(Element)} method. * * @param inputSource the inputSource to read the document from - * * @return the W3C Document */ public static Document parse(InputSource inputSource) { return parse(inputSource, null); } - - + + /** * Creates a W3C Document that remembers the location of each element in * the source file. The location of element nodes can then be retrieved @@ -77,17 +81,16 @@ public class DomHelper { * * @param inputSource the inputSource to read the document from * @param dtdMappings a map of DTD names and public ids - * * @return the W3C Document */ public static Document parse(InputSource inputSource, Map dtdMappings) { - + SAXParserFactory factory = null; String parserProp = System.getProperty("xwork.saxParserFactory"); if (parserProp != null) { try { ObjectFactory objectFactory = ActionContext.getContext().getContainer().getInstance(ObjectFactory.class); - Class clazz = objectFactory.getClassInstance(parserProp); + Class clazz = objectFactory.getClassInstance(parserProp); factory = (SAXParserFactory) clazz.newInstance(); } catch (Exception e) { LOG.error("Unable to load saxParserFactory set by system property 'xwork.saxParserFactory': {}", parserProp, e); @@ -98,6 +101,13 @@ public class DomHelper { factory = SAXParserFactory.newInstance(); } + try { + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + } catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) { + throw new StrutsException("Unable to disable resolving external entities!", e); + } + factory.setValidating((dtdMappings != null)); factory.setNamespaceAware(true); @@ -107,22 +117,22 @@ public class DomHelper { } catch (Exception ex) { throw new StrutsException("Unable to create SAX parser", ex); } - - + + DOMBuilder builder = new DOMBuilder(); // Enhance the sax stream with location information ContentHandler locationHandler = new LocationAttributes.Pipe(builder); - + try { parser.parse(inputSource, new StartHandler(locationHandler, dtdMappings)); } catch (Exception ex) { throw new StrutsException(ex); } - + return builder.getDocument(); } - + /** * The DOMBuilder is a utility class that will generate a W3C * DOM Document from SAX events. @@ -130,27 +140,35 @@ public class DomHelper { * @author Carsten Ziegeler */ static public class DOMBuilder implements ContentHandler { - - /** The default transformer factory shared by all instances */ + + /** + * The default transformer factory shared by all instances + */ protected static SAXTransformerFactory FACTORY; - - /** The transformer factory */ + + /** + * The transformer factory + */ protected SAXTransformerFactory factory; - - /** The result */ + + /** + * The result + */ protected DOMResult result; - - /** The parentNode */ + + /** + * The parentNode + */ protected Node parentNode; - + protected ContentHandler nextHandler; - + static { String parserProp = System.getProperty("xwork.saxTransformerFactory"); if (parserProp != null) { try { ObjectFactory objectFactory = ActionContext.getContext().getContainer().getInstance(ObjectFactory.class); - Class clazz = objectFactory.getClassInstance(parserProp); + Class clazz = objectFactory.getClassInstance(parserProp); FACTORY = (SAXTransformerFactory) clazz.newInstance(); } catch (Exception e) { LOG.error("Unable to load SAXTransformerFactory set by system property 'xwork.saxTransformerFactory': {}", parserProp, e); @@ -158,7 +176,7 @@ public class DomHelper { } if (FACTORY == null) { - FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance(); + FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance(); } } @@ -168,15 +186,16 @@ public class DomHelper { public DOMBuilder() { this((Node) null); } - + /** * Construct a new instance of this DOMBuilder. + * * @param factory the SAX transformer factory */ public DOMBuilder(SAXTransformerFactory factory) { this(factory, null); } - + /** * Constructs a new instance that appends nodes to the given parent node. * @@ -185,19 +204,19 @@ public class DomHelper { public DOMBuilder(Node parentNode) { this(null, parentNode); } - + /** * Construct a new instance of this DOMBuilder. * - * @param factory the SAX transformer factory + * @param factory the SAX transformer factory * @param parentNode the parent node */ public DOMBuilder(SAXTransformerFactory factory, Node parentNode) { - this.factory = factory == null? FACTORY: factory; + this.factory = factory == null ? FACTORY : factory; this.parentNode = parentNode; setup(); } - + /** * Setup this instance transformer and result objects. */ @@ -215,7 +234,7 @@ public class DomHelper { throw new StrutsException("Fatal-Error: Unable to get transformer handler", local); } } - + /** * Return the newly built Document. * @@ -230,60 +249,61 @@ public class DomHelper { return this.result.getNode().getOwnerDocument(); } } - + public void setDocumentLocator(Locator locator) { nextHandler.setDocumentLocator(locator); } - + public void startDocument() throws SAXException { nextHandler.startDocument(); } - + public void endDocument() throws SAXException { nextHandler.endDocument(); } - + public void startElement(String uri, String loc, String raw, Attributes attrs) throws SAXException { nextHandler.startElement(uri, loc, raw, attrs); } - + public void endElement(String arg0, String arg1, String arg2) throws SAXException { nextHandler.endElement(arg0, arg1, arg2); } - + public void startPrefixMapping(String arg0, String arg1) throws SAXException { nextHandler.startPrefixMapping(arg0, arg1); } - + public void endPrefixMapping(String arg0) throws SAXException { nextHandler.endPrefixMapping(arg0); } - + public void characters(char[] arg0, int arg1, int arg2) throws SAXException { nextHandler.characters(arg0, arg1, arg2); } - + public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException { nextHandler.ignorableWhitespace(arg0, arg1, arg2); } - + public void processingInstruction(String arg0, String arg1) throws SAXException { nextHandler.processingInstruction(arg0, arg1); } - + public void skippedEntity(String arg0) throws SAXException { nextHandler.skippedEntity(arg0); } } - + public static class StartHandler extends DefaultHandler { - - private ContentHandler nextHandler; - private Map dtdMappings; - + + private final ContentHandler nextHandler; + private final Map dtdMappings; + /** * Create a filter that is chained to another handler. - * @param next the next handler in the chain. + * + * @param next the next handler in the chain. * @param dtdMappings map of DTD mappings */ public StartHandler(ContentHandler next, Map dtdMappings) { @@ -295,12 +315,12 @@ public class DomHelper { public void setDocumentLocator(Locator locator) { nextHandler.setDocumentLocator(locator); } - + @Override public void startDocument() throws SAXException { nextHandler.startDocument(); } - + @Override public void endDocument() throws SAXException { nextHandler.endDocument(); @@ -345,7 +365,7 @@ public class DomHelper { public void skippedEntity(String arg0) throws SAXException { nextHandler.skippedEntity(arg0); } - + @Override public InputSource resolveEntity(String publicId, String systemId) { if (dtdMappings != null && dtdMappings.containsKey(publicId)) { @@ -356,7 +376,7 @@ public class DomHelper { } return null; } - + @Override public void warning(SAXParseException exception) { } diff --git a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java index d310a6db9..31690362c 100644 --- a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java +++ b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java @@ -18,7 +18,6 @@ */ package org.apache.struts2.views.xslt; -import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.Result; import com.opensymphony.xwork2.inject.Inject; @@ -32,7 +31,15 @@ import org.apache.struts2.StrutsConstants; import org.apache.struts2.StrutsException; import javax.servlet.http.HttpServletResponse; -import javax.xml.transform.*; +import javax.xml.XMLConstants; +import javax.xml.transform.ErrorListener; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; @@ -49,10 +56,14 @@ public class XSLTResult implements Result { private static final long serialVersionUID = 6424691441777176763L; - /** Log instance for this result. */ + /** + * Log instance for this result. + */ private static final Logger LOG = LogManager.getLogger(XSLTResult.class); - /** 'stylesheetLocation' parameter. Points to the xsl. */ + /** + * 'stylesheetLocation' parameter. Points to the xsl. + */ public static final String DEFAULT_PARAM = "stylesheetLocation"; /** @@ -66,22 +77,34 @@ public class XSLTResult implements Result { // Configurable Parameters - /** Determines whether or not the result should allow caching. */ + /** + * Determines whether or not the result should allow caching. + */ protected boolean noCache; - /** Indicates the location of the xsl template. */ + /** + * Indicates the location of the xsl template. + */ private String stylesheetLocation; - /** Indicates the property name patterns which should be exposed to the xml. */ + /** + * Indicates the property name patterns which should be exposed to the xml. + */ private String matchingPattern; - /** Indicates the property name patterns which should be excluded from the xml. */ + /** + * Indicates the property name patterns which should be excluded from the xml. + */ private String excludingPattern; - /** Indicates the ognl expression representing the bean which is to be exposed as xml. */ + /** + * Indicates the ognl expression representing the bean which is to be exposed as xml. + */ private String exposedValue; - /** Indicates the status to return in the response */ + /** + * Indicates the status to return in the response + */ private int status = 200; private String encoding = "UTF-8"; @@ -96,7 +119,7 @@ public class XSLTResult implements Result { this(); setStylesheetLocation(stylesheetLocation); } - + @Inject(StrutsConstants.STRUTS_XSLT_NOCACHE) public void setNoCache(String xsltNoCache) { this.noCache = BooleanUtils.toBoolean(xsltNoCache); @@ -124,7 +147,7 @@ public class XSLTResult implements Result { public void setStatus(String status) { try { - this.status = Integer.valueOf(status); + this.status = Integer.parseInt(status); } catch (NumberFormatException e) { throw new IllegalArgumentException("Status value not number " + e.getMessage(), e); } @@ -175,7 +198,8 @@ public class XSLTResult implements Result { templates = getTemplates(location); transformer = templates.newTransformer(); } else { - transformer = TransformerFactory.newInstance().newTransformer(); + TransformerFactory factory = createTransformerFactory(); + transformer = factory.newTransformer(); } transformer.setURIResolver(getURIResolver()); @@ -217,6 +241,14 @@ public class XSLTResult implements Result { } } + protected TransformerFactory createTransformerFactory() { + TransformerFactory factory = TransformerFactory.newInstance(); + LOG.debug("Disables parsing external entities"); + factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + return factory; + } + protected ErrorListener buildErrorListener() { return new ErrorListener() { @@ -282,6 +314,6 @@ public class XSLTResult implements Result { } protected Source getDOMSourceForStack(Object value) throws IllegalAccessException, InstantiationException { - return new DOMSource(getAdapterFactory().adaptDocument("result", value) ); + return new DOMSource(getAdapterFactory().adaptDocument("result", value)); } } diff --git a/core/src/main/resources/author.dtd b/core/src/main/resources/author.dtd new file mode 100644 index 000000000..4521075a0 --- /dev/null +++ b/core/src/main/resources/author.dtd @@ -0,0 +1,22 @@ + + + diff --git a/core/src/test/java/com/opensymphony/xwork2/util/DomHelperTest.java b/core/src/test/java/com/opensymphony/xwork2/util/DomHelperTest.java index 330dfe35f..4c56f5759 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/DomHelperTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/DomHelperTest.java @@ -32,42 +32,46 @@ import java.io.StringReader; */ public class DomHelperTest extends TestCase { - private String xml = "\n" + - "\n" + - "]>\n" + - "\n" + - " \n" + - "\n"; - - public void testParse() throws Exception { + private final String xml = "]>\n\n\n\n"; + + public void testParse() { InputSource in = new InputSource(new StringReader(xml)); in.setSystemId("foo://bar"); - + Document doc = DomHelper.parse(in); assertNotNull(doc); - assertTrue("Wrong root node", - "foo".equals(doc.getDocumentElement().getNodeName())); - + assertEquals("Wrong root node", "foo", doc.getDocumentElement().getNodeName()); + NodeList nl = doc.getElementsByTagName("bar"); - assertTrue(nl.getLength() == 1); - - - + assertEquals(1, nl.getLength()); } - - public void testGetLocationObject() throws Exception { + + public void testGetLocationObject() { InputSource in = new InputSource(new StringReader(xml)); in.setSystemId("foo://bar"); - + Document doc = DomHelper.parse(in); - + NodeList nl = doc.getElementsByTagName("bar"); - - Location loc = DomHelper.getLocationObject((Element)nl.item(0)); - + + Location loc = DomHelper.getLocationObject((Element) nl.item(0)); + assertNotNull(loc); - assertTrue("Should be line 6, was "+loc.getLineNumber(), - 6==loc.getLineNumber()); + assertEquals("Should be line 3, was " + loc.getLineNumber(), 3, loc.getLineNumber()); + } + + public void testExternalEntities() { + String dtdFile = getClass().getResource("/author.dtd").getPath(); + String xml = "]>&writer;"; + InputSource in = new InputSource(new StringReader(xml)); + in.setSystemId("foo://bar"); + + Document doc = DomHelper.parse(in); + assertNotNull(doc); + assertEquals("Wrong root node", "foo", doc.getDocumentElement().getNodeName()); + + NodeList nl = doc.getElementsByTagName("bar"); + assertEquals(1, nl.getLength()); + assertNull(nl.item(0).getNodeValue()); } } From 8d2d996056db234701cf79174e2ed3e70043f8fa Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 30 Oct 2022 12:37:23 +0100 Subject: [PATCH 084/143] WW-5252 Reuses factory method --- .../src/main/java/org/apache/struts2/views/xslt/XSLTResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java index 31690362c..1361c628a 100644 --- a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java +++ b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java @@ -302,7 +302,7 @@ public class XSLTResult implements Result { LOG.debug("Preparing XSLT stylesheet templates: {}", path); - TransformerFactory factory = TransformerFactory.newInstance(); + TransformerFactory factory = createTransformerFactory(); factory.setURIResolver(getURIResolver()); factory.setErrorListener(buildErrorListener()); templates = factory.newTemplates(new StreamSource(resource.openStream())); From 2660aaec56f607473b09fc5297f99e25d233fa08 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 2 Nov 2022 10:32:13 +0100 Subject: [PATCH 085/143] [WW-4692] Extracts Url encoder/decoder into dedicated interfaces/classes (#626) * WW-4692 Extracts Url encoder/decoder into dedicated interfaces/classes * WW-4692 Removes code smells reported by Sonar and adds additional test case * WW-4692 Adds missing header with license * WW-4692 Prevents int promotion behaviour * WW-4692 Drops unused imports * WW-4692 Fixes int promotion behaviour * WW-4692 Improves code coverage --- .../StrutsDefaultConfigurationProvider.java | 185 ++-- .../org/apache/struts2/StrutsConstants.java | 3 + .../config/AbstractBeanSelectionProvider.java | 1 - .../config/StrutsBeanSelectionProvider.java | 5 + .../mapper/Restful2ActionMapper.java | 34 +- .../mapper/RestfulActionMapper.java | 19 +- .../apache/struts2/url/StrutsUrlDecoder.java | 118 +++ .../apache/struts2/url/StrutsUrlEncoder.java | 58 ++ .../org/apache/struts2/url/UrlDecoder.java | 50 + .../org/apache/struts2/url/UrlEncoder.java | 40 + .../apache/struts2/util/URLDecoderUtil.java | 52 - .../apache/struts2/util/tomcat/buf/Ascii.java | 257 ----- .../struts2/util/tomcat/buf/B2CConverter.java | 203 ---- .../struts2/util/tomcat/buf/ByteChunk.java | 937 ------------------ .../struts2/util/tomcat/buf/CharChunk.java | 702 ------------- .../struts2/util/tomcat/buf/HexUtils.java | 115 --- .../struts2/util/tomcat/buf/MessageBytes.java | 548 ---------- .../struts2/util/tomcat/buf/StringCache.java | 697 ------------- .../struts2/util/tomcat/buf/UDecoder.java | 423 -------- .../struts2/util/tomcat/buf/Utf8Decoder.java | 295 ------ .../struts2/views/util/DefaultUrlHelper.java | 134 ++- .../org/apache/struts2/default.properties | 3 + core/src/main/resources/struts-default.xml | 5 + .../mapper/Restful2ActionMapperTest.java | 10 +- .../mapper/RestfulActionMapperTest.java | 21 +- .../ServletActionRedirectResultTest.java | 95 +- .../result/ServletRedirectResultTest.java | 4 +- .../StrutsUrlDecoderTest.java} | 70 +- .../struts2/url/StrutsUrlEncoderTest.java | 90 ++ .../struts2/views/jsp/ui/SelectTest.java | 2 +- .../views/util/DefaultUrlHelperTest.java | 18 +- .../apache/struts2/EmbeddedJSPResultTest.java | 6 +- .../resources/org/apache/struts2/complex0.jsp | 13 +- 33 files changed, 691 insertions(+), 4522 deletions(-) create mode 100644 core/src/main/java/org/apache/struts2/url/StrutsUrlDecoder.java create mode 100644 core/src/main/java/org/apache/struts2/url/StrutsUrlEncoder.java create mode 100644 core/src/main/java/org/apache/struts2/url/UrlDecoder.java create mode 100644 core/src/main/java/org/apache/struts2/url/UrlEncoder.java delete mode 100644 core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/Ascii.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/B2CConverter.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/ByteChunk.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/CharChunk.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/HexUtils.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/MessageBytes.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/StringCache.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/UDecoder.java delete mode 100644 core/src/main/java/org/apache/struts2/util/tomcat/buf/Utf8Decoder.java rename core/src/test/java/org/apache/struts2/{util/URLDecoderUtilTest.java => url/StrutsUrlDecoderTest.java} (51%) create mode 100644 core/src/test/java/org/apache/struts2/url/StrutsUrlEncoderTest.java diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java index 49308d263..2ac045d45 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java @@ -21,26 +21,16 @@ package com.opensymphony.xwork2.config.providers; import com.opensymphony.xwork2.ActionProxyFactory; import com.opensymphony.xwork2.DefaultActionProxyFactory; import com.opensymphony.xwork2.DefaultLocaleProviderFactory; -import com.opensymphony.xwork2.LocaleProviderFactory; -import com.opensymphony.xwork2.StrutsTextProviderFactory; -import com.opensymphony.xwork2.TextProviderFactory; -import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory; -import com.opensymphony.xwork2.factory.UnknownHandlerFactory; -import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory; -import com.opensymphony.xwork2.ognl.ExpressionCacheFactory; -import com.opensymphony.xwork2.ognl.accessor.HttpParametersPropertyAccessor; -import com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor; -import com.opensymphony.xwork2.security.AcceptedPatternsChecker; -import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker; -import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker; import com.opensymphony.xwork2.DefaultTextProvider; import com.opensymphony.xwork2.DefaultUnknownHandlerManager; -import com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPatternsChecker; -import com.opensymphony.xwork2.security.ExcludedPatternsChecker; import com.opensymphony.xwork2.FileManager; import com.opensymphony.xwork2.FileManagerFactory; +import com.opensymphony.xwork2.LocaleProviderFactory; +import com.opensymphony.xwork2.LocalizedTextProvider; import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.StrutsTextProviderFactory; import com.opensymphony.xwork2.TextProvider; +import com.opensymphony.xwork2.TextProviderFactory; import com.opensymphony.xwork2.UnknownHandlerManager; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.ConfigurationException; @@ -57,14 +47,7 @@ import com.opensymphony.xwork2.conversion.impl.CollectionConverter; import com.opensymphony.xwork2.conversion.impl.DateConverter; import com.opensymphony.xwork2.conversion.impl.DefaultConversionAnnotationProcessor; import com.opensymphony.xwork2.conversion.impl.DefaultConversionFileProcessor; -import com.opensymphony.xwork2.security.NotExcludedAcceptedPatternsChecker; -import org.apache.struts2.components.date.DateFormatter; -import org.apache.struts2.components.date.DateTimeFormatterAdapter; -import org.apache.struts2.components.date.SimpleDateFormatAdapter; -import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor; import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer; -import org.apache.struts2.conversion.StrutsTypeConverterCreator; -import org.apache.struts2.conversion.StrutsTypeConverterHolder; import com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler; import com.opensymphony.xwork2.conversion.impl.NumberConverter; import com.opensymphony.xwork2.conversion.impl.StringConverter; @@ -73,34 +56,45 @@ import com.opensymphony.xwork2.conversion.impl.XWorkConverter; import com.opensymphony.xwork2.factory.ActionFactory; import com.opensymphony.xwork2.factory.ConverterFactory; import com.opensymphony.xwork2.factory.DefaultActionFactory; -import com.opensymphony.xwork2.factory.StrutsConverterFactory; import com.opensymphony.xwork2.factory.DefaultInterceptorFactory; import com.opensymphony.xwork2.factory.DefaultResultFactory; +import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory; import com.opensymphony.xwork2.factory.InterceptorFactory; import com.opensymphony.xwork2.factory.ResultFactory; +import com.opensymphony.xwork2.factory.StrutsConverterFactory; +import com.opensymphony.xwork2.factory.UnknownHandlerFactory; import com.opensymphony.xwork2.inject.ContainerBuilder; import com.opensymphony.xwork2.inject.Scope; +import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory; +import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory; +import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory; +import com.opensymphony.xwork2.ognl.ExpressionCacheFactory; import com.opensymphony.xwork2.ognl.ObjectProxy; import com.opensymphony.xwork2.ognl.OgnlReflectionContextFactory; import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; import com.opensymphony.xwork2.ognl.OgnlUtil; import com.opensymphony.xwork2.ognl.OgnlValueStackFactory; import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; +import com.opensymphony.xwork2.ognl.accessor.HttpParametersPropertyAccessor; import com.opensymphony.xwork2.ognl.accessor.ObjectAccessor; import com.opensymphony.xwork2.ognl.accessor.ObjectProxyPropertyAccessor; +import com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor; import com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor; import com.opensymphony.xwork2.ognl.accessor.XWorkEnumerationAccessor; import com.opensymphony.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor; import com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor; import com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor; import com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor; +import com.opensymphony.xwork2.security.AcceptedPatternsChecker; +import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker; +import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker; +import com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPatternsChecker; +import com.opensymphony.xwork2.security.ExcludedPatternsChecker; +import com.opensymphony.xwork2.security.NotExcludedAcceptedPatternsChecker; import com.opensymphony.xwork2.util.CompoundRoot; -import com.opensymphony.xwork2.LocalizedTextProvider; -import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory; -import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory; -import com.opensymphony.xwork2.util.StrutsLocalizedTextProvider; import com.opensymphony.xwork2.util.OgnlTextParser; import com.opensymphony.xwork2.util.PatternMatcher; +import com.opensymphony.xwork2.util.StrutsLocalizedTextProvider; import com.opensymphony.xwork2.util.TextParser; import com.opensymphony.xwork2.util.ValueStackFactory; import com.opensymphony.xwork2.util.WildcardHelper; @@ -119,8 +113,15 @@ import com.opensymphony.xwork2.validator.ValidatorFileParser; import ognl.MethodAccessor; import ognl.PropertyAccessor; import org.apache.struts2.StrutsConstants; +import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor; +import org.apache.struts2.conversion.StrutsTypeConverterCreator; +import org.apache.struts2.conversion.StrutsTypeConverterHolder; import org.apache.struts2.dispatcher.HttpParameters; import org.apache.struts2.dispatcher.Parameter; +import org.apache.struts2.url.StrutsUrlDecoder; +import org.apache.struts2.url.StrutsUrlEncoder; +import org.apache.struts2.url.UrlDecoder; +import org.apache.struts2.url.UrlEncoder; import java.util.ArrayList; import java.util.Collection; @@ -153,88 +154,88 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider @Override public void register(ContainerBuilder builder, LocatableProperties props) - throws ConfigurationException { + throws ConfigurationException { builder - .factory(ObjectFactory.class) - .factory(ActionFactory.class, DefaultActionFactory.class) - .factory(ResultFactory.class, DefaultResultFactory.class) - .factory(InterceptorFactory.class, DefaultInterceptorFactory.class) - .factory(com.opensymphony.xwork2.factory.ValidatorFactory.class, com.opensymphony.xwork2.factory.DefaultValidatorFactory.class) - .factory(ConverterFactory.class, StrutsConverterFactory.class) - .factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class) + .factory(ObjectFactory.class) + .factory(ActionFactory.class, DefaultActionFactory.class) + .factory(ResultFactory.class, DefaultResultFactory.class) + .factory(InterceptorFactory.class, DefaultInterceptorFactory.class) + .factory(com.opensymphony.xwork2.factory.ValidatorFactory.class, com.opensymphony.xwork2.factory.DefaultValidatorFactory.class) + .factory(ConverterFactory.class, StrutsConverterFactory.class) + .factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class) - .factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON) - .factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON) + .factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON) + .factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON) - .factory(XWorkConverter.class, Scope.SINGLETON) - .factory(XWorkBasicConverter.class, Scope.SINGLETON) - .factory(ConversionPropertiesProcessor.class, StrutsConversionPropertiesProcessor.class, Scope.SINGLETON) - .factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON) - .factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON) - .factory(TypeConverterCreator.class, StrutsTypeConverterCreator.class, Scope.SINGLETON) - .factory(TypeConverterHolder.class, StrutsTypeConverterHolder.class, Scope.SINGLETON) + .factory(XWorkConverter.class, Scope.SINGLETON) + .factory(XWorkBasicConverter.class, Scope.SINGLETON) + .factory(ConversionPropertiesProcessor.class, StrutsConversionPropertiesProcessor.class, Scope.SINGLETON) + .factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON) + .factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON) + .factory(TypeConverterCreator.class, StrutsTypeConverterCreator.class, Scope.SINGLETON) + .factory(TypeConverterHolder.class, StrutsTypeConverterHolder.class, Scope.SINGLETON) - .factory(FileManager.class, "system", DefaultFileManager.class, Scope.SINGLETON) - .factory(FileManagerFactory.class, DefaultFileManagerFactory.class, Scope.SINGLETON) - .factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON) - .factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.SINGLETON) - .factory(ValidatorFileParser.class, DefaultValidatorFileParser.class, Scope.SINGLETON) - .factory(PatternMatcher.class, WildcardHelper.class, Scope.SINGLETON) - .factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON) - .factory(ReflectionContextFactory.class, OgnlReflectionContextFactory.class, Scope.SINGLETON) + .factory(FileManager.class, "system", DefaultFileManager.class, Scope.SINGLETON) + .factory(FileManagerFactory.class, DefaultFileManagerFactory.class, Scope.SINGLETON) + .factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON) + .factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.SINGLETON) + .factory(ValidatorFileParser.class, DefaultValidatorFileParser.class, Scope.SINGLETON) + .factory(PatternMatcher.class, WildcardHelper.class, Scope.SINGLETON) + .factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON) + .factory(ReflectionContextFactory.class, OgnlReflectionContextFactory.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Object.class.getName(), ObjectAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Iterator.class.getName(), XWorkIteratorPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Enumeration.class.getName(), XWorkEnumerationAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Object.class.getName(), ObjectAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Iterator.class.getName(), XWorkIteratorPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Enumeration.class.getName(), XWorkEnumerationAccessor.class, Scope.SINGLETON) - .factory(UnknownHandlerManager.class, DefaultUnknownHandlerManager.class, Scope.SINGLETON) + .factory(UnknownHandlerManager.class, DefaultUnknownHandlerManager.class, Scope.SINGLETON) - // silly workarounds for ognl since there is no way to flush its caches - .factory(PropertyAccessor.class, List.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, ArrayList.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, HashSet.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, HashMap.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Map.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Collection.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, ObjectProxy.class.getName(), ObjectProxyPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, HttpParameters.class.getName(), HttpParametersPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Parameter.class.getName(), ParameterPropertyAccessor.class, Scope.SINGLETON) + // silly workarounds for ognl since there is no way to flush its caches + .factory(PropertyAccessor.class, List.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, ArrayList.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, HashSet.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, HashMap.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Map.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Collection.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, ObjectProxy.class.getName(), ObjectProxyPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, HttpParameters.class.getName(), HttpParametersPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Parameter.class.getName(), ParameterPropertyAccessor.class, Scope.SINGLETON) - .factory(MethodAccessor.class, Object.class.getName(), XWorkMethodAccessor.class, Scope.SINGLETON) - .factory(MethodAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON) + .factory(MethodAccessor.class, Object.class.getName(), XWorkMethodAccessor.class, Scope.SINGLETON) + .factory(MethodAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON) - .factory(TextParser.class, OgnlTextParser.class, Scope.SINGLETON) + .factory(TextParser.class, OgnlTextParser.class, Scope.SINGLETON) - .factory(NullHandler.class, Object.class.getName(), InstantiatingNullHandler.class, Scope.SINGLETON) - .factory(ActionValidatorManager.class, AnnotationActionValidatorManager.class, Scope.SINGLETON) - .factory(ActionValidatorManager.class, "no-annotations", DefaultActionValidatorManager.class, Scope.SINGLETON) + .factory(NullHandler.class, Object.class.getName(), InstantiatingNullHandler.class, Scope.SINGLETON) + .factory(ActionValidatorManager.class, AnnotationActionValidatorManager.class, Scope.SINGLETON) + .factory(ActionValidatorManager.class, "no-annotations", DefaultActionValidatorManager.class, Scope.SINGLETON) - .factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON) - .factory(LocalizedTextProvider.class, StrutsLocalizedTextProvider.class, Scope.SINGLETON) - .factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON) - .factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON) + .factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON) + .factory(LocalizedTextProvider.class, StrutsLocalizedTextProvider.class, Scope.SINGLETON) + .factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON) + .factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON) - .factory(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON) - .factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON) - .factory(OgnlUtil.class, Scope.SINGLETON) - .factory(CollectionConverter.class, Scope.SINGLETON) - .factory(ArrayConverter.class, Scope.SINGLETON) - .factory(DateConverter.class, Scope.SINGLETON) - .factory(NumberConverter.class, Scope.SINGLETON) - .factory(StringConverter.class, Scope.SINGLETON) + .factory(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON) + .factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON) + .factory(OgnlUtil.class, Scope.SINGLETON) + .factory(CollectionConverter.class, Scope.SINGLETON) + .factory(ArrayConverter.class, Scope.SINGLETON) + .factory(DateConverter.class, Scope.SINGLETON) + .factory(NumberConverter.class, Scope.SINGLETON) + .factory(StringConverter.class, Scope.SINGLETON) - .factory(ExcludedPatternsChecker.class, DefaultExcludedPatternsChecker.class, Scope.PROTOTYPE) - .factory(AcceptedPatternsChecker.class, DefaultAcceptedPatternsChecker.class, Scope.PROTOTYPE) - .factory(NotExcludedAcceptedPatternsChecker.class, DefaultNotExcludedAcceptedPatternsChecker.class - , Scope.SINGLETON) + .factory(ExcludedPatternsChecker.class, DefaultExcludedPatternsChecker.class, Scope.PROTOTYPE) + .factory(AcceptedPatternsChecker.class, DefaultAcceptedPatternsChecker.class, Scope.PROTOTYPE) + .factory(NotExcludedAcceptedPatternsChecker.class, DefaultNotExcludedAcceptedPatternsChecker.class + , Scope.SINGLETON) - .factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON) + .factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON) - .factory(DateFormatter.class, "simpleDateFormatter", SimpleDateFormatAdapter.class, Scope.SINGLETON) - .factory(DateFormatter.class, "dateTimeFormatter", DateTimeFormatterAdapter.class, Scope.SINGLETON) + .factory(UrlEncoder.class, StrutsUrlEncoder.class, Scope.SINGLETON) + .factory(UrlDecoder.class, StrutsUrlDecoder.class, Scope.SINGLETON) ; props.setProperty(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, Boolean.FALSE.toString()); diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java index f37a85078..5dff4724c 100644 --- a/core/src/main/java/org/apache/struts2/StrutsConstants.java +++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java @@ -457,4 +457,7 @@ public final class StrutsConstants { /** See {@link org.apache.struts2.components.Date#setDateFormatter(DateFormatter)} */ public static final String STRUTS_DATE_FORMATTER = "struts.date.formatter"; + + public static final String STRUTS_URL_ENCODER = "struts.url.encoder"; + public static final String STRUTS_URL_DECODER = "struts.url.decoder"; } diff --git a/core/src/main/java/org/apache/struts2/config/AbstractBeanSelectionProvider.java b/core/src/main/java/org/apache/struts2/config/AbstractBeanSelectionProvider.java index 34db87d3a..f672ae041 100644 --- a/core/src/main/java/org/apache/struts2/config/AbstractBeanSelectionProvider.java +++ b/core/src/main/java/org/apache/struts2/config/AbstractBeanSelectionProvider.java @@ -24,7 +24,6 @@ import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.ConfigurationException; import com.opensymphony.xwork2.inject.*; import com.opensymphony.xwork2.util.ClassLoaderUtil; -import com.opensymphony.xwork2.util.location.LocatableProperties; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java b/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java index f47bbc354..2e5a9315c 100644 --- a/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java +++ b/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java @@ -66,6 +66,8 @@ import org.apache.struts2.dispatcher.DispatcherErrorHandler; import org.apache.struts2.dispatcher.StaticContentLoader; import org.apache.struts2.dispatcher.mapper.ActionMapper; import org.apache.struts2.dispatcher.multipart.MultiPartRequest; +import org.apache.struts2.url.UrlDecoder; +import org.apache.struts2.url.UrlEncoder; import org.apache.struts2.util.ContentTypeMatcher; import org.apache.struts2.views.freemarker.FreemarkerManager; import org.apache.struts2.views.util.UrlHelper; @@ -429,6 +431,9 @@ public class StrutsBeanSelectionProvider extends AbstractBeanSelectionProvider { alias(ExpressionCacheFactory.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, builder, props, Scope.SINGLETON); alias(BeanInfoCacheFactory.class, StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, builder, props, Scope.SINGLETON); + alias(UrlEncoder.class, StrutsConstants.STRUTS_URL_ENCODER, builder, props, Scope.SINGLETON); + alias(UrlDecoder.class, StrutsConstants.STRUTS_URL_DECODER, builder, props, Scope.SINGLETON); + switchDevMode(props); } diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapper.java index 2dc418241..1a11b06bf 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapper.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapper.java @@ -24,7 +24,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.StrutsConstants; -import org.apache.struts2.util.URLDecoderUtil; +import org.apache.struts2.url.UrlDecoder; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; @@ -32,18 +32,26 @@ import java.util.StringTokenizer; /** * Extended version of {@link RestfulActionMapper}, see documentation for more details - * https://struts.apache.org/core-developers/restful-action-mapper.html + * Restful2ActionMapper */ public class Restful2ActionMapper extends DefaultActionMapper { - protected static final Logger LOG = LogManager.getLogger(Restful2ActionMapper.class); + private static final Logger LOG = LogManager.getLogger(Restful2ActionMapper.class); + public static final String HTTP_METHOD_PARAM = "__http_method"; + private String idParameterName = null; - + private UrlDecoder decoder; + public Restful2ActionMapper() { setSlashesInActionNames("true"); } + @Inject + public void setDecoder(UrlDecoder decoder) { + this.decoder = decoder; + } + /* * (non-Javadoc) * @@ -54,7 +62,7 @@ public class Restful2ActionMapper extends DefaultActionMapper { throw new IllegalStateException("This action mapper requires the setting 'slashesInActionNames' to be set to 'true'"); } ActionMapping mapping = super.getMapping(request, configManager); - + if (mapping == null) { return null; } @@ -78,7 +86,7 @@ public class Restful2ActionMapper extends DefaultActionMapper { // Index e.g. foo/ if (isGet(request)) { mapping.setMethod("index"); - + // Creating a new entry on POST e.g. foo/ } else if (isPost(request)) { mapping.setMethod("create"); @@ -96,14 +104,14 @@ public class Restful2ActionMapper extends DefaultActionMapper { // Removing an item e.g. foo/1 } else if (isDelete(request)) { mapping.setMethod("remove"); - - // Updating an item e.g. foo/1 + + // Updating an item e.g. foo/1 } else if (isPut(request)) { mapping.setMethod("update"); } - + } - + if (idParameterName != null && lastSlashPos > -1) { actionName = actionName.substring(0, lastSlashPos); } @@ -129,10 +137,10 @@ public class Restful2ActionMapper extends DefaultActionMapper { while (st.hasMoreTokens()) { if (isNameTok) { - paramName = URLDecoderUtil.decode(st.nextToken(), "UTF-8"); + paramName = decoder.decode(st.nextToken(), "UTF-8", false); isNameTok = false; } else { - paramValue = URLDecoderUtil.decode(st.nextToken(), "UTF-8"); + paramValue = decoder.decode(st.nextToken(), "UTF-8", false); if ((paramName != null) && (paramName.length() > 0)) { parameters.put(paramName, paramValue); @@ -143,7 +151,7 @@ public class Restful2ActionMapper extends DefaultActionMapper { } if (parameters.size() > 0) { if (mapping.getParams() == null) { - mapping.setParams(new HashMap()); + mapping.setParams(new HashMap<>()); } mapping.getParams().putAll(parameters); } diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapper.java index 888bb97a4..1709834a1 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapper.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapper.java @@ -19,10 +19,11 @@ package org.apache.struts2.dispatcher.mapper; import com.opensymphony.xwork2.config.ConfigurationManager; +import com.opensymphony.xwork2.inject.Inject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.RequestUtils; -import org.apache.struts2.util.URLDecoderUtil; +import org.apache.struts2.url.UrlDecoder; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; @@ -32,11 +33,19 @@ import java.util.StringTokenizer; /** * Simple Restfull Action Mapper to support REST application * See docs for more information - * https://struts.apache.org/core-developers/restful-action-mapper.html + * RestfulActionMapper */ public class RestfulActionMapper implements ActionMapper { + protected static final Logger LOG = LogManager.getLogger(RestfulActionMapper.class); + private UrlDecoder decoder; + + @Inject + public void setDecoder(UrlDecoder decoder) { + this.decoder = decoder; + } + /* (non-Javadoc) * @see org.apache.struts2.dispatcher.mapper.ActionMapper#getMapping(javax.servlet.http.HttpServletRequest) */ @@ -64,10 +73,10 @@ public class RestfulActionMapper implements ActionMapper { while (st.hasMoreTokens()) { if (isNameTok) { - paramName = URLDecoderUtil.decode(st.nextToken(), "UTF-8"); + paramName = decoder.decode(st.nextToken(), "UTF-8", false); isNameTok = false; } else { - paramValue = URLDecoderUtil.decode(st.nextToken(), "UTF-8"); + paramValue = decoder.decode(st.nextToken(), "UTF-8", false); if ((paramName != null) && (paramName.length() > 0)) { parameters.put(paramName, paramValue); @@ -98,7 +107,7 @@ public class RestfulActionMapper implements ActionMapper { if (value != null) { retVal.append("/"); retVal.append(value); - } + } return retVal.toString(); } diff --git a/core/src/main/java/org/apache/struts2/url/StrutsUrlDecoder.java b/core/src/main/java/org/apache/struts2/url/StrutsUrlDecoder.java new file mode 100644 index 000000000..3a480d87f --- /dev/null +++ b/core/src/main/java/org/apache/struts2/url/StrutsUrlDecoder.java @@ -0,0 +1,118 @@ +/* + * 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.url; + +import com.opensymphony.xwork2.inject.Inject; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.apache.struts2.StrutsConstants; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; + +public class StrutsUrlDecoder implements UrlDecoder { + + private static final Logger LOG = LogManager.getLogger(StrutsUrlDecoder.class); + + private String encoding = "UTF-8"; + + @Inject(value = StrutsConstants.STRUTS_I18N_ENCODING, required = false) + public void setEncoding(String encoding) { + LOG.debug("Using default encoding: {}", encoding); + if (StringUtils.isNotEmpty(encoding)) { + this.encoding = encoding; + } + } + + @Override + public String decode(String input, String encoding, boolean isQueryString) { + if (input == null) { + return (null); + } + byte[] bytes = null; + try { + bytes = input.getBytes(getCharset(encoding)); + } catch (UnsupportedEncodingException uee) { + LOG.debug(new ParameterizedMessage("Unable to URL decode the specified input since the encoding: {} is not supported.", encoding), uee); + } + + return internalDecode(bytes, encoding, isQueryString); + } + + @Override + public String decode(String input, boolean isQueryString) { + return this.decode(input, this.encoding, isQueryString); + } + + @Override + public String decode(String input) { + return decode(input, false); + } + + private String internalDecode(byte[] bytes, String encoding, boolean isQuery) { + if (bytes == null) { + return null; + } + + int len = bytes.length; + int ix = 0; + int ox = 0; + while (ix < len) { + byte b = bytes[ix++]; // Get byte to test + if (b == '+' && isQuery) { + b = (byte) ' '; + } else if (b == '%') { + if (ix + 2 > len) { + throw new IllegalArgumentException("The % character must be followed by two hexadecimal digits"); + } + b = (byte) ((((convertHexDigit(bytes[ix++]) << 4) & 0xff) + convertHexDigit(bytes[ix++]) & 0xff) & 0xff); + } + bytes[ox++] = b; + } + if (encoding != null) { + try { + return new String(bytes, 0, ox, getCharset(encoding)); + } catch (UnsupportedEncodingException uee) { + LOG.debug(new ParameterizedMessage("Unable to URL decode the specified input since the encoding: {} is not supported.", encoding), uee); + return null; + } + } + return new String(bytes, 0, ox); + + } + + private byte convertHexDigit(byte b) { + if ((b >= '0') && (b <= '9')) return (byte) (b - '0'); + if ((b >= 'a') && (b <= 'f')) return (byte) (b - 'a' + 10); + if ((b >= 'A') && (b <= 'F')) return (byte) (b - 'A' + 10); + throw new IllegalArgumentException(((char) b) + " is not a hexadecimal digit"); + } + + private Charset getCharset(String encoding) throws UnsupportedEncodingException { + for (Charset charset : Charset.availableCharsets().values()) { + if (encoding.equalsIgnoreCase(charset.name())) { + return charset; + } + } + throw new UnsupportedEncodingException("The character encoding " + encoding + " is not supported"); + } + +} diff --git a/core/src/main/java/org/apache/struts2/url/StrutsUrlEncoder.java b/core/src/main/java/org/apache/struts2/url/StrutsUrlEncoder.java new file mode 100644 index 000000000..12b5a0104 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/url/StrutsUrlEncoder.java @@ -0,0 +1,58 @@ +/* + * 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.url; + +import com.opensymphony.xwork2.inject.Inject; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.struts2.StrutsConstants; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +public class StrutsUrlEncoder implements UrlEncoder { + + private static final Logger LOG = LogManager.getLogger(StrutsUrlEncoder.class); + + private String encoding = "UTF-8"; + + @Inject(value = StrutsConstants.STRUTS_I18N_ENCODING, required = false) + public void setEncoding(String encoding) { + LOG.debug("Using default encoding: {}", encoding); + if (StringUtils.isNotEmpty(encoding)) { + this.encoding = encoding; + } + } + + @Override + public String encode(String input, String encoding) { + try { + return URLEncoder.encode(input, encoding); + } catch (UnsupportedEncodingException e) { + LOG.warn("Could not encode URL parameter '{}', returning value un-encoded", input); + return input; + } + } + + @Override + public String encode(String input) { + return encode(input, encoding); + } +} diff --git a/core/src/main/java/org/apache/struts2/url/UrlDecoder.java b/core/src/main/java/org/apache/struts2/url/UrlDecoder.java new file mode 100644 index 000000000..b54c563f5 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/url/UrlDecoder.java @@ -0,0 +1,50 @@ +/* + * 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.url; + +public interface UrlDecoder { + + /** + * Decodes the input using default encoding, e.g.: struts.i18n.encoding + * + * @param input String to decode + * @param encoding encoding used in decoding + * @param isQueryString indicates if input is a query string + * @return the decoded string + */ + String decode(String input, String encoding, boolean isQueryString); + + /** + * Decodes the input using default encoding, e.g.: struts.i18n.encoding + * + * @param input String to decode + * @param isQueryString indicates if input is a query string + * @return the decoded string + */ + String decode(String input, boolean isQueryString); + + /** + * Decodes the input using default encoding, e.g.: struts.i18n.encoding + * + * @param input String to decode + * @return the decoded string + */ + String decode(String input); + +} diff --git a/core/src/main/java/org/apache/struts2/url/UrlEncoder.java b/core/src/main/java/org/apache/struts2/url/UrlEncoder.java new file mode 100644 index 000000000..976645a53 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/url/UrlEncoder.java @@ -0,0 +1,40 @@ +/* + * 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.url; + +public interface UrlEncoder { + + /** + * Encodes the input tb be used with URL using the provided encoding + * + * @param input String to encode + * @param encoding encoding to use + * @return encoded string + */ + String encode(String input, String encoding); + + /** + * Encodes the input to be used with URL using default encoding, e.g.: struts.i18n.encoding + * + * @param input String to encode + * @return encoded string + */ + String encode(String input); + +} diff --git a/core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java b/core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java deleted file mode 100644 index 04f58e157..000000000 --- a/core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.util; - -import org.apache.struts2.util.tomcat.buf.UDecoder; - -/** - * URLDecoderUtil serves as a facade for a correct URL decoding implementation. - * As of Struts 2.3.25 it uses Tomcat URLDecoder functionality rather than the one found in java.io. - */ -public class URLDecoderUtil { - - /** - * Decodes a x-www-form-urlencoded string. - * @param sequence the String to decode - * @param charset The name of a supported character encoding. - * @return the newly decoded String - * @exception IllegalArgumentException If the encoding is not valid - */ - public static String decode(String sequence, String charset) { - return UDecoder.URLDecode(sequence, charset); - } - - /** - * Decodes a x-www-form-urlencoded string. - * @param sequence the String to decode - * @param charset The name of a supported character encoding. - * @param isQueryString whether input is a query string. If true other decoding rules apply. - * @return the newly decoded String - * @exception IllegalArgumentException If the encoding is not valid - */ - public static String decode(String sequence, String charset, boolean isQueryString) { - return UDecoder.URLDecode(sequence, charset, isQueryString); - } - -} diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/Ascii.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/Ascii.java deleted file mode 100644 index 13be1ef6d..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/Ascii.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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.util.tomcat.buf; - -/** - * This class implements some basic ASCII character handling functions. - * - * @author dac@eng.sun.com - * @author James Todd [gonzo@eng.sun.com] - */ -public final class Ascii { - /* - * Character translation tables. - */ - - private static final byte[] toUpper = new byte[256]; - private static final byte[] toLower = new byte[256]; - - /* - * Character type tables. - */ - - private static final boolean[] isAlpha = new boolean[256]; - private static final boolean[] isUpper = new boolean[256]; - private static final boolean[] isLower = new boolean[256]; - private static final boolean[] isWhite = new boolean[256]; - private static final boolean[] isDigit = new boolean[256]; - - private static final long OVERFLOW_LIMIT = Long.MAX_VALUE / 10; - - /* - * Initialize character translation and type tables. - */ - static { - for (int i = 0; i < 256; i++) { - toUpper[i] = (byte)i; - toLower[i] = (byte)i; - } - - for (int lc = 'a'; lc <= 'z'; lc++) { - int uc = lc + 'A' - 'a'; - - toUpper[lc] = (byte)uc; - toLower[uc] = (byte)lc; - isAlpha[lc] = true; - isAlpha[uc] = true; - isLower[lc] = true; - isUpper[uc] = true; - } - - isWhite[ ' '] = true; - isWhite['\t'] = true; - isWhite['\r'] = true; - isWhite['\n'] = true; - isWhite['\f'] = true; - isWhite['\b'] = true; - - for (int d = '0'; d <= '9'; d++) { - isDigit[d] = true; - } - } - - /** - * Returns the upper case equivalent of the specified ASCII character. - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static int toUpper(int c) { - return toUpper[c & 0xff] & 0xff; - } - - /** - * Returns the lower case equivalent of the specified ASCII character. - */ - - public static int toLower(int c) { - return toLower[c & 0xff] & 0xff; - } - - /** - * Returns true if the specified ASCII character is upper or lower case. - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static boolean isAlpha(int c) { - return isAlpha[c & 0xff]; - } - - /** - * Returns true if the specified ASCII character is upper case. - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static boolean isUpper(int c) { - return isUpper[c & 0xff]; - } - - /** - * Returns true if the specified ASCII character is lower case. - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static boolean isLower(int c) { - return isLower[c & 0xff]; - } - - /** - * Returns true if the specified ASCII character is white space. - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static boolean isWhite(int c) { - return isWhite[c & 0xff]; - } - - /** - * Returns true if the specified ASCII character is a digit. - */ - - public static boolean isDigit(int c) { - return isDigit[c & 0xff]; - } - - /** - * Parses an unsigned integer from the specified subarray of bytes. - * @param b the bytes to parse - * @param off the start offset of the bytes - * @param len the length of the bytes - * @exception NumberFormatException if the integer format was invalid - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static int parseInt(byte[] b, int off, int len) - throws NumberFormatException - { - int c; - - if (b == null || len <= 0 || !isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - - int n = c - '0'; - - while (--len > 0) { - if (!isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - n = n * 10 + c - '0'; - } - - return n; - } - - /** - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static int parseInt(char[] b, int off, int len) - throws NumberFormatException - { - int c; - - if (b == null || len <= 0 || !isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - - int n = c - '0'; - - while (--len > 0) { - if (!isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - n = n * 10 + c - '0'; - } - - return n; - } - - /** - * Parses an unsigned long from the specified subarray of bytes. - * @param b the bytes to parse - * @param off the start offset of the bytes - * @param len the length of the bytes - * @exception NumberFormatException if the long format was invalid - */ - public static long parseLong(byte[] b, int off, int len) - throws NumberFormatException - { - int c; - - if (b == null || len <= 0 || !isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - - long n = c - '0'; - while (--len > 0) { - if (isDigit(c = b[off++]) && - (n < OVERFLOW_LIMIT || (n == OVERFLOW_LIMIT && (c - '0') < 8))) { - n = n * 10 + c - '0'; - } else { - throw new NumberFormatException(); - } - } - - return n; - } - - /** - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static long parseLong(char[] b, int off, int len) - throws NumberFormatException - { - int c; - - if (b == null || len <= 0 || !isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - - long n = c - '0'; - long m; - - while (--len > 0) { - if (!isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - m = n * 10 + c - '0'; - - if (m < n) { - // Overflow - throw new NumberFormatException(); - } else { - n = m; - } - } - - return n; - } - -} \ No newline at end of file diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/B2CConverter.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/B2CConverter.java deleted file mode 100644 index 00581cb5c..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/B2CConverter.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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.util.tomcat.buf; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -/** - * NIO based character decoder. - */ -public class B2CConverter { - - private static final Map encodingToCharsetCache = - new HashMap(); - - public static final Charset ISO_8859_1; - public static final Charset UTF_8; - - // Protected so unit tests can use it - protected static final int LEFTOVER_SIZE = 9; - - static { - for (Charset charset: Charset.availableCharsets().values()) { - encodingToCharsetCache.put( - charset.name().toLowerCase(Locale.ENGLISH), charset); - for (String alias : charset.aliases()) { - encodingToCharsetCache.put( - alias.toLowerCase(Locale.ENGLISH), charset); - } - } - Charset iso88591 = null; - Charset utf8 = null; - try { - iso88591 = getCharset("ISO-8859-1"); - utf8 = getCharset("UTF-8"); - } catch (UnsupportedEncodingException e) { - // Impossible. All JVMs must support these. - e.printStackTrace(); - } - ISO_8859_1 = iso88591; - UTF_8 = utf8; - } - - public static Charset getCharset(String enc) - throws UnsupportedEncodingException { - - // Encoding names should all be ASCII - String lowerCaseEnc = enc.toLowerCase(Locale.ENGLISH); - - return getCharsetLower(lowerCaseEnc); - } - - /** - * Only to be used when it is known that the encoding name is in lower case. - */ - public static Charset getCharsetLower(String lowerCaseEnc) - throws UnsupportedEncodingException { - - Charset charset = encodingToCharsetCache.get(lowerCaseEnc); - - if (charset == null) { - // Pre-population of the cache means this must be invalid - throw new UnsupportedEncodingException("The character encoding " + lowerCaseEnc + " is not supported"); - } - return charset; - } - - private final CharsetDecoder decoder; - private ByteBuffer bb = null; - private CharBuffer cb = null; - - /** - * Leftover buffer used for incomplete characters. - */ - private final ByteBuffer leftovers; - - public B2CConverter(String encoding) throws IOException { - this(encoding, false); - } - - public B2CConverter(String encoding, boolean replaceOnError) - throws IOException { - byte[] left = new byte[LEFTOVER_SIZE]; - leftovers = ByteBuffer.wrap(left); - CodingErrorAction action; - if (replaceOnError) { - action = CodingErrorAction.REPLACE; - } else { - action = CodingErrorAction.REPORT; - } - Charset charset = getCharset(encoding); - // Special case. Use the Apache Harmony based UTF-8 decoder because it - // - a) rejects invalid sequences that the JVM decoder does not - // - b) fails faster for some invalid sequences - if (charset.equals(UTF_8)) { - decoder = new Utf8Decoder(); - } else { - decoder = charset.newDecoder(); - } - decoder.onMalformedInput(action); - decoder.onUnmappableCharacter(action); - } - - /** - * Reset the decoder state. - */ - public void recycle() { - decoder.reset(); - leftovers.position(0); - } - - /** - * Convert the given bytes to characters. - * - * @param bc byte input - * @param cc char output - * @param endOfInput Is this all of the available data - */ - public void convert(ByteChunk bc, CharChunk cc, boolean endOfInput) - throws IOException { - if ((bb == null) || (bb.array() != bc.getBuffer())) { - // Create a new byte buffer if anything changed - bb = ByteBuffer.wrap(bc.getBuffer(), bc.getStart(), bc.getLength()); - } else { - // Initialize the byte buffer - bb.limit(bc.getEnd()); - bb.position(bc.getStart()); - } - if ((cb == null) || (cb.array() != cc.getBuffer())) { - // Create a new char buffer if anything changed - cb = CharBuffer.wrap(cc.getBuffer(), cc.getEnd(), - cc.getBuffer().length - cc.getEnd()); - } else { - // Initialize the char buffer - cb.limit(cc.getBuffer().length); - cb.position(cc.getEnd()); - } - CoderResult result = null; - // Parse leftover if any are present - if (leftovers.position() > 0) { - int pos = cb.position(); - // Loop until one char is decoded or there is a decoder error - do { - leftovers.put(bc.substractB()); - leftovers.flip(); - result = decoder.decode(leftovers, cb, endOfInput); - leftovers.position(leftovers.limit()); - leftovers.limit(leftovers.array().length); - } while (result.isUnderflow() && (cb.position() == pos)); - if (result.isError() || result.isMalformed()) { - result.throwException(); - } - bb.position(bc.getStart()); - leftovers.position(0); - } - // Do the decoding and get the results into the byte chunk and the char - // chunk - result = decoder.decode(bb, cb, endOfInput); - if (result.isError() || result.isMalformed()) { - result.throwException(); - } else if (result.isOverflow()) { - // Propagate current positions to the byte chunk and char chunk, if - // this continues the char buffer will get resized - bc.setOffset(bb.position()); - cc.setEnd(cb.position()); - } else if (result.isUnderflow()) { - // Propagate current positions to the byte chunk and char chunk - bc.setOffset(bb.position()); - cc.setEnd(cb.position()); - // Put leftovers in the leftovers byte buffer - if (bc.getLength() > 0) { - leftovers.limit(leftovers.array().length); - leftovers.position(bc.getLength()); - bc.substract(leftovers.array(), 0, bc.getLength()); - } - } - } -} \ No newline at end of file diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/ByteChunk.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/ByteChunk.java deleted file mode 100644 index 49cb3cde4..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/ByteChunk.java +++ /dev/null @@ -1,937 +0,0 @@ -/* - * 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.util.tomcat.buf; - -import java.io.IOException; -import java.io.Serializable; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; - -/* - * In a server it is very important to be able to operate on - * the original byte[] without converting everything to chars. - * Some protocols are ASCII only, and some allow different - * non-UNICODE encodings. The encoding is not known beforehand, - * and can even change during the execution of the protocol. - * ( for example a multipart message may have parts with different - * encoding ) - * - * For HTTP it is not very clear how the encoding of RequestURI - * and mime values can be determined, but it is a great advantage - * to be able to parse the request without converting to string. - */ - -// TODO: This class could either extend ByteBuffer, or better a ByteBuffer -// inside this way it could provide the search/etc on ByteBuffer, as a helper. - -/** - * This class is used to represent a chunk of bytes, and - * utilities to manipulate byte[]. - * - * The buffer can be modified and used for both input and output. - * - * There are 2 modes: The chunk can be associated with a sink - ByteInputChannel - * or ByteOutputChannel, which will be used when the buffer is empty (on input) - * or filled (on output). - * For output, it can also grow. This operating mode is selected by calling - * setLimit() or allocate(initial, limit) with limit != -1. - * - * Various search and append method are defined - similar with String and - * StringBuffer, but operating on bytes. - * - * This is important because it allows processing the http headers directly on - * the received bytes, without converting to chars and Strings until the strings - * are needed. In addition, the charset is determined later, from headers or - * user code. - * - * @author dac@sun.com - * @author James Todd [gonzo@sun.com] - * @author Costin Manolache - * @author Remy Maucherat - */ -public final class ByteChunk implements Cloneable, Serializable { - - private static final long serialVersionUID = 1L; - - /** Input interface, used when the buffer is empty - * - * Same as java.nio.channel.ReadableByteChannel - */ - public static interface ByteInputChannel { - /** - * Read new bytes ( usually the internal conversion buffer ). - * The implementation is allowed to ignore the parameters, - * and mutate the chunk if it wishes to implement its own buffering. - */ - public int realReadBytes(byte cbuf[], int off, int len) - throws IOException; - } - - /** Same as java.nio.channel.WrittableByteChannel. - */ - public static interface ByteOutputChannel { - /** - * Send the bytes ( usually the internal conversion buffer ). - * Expect 8k output if the buffer is full. - */ - public void realWriteBytes(byte cbuf[], int off, int len) - throws IOException; - } - - // -------------------- - - /** Default encoding used to convert to strings. It should be UTF8, - as most standards seem to converge, but the servlet API requires - 8859_1, and this object is used mostly for servlets. - */ - public static final Charset DEFAULT_CHARSET = B2CConverter.ISO_8859_1; - - // byte[] - private byte[] buff; - - private int start=0; - private int end; - - private Charset charset; - - private boolean isSet=false; // XXX - - // How much can it grow, when data is added - private int limit=-1; - - private ByteInputChannel in = null; - private ByteOutputChannel out = null; - - private boolean optimizedWrite=true; - - /** - * Creates a new, uninitialized ByteChunk object. - */ - public ByteChunk() { - // NO-OP - } - - public ByteChunk( int initial ) { - allocate( initial, -1 ); - } - - /** - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public ByteChunk getClone() { - try { - return (ByteChunk)this.clone(); - } catch( Exception ex) { - return null; - } - } - - public boolean isNull() { - return ! isSet; // buff==null; - } - - /** - * Resets the message buff to an uninitialized state. - */ - public void recycle() { - // buff = null; - charset=null; - start=0; - end=0; - isSet=false; - } - - public void reset() { - buff=null; - } - - // -------------------- Setup -------------------- - - public void allocate( int initial, int limit ) { - if( buff==null || buff.length < initial ) { - buff=new byte[initial]; - } - this.limit=limit; - start=0; - end=0; - isSet=true; - } - - /** - * Sets the message bytes to the specified subarray of bytes. - * - * @param b the ascii bytes - * @param off the start offset of the bytes - * @param len the length of the bytes - */ - public void setBytes(byte[] b, int off, int len) { - buff = b; - start = off; - end = start+ len; - isSet=true; - } - - /** - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public void setOptimizedWrite(boolean optimizedWrite) { - this.optimizedWrite = optimizedWrite; - } - - public void setCharset(Charset charset) { - this.charset = charset; - } - - public Charset getCharset() { - if (charset == null) { - charset = DEFAULT_CHARSET; - } - return charset; - } - - /** - * Returns the message bytes. - */ - public byte[] getBytes() { - return getBuffer(); - } - - /** - * Returns the message bytes. - */ - public byte[] getBuffer() { - return buff; - } - - /** - * Returns the start offset of the bytes. - * For output this is the end of the buffer. - */ - public int getStart() { - return start; - } - - public int getOffset() { - return start; - } - - public void setOffset(int off) { - if (end < off ) { - end=off; - } - start=off; - } - - /** - * Returns the length of the bytes. - * XXX need to clean this up - */ - public int getLength() { - return end-start; - } - - /** Maximum amount of data in this buffer. - * - * If -1 or not set, the buffer will grow indefinitely. - * Can be smaller than the current buffer size ( which will not shrink ). - * When the limit is reached, the buffer will be flushed ( if out is set ) - * or throw exception. - */ - public void setLimit(int limit) { - this.limit=limit; - } - - public int getLimit() { - return limit; - } - - /** - * When the buffer is empty, read the data from the input channel. - */ - public void setByteInputChannel(ByteInputChannel in) { - this.in = in; - } - - /** When the buffer is full, write the data to the output channel. - * Also used when large amount of data is appended. - * - * If not set, the buffer will grow to the limit. - */ - public void setByteOutputChannel(ByteOutputChannel out) { - this.out=out; - } - - public int getEnd() { - return end; - } - - public void setEnd( int i ) { - end=i; - } - - // -------------------- Adding data to the buffer -------------------- - /** Append a char, by casting it to byte. This IS NOT intended for unicode. - * - * @param c - * @throws IOException - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public void append( char c ) - throws IOException - { - append( (byte)c); - } - - public void append( byte b ) - throws IOException - { - makeSpace( 1 ); - - // couldn't make space - if( limit >0 && end >= limit ) { - flushBuffer(); - } - buff[end++]=b; - } - - public void append( ByteChunk src ) - throws IOException - { - append( src.getBytes(), src.getStart(), src.getLength()); - } - - /** Add data to the buffer - */ - public void append( byte src[], int off, int len ) - throws IOException - { - // will grow, up to limit - makeSpace( len ); - - // if we don't have limit: makeSpace can grow as it wants - if( limit < 0 ) { - // assert: makeSpace made enough space - System.arraycopy( src, off, buff, end, len ); - end+=len; - return; - } - - // Optimize on a common case. - // If the buffer is empty and the source is going to fill up all the - // space in buffer, may as well write it directly to the output, - // and avoid an extra copy - if ( optimizedWrite && len == limit && end == start && out != null ) { - out.realWriteBytes( src, off, len ); - return; - } - // if we have limit and we're below - if( len <= limit - end ) { - // makeSpace will grow the buffer to the limit, - // so we have space - System.arraycopy( src, off, buff, end, len ); - end+=len; - return; - } - - // need more space than we can afford, need to flush - // buffer - - // the buffer is already at ( or bigger than ) limit - - // We chunk the data into slices fitting in the buffer limit, although - // if the data is written directly if it doesn't fit - - int avail=limit-end; - System.arraycopy(src, off, buff, end, avail); - end += avail; - - flushBuffer(); - - int remain = len - avail; - - while (remain > (limit - end)) { - out.realWriteBytes( src, (off + len) - remain, limit - end ); - remain = remain - (limit - end); - } - - System.arraycopy(src, (off + len) - remain, buff, end, remain); - end += remain; - - } - - - // -------------------- Removing data from the buffer -------------------- - - public int substract() - throws IOException { - - if ((end - start) == 0) { - if (in == null) { - return -1; - } - int n = in.realReadBytes( buff, 0, buff.length ); - if (n < 0) { - return -1; - } - } - - return (buff[start++] & 0xFF); - - } - - - /** - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public int substract(ByteChunk src) - throws IOException { - - if ((end - start) == 0) { - if (in == null) { - return -1; - } - int n = in.realReadBytes( buff, 0, buff.length ); - if (n < 0) { - return -1; - } - } - - int len = getLength(); - src.append(buff, start, len); - start = end; - return len; - - } - - - public byte substractB() - throws IOException { - - if ((end - start) == 0) { - if (in == null) - return -1; - int n = in.realReadBytes( buff, 0, buff.length ); - if (n < 0) - return -1; - } - - return (buff[start++]); - - } - - - public int substract( byte src[], int off, int len ) - throws IOException { - - if ((end - start) == 0) { - if (in == null) { - return -1; - } - int n = in.realReadBytes( buff, 0, buff.length ); - if (n < 0) { - return -1; - } - } - - int n = len; - if (len > getLength()) { - n = getLength(); - } - System.arraycopy(buff, start, src, off, n); - start += n; - return n; - - } - - - /** - * Send the buffer to the sink. Called by append() when the limit is - * reached. You can also call it explicitly to force the data to be written. - * - * @throws IOException - */ - public void flushBuffer() - throws IOException - { - //assert out!=null - if( out==null ) { - throw new IOException( "Buffer overflow, no sink " + limit + " " + - buff.length ); - } - out.realWriteBytes( buff, start, end-start ); - end=start; - } - - /** - * Make space for len chars. If len is small, allocate a reserve space too. - * Never grow bigger than limit. - */ - public void makeSpace(int count) { - byte[] tmp = null; - - int newSize; - int desiredSize=end + count; - - // Can't grow above the limit - if( limit > 0 && - desiredSize > limit) { - desiredSize=limit; - } - - if( buff==null ) { - if( desiredSize < 256 ) - { - desiredSize=256; // take a minimum - } - buff=new byte[desiredSize]; - } - - // limit < buf.length ( the buffer is already big ) - // or we already have space XXX - if( desiredSize <= buff.length ) { - return; - } - // grow in larger chunks - if( desiredSize < 2 * buff.length ) { - newSize= buff.length * 2; - if( limit >0 && - newSize > limit ) { - newSize=limit; - } - tmp=new byte[newSize]; - } else { - newSize= buff.length * 2 + count ; - if( limit > 0 && - newSize > limit ) { - newSize=limit; - } - tmp=new byte[newSize]; - } - - System.arraycopy(buff, start, tmp, 0, end-start); - buff = tmp; - tmp = null; - end=end-start; - start=0; - } - - // -------------------- Conversion and getters -------------------- - - @Override - public String toString() { - if (null == buff) { - return null; - } else if (end-start == 0) { - return ""; - } - return StringCache.toString(this); - } - - public String toStringInternal() { - if (charset == null) { - charset = DEFAULT_CHARSET; - } - // new String(byte[], int, int, Charset) takes a defensive copy of the - // entire byte array. This is expensive if only a small subset of the - // bytes will be used. The code below is from Apache Harmony. - CharBuffer cb; - cb = charset.decode(ByteBuffer.wrap(buff, start, end-start)); - return new String(cb.array(), cb.arrayOffset(), cb.length()); - } - - /** - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public int getInt() - { - return Ascii.parseInt(buff, start,end-start); - } - - public long getLong() { - return Ascii.parseLong(buff, start,end-start); - } - - - // -------------------- equals -------------------- - - /** - * Compares the message bytes to the specified String object. - * @param s the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equals(String s) { - // XXX ENCODING - this only works if encoding is UTF8-compat - // ( ok for tomcat, where we compare ascii - header names, etc )!!! - - byte[] b = buff; - int blen = end-start; - if (b == null || blen != s.length()) { - return false; - } - int boff = start; - for (int i = 0; i < blen; i++) { - if (b[boff++] != s.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Compares the message bytes to the specified String object. - * @param s the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equalsIgnoreCase(String s) { - byte[] b = buff; - int blen = end-start; - if (b == null || blen != s.length()) { - return false; - } - int boff = start; - for (int i = 0; i < blen; i++) { - if (Ascii.toLower(b[boff++]) != Ascii.toLower(s.charAt(i))) { - return false; - } - } - return true; - } - - public boolean equals( ByteChunk bb ) { - return equals( bb.getBytes(), bb.getStart(), bb.getLength()); - } - - public boolean equals( byte b2[], int off2, int len2) { - byte b1[]=buff; - if( b1==null && b2==null ) { - return true; - } - - int len=end-start; - if ( len2 != len || b1==null || b2==null ) { - return false; - } - - int off1 = start; - - while ( len-- > 0) { - if (b1[off1++] != b2[off2++]) { - return false; - } - } - return true; - } - - public boolean equals( CharChunk cc ) { - return equals( cc.getChars(), cc.getStart(), cc.getLength()); - } - - public boolean equals( char c2[], int off2, int len2) { - // XXX works only for enc compatible with ASCII/UTF !!! - byte b1[]=buff; - if( c2==null && b1==null ) { - return true; - } - - if (b1== null || c2==null || end-start != len2 ) { - return false; - } - int off1 = start; - int len=end-start; - - while ( len-- > 0) { - if ( (char)b1[off1++] != c2[off2++]) { - return false; - } - } - return true; - } - - /** - * Returns true if the message bytes starts with the specified string. - * @param s the string - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public boolean startsWith(String s) { - // Works only if enc==UTF - byte[] b = buff; - int blen = s.length(); - if (b == null || blen > end-start) { - return false; - } - int boff = start; - for (int i = 0; i < blen; i++) { - if (b[boff++] != s.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Returns true if the message bytes start with the specified byte array. - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public boolean startsWith(byte[] b2) { - byte[] b1 = buff; - if (b1 == null && b2 == null) { - return true; - } - - int len = end - start; - if (b1 == null || b2 == null || b2.length > len) { - return false; - } - for (int i = start, j = 0; i < end && j < b2.length;) { - if (b1[i++] != b2[j++]) { - return false; - } - } - return true; - } - - /** - * Returns true if the message bytes starts with the specified string. - * @param s the string - * @param pos The position - */ - public boolean startsWithIgnoreCase(String s, int pos) { - byte[] b = buff; - int len = s.length(); - if (b == null || len+pos > end-start) { - return false; - } - int off = start+pos; - for (int i = 0; i < len; i++) { - if (Ascii.toLower( b[off++] ) != Ascii.toLower( s.charAt(i))) { - return false; - } - } - return true; - } - - public int indexOf( String src, int srcOff, int srcLen, int myOff ) { - char first=src.charAt( srcOff ); - - // Look for first char - int srcEnd = srcOff + srcLen; - - mainLoop: - for( int i=myOff+start; i <= (end - srcLen); i++ ) { - if( buff[i] != first ) { - continue; - } - // found first char, now look for a match - int myPos=i+1; - for( int srcPos=srcOff + 1; srcPos< srcEnd;) { - if( buff[myPos++] != src.charAt( srcPos++ )) { - continue mainLoop; - } - } - return i-start; // found it - } - return -1; - } - - // -------------------- Hash code -------------------- - - // normal hash. - public int hash() { - return hashBytes( buff, start, end-start); - } - - /** - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public int hashIgnoreCase() { - return hashBytesIC( buff, start, end-start ); - } - - private static int hashBytes( byte buff[], int start, int bytesLen ) { - int max=start+bytesLen; - byte bb[]=buff; - int code=0; - for (int i = start; i < max ; i++) { - code = code * 37 + bb[i]; - } - return code; - } - - private static int hashBytesIC( byte bytes[], int start, - int bytesLen ) - { - int max=start+bytesLen; - byte bb[]=bytes; - int code=0; - for (int i = start; i < max ; i++) { - code = code * 37 + Ascii.toLower(bb[i]); - } - return code; - } - - /** - * Returns the first instance of the given character in this ByteChunk - * starting at the specified byte. If the character is not found, -1 is - * returned. - *
    - * NOTE: This only works for characters in the range 0-127. - * - * @param c The character - * @param starting The start position - * @return The position of the first instance of the character or - * -1 if the character is not found. - */ - public int indexOf(char c, int starting) { - int ret = indexOf(buff, start + starting, end, c); - return (ret >= start) ? ret - start : -1; - } - - /** - * Returns the first instance of the given character in the given byte array - * between the specified start and end. - *
    - * NOTE: This only works for characters in the range 0-127. - * - * @param bytes The byte array to search - * @param start The point to start searching from in the byte array - * @param end The point to stop searching in the byte array - * @param c The character to search for - * @return The position of the first instance of the character or -1 - * if the character is not found. - */ - public static int indexOf(byte bytes[], int start, int end, char c) { - int offset = start; - - while (offset < end) { - byte b=bytes[offset]; - if (b == c) { - return offset; - } - offset++; - } - return -1; - } - - /** - * Returns the first instance of the given byte in the byte array between - * the specified start and end. - * - * @param bytes The byte array to search - * @param start The point to start searching from in the byte array - * @param end The point to stop searching in the byte array - * @param b The byte to search for - * @return The position of the first instance of the byte or -1 if the - * byte is not found. - */ - public static int findByte(byte bytes[], int start, int end, byte b) { - int offset = start; - while (offset < end) { - if (bytes[offset] == b) { - return offset; - } - offset++; - } - return -1; - } - - /** - * Returns the first instance of any of the given bytes in the byte array - * between the specified start and end. - * - * @param bytes The byte array to search - * @param start The point to start searching from in the byte array - * @param end The point to stop searching in the byte array - * @param b The array of bytes to search for - * @return The position of the first instance of the byte or -1 if the - * byte is not found. - */ - public static int findBytes(byte bytes[], int start, int end, byte b[]) { - int blen = b.length; - int offset = start; - while (offset < end) { - for (int i = 0; i < blen; i++) { - if (bytes[offset] == b[i]) { - return offset; - } - } - offset++; - } - return -1; - } - - /** - * Returns the first instance of any byte that is not one of the given bytes - * in the byte array between the specified start and end. - * - * @param bytes The byte array to search - * @param start The point to start searching from in the byte array - * @param end The point to stop searching in the byte array - * @param b The list of bytes to search for - * @return The position of the first instance a byte that is not - * in the list of bytes to search for or -1 if no such byte - * is found. - * @deprecated Unused. Will be removed in Tomcat 8.0.x onwards. - */ - @Deprecated - public static int findNotBytes(byte bytes[], int start, int end, byte b[]) { - int blen = b.length; - int offset = start; - boolean found; - - while (offset < end) { - found = true; - for (int i = 0; i < blen; i++) { - if (bytes[offset] == b[i]) { - found=false; - break; - } - } - if (found) { - return offset; - } - offset++; - } - return -1; - } - - - /** - * Convert specified String to a byte array. This ONLY WORKS for ascii, UTF - * chars will be truncated. - * - * @param value to convert to byte array - * @return the byte array value - */ - public static final byte[] convertToBytes(String value) { - byte[] result = new byte[value.length()]; - for (int i = 0; i < value.length(); i++) { - result[i] = (byte) value.charAt(i); - } - return result; - } -} \ No newline at end of file diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/CharChunk.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/CharChunk.java deleted file mode 100644 index c612abe49..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/CharChunk.java +++ /dev/null @@ -1,702 +0,0 @@ -/* - * 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.util.tomcat.buf; - -import java.io.IOException; -import java.io.Serializable; - -/** - * Utilities to manipulate char chunks. While String is - * the easiest way to manipulate chars ( search, substrings, etc), - * it is known to not be the most efficient solution - Strings are - * designed as immutable and secure objects. - * - * @author dac@sun.com - * @author James Todd [gonzo@sun.com] - * @author Costin Manolache - * @author Remy Maucherat - */ -public final class CharChunk implements Cloneable, Serializable, CharSequence { - - private static final long serialVersionUID = 1L; - - // Input interface, used when the buffer is emptied. - public static interface CharInputChannel { - /** - * Read new bytes ( usually the internal conversion buffer ). - * The implementation is allowed to ignore the parameters, - * and mutate the chunk if it wishes to implement its own buffering. - */ - public int realReadChars(char cbuf[], int off, int len) - throws IOException; - } - /** - * When we need more space we'll either - * grow the buffer ( up to the limit ) or send it to a channel. - */ - public static interface CharOutputChannel { - /** Send the bytes ( usually the internal conversion buffer ). - * Expect 8k output if the buffer is full. - */ - public void realWriteChars(char cbuf[], int off, int len) - throws IOException; - } - - // -------------------- - - private int hashCode = 0; - // did we compute the hashcode ? - private boolean hasHashCode = false; - - // char[] - private char buff[]; - - private int start; - private int end; - - private boolean isSet=false; // XXX - - // -1: grow indefinitely - // maximum amount to be cached - private int limit=-1; - - private CharInputChannel in = null; - private CharOutputChannel out = null; - - private boolean optimizedWrite=true; - - /** - * Creates a new, uninitialized CharChunk object. - */ - public CharChunk() { - } - - public CharChunk(int size) { - allocate( size, -1 ); - } - - // -------------------- - - public boolean isNull() { - if( end > 0 ) { - return false; - } - return !isSet; //XXX - } - - /** - * Resets the message bytes to an uninitialized state. - */ - public void recycle() { - // buff=null; - isSet=false; // XXX - hasHashCode = false; - start=0; - end=0; - } - - // -------------------- Setup -------------------- - - public void allocate( int initial, int limit ) { - if( buff==null || buff.length < initial ) { - buff=new char[initial]; - } - this.limit=limit; - start=0; - end=0; - isSet=true; - hasHashCode = false; - } - - - public void setOptimizedWrite(boolean optimizedWrite) { - this.optimizedWrite = optimizedWrite; - } - - public void setChars( char[] c, int off, int len ) { - buff=c; - start=off; - end=start + len; - isSet=true; - hasHashCode = false; - } - - /** Maximum amount of data in this buffer. - * - * If -1 or not set, the buffer will grow indefinitely. - * Can be smaller than the current buffer size ( which will not shrink ). - * When the limit is reached, the buffer will be flushed ( if out is set ) - * or throw exception. - */ - public void setLimit(int limit) { - this.limit=limit; - } - - public int getLimit() { - return limit; - } - - /** - * When the buffer is empty, read the data from the input channel. - */ - public void setCharInputChannel(CharInputChannel in) { - this.in = in; - } - - /** When the buffer is full, write the data to the output channel. - * Also used when large amount of data is appended. - * - * If not set, the buffer will grow to the limit. - */ - public void setCharOutputChannel(CharOutputChannel out) { - this.out=out; - } - - // compat - public char[] getChars() - { - return getBuffer(); - } - - public char[] getBuffer() - { - return buff; - } - - /** - * Returns the start offset of the bytes. - * For output this is the end of the buffer. - */ - public int getStart() { - return start; - } - - public int getOffset() { - return start; - } - - /** - * Returns the start offset of the bytes. - */ - public void setOffset(int off) { - start=off; - } - - /** - * Returns the length of the bytes. - */ - public int getLength() { - return end-start; - } - - - public int getEnd() { - return end; - } - - public void setEnd( int i ) { - end=i; - } - - // -------------------- Adding data -------------------- - - public void append( char b ) - throws IOException - { - makeSpace( 1 ); - - // couldn't make space - if( limit >0 && end >= limit ) { - flushBuffer(); - } - buff[end++]=b; - } - - public void append( CharChunk src ) - throws IOException - { - append( src.getBuffer(), src.getOffset(), src.getLength()); - } - - /** Add data to the buffer - */ - public void append( char src[], int off, int len ) - throws IOException - { - // will grow, up to limit - makeSpace( len ); - - // if we don't have limit: makeSpace can grow as it wants - if( limit < 0 ) { - // assert: makeSpace made enough space - System.arraycopy( src, off, buff, end, len ); - end+=len; - return; - } - - // Optimize on a common case. - // If the source is going to fill up all the space in buffer, may - // as well write it directly to the output, and avoid an extra copy - if ( optimizedWrite && len == limit && end == start && out != null ) { - out.realWriteChars( src, off, len ); - return; - } - - // if we have limit and we're below - if( len <= limit - end ) { - // makeSpace will grow the buffer to the limit, - // so we have space - System.arraycopy( src, off, buff, end, len ); - - end+=len; - return; - } - - // need more space than we can afford, need to flush - // buffer - - // the buffer is already at ( or bigger than ) limit - - // Optimization: - // If len-avail < length ( i.e. after we fill the buffer with - // what we can, the remaining will fit in the buffer ) we'll just - // copy the first part, flush, then copy the second part - 1 write - // and still have some space for more. We'll still have 2 writes, but - // we write more on the first. - - if( len + end < 2 * limit ) { - /* If the request length exceeds the size of the output buffer, - flush the output buffer and then write the data directly. - We can't avoid 2 writes, but we can write more on the second - */ - int avail=limit-end; - System.arraycopy(src, off, buff, end, avail); - end += avail; - - flushBuffer(); - - System.arraycopy(src, off+avail, buff, end, len - avail); - end+= len - avail; - - } else { // len > buf.length + avail - // long write - flush the buffer and write the rest - // directly from source - flushBuffer(); - - out.realWriteChars( src, off, len ); - } - } - - - /** Append a string to the buffer - */ - public void append(String s) throws IOException { - append(s, 0, s.length()); - } - - /** Append a string to the buffer - */ - public void append(String s, int off, int len) throws IOException { - if (s==null) { - return; - } - - // will grow, up to limit - makeSpace( len ); - - // if we don't have limit: makeSpace can grow as it wants - if( limit < 0 ) { - // assert: makeSpace made enough space - s.getChars(off, off+len, buff, end ); - end+=len; - return; - } - - int sOff = off; - int sEnd = off + len; - while (sOff < sEnd) { - int d = min(limit - end, sEnd - sOff); - s.getChars( sOff, sOff+d, buff, end); - sOff += d; - end += d; - if (end >= limit) { - flushBuffer(); - } - } - } - - // -------------------- Removing data from the buffer -------------------- - - public int substract() - throws IOException { - - if ((end - start) == 0) { - if (in == null) { - return -1; - } - int n = in.realReadChars(buff, end, buff.length - end); - if (n < 0) { - return -1; - } - } - - return (buff[start++]); - - } - - public int substract( char src[], int off, int len ) - throws IOException { - - if ((end - start) == 0) { - if (in == null) { - return -1; - } - int n = in.realReadChars( buff, end, buff.length - end); - if (n < 0) { - return -1; - } - } - - int n = len; - if (len > getLength()) { - n = getLength(); - } - System.arraycopy(buff, start, src, off, n); - start += n; - return n; - - } - - - public void flushBuffer() - throws IOException - { - //assert out!=null - if( out==null ) { - throw new IOException( "Buffer overflow, no sink " + limit + " " + - buff.length ); - } - out.realWriteChars( buff, start, end - start ); - end=start; - } - - /** Make space for len chars. If len is small, allocate - * a reserve space too. Never grow bigger than limit. - */ - public void makeSpace(int count) - { - char[] tmp = null; - - int newSize; - int desiredSize=end + count; - - // Can't grow above the limit - if( limit > 0 && - desiredSize > limit) { - desiredSize=limit; - } - - if( buff==null ) { - if( desiredSize < 256 ) - { - desiredSize=256; // take a minimum - } - buff=new char[desiredSize]; - } - - // limit < buf.length ( the buffer is already big ) - // or we already have space XXX - if( desiredSize <= buff.length) { - return; - } - // grow in larger chunks - if( desiredSize < 2 * buff.length ) { - newSize= buff.length * 2; - if( limit >0 && - newSize > limit ) { - newSize=limit; - } - tmp=new char[newSize]; - } else { - newSize= buff.length * 2 + count ; - if( limit > 0 && - newSize > limit ) { - newSize=limit; - } - tmp=new char[newSize]; - } - - System.arraycopy(buff, 0, tmp, 0, end); - buff = tmp; - tmp = null; - } - - // -------------------- Conversion and getters -------------------- - - @Override - public String toString() { - if (null == buff) { - return null; - } else if (end-start == 0) { - return ""; - } - return StringCache.toString(this); - } - - public String toStringInternal() { - return new String(buff, start, end-start); - } - - // -------------------- equals -------------------- - - @Override - public boolean equals(Object obj) { - if (obj instanceof CharChunk) { - return equals((CharChunk) obj); - } - return false; - } - - /** - * Compares the message bytes to the specified String object. - * @param s the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equals(String s) { - char[] c = buff; - int len = end-start; - if (c == null || len != s.length()) { - return false; - } - int off = start; - for (int i = 0; i < len; i++) { - if (c[off++] != s.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Compares the message bytes to the specified String object. - * @param s the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equalsIgnoreCase(String s) { - char[] c = buff; - int len = end-start; - if (c == null || len != s.length()) { - return false; - } - int off = start; - for (int i = 0; i < len; i++) { - if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) { - return false; - } - } - return true; - } - - public boolean equals(CharChunk cc) { - return equals( cc.getChars(), cc.getOffset(), cc.getLength()); - } - - public boolean equals(char b2[], int off2, int len2) { - char b1[]=buff; - if( b1==null && b2==null ) { - return true; - } - - if (b1== null || b2==null || end-start != len2) { - return false; - } - int off1 = start; - int len=end-start; - while ( len-- > 0) { - if (b1[off1++] != b2[off2++]) { - return false; - } - } - return true; - } - - /** - * Returns true if the message bytes starts with the specified string. - * @param s the string - */ - public boolean startsWith(String s) { - char[] c = buff; - int len = s.length(); - if (c == null || len > end-start) { - return false; - } - int off = start; - for (int i = 0; i < len; i++) { - if (c[off++] != s.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Returns true if the message bytes starts with the specified string. - * @param s the string - */ - public boolean startsWithIgnoreCase(String s, int pos) { - char[] c = buff; - int len = s.length(); - if (c == null || len+pos > end-start) { - return false; - } - int off = start+pos; - for (int i = 0; i < len; i++) { - if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) { - return false; - } - } - return true; - } - - - /** - * Returns true if the message bytes end with the specified string. - * @param s the string - */ - public boolean endsWith(String s) { - char[] c = buff; - int len = s.length(); - if (c == null || len > end-start) { - return false; - } - int off = end - len; - for (int i = 0; i < len; i++) { - if (c[off++] != s.charAt(i)) { - return false; - } - } - return true; - } - - // -------------------- Hash code -------------------- - - @Override - public int hashCode() { - if (hasHashCode) { - return hashCode; - } - int code = 0; - - code = hash(); - hashCode = code; - hasHashCode = true; - return code; - } - - // normal hash. - public int hash() { - int code=0; - for (int i = start; i < start + end-start; i++) { - code = code * 37 + buff[i]; - } - return code; - } - - public int indexOf(char c) { - return indexOf( c, start); - } - - /** - * Returns true if the message bytes starts with the specified string. - * @param c the character - */ - public int indexOf(char c, int starting) { - int ret = indexOf( buff, start+starting, end, c ); - return (ret >= start) ? ret - start : -1; - } - - public static int indexOf( char chars[], int off, int cend, char qq ) - { - while( off < cend ) { - char b=chars[off]; - if( b==qq ) { - return off; - } - off++; - } - return -1; - } - - - public int indexOf(String src, int srcOff, int srcLen, int myOff ) { - char first=src.charAt( srcOff ); - - // Look for first char - int srcEnd = srcOff + srcLen; - - for( int i=myOff+start; i <= (end - srcLen); i++ ) { - if( buff[i] != first ) { - continue; - } - // found first char, now look for a match - int myPos=i+1; - for( int srcPos=srcOff + 1; srcPos< srcEnd;) { - if( buff[myPos++] != src.charAt( srcPos++ )) { - break; - } - if( srcPos==srcEnd ) - { - return i-start; // found it - } - } - } - return -1; - } - - // -------------------- utils - private int min(int a, int b) { - if (a < b) { - return a; - } - return b; - } - - // Char sequence impl - - public char charAt(int index) { - return buff[index + start]; - } - - public CharSequence subSequence(int start, int end) { - try { - CharChunk result = (CharChunk) this.clone(); - result.setOffset(this.start + start); - result.setEnd(this.start + end); - return result; - } catch (CloneNotSupportedException e) { - // Cannot happen - return null; - } - } - - public int length() { - return end - start; - } - -} diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/HexUtils.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/HexUtils.java deleted file mode 100644 index 461675276..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/HexUtils.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.util.tomcat.buf; - -/** - * Tables useful when converting byte arrays to and from strings of hexadecimal - * digits. - * Code from Ajp11, from Apache's JServ. - * - * @author Craig R. McClanahan - */ -public final class HexUtils { - - // -------------------------------------------------------------- Constants - - /** - * Table for HEX to DEC byte translation. - */ - private static final int[] DEC = { - 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, - }; - - - /** - * Table for DEC to HEX byte translation. - */ - private static final byte[] HEX = - { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', - (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', - (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' }; - - - /** - * Table for byte to hex string translation. - */ - private static final char[] hex = "0123456789abcdef".toCharArray(); - - - // --------------------------------------------------------- Static Methods - - public static int getDec(int index) { - // Fast for correct values, slower for incorrect ones - try { - return DEC[index - '0']; - } catch (ArrayIndexOutOfBoundsException ex) { - return -1; - } - } - - - public static byte getHex(int index) { - return HEX[index]; - } - - - public static String toHexString(byte[] bytes) { - if (null == bytes) { - return null; - } - - StringBuilder sb = new StringBuilder(bytes.length << 1); - - for(int i = 0; i < bytes.length; ++i) { - sb.append(hex[(bytes[i] & 0xf0) >> 4]) - .append(hex[(bytes[i] & 0x0f)]) - ; - } - - return sb.toString(); - } - - - public static byte[] fromHexString(String input) { - if (input == null) { - return null; - } - - if ((input.length() & 1) == 1) { - // Odd number of characters - throw new IllegalArgumentException("The input must consist of an even number of hex digits"); - } - - char[] inputChars = input.toCharArray(); - byte[] result = new byte[input.length() >> 1]; - for (int i = 0; i < result.length; i++) { - int upperNibble = getDec(inputChars[2*i]); - int lowerNibble = getDec(inputChars[2*i + 1]); - if (upperNibble < 0 || lowerNibble < 0) { - // Non hex character - throw new IllegalArgumentException("The input must consist only of hex digits"); - } - result[i] = (byte) ((upperNibble << 4) + lowerNibble); - } - return result; - } -} diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/MessageBytes.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/MessageBytes.java deleted file mode 100644 index db7ab8a71..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/MessageBytes.java +++ /dev/null @@ -1,548 +0,0 @@ -/* - * 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.util.tomcat.buf; - -import java.io.IOException; -import java.io.Serializable; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.Locale; - -/** - * This class is used to represent a subarray of bytes in an HTTP message. - * It represents all request/response elements. The byte/char conversions are - * delayed and cached. Everything is recyclable. - * - * The object can represent a byte[], a char[], or a (sub) String. All - * operations can be made in case sensitive mode or not. - * - * @author dac@eng.sun.com - * @author James Todd [gonzo@eng.sun.com] - * @author Costin Manolache - */ -public final class MessageBytes implements Cloneable, Serializable { - private static final long serialVersionUID = 1L; - - // primary type ( whatever is set as original value ) - private int type = T_NULL; - - public static final int T_NULL = 0; - /** getType() is T_STR if the the object used to create the MessageBytes - was a String */ - public static final int T_STR = 1; - /** getType() is T_STR if the the object used to create the MessageBytes - was a byte[] */ - public static final int T_BYTES = 2; - /** getType() is T_STR if the the object used to create the MessageBytes - was a char[] */ - public static final int T_CHARS = 3; - - private int hashCode=0; - // did we compute the hashcode ? - private boolean hasHashCode=false; - - // Internal objects to represent array + offset, and specific methods - private final ByteChunk byteC=new ByteChunk(); - private final CharChunk charC=new CharChunk(); - - // String - private String strValue; - // true if a String value was computed. Probably not needed, - // strValue!=null is the same - private boolean hasStrValue=false; - - /** - * Creates a new, uninitialized MessageBytes object. - * Use static newInstance() in order to allow - * future hooks. - */ - private MessageBytes() { - } - - /** Construct a new MessageBytes instance - */ - public static MessageBytes newInstance() { - return factory.newInstance(); - } - - public boolean isNull() { - // should we check also hasStrValue ??? - return byteC.isNull() && charC.isNull() && ! hasStrValue; - // bytes==null && strValue==null; - } - - /** - * Resets the message bytes to an uninitialized (NULL) state. - */ - public void recycle() { - type=T_NULL; - byteC.recycle(); - charC.recycle(); - - strValue=null; - - hasStrValue=false; - hasHashCode=false; - hasLongValue=false; - } - - - /** - * Sets the content to the specified subarray of bytes. - * - * @param b the bytes - * @param off the start offset of the bytes - * @param len the length of the bytes - */ - public void setBytes(byte[] b, int off, int len) { - byteC.setBytes( b, off, len ); - type=T_BYTES; - hasStrValue=false; - hasHashCode=false; - hasLongValue=false; - } - - /** - * Sets the content to be a char[] - * - * @param c the bytes - * @param off the start offset of the bytes - * @param len the length of the bytes - */ - public void setChars( char[] c, int off, int len ) { - charC.setChars( c, off, len ); - type=T_CHARS; - hasStrValue=false; - hasHashCode=false; - hasLongValue=false; - } - - /** - * Set the content to be a string - */ - public void setString( String s ) { - strValue=s; - hasHashCode=false; - hasLongValue=false; - if (s == null) { - hasStrValue=false; - type=T_NULL; - } else { - hasStrValue=true; - type=T_STR; - } - } - - // -------------------- Conversion and getters -------------------- - - /** Compute the string value - */ - @Override - public String toString() { - if( hasStrValue ) { - return strValue; - } - - switch (type) { - case T_CHARS: - strValue=charC.toString(); - hasStrValue=true; - return strValue; - case T_BYTES: - strValue=byteC.toString(); - hasStrValue=true; - return strValue; - } - return null; - } - - //---------------------------------------- - /** Return the type of the original content. Can be - * T_STR, T_BYTES, T_CHARS or T_NULL - */ - public int getType() { - return type; - } - - /** - * Returns the byte chunk, representing the byte[] and offset/length. - * Valid only if T_BYTES or after a conversion was made. - */ - public ByteChunk getByteChunk() { - return byteC; - } - - /** - * Returns the char chunk, representing the char[] and offset/length. - * Valid only if T_CHARS or after a conversion was made. - */ - public CharChunk getCharChunk() { - return charC; - } - - /** - * Returns the string value. - * Valid only if T_STR or after a conversion was made. - */ - public String getString() { - return strValue; - } - - /** - * Get the Charset used for string<->byte conversions. - */ - public Charset getCharset() { - return byteC.getCharset(); - } - - /** - * Set the Charset used for string<->byte conversions. - */ - public void setCharset(Charset charset) { - byteC.setCharset(charset); - } - - /** Do a char->byte conversion. - */ - public void toBytes() { - if (!byteC.isNull()) { - type=T_BYTES; - return; - } - toString(); - type=T_BYTES; - Charset charset = byteC.getCharset(); - ByteBuffer result = charset.encode(strValue); - byteC.setBytes(result.array(), result.arrayOffset(), result.limit()); - } - - /** Convert to char[] and fill the CharChunk. - * XXX Not optimized - it converts to String first. - */ - public void toChars() { - if( ! charC.isNull() ) { - type=T_CHARS; - return; - } - // inefficient - toString(); - type=T_CHARS; - char cc[]=strValue.toCharArray(); - charC.setChars(cc, 0, cc.length); - } - - - /** - * Returns the length of the original buffer. - * Note that the length in bytes may be different from the length - * in chars. - */ - public int getLength() { - if(type==T_BYTES) { - return byteC.getLength(); - } - if(type==T_CHARS) { - return charC.getLength(); - } - if(type==T_STR) { - return strValue.length(); - } - toString(); - if( strValue==null ) { - return 0; - } - return strValue.length(); - } - - // -------------------- equals -------------------- - - /** - * Compares the message bytes to the specified String object. - * @param s the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equals(String s) { - switch (type) { - case T_STR: - if (strValue == null) { - return s == null; - } - return strValue.equals( s ); - case T_CHARS: - return charC.equals( s ); - case T_BYTES: - return byteC.equals( s ); - default: - return false; - } - } - - /** - * Compares the message bytes to the specified String object. - * @param s the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equalsIgnoreCase(String s) { - switch (type) { - case T_STR: - if (strValue == null) { - return s == null; - } - return strValue.equalsIgnoreCase( s ); - case T_CHARS: - return charC.equalsIgnoreCase( s ); - case T_BYTES: - return byteC.equalsIgnoreCase( s ); - default: - return false; - } - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof MessageBytes) { - return equals((MessageBytes) obj); - } - return false; - } - - public boolean equals(MessageBytes mb) { - switch (type) { - case T_STR: - return mb.equals( strValue ); - } - - if( mb.type != T_CHARS && - mb.type!= T_BYTES ) { - // it's a string or int/date string value - return equals( mb.toString() ); - } - - // mb is either CHARS or BYTES. - // this is either CHARS or BYTES - // Deal with the 4 cases ( in fact 3, one is symmetric) - - if( mb.type == T_CHARS && type==T_CHARS ) { - return charC.equals( mb.charC ); - } - if( mb.type==T_BYTES && type== T_BYTES ) { - return byteC.equals( mb.byteC ); - } - if( mb.type== T_CHARS && type== T_BYTES ) { - return byteC.equals( mb.charC ); - } - if( mb.type== T_BYTES && type== T_CHARS ) { - return mb.byteC.equals( charC ); - } - // can't happen - return true; - } - - - /** - * Returns true if the message bytes starts with the specified string. - * @param s the string - * @param pos The start position - */ - public boolean startsWithIgnoreCase(String s, int pos) { - switch (type) { - case T_STR: - if( strValue==null ) { - return false; - } - if( strValue.length() < pos + s.length() ) { - return false; - } - - for( int i=0; i 0) { - int digit = (int) (current % 10); - current = current / 10; - buf[end++] = HexUtils.getHex(digit); - } - byteC.setOffset(0); - byteC.setEnd(end); - // Inverting buffer - end--; - if (l < 0) { - start++; - } - while (end > start) { - byte temp = buf[start]; - buf[start] = buf[end]; - buf[end] = temp; - start++; - end--; - } - longValue=l; - hasStrValue=false; - hasHashCode=false; - hasLongValue=true; - type=T_BYTES; - } - - // Used for headers conversion - /** Convert the buffer to an long, cache the value - */ - public long getLong() { - if( hasLongValue ) { - return longValue; - } - - switch (type) { - case T_BYTES: - longValue=byteC.getLong(); - break; - default: - longValue= Long.parseLong(toString()); - } - - hasLongValue=true; - return longValue; - - } - - // -------------------- Future may be different -------------------- - - private static final MessageBytesFactory factory=new MessageBytesFactory(); - - private static class MessageBytesFactory { - protected MessageBytesFactory() { - } - public MessageBytes newInstance() { - return new MessageBytes(); - } - } -} diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/StringCache.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/StringCache.java deleted file mode 100644 index d568ea5fa..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/StringCache.java +++ /dev/null @@ -1,697 +0,0 @@ -/* - * 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.util.tomcat.buf; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map.Entry; -import java.util.TreeMap; - -/** - * This class implements a String cache for ByteChunk and CharChunk. - * - * @author Remy Maucherat - */ -public class StringCache { - - - private static final Logger log = LogManager.getLogger(StringCache.class); - - - // ------------------------------------------------------- Static Variables - - - /** - * Enabled ? - */ - protected static boolean byteEnabled = ("true".equals(System.getProperty( - "tomcat.util.buf.StringCache.byte.enabled", "false"))); - - - protected static boolean charEnabled = ("true".equals(System.getProperty( - "tomcat.util.buf.StringCache.char.enabled", "false"))); - - - protected static int trainThreshold = Integer.parseInt(System.getProperty( - "tomcat.util.buf.StringCache.trainThreshold", "20000")); - - - protected static int cacheSize = Integer.parseInt(System.getProperty( - "tomcat.util.buf.StringCache.cacheSize", "200")); - - - protected static final int maxStringSize = - Integer.parseInt(System.getProperty( - "tomcat.util.buf.StringCache.maxStringSize", "128")); - - - /** - * Statistics hash map for byte chunk. - */ - protected static final HashMap bcStats = - new HashMap(cacheSize); - - - /** - * toString count for byte chunk. - */ - protected static int bcCount = 0; - - - /** - * Cache for byte chunk. - */ - protected static ByteEntry[] bcCache = null; - - - /** - * Statistics hash map for char chunk. - */ - protected static final HashMap ccStats = - new HashMap(cacheSize); - - - /** - * toString count for char chunk. - */ - protected static int ccCount = 0; - - - /** - * Cache for char chunk. - */ - protected static CharEntry[] ccCache = null; - - - /** - * Access count. - */ - protected static int accessCount = 0; - - - /** - * Hit count. - */ - protected static int hitCount = 0; - - - // ------------------------------------------------------------ Properties - - - /** - * @return Returns the cacheSize. - */ - public int getCacheSize() { - return cacheSize; - } - - - /** - * @param cacheSize The cacheSize to set. - */ - public void setCacheSize(int cacheSize) { - StringCache.cacheSize = cacheSize; - } - - - /** - * @return Returns the enabled. - */ - public boolean getByteEnabled() { - return byteEnabled; - } - - - /** - * @param byteEnabled The enabled to set. - */ - public void setByteEnabled(boolean byteEnabled) { - StringCache.byteEnabled = byteEnabled; - } - - - /** - * @return Returns the enabled. - */ - public boolean getCharEnabled() { - return charEnabled; - } - - - /** - * @param charEnabled The enabled to set. - */ - public void setCharEnabled(boolean charEnabled) { - StringCache.charEnabled = charEnabled; - } - - - /** - * @return Returns the trainThreshold. - */ - public int getTrainThreshold() { - return trainThreshold; - } - - - /** - * @param trainThreshold The trainThreshold to set. - */ - public void setTrainThreshold(int trainThreshold) { - StringCache.trainThreshold = trainThreshold; - } - - - /** - * @return Returns the accessCount. - */ - public int getAccessCount() { - return accessCount; - } - - - /** - * @return Returns the hitCount. - */ - public int getHitCount() { - return hitCount; - } - - - // -------------------------------------------------- Public Static Methods - - - public void reset() { - hitCount = 0; - accessCount = 0; - synchronized (bcStats) { - bcCache = null; - bcCount = 0; - } - synchronized (ccStats) { - ccCache = null; - ccCount = 0; - } - } - - - public static String toString(ByteChunk bc) { - - // If the cache is null, then either caching is disabled, or we're - // still training - if (bcCache == null) { - String value = bc.toStringInternal(); - if (byteEnabled && (value.length() < maxStringSize)) { - // If training, everything is synced - synchronized (bcStats) { - // If the cache has been generated on a previous invocation - // while waiting for the lock, just return the toString - // value we just calculated - if (bcCache != null) { - return value; - } - // Two cases: either we just exceeded the train count, in - // which case the cache must be created, or we just update - // the count for the string - if (bcCount > trainThreshold) { - long t1 = System.currentTimeMillis(); - // Sort the entries according to occurrence - TreeMap> tempMap = - new TreeMap>(); - for (Entry item : bcStats.entrySet()) { - ByteEntry entry = item.getKey(); - int[] countA = item.getValue(); - Integer count = Integer.valueOf(countA[0]); - // Add to the list for that count - ArrayList list = tempMap.get(count); - if (list == null) { - // Create list - list = new ArrayList(); - tempMap.put(count, list); - } - list.add(entry); - } - // Allocate array of the right size - int size = bcStats.size(); - if (size > cacheSize) { - size = cacheSize; - } - ByteEntry[] tempbcCache = new ByteEntry[size]; - // Fill it up using an alphabetical order - // and a dumb insert sort - ByteChunk tempChunk = new ByteChunk(); - int n = 0; - while (n < size) { - Object key = tempMap.lastKey(); - ArrayList list = tempMap.get(key); - for (int i = 0; i < list.size() && n < size; i++) { - ByteEntry entry = list.get(i); - tempChunk.setBytes(entry.name, 0, - entry.name.length); - int insertPos = findClosest(tempChunk, - tempbcCache, n); - if (insertPos == n) { - tempbcCache[n + 1] = entry; - } else { - System.arraycopy(tempbcCache, insertPos + 1, - tempbcCache, insertPos + 2, - n - insertPos - 1); - tempbcCache[insertPos + 1] = entry; - } - n++; - } - tempMap.remove(key); - } - bcCount = 0; - bcStats.clear(); - bcCache = tempbcCache; - if (log.isDebugEnabled()) { - long t2 = System.currentTimeMillis(); - log.debug("ByteCache generation time: " + - (t2 - t1) + "ms"); - } - } else { - bcCount++; - // Allocate new ByteEntry for the lookup - ByteEntry entry = new ByteEntry(); - entry.value = value; - int[] count = bcStats.get(entry); - if (count == null) { - int end = bc.getEnd(); - int start = bc.getStart(); - // Create byte array and copy bytes - entry.name = new byte[bc.getLength()]; - System.arraycopy(bc.getBuffer(), start, entry.name, - 0, end - start); - // Set encoding - entry.charset = bc.getCharset(); - // Initialize occurrence count to one - count = new int[1]; - count[0] = 1; - // Set in the stats hash map - bcStats.put(entry, count); - } else { - count[0] = count[0] + 1; - } - } - } - } - return value; - } else { - accessCount++; - // Find the corresponding String - String result = find(bc); - if (result == null) { - return bc.toStringInternal(); - } - // Note: We don't care about safety for the stats - hitCount++; - return result; - } - - } - - - public static String toString(CharChunk cc) { - - // If the cache is null, then either caching is disabled, or we're - // still training - if (ccCache == null) { - String value = cc.toStringInternal(); - if (charEnabled && (value.length() < maxStringSize)) { - // If training, everything is synced - synchronized (ccStats) { - // If the cache has been generated on a previous invocation - // while waiting for the lock, just return the toString - // value we just calculated - if (ccCache != null) { - return value; - } - // Two cases: either we just exceeded the train count, in - // which case the cache must be created, or we just update - // the count for the string - if (ccCount > trainThreshold) { - long t1 = System.currentTimeMillis(); - // Sort the entries according to occurrence - TreeMap> tempMap = - new TreeMap>(); - for (Entry item : ccStats.entrySet()) { - CharEntry entry = item.getKey(); - int[] countA = item.getValue(); - Integer count = Integer.valueOf(countA[0]); - // Add to the list for that count - ArrayList list = tempMap.get(count); - if (list == null) { - // Create list - list = new ArrayList(); - tempMap.put(count, list); - } - list.add(entry); - } - // Allocate array of the right size - int size = ccStats.size(); - if (size > cacheSize) { - size = cacheSize; - } - CharEntry[] tempccCache = new CharEntry[size]; - // Fill it up using an alphabetical order - // and a dumb insert sort - CharChunk tempChunk = new CharChunk(); - int n = 0; - while (n < size) { - Object key = tempMap.lastKey(); - ArrayList list = tempMap.get(key); - for (int i = 0; i < list.size() && n < size; i++) { - CharEntry entry = list.get(i); - tempChunk.setChars(entry.name, 0, - entry.name.length); - int insertPos = findClosest(tempChunk, - tempccCache, n); - if (insertPos == n) { - tempccCache[n + 1] = entry; - } else { - System.arraycopy(tempccCache, insertPos + 1, - tempccCache, insertPos + 2, - n - insertPos - 1); - tempccCache[insertPos + 1] = entry; - } - n++; - } - tempMap.remove(key); - } - ccCount = 0; - ccStats.clear(); - ccCache = tempccCache; - if (log.isDebugEnabled()) { - long t2 = System.currentTimeMillis(); - log.debug("CharCache generation time: " + - (t2 - t1) + "ms"); - } - } else { - ccCount++; - // Allocate new CharEntry for the lookup - CharEntry entry = new CharEntry(); - entry.value = value; - int[] count = ccStats.get(entry); - if (count == null) { - int end = cc.getEnd(); - int start = cc.getStart(); - // Create char array and copy chars - entry.name = new char[cc.getLength()]; - System.arraycopy(cc.getBuffer(), start, entry.name, - 0, end - start); - // Initialize occurrence count to one - count = new int[1]; - count[0] = 1; - // Set in the stats hash map - ccStats.put(entry, count); - } else { - count[0] = count[0] + 1; - } - } - } - } - return value; - } else { - accessCount++; - // Find the corresponding String - String result = find(cc); - if (result == null) { - return cc.toStringInternal(); - } - // Note: We don't care about safety for the stats - hitCount++; - return result; - } - - } - - - // ----------------------------------------------------- Protected Methods - - - /** - * Compare given byte chunk with byte array. - * Return -1, 0 or +1 if inferior, equal, or superior to the String. - */ - protected static final int compare(ByteChunk name, byte[] compareTo) { - int result = 0; - - byte[] b = name.getBuffer(); - int start = name.getStart(); - int end = name.getEnd(); - int len = compareTo.length; - - if ((end - start) < len) { - len = end - start; - } - for (int i = 0; (i < len) && (result == 0); i++) { - if (b[i + start] > compareTo[i]) { - result = 1; - } else if (b[i + start] < compareTo[i]) { - result = -1; - } - } - if (result == 0) { - if (compareTo.length > (end - start)) { - result = -1; - } else if (compareTo.length < (end - start)) { - result = 1; - } - } - return result; - } - - - /** - * Find an entry given its name in the cache and return the associated - * String. - */ - protected static final String find(ByteChunk name) { - int pos = findClosest(name, bcCache, bcCache.length); - if ((pos < 0) || (compare(name, bcCache[pos].name) != 0) - || !(name.getCharset().equals(bcCache[pos].charset))) { - return null; - } else { - return bcCache[pos].value; - } - } - - - /** - * Find an entry given its name in a sorted array of map elements. - * This will return the index for the closest inferior or equal item in the - * given array. - */ - protected static final int findClosest(ByteChunk name, ByteEntry[] array, - int len) { - - int a = 0; - int b = len - 1; - - // Special cases: -1 and 0 - if (b == -1) { - return -1; - } - - if (compare(name, array[0].name) < 0) { - return -1; - } - if (b == 0) { - return 0; - } - - int i = 0; - while (true) { - i = (b + a) >>> 1; - int result = compare(name, array[i].name); - if (result == 1) { - a = i; - } else if (result == 0) { - return i; - } else { - b = i; - } - if ((b - a) == 1) { - int result2 = compare(name, array[b].name); - if (result2 < 0) { - return a; - } else { - return b; - } - } - } - - } - - - /** - * Compare given char chunk with char array. - * Return -1, 0 or +1 if inferior, equal, or superior to the String. - */ - protected static final int compare(CharChunk name, char[] compareTo) { - int result = 0; - - char[] c = name.getBuffer(); - int start = name.getStart(); - int end = name.getEnd(); - int len = compareTo.length; - - if ((end - start) < len) { - len = end - start; - } - for (int i = 0; (i < len) && (result == 0); i++) { - if (c[i + start] > compareTo[i]) { - result = 1; - } else if (c[i + start] < compareTo[i]) { - result = -1; - } - } - if (result == 0) { - if (compareTo.length > (end - start)) { - result = -1; - } else if (compareTo.length < (end - start)) { - result = 1; - } - } - return result; - } - - - /** - * Find an entry given its name in the cache and return the associated - * String. - */ - protected static final String find(CharChunk name) { - int pos = findClosest(name, ccCache, ccCache.length); - if ((pos < 0) || (compare(name, ccCache[pos].name) != 0)) { - return null; - } else { - return ccCache[pos].value; - } - } - - - /** - * Find an entry given its name in a sorted array of map elements. - * This will return the index for the closest inferior or equal item in the - * given array. - */ - protected static final int findClosest(CharChunk name, CharEntry[] array, - int len) { - - int a = 0; - int b = len - 1; - - // Special cases: -1 and 0 - if (b == -1) { - return -1; - } - - if (compare(name, array[0].name) < 0 ) { - return -1; - } - if (b == 0) { - return 0; - } - - int i = 0; - while (true) { - i = (b + a) >>> 1; - int result = compare(name, array[i].name); - if (result == 1) { - a = i; - } else if (result == 0) { - return i; - } else { - b = i; - } - if ((b - a) == 1) { - int result2 = compare(name, array[b].name); - if (result2 < 0) { - return a; - } else { - return b; - } - } - } - - } - - - // -------------------------------------------------- ByteEntry Inner Class - - - private static class ByteEntry { - - private byte[] name = null; - private Charset charset = null; - private String value = null; - - @Override - public String toString() { - return value; - } - @Override - public int hashCode() { - return value.hashCode(); - } - @Override - public boolean equals(Object obj) { - if (obj instanceof ByteEntry) { - return value.equals(((ByteEntry) obj).value); - } - return false; - } - - } - - - // -------------------------------------------------- CharEntry Inner Class - - - private static class CharEntry { - - private char[] name = null; - private String value = null; - - @Override - public String toString() { - return value; - } - @Override - public int hashCode() { - return value.hashCode(); - } - @Override - public boolean equals(Object obj) { - if (obj instanceof CharEntry) { - return value.equals(((CharEntry) obj).value); - } - return false; - } - - } - - -} diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/UDecoder.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/UDecoder.java deleted file mode 100644 index 1719986b2..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/UDecoder.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * 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.util.tomcat.buf; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.CharConversionException; -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -/** - * All URL decoding happens here. This way we can reuse, review, optimize - * without adding complexity to the buffers. - * - * The conversion will modify the original buffer. - * - * @author Costin Manolache - */ -public final class UDecoder { - - private static final Logger log = LogManager.getLogger(UDecoder.class); - - public static final boolean ALLOW_ENCODED_SLASH = - Boolean.parseBoolean(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false")); - - private static class DecodeException extends CharConversionException { - private static final long serialVersionUID = 1L; - public DecodeException(String s) { - super(s); - } - - @Override - public synchronized Throwable fillInStackTrace() { - // This class does not provide a stack trace - return this; - } - } - - /** Unexpected end of data. */ - private static final IOException EXCEPTION_EOF = new DecodeException("EOF"); - - /** %xx with not-hex digit */ - private static final IOException EXCEPTION_NOT_HEX_DIGIT = new DecodeException( - "isHexDigit"); - - /** %-encoded slash is forbidden in resource path */ - private static final IOException EXCEPTION_SLASH = new DecodeException( - "noSlash"); - - public UDecoder() - { - } - - /** URLDecode, will modify the source. - */ - public void convert( ByteChunk mb, boolean query ) - throws IOException - { - int start=mb.getOffset(); - byte buff[]=mb.getBytes(); - int end=mb.getEnd(); - - int idx= ByteChunk.findByte( buff, start, end, (byte) '%' ); - int idx2=-1; - if( query ) { - idx2= ByteChunk.findByte( buff, start, (idx >= 0 ? idx : end), (byte) '+' ); - } - if( idx<0 && idx2<0 ) { - return; - } - - // idx will be the smallest positive index ( first % or + ) - if( (idx2 >= 0 && idx2 < idx) || idx < 0 ) { - idx=idx2; - } - - final boolean noSlash = !(ALLOW_ENCODED_SLASH || query); - - for( int j=idx; j= end ) { - throw EXCEPTION_EOF; - } - byte b1= buff[j+1]; - byte b2=buff[j+2]; - if( !isHexDigit( b1 ) || ! isHexDigit(b2 )) { - throw EXCEPTION_NOT_HEX_DIGIT; - } - - j+=2; - int res=x2c( b1, b2 ); - if (noSlash && (res == '/')) { - throw EXCEPTION_SLASH; - } - buff[idx]=(byte)res; - } - } - - mb.setEnd( idx ); - - return; - } - - // -------------------- Additional methods -------------------- - // XXX What do we do about charset ???? - - /** In-buffer processing - the buffer will be modified - */ - public void convert( CharChunk mb, boolean query ) - throws IOException - { - // log( "Converting a char chunk "); - int start=mb.getOffset(); - char buff[]=mb.getBuffer(); - int cend=mb.getEnd(); - - int idx= CharChunk.indexOf( buff, start, cend, '%' ); - int idx2=-1; - if( query ) { - idx2= CharChunk.indexOf( buff, start, (idx >= 0 ? idx : cend), '+' ); - } - if( idx<0 && idx2<0 ) { - return; - } - - // idx will be the smallest positive index ( first % or + ) - if( (idx2 >= 0 && idx2 < idx) || idx < 0 ) { - idx=idx2; - } - - final boolean noSlash = !(ALLOW_ENCODED_SLASH || query); - - for( int j=idx; j= cend ) { - // invalid - throw EXCEPTION_EOF; - } - char b1= buff[j+1]; - char b2=buff[j+2]; - if( !isHexDigit( b1 ) || ! isHexDigit(b2 )) { - throw EXCEPTION_NOT_HEX_DIGIT; - } - - j+=2; - int res=x2c( b1, b2 ); - if (noSlash && (res == '/')) { - throw EXCEPTION_SLASH; - } - buff[idx]=(char)res; - } - } - mb.setEnd( idx ); - } - - /** URLDecode, will modify the source - */ - public void convert(MessageBytes mb, boolean query) - throws IOException - { - - switch (mb.getType()) { - case MessageBytes.T_STR: - String strValue=mb.toString(); - if( strValue==null ) { - return; - } - try { - mb.setString( convert( strValue, query )); - } catch (RuntimeException ex) { - throw new DecodeException(ex.getMessage()); - } - break; - case MessageBytes.T_CHARS: - CharChunk charC=mb.getCharChunk(); - convert( charC, query ); - break; - case MessageBytes.T_BYTES: - ByteChunk bytesC=mb.getByteChunk(); - convert( bytesC, query ); - break; - } - } - - // XXX Old code, needs to be replaced !!!! - // - public final String convert(String str, boolean query) - { - if (str == null) { - return null; - } - - if( (!query || str.indexOf( '+' ) < 0) && str.indexOf( '%' ) < 0 ) { - return str; - } - - final boolean noSlash = !(ALLOW_ENCODED_SLASH || query); - - StringBuilder dec = new StringBuilder(); // decoded string output - int strPos = 0; - int strLen = str.length(); - - dec.ensureCapacity(str.length()); - while (strPos < strLen) { - int laPos; // lookahead position - - // look ahead to next URLencoded metacharacter, if any - for (laPos = strPos; laPos < strLen; laPos++) { - char laChar = str.charAt(laPos); - if ((laChar == '+' && query) || (laChar == '%')) { - break; - } - } - - // if there were non-metacharacters, copy them all as a block - if (laPos > strPos) { - dec.append(str.substring(strPos,laPos)); - strPos = laPos; - } - - // shortcut out of here if we're at the end of the string - if (strPos >= strLen) { - break; - } - - // process next metacharacter - char metaChar = str.charAt(strPos); - if (metaChar == '+') { - dec.append(' '); - strPos++; - continue; - } else if (metaChar == '%') { - // We throw the original exception - the super will deal with - // it - // try { - char res = (char) Integer.parseInt( - str.substring(strPos + 1, strPos + 3), 16); - if (noSlash && (res == '/')) { - throw new IllegalArgumentException("noSlash"); - } - dec.append(res); - strPos += 3; - } - } - - return dec.toString(); - } - - - /** - * Decode and return the specified URL-encoded String. - * When the byte array is converted to a string, the system default - * character encoding is used... This may be different than some other - * servers. It is assumed the string is not a query string. - * - * @param str The url-encoded string - * - * @exception IllegalArgumentException if a '%' character is not followed - * by a valid 2-digit hexadecimal number - */ - public static String URLDecode(String str) { - return URLDecode(str, null); - } - - - /** - * Decode and return the specified URL-encoded String. It is assumed the - * string is not a query string. - * - * @param str The url-encoded string - * @param enc The encoding to use; if null, the default encoding is used. If - * an unsupported encoding is specified null will be returned - * @exception IllegalArgumentException if a '%' character is not followed - * by a valid 2-digit hexadecimal number - */ - public static String URLDecode(String str, String enc) { - return URLDecode(str, enc, false); - } - - - /** - * Decode and return the specified URL-encoded String. - * - * @param str The url-encoded string - * @param enc The encoding to use; if null, the default encoding is used. If - * an unsupported encoding is specified null will be returned - * @param isQuery Is this a query string being processed - * @exception IllegalArgumentException if a '%' character is not followed - * by a valid 2-digit hexadecimal number - */ - public static String URLDecode(String str, String enc, boolean isQuery) { - if (str == null) - return (null); - - // use the specified encoding to extract bytes out of the - // given string so that the encoding is not lost. If an - // encoding is not specified, use ISO-8859-1 - byte[] bytes = null; - try { - if (enc == null) { - bytes = str.getBytes("ISO-8859-1"); - } else { - bytes = str.getBytes(B2CConverter.getCharset(enc)); - } - } catch (UnsupportedEncodingException uee) { - if (log.isDebugEnabled()) { - log.debug("Unable to URL decode the specified input since the encoding "+ enc + " is not supported.", uee); - } - } - - return URLDecode(bytes, enc, isQuery); - - } - - - /** - * Decode and return the specified URL-encoded byte array. - * - * @param bytes The url-encoded byte array - * @param enc The encoding to use; if null, the default encoding is used. If - * an unsupported encoding is specified null will be returned - * @param isQuery Is this a query string being processed - * @exception IllegalArgumentException if a '%' character is not followed - * by a valid 2-digit hexadecimal number - */ - public static String URLDecode(byte[] bytes, String enc, boolean isQuery) { - - if (bytes == null) - return null; - - int len = bytes.length; - int ix = 0; - int ox = 0; - while (ix < len) { - byte b = bytes[ix++]; // Get byte to test - if (b == '+' && isQuery) { - b = (byte)' '; - } else if (b == '%') { - if (ix + 2 > len) { - throw new IllegalArgumentException( - "The % character must be followed by two hexademical digits"); - } - b = (byte) ((convertHexDigit(bytes[ix++]) << 4) - + convertHexDigit(bytes[ix++])); - } - bytes[ox++] = b; - } - if (enc != null) { - try { - return new String(bytes, 0, ox, B2CConverter.getCharset(enc)); - } catch (UnsupportedEncodingException uee) { - if (log.isDebugEnabled()) { - log.debug("Unable to URL decode the specified input since the encoding " + enc + " is not supported.", uee); - } - return null; - } - } - return new String(bytes, 0, ox); - - } - - - private static byte convertHexDigit( byte b ) { - if ((b >= '0') && (b <= '9')) return (byte)(b - '0'); - if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10); - if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10); - throw new IllegalArgumentException(((char) b) + " is not a hexadecimal digit"); - } - - - private static boolean isHexDigit( int c ) { - return ( ( c>='0' && c<='9' ) || - ( c>='a' && c<='f' ) || - ( c>='A' && c<='F' )); - } - - - private static int x2c( byte b1, byte b2 ) { - int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 : - (b1 -'0'); - digit*=16; - digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 : - (b2 -'0'); - return digit; - } - - - private static int x2c( char b1, char b2 ) { - int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 : - (b1 -'0'); - digit*=16; - digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 : - (b2 -'0'); - return digit; - } -} diff --git a/core/src/main/java/org/apache/struts2/util/tomcat/buf/Utf8Decoder.java b/core/src/main/java/org/apache/struts2/util/tomcat/buf/Utf8Decoder.java deleted file mode 100644 index bca4de8d6..000000000 --- a/core/src/main/java/org/apache/struts2/util/tomcat/buf/Utf8Decoder.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * 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.util.tomcat.buf; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; - -/** - * Decodes bytes to UTF-8. Extracted from Apache Harmony and modified to reject - * code points from U+D800 to U+DFFF as per RFC3629. The standard Java decoder - * does not reject these. It has also been modified to reject code points - * greater than U+10FFFF which the standard Java decoder rejects but the harmony - * one does not. - */ -public class Utf8Decoder extends CharsetDecoder { - - // The next table contains information about UTF-8 charset and - // correspondence of 1st byte to the length of sequence - // For information please visit http://www.ietf.org/rfc/rfc3629.txt - // - // Please note, o means 0, actually. - // ------------------------------------------------------------------- - // 0 1 2 3 Value - // ------------------------------------------------------------------- - // oxxxxxxx 00000000 00000000 0xxxxxxx - // 11oyyyyy 1oxxxxxx 00000000 00000yyy yyxxxxxx - // 111ozzzz 1oyyyyyy 1oxxxxxx 00000000 zzzzyyyy yyxxxxxx - // 1111ouuu 1ouuzzzz 1oyyyyyy 1oxxxxxx 000uuuuu zzzzyyyy yyxxxxxx - private static final int remainingBytes[] = { - // 1owwwwww - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - // 11oyyyyy - -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - // 111ozzzz - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - // 1111ouuu - 3, 3, 3, 3, 3, -1, -1, -1, - // > 11110111 - -1, -1, -1, -1, -1, -1, -1, -1}; - private static final int remainingNumbers[] = {0, // 0 1 2 3 - 4224, // (01o00000b << 6)+(1o000000b) - 401536, // (011o0000b << 12)+(1o000000b << 6)+(1o000000b) - 29892736 // (0111o000b << 18)+(1o000000b << 12)+(1o000000b << - // 6)+(1o000000b) - }; - private static final int lowerEncodingLimit[] = {-1, 0x80, 0x800, 0x10000}; - - - public Utf8Decoder() { - super(B2CConverter.UTF_8, 1.0f, 1.0f); - } - - - @Override - protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { - if (in.hasArray() && out.hasArray()) { - return decodeHasArray(in, out); - } - return decodeNotHasArray(in, out); - } - - - private CoderResult decodeNotHasArray(ByteBuffer in, CharBuffer out) { - int outRemaining = out.remaining(); - int pos = in.position(); - int limit = in.limit(); - try { - while (pos < limit) { - if (outRemaining == 0) { - return CoderResult.OVERFLOW; - } - int jchar = in.get(); - if (jchar < 0) { - jchar = jchar & 0x7F; - int tail = remainingBytes[jchar]; - if (tail == -1) { - return CoderResult.malformedForLength(1); - } - if (limit - pos < 1 + tail) { - // No early test for invalid sequences here as peeking - // at the next byte is harder - return CoderResult.UNDERFLOW; - } - int nextByte; - for (int i = 0; i < tail; i++) { - nextByte = in.get() & 0xFF; - if ((nextByte & 0xC0) != 0x80) { - return CoderResult.malformedForLength(1 + i); - } - jchar = (jchar << 6) + nextByte; - } - jchar -= remainingNumbers[tail]; - if (jchar < lowerEncodingLimit[tail]) { - // Should have been encoded in a fewer octets - return CoderResult.malformedForLength(1); - } - pos += tail; - } - // Apache Tomcat added test - if (jchar >= 0xD800 && jchar <= 0xDFFF) { - return CoderResult.unmappableForLength(3); - } - // Apache Tomcat added test - if (jchar > 0x10FFFF) { - return CoderResult.unmappableForLength(4); - } - if (jchar <= 0xffff) { - out.put((char) jchar); - outRemaining--; - } else { - if (outRemaining < 2) { - return CoderResult.OVERFLOW; - } - out.put((char) ((jchar >> 0xA) + 0xD7C0)); - out.put((char) ((jchar & 0x3FF) + 0xDC00)); - outRemaining -= 2; - } - pos++; - } - return CoderResult.UNDERFLOW; - } finally { - in.position(pos); - } - } - - - private CoderResult decodeHasArray(ByteBuffer in, CharBuffer out) { - int outRemaining = out.remaining(); - int pos = in.position(); - int limit = in.limit(); - final byte[] bArr = in.array(); - final char[] cArr = out.array(); - final int inIndexLimit = limit + in.arrayOffset(); - int inIndex = pos + in.arrayOffset(); - int outIndex = out.position() + out.arrayOffset(); - // if someone would change the limit in process, - // he would face consequences - for (; inIndex < inIndexLimit && outRemaining > 0; inIndex++) { - int jchar = bArr[inIndex]; - if (jchar < 0) { - jchar = jchar & 0x7F; - // If first byte is invalid, tail will be set to -1 - int tail = remainingBytes[jchar]; - if (tail == -1) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - // Additional checks to detect invalid sequences ASAP - // Checks derived from Unicode 6.2, Chapter 3, Table 3-7 - // Check 2nd byte - int tailAvailable = inIndexLimit - inIndex - 1; - if (tailAvailable > 0) { - // First byte C2..DF, second byte 80..BF - if (jchar > 0x41 && jchar < 0x60 && - (bArr[inIndex + 1] & 0xC0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - // First byte E0, second byte A0..BF - if (jchar == 0x60 && (bArr[inIndex + 1] & 0xE0) != 0xA0) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - // First byte E1..EC, second byte 80..BF - if (jchar > 0x60 && jchar < 0x6D && - (bArr[inIndex + 1] & 0xC0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - // First byte ED, second byte 80..9F - if (jchar == 0x6D && (bArr[inIndex + 1] & 0xE0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - // First byte EE..EF, second byte 80..BF - if (jchar > 0x6D && jchar < 0x70 && - (bArr[inIndex + 1] & 0xC0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - // First byte F0, second byte 90..BF - if (jchar == 0x70 && - ((bArr[inIndex + 1] & 0xFF) < 0x90 || - (bArr[inIndex + 1] & 0xFF) > 0xBF)) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - // First byte F1..F3, second byte 80..BF - if (jchar > 0x70 && jchar < 0x74 && - (bArr[inIndex + 1] & 0xC0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - // First byte F4, second byte 80..8F - if (jchar == 0x74 && - (bArr[inIndex + 1] & 0xF0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - } - // Check third byte if present and expected - if (tailAvailable > 1 && tail > 1) { - if ((bArr[inIndex + 2] & 0xC0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(2); - } - } - // Check fourth byte if present and expected - if (tailAvailable > 2 && tail > 2) { - if ((bArr[inIndex + 3] & 0xC0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(3); - } - } - if (tailAvailable < tail) { - break; - } - for (int i = 0; i < tail; i++) { - int nextByte = bArr[inIndex + i + 1] & 0xFF; - if ((nextByte & 0xC0) != 0x80) { - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1 + i); - } - jchar = (jchar << 6) + nextByte; - } - jchar -= remainingNumbers[tail]; - if (jchar < lowerEncodingLimit[tail]) { - // Should have been encoded in fewer octets - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return CoderResult.malformedForLength(1); - } - inIndex += tail; - } - // Apache Tomcat added test - if (jchar >= 0xD800 && jchar <= 0xDFFF) { - return CoderResult.unmappableForLength(3); - } - // Apache Tomcat added test - if (jchar > 0x10FFFF) { - return CoderResult.unmappableForLength(4); - } - if (jchar <= 0xffff) { - cArr[outIndex++] = (char) jchar; - outRemaining--; - } else { - if (outRemaining < 2) { - return CoderResult.OVERFLOW; - } - cArr[outIndex++] = (char) ((jchar >> 0xA) + 0xD7C0); - cArr[outIndex++] = (char) ((jchar & 0x3FF) + 0xDC00); - outRemaining -= 2; - } - } - in.position(inIndex - in.arrayOffset()); - out.position(outIndex - out.arrayOffset()); - return (outRemaining == 0 && inIndex < inIndexLimit) ? - CoderResult.OVERFLOW : - CoderResult.UNDERFLOW; - } -} \ No newline at end of file diff --git a/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java b/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java index c27361177..9f383c611 100644 --- a/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java +++ b/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java @@ -18,8 +18,17 @@ */ package org.apache.struts2.views.util; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; +import com.opensymphony.xwork2.inject.Inject; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.url.UrlDecoder; +import org.apache.struts2.url.UrlEncoder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -27,18 +36,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.text.StringEscapeUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.StrutsConstants; -import org.apache.struts2.util.URLDecoderUtil; - -import com.opensymphony.xwork2.inject.Inject; - /** * Default implementation of UrlHelper */ @@ -49,16 +46,11 @@ public class DefaultUrlHelper implements UrlHelper { public static final String HTTP_PROTOCOL = "http"; public static final String HTTPS_PROTOCOL = "https"; - private String encoding = "UTF-8"; private int httpPort = DEFAULT_HTTP_PORT; private int httpsPort = DEFAULT_HTTPS_PORT; - @Inject(StrutsConstants.STRUTS_I18N_ENCODING) - public void setEncoding(String encoding) { - if (StringUtils.isNotEmpty(encoding)) { - this.encoding = encoding; - } - } + private UrlEncoder encoder; + private UrlDecoder decoder; @Inject(StrutsConstants.STRUTS_URL_HTTP_PORT) public void setHttpPort(String httpPort) { @@ -70,6 +62,16 @@ public class DefaultUrlHelper implements UrlHelper { this.httpsPort = Integer.parseInt(httpsPort); } + @Inject + public void setEncoder(UrlEncoder encoder) { + this.encoder = encoder; + } + + @Inject + public void setDecoder(UrlDecoder decoder) { + this.decoder = decoder; + } + public String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params) { return buildUrl(action, request, response, params, null, true, true); } @@ -81,7 +83,7 @@ public class DefaultUrlHelper implements UrlHelper { public String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) { - return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, true); + return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, true); } public String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String urlScheme, @@ -108,7 +110,7 @@ public class DefaultUrlHelper implements UrlHelper { // If switching schemes, use the configured port for the particular scheme. if (!scheme.equals(reqScheme)) { appendPort(link, scheme, HTTP_PROTOCOL.equals(scheme) ? httpPort : httpsPort); - // Else use the port from the current request. + // Else use the port from the current request. } else { appendPort(link, scheme, request.getServerPort()); } @@ -143,7 +145,7 @@ public class DefaultUrlHelper implements UrlHelper { uri = request.getRequestURI(); } - link.append(uri.substring(0, uri.lastIndexOf('/') + 1)); + link.append(uri, 0, uri.lastIndexOf('/') + 1); } // Add page @@ -175,7 +177,7 @@ public class DefaultUrlHelper implements UrlHelper { String result = link.toString(); - if (StringUtils.containsIgnoreCase(result, " iterator = ((Iterable) value).iterator(); iterator.hasNext(); ) { Object paramValue = iterator.next(); link.append(buildParameterSubstring(name, paramValue != null ? paramValue.toString() : StringUtils.EMPTY, encode)); @@ -249,56 +251,50 @@ public class DefaultUrlHelper implements UrlHelper { } private String buildParameterSubstring(String name, String value, boolean encode) { - StringBuilder builder = new StringBuilder(); - builder.append(encode ? encode(name) : name); - builder.append('='); - builder.append(encode ? encode(value) : value); - return builder.toString(); + String encodedName = encode ? encoder.encode(name) : name; + String encodedValue = encode ? encoder.encode(value) : value; + return encodedName + '=' + encodedValue; } - /** - * Encodes the URL using {@link java.net.URLEncoder#encode} with the encoding specified in the configuration. - * - * @param input the input to encode - * @return the encoded string - */ - public String encode( String input ) { - try { - return URLEncoder.encode(input, encoding); - } catch (UnsupportedEncodingException e) { - LOG.warn("Could not encode URL parameter '{}', returning value un-encoded", input); - return input; - } - } - - /** - * Decodes the URL using {@link URLDecoderUtil#decode(String, String)} with the encoding specified in the configuration. - * - * @param input the input to decode - * @return the encoded string - */ - public String decode( String input ) { - return URLDecoderUtil.decode(input, encoding, false); - } + /** + * Encodes the URL using {@link UrlEncoder#encode} with the encoding specified in the configuration. + * + * @param input the input to encode + * @return the encoded string + * @deprecated since 6.1.0, use {@link UrlEncoder} directly, use {@link Inject} to inject a proper instance + */ + @Deprecated + public String encode(String input) { + return encoder.encode(input); + } /** - * Decodes the URL using {@link URLDecoderUtil#decode(String, String, boolean)} with the encoding specified in the configuration. + * Decodes the URL using {@link UrlDecoder#decode(String, boolean)} with the encoding specified in the configuration. * * @param input the input to decode + * @return the encoded string + * @deprecated since 6.1.0, use {@link UrlDecoder} directly, use {@link Inject} to inject a proper instance + */ + @Deprecated + public String decode(String input) { + return decoder.decode(input, false); + } + + /** + * Decodes the URL using {@link UrlDecoder#decode(String, boolean)} with the encoding specified in the configuration. + * + * @param input the input to decode * @param isQueryString whether input is a query string. If true other decoding rules apply. * @return the encoded string + * @deprecated since 6.1.0, use {@link UrlDecoder} directly, use {@link Inject} to inject a proper instance */ - public String decode( String input, boolean isQueryString ) { - try { - return URLDecoderUtil.decode(input, encoding, isQueryString); - } catch (Exception e) { - LOG.warn("Could not decode URL parameter '{}', returning value un-decoded", input); - return input; - } + @Deprecated + public String decode(String input, boolean isQueryString) { + return decoder.decode(input, isQueryString); } public Map parseQueryString(String queryString, boolean forceValueArray) { - Map queryParams = new LinkedHashMap(); + Map queryParams = new LinkedHashMap<>(); if (queryString != null) { String[] params = queryString.split("&"); for (String param : params) { @@ -313,8 +309,8 @@ public class DefaultUrlHelper implements UrlHelper { paramValue = tmpParams[1]; } if (paramName != null) { - paramName = decode(paramName, true); - String translatedParamValue = decode(paramValue, true); + paramName = decoder.decode(paramName, true); + String translatedParamValue = decoder.decode(paramValue, true); if (queryParams.containsKey(paramName) || forceValueArray) { // WW-1619 append new param value to existing value(s) @@ -322,11 +318,11 @@ public class DefaultUrlHelper implements UrlHelper { if (currentParam instanceof String) { queryParams.put(paramName, new String[]{(String) currentParam, translatedParamValue}); } else { - String currentParamValues[] = (String[]) currentParam; + String[] currentParamValues = (String[]) currentParam; if (currentParamValues != null) { - List paramList = new ArrayList(Arrays.asList(currentParamValues)); + List paramList = new ArrayList<>(Arrays.asList(currentParamValues)); paramList.add(translatedParamValue); - queryParams.put(paramName, paramList.toArray(new String[paramList.size()])); + queryParams.put(paramName, paramList.toArray(new String[0])); } else { queryParams.put(paramName, new String[]{translatedParamValue}); } diff --git a/core/src/main/resources/org/apache/struts2/default.properties b/core/src/main/resources/org/apache/struts2/default.properties index 753a80b8d..07f362a7a 100644 --- a/core/src/main/resources/org/apache/struts2/default.properties +++ b/core/src/main/resources/org/apache/struts2/default.properties @@ -279,4 +279,7 @@ struts.ognl.expressionMaxLength=256 ### These formatters are using a slightly different patterns, please check JavaDocs of both and more details is in WW-5016 struts.date.formatter=dateTimeFormatter +struts.url.encoder=strutsUrlEncoder +struts.url.decoder=strutsUrlDecoder + ### END SNIPPET: complete_file diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml index 467b9007c..7980af2f2 100644 --- a/core/src/main/resources/struts-default.xml +++ b/core/src/main/resources/struts-default.xml @@ -313,6 +313,11 @@ + + + diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java index 5a6e8af5c..d792b227e 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java @@ -25,6 +25,7 @@ import com.opensymphony.xwork2.config.ConfigurationManager; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.entities.PackageConfig; import com.opensymphony.xwork2.config.impl.DefaultConfiguration; +import org.apache.struts2.url.StrutsUrlDecoder; import java.util.HashMap; @@ -40,6 +41,7 @@ public class Restful2ActionMapperTest extends StrutsInternalTestCase { super.setUp(); mapper = new Restful2ActionMapper(); mapper.setExtensions(""); + mapper.setDecoder(new StrutsUrlDecoder()); req = new MockHttpServletRequest(); req.setupGetParameterMap(new HashMap()); req.setupGetContextPath("/my/namespace"); @@ -57,7 +59,7 @@ public class Restful2ActionMapperTest extends StrutsInternalTestCase { } }; } - + public void testGetIndex() throws Exception { req.setupGetRequestURI("/my/namespace/foo/"); req.setupGetServletPath("/my/namespace/foo/"); @@ -136,7 +138,7 @@ public class Restful2ActionMapperTest extends StrutsInternalTestCase { assertEquals(1, mapping.getParams().size()); assertEquals("1", mapping.getParams().get("bar")); } - + public void testPutUpdate() throws Exception { req.setupGetRequestURI("/my/namespace/bar/1/foo/2"); @@ -153,7 +155,7 @@ public class Restful2ActionMapperTest extends StrutsInternalTestCase { assertEquals(1, mapping.getParams().size()); assertEquals("1", mapping.getParams().get("bar")); } - + public void testPutUpdateWithIdParam() throws Exception { mapper.setIdParameterName("id"); @@ -171,7 +173,7 @@ public class Restful2ActionMapperTest extends StrutsInternalTestCase { assertEquals(2, mapping.getParams().size()); assertEquals("1", mapping.getParams().get("bar")); assertEquals("2", mapping.getParams().get("id")); - + } public void testPutUpdateWithFakePut() throws Exception { diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapperTest.java index e327b6556..0ee3b1956 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapperTest.java @@ -24,13 +24,13 @@ import java.util.Map; import junit.framework.TestCase; +import org.apache.struts2.StrutsInternalTestCase; import org.apache.struts2.views.jsp.StrutsMockHttpServletRequest; /** * Unit test for {@link RestfulActionMapper}. - * */ -public class RestfulActionMapperTest extends TestCase { +public class RestfulActionMapperTest extends StrutsInternalTestCase { private RestfulActionMapper mapper; @@ -38,13 +38,13 @@ public class RestfulActionMapperTest extends TestCase { ActionMapping am = new ActionMapping(); am.setName("view"); am.setNamespace("secure"); - am.setParams(Collections.emptyMap()); + am.setParams(Collections.emptyMap()); assertEquals("secureview", mapper.getUriFromActionMapping(am)); } public void testGetUriParam() { - Map param = new HashMap(); + Map param = new HashMap<>(); param.put("article", "123"); ActionMapping am = new ActionMapping(); am.setName("view"); @@ -55,7 +55,7 @@ public class RestfulActionMapperTest extends TestCase { } public void testGetUriParamId() { - Map param = new HashMap(); + Map param = new HashMap<>(); param.put("article", "123"); param.put("viewId", "456"); ActionMapping am = new ActionMapping(); @@ -66,14 +66,14 @@ public class RestfulActionMapperTest extends TestCase { assertEquals("secureview/456", mapper.getUriFromActionMapping(am)); } - public void testGetMappingNoSlash() throws Exception { + public void testGetMappingNoSlash() { StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); request.setupGetServletPath("noslash"); assertNull(mapper.getMapping(request, null)); } - public void testGetMapping() throws Exception { + public void testGetMapping() { StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); request.setupGetServletPath("/myapp/view/12"); @@ -83,7 +83,7 @@ public class RestfulActionMapperTest extends TestCase { assertEquals("12", am.getParams().get("view")); } - public void testGetMapping2() throws Exception { + public void testGetMapping2() { StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); request.setupGetServletPath("/myapp/12/region/europe"); @@ -94,7 +94,7 @@ public class RestfulActionMapperTest extends TestCase { assertEquals("europe", am.getParams().get("region")); } - public void testGetMapping3() throws Exception { + public void testGetMapping3() { StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); request.setupGetServletPath("/myapp/view/12/region/europe"); @@ -106,10 +106,13 @@ public class RestfulActionMapperTest extends TestCase { } protected void setUp() throws Exception { + super.setUp(); mapper = new RestfulActionMapper(); + container.inject(mapper); } protected void tearDown() throws Exception { + super.tearDown(); mapper = null; } diff --git a/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java b/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java index 216bb98e0..0933f8ea7 100644 --- a/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java +++ b/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java @@ -44,7 +44,6 @@ import static org.easymock.EasyMock.expect; public class ServletActionRedirectResultTest extends StrutsInternalTestCase { public void testIncludeParameterInResultWithConditionParseOn() throws Exception { - ResultConfig resultConfig = new ResultConfig.Builder("", "") .addParam("actionName", "someActionName") .addParam("namespace", "someNamespace") @@ -53,15 +52,13 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { .addParam("location", "someLocation") .addParam("prependServletContext", "true") .addParam("method", "someMethod") - .addParam("statusCode", "333") - .addParam("param1", "${#value1}") + .addParam("statusCode", "333") + .addParam("param1", "${#value1}") .addParam("param2", "${#value2}") .addParam("param3", "${#value3}") .addParam("anchor", "${#fragment}") .build(); - - ActionContext context = ActionContext.getContext(); ValueStack stack = context.getValueStack(); context.getContextMap().put("value1", "value 1"); @@ -72,12 +69,11 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { context.put(ServletActionContext.HTTP_REQUEST, req); context.put(ServletActionContext.HTTP_RESPONSE, res); - - Map results= new HashMap<>(); + Map results = new HashMap<>(); results.put("myResult", resultConfig); ActionConfig actionConfig = new ActionConfig.Builder("", "", "") - .addResultConfigs(results).build(); + .addResultConfigs(results).build(); ServletActionRedirectResult result = new ServletActionRedirectResult(); result.setActionName("myAction${1-1}"); @@ -98,7 +94,7 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { expect(mockInvocation.getStack()).andReturn(stack).anyTimes(); control.replay(); - result.setActionMapper(container.getInstance(ActionMapper.class)); + container.inject(result); result.execute(mockInvocation); assertEquals("/myNamespace0/myAction0.action?param1=value+1¶m2=value+2¶m3=value+3#fragment", res.getRedirectedUrl()); @@ -106,23 +102,20 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { } public void testExpressionParameterInResultWithConditionParseOn() throws Exception { - ResultConfig resultConfig = new ResultConfig.Builder("", "") - .addParam("actionName", "someActionName") - .addParam("namespace", "someNamespace") - .addParam("encode", "true") - .addParam("parse", "true") - .addParam("location", "someLocation") - .addParam("prependServletContext", "true") - .addParam("method", "someMethod") - .addParam("statusCode", "333") - .addParam("param1", "${#value1}") - .addParam("param2", "${#value2}") - .addParam("param3", "${#value3}") - .addParam("anchor", "${#fragment}") - .build(); - - + .addParam("actionName", "someActionName") + .addParam("namespace", "someNamespace") + .addParam("encode", "true") + .addParam("parse", "true") + .addParam("location", "someLocation") + .addParam("prependServletContext", "true") + .addParam("method", "someMethod") + .addParam("statusCode", "333") + .addParam("param1", "${#value1}") + .addParam("param2", "${#value2}") + .addParam("param3", "${#value3}") + .addParam("anchor", "${#fragment}") + .build(); ActionContext context = ActionContext.getContext(); ValueStack stack = context.getValueStack(); @@ -137,12 +130,11 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { context.put(ServletActionContext.HTTP_REQUEST, req); context.put(ServletActionContext.HTTP_RESPONSE, res); - - Map results= new HashMap<>(); + Map results = new HashMap<>(); results.put("myResult", resultConfig); ActionConfig actionConfig = new ActionConfig.Builder("", "", "") - .addResultConfigs(results).build(); + .addResultConfigs(results).build(); ServletActionRedirectResult result = new ServletActionRedirectResult(); result.setNamespace("/myNamespace${#namespaceName}"); @@ -166,7 +158,7 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { control.replay(); DefaultActionMapper mapper = (DefaultActionMapper) container.getInstance(ActionMapper.class); mapper.setAllowDynamicMethodCalls("true"); - result.setActionMapper(mapper); + container.inject(result); result.execute(mockInvocation); assertEquals("/myNamespace${1-1}/myAction${1-1}!myMethod${1-1}.action?param1=value+1¶m2=value+2¶m3=value+3#fragment", res.getRedirectedUrl()); @@ -181,23 +173,20 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { } public void testIncludeParameterInResultWithConditionParseOnWithNoNamespace() throws Exception { - ResultConfig resultConfig = new ResultConfig.Builder("", "") - .addParam("actionName", "someActionName") - .addParam("namespace", "someNamespace") - .addParam("encode", "true") - .addParam("parse", "true") - .addParam("location", "someLocation") - .addParam("prependServletContext", "true") - .addParam("method", "someMethod") - .addParam("statusCode", "333") - .addParam("param1", "${#value1}") - .addParam("param2", "${#value2}") - .addParam("param3", "${#value3}") - .addParam("anchor", "${#fragment}") - .build(); - - + .addParam("actionName", "someActionName") + .addParam("namespace", "someNamespace") + .addParam("encode", "true") + .addParam("parse", "true") + .addParam("location", "someLocation") + .addParam("prependServletContext", "true") + .addParam("method", "someMethod") + .addParam("statusCode", "333") + .addParam("param1", "${#value1}") + .addParam("param2", "${#value2}") + .addParam("param3", "${#value3}") + .addParam("anchor", "${#fragment}") + .build(); ActionContext context = ActionContext.getContext(); ValueStack stack = context.getValueStack(); @@ -209,12 +198,11 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { context.put(ServletActionContext.HTTP_REQUEST, req); context.put(ServletActionContext.HTTP_RESPONSE, res); - - Map results= new HashMap<>(); + Map results = new HashMap<>(); results.put("myResult", resultConfig); ActionConfig actionConfig = new ActionConfig.Builder("", "", "") - .addResultConfigs(results).build(); + .addResultConfigs(results).build(); ServletActionRedirectResult result = new ServletActionRedirectResult(); result.setActionName("myAction${1-1}"); @@ -235,7 +223,7 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { expect(mockInvocation.getStack()).andReturn(stack).anyTimes(); control.replay(); - result.setActionMapper(container.getInstance(ActionMapper.class)); + container.inject(result); result.execute(mockInvocation); assertEquals("/${1-1}/myAction0.action?param1=value+1¶m2=value+2¶m3=value+3#fragment", res.getRedirectedUrl()); @@ -243,7 +231,6 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { } public void testIncludeParameterInResult() throws Exception { - ResultConfig resultConfig = new ResultConfig.Builder("", "") .addParam("actionName", "someActionName") .addParam("namespace", "someNamespace") @@ -264,12 +251,11 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { context.put(ServletActionContext.HTTP_REQUEST, req); context.put(ServletActionContext.HTTP_RESPONSE, res); - - Map results= new HashMap<>(); + Map results = new HashMap<>(); results.put("myResult", resultConfig); ActionConfig actionConfig = new ActionConfig.Builder("", "", "") - .addResultConfigs(results).build(); + .addResultConfigs(results).build(); ServletActionRedirectResult result = new ServletActionRedirectResult(); result.setActionName("myAction"); @@ -289,7 +275,7 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { expect(mockInvocation.getInvocationContext()).andReturn(context); control.replay(); - result.setActionMapper(container.getInstance(ActionMapper.class)); + container.inject(result); result.execute(mockInvocation); assertEquals("/myNamespace/myAction.action?param1=value+1¶m2=value+2¶m3=value+3#fragment", res.getRedirectedUrl()); @@ -297,7 +283,6 @@ public class ServletActionRedirectResultTest extends StrutsInternalTestCase { } public void testBuildResultWithParameter() throws Exception { - ResultConfig resultConfig = new ResultConfig.Builder("", ServletActionRedirectResult.class.getName()) .addParam("actionName", "someActionName") .addParam("namespace", "someNamespace") diff --git a/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java b/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java index 321b3b525..8936783fc 100644 --- a/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java +++ b/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java @@ -251,7 +251,7 @@ public class ServletRedirectResultTest extends StrutsInternalTestCase implements expect(mockInvocation.getInvocationContext()).andReturn(context); control.replay(); - result.setActionMapper(container.getInstance(ActionMapper.class)); + container.inject(result); result.execute(mockInvocation); assertEquals("/myNamespace/myAction.action?param1=value+1¶m2=value+2¶m3=value+3#fragment", res.getRedirectedUrl()); control.verify(); @@ -311,7 +311,7 @@ public class ServletRedirectResultTest extends StrutsInternalTestCase implements expect(mockValueStack.getActionContext()).andReturn(actionContext); control.replay(); - result.setActionMapper(container.getInstance(ActionMapper.class)); + container.inject(result); result.execute(mockInvocation); assertEquals("/myNamespace/myAction.action?param=value+1¶m=value+2", res.getRedirectedUrl()); control.verify(); diff --git a/core/src/test/java/org/apache/struts2/util/URLDecoderUtilTest.java b/core/src/test/java/org/apache/struts2/url/StrutsUrlDecoderTest.java similarity index 51% rename from core/src/test/java/org/apache/struts2/util/URLDecoderUtilTest.java rename to core/src/test/java/org/apache/struts2/url/StrutsUrlDecoderTest.java index 3d75860ee..5dd44f897 100644 --- a/core/src/test/java/org/apache/struts2/util/URLDecoderUtilTest.java +++ b/core/src/test/java/org/apache/struts2/url/StrutsUrlDecoderTest.java @@ -16,20 +16,25 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2.util; +package org.apache.struts2.url; +import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -public class URLDecoderUtilTest { +public class StrutsUrlDecoderTest { + + private StrutsUrlDecoder decoder; @Test - public void testURLDecodeStringInvalid() { + public void testDecodeStringInvalid() { // %n rather than %nn should throw an IAE according to the Javadoc Exception exception = null; try { - URLDecoderUtil.decode("%5xxxxx", "ISO-8859-1"); + decoder.decode("%5xxxxx", "ISO-8859-1", false); } catch (Exception e) { exception = e; } @@ -38,7 +43,7 @@ public class URLDecoderUtilTest { // Edge case trying to trigger ArrayIndexOutOfBoundsException exception = null; try { - URLDecoderUtil.decode("%5", "ISO-8859-1"); + decoder.decode("%5", "ISO-8859-1", false); } catch (Exception e) { exception = e; } @@ -46,51 +51,62 @@ public class URLDecoderUtilTest { } @Test - public void testURLDecodeStringValidIso88591Start() { - - String result = URLDecoderUtil.decode("%41xxxx", "ISO-8859-1"); + public void testDecodeStringValidIso88591Start() { + String result = decoder.decode("%41xxxx", "ISO-8859-1", false); assertEquals("Axxxx", result); } @Test - public void testURLDecodeStringValidIso88591Middle() { - - String result = URLDecoderUtil.decode("xx%41xx", "ISO-8859-1"); + public void testDecodeStringValidIso88591Middle() { + String result = decoder.decode("xx%41xx", "ISO-8859-1", false); assertEquals("xxAxx", result); } @Test - public void testURLDecodeStringValidIso88591End() { - - String result = URLDecoderUtil.decode("xxxx%41", "ISO-8859-1"); + public void testDecodeStringValidIso88591End() { + String result = decoder.decode("xxxx%41", "ISO-8859-1", false); assertEquals("xxxxA", result); } @Test - public void testURLDecodeStringValidUtf8Start() { - String result = URLDecoderUtil.decode("%c3%aaxxxx", "UTF-8"); + public void testDecodeStringValidUtf8Start() { + String result = decoder.decode("%c3%aaxxxx", "UTF-8", false); assertEquals("\u00eaxxxx", result); } @Test - public void testURLDecodeStringValidUtf8Middle() { - - String result = URLDecoderUtil.decode("xx%c3%aaxx", "UTF-8"); + public void testDecodeStringValidUtf8Middle() { + String result = decoder.decode("xx%c3%aaxx", "UTF-8", false); assertEquals("xx\u00eaxx", result); } @Test - public void testURLDecodeStringValidUtf8End() { - - String result = URLDecoderUtil.decode("xxxx%c3%aa", "UTF-8"); + public void testDecodeStringValidUtf8End() { + String result = decoder.decode("xxxx%c3%aa", "UTF-8", false); assertEquals("xxxx\u00ea", result); } @Test - public void testURLDecodePlusCharAsSpace() { - - String result = URLDecoderUtil.decode("a+b", "UTF-8", true); + public void testDecodePlusCharAsSpace() { + String result = decoder.decode("a+b", "UTF-8", true); assertEquals("a b", result); } -} \ No newline at end of file + @Test + public void testDecodeNull() { + String result = decoder.decode(null); + assertNull(result); + } + + @Test + public void testSettingEncoding() { + decoder.setEncoding("ISO-8859-1"); + String result = decoder.decode("xxxx%41"); + assertEquals("xxxxA", result); + } + + @Before + public void setUp() throws Exception { + this.decoder = new StrutsUrlDecoder(); + } +} diff --git a/core/src/test/java/org/apache/struts2/url/StrutsUrlEncoderTest.java b/core/src/test/java/org/apache/struts2/url/StrutsUrlEncoderTest.java new file mode 100644 index 000000000..95aaacda6 --- /dev/null +++ b/core/src/test/java/org/apache/struts2/url/StrutsUrlEncoderTest.java @@ -0,0 +1,90 @@ +/* + * 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.url; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class StrutsUrlEncoderTest { + + private StrutsUrlEncoder encoder; + + @Test + public void testEncodeValidIso88591Start() { + String result = encoder.encode("%xxxx", "ISO-8859-1"); + assertEquals("%25xxxx", result); + } + + @Test + public void testEncodeValidIso88591Middle() { + String result = encoder.encode("xx%xx", "ISO-8859-1"); + assertEquals("xx%25xx", result); + } + + @Test + public void testEncodeValidIso88591End() { + String result = encoder.encode("xxxx%", "ISO-8859-1"); + assertEquals("xxxx%25", result); + } + + @Test + public void testEncodeValidUtf8Start() { + String result = encoder.encode("\u00eaxxxx", "UTF-8"); + assertEquals("%C3%AAxxxx", result); + } + + @Test + public void testEncodeValidUtf8Middle() { + String result = encoder.encode("xx\u00eaxx", "UTF-8"); + assertEquals("xx%C3%AAxx", result); + } + + @Test + public void testEncodeValidUtf8End() { + String result = encoder.encode("xxxx\u00ea", "UTF-8"); + assertEquals("xxxx%C3%AA", result); + } + + @Test + public void testEncodePlusCharAsSpace() { + String result = encoder.encode("a b", "UTF-8"); + assertEquals("a+b", result); + } + + @Test + public void testEncodeException() { + String result = encoder.encode("a b", "UNKNOWN-8"); + assertEquals("a b", result); + } + + @Test + public void testSettingEncoding() { + encoder.setEncoding("ISO-8859-1"); + String result = encoder.encode("%xxxx"); + assertEquals("%25xxxx", result); + } + + @Before + public void setUp() throws Exception { + this.encoder = new StrutsUrlEncoder(); + } + +} diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java index e739ffe01..a087da478 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java @@ -1442,7 +1442,7 @@ public class SelectTest extends AbstractUITagTest { return id; } } - + private void prepareTagGeneric(SelectTag tag) { TestAction testAction = (TestAction) action; ArrayList collection = new ArrayList(); diff --git a/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java b/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java index 9266e4923..3e70e7a44 100644 --- a/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java +++ b/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java @@ -34,6 +34,8 @@ import com.mockobjects.dynamic.Mock; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.inject.Container; import com.opensymphony.xwork2.inject.Scope.Strategy; +import org.apache.struts2.url.StrutsUrlDecoder; +import org.apache.struts2.url.StrutsUrlEncoder; /** @@ -41,7 +43,7 @@ import com.opensymphony.xwork2.inject.Scope.Strategy; * */ public class DefaultUrlHelperTest extends StrutsInternalTestCase { - + private StubContainer stubContainer; private DefaultUrlHelper urlHelper; @@ -204,7 +206,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params); assertEquals(expectedString, urlString); } - + /** * just one &, not & */ @@ -429,21 +431,23 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { stubContainer = new StubContainer(container); ActionContext.getContext().withContainer(stubContainer); urlHelper = new DefaultUrlHelper(); + urlHelper.setEncoder(new StrutsUrlEncoder()); + urlHelper.setDecoder(new StrutsUrlDecoder()); } - + private void setProp(String key, String val) { stubContainer.overrides.put(key, val); } - + class StubContainer implements Container { Container parent; - + public StubContainer(Container parent) { super(); this.parent = parent; } - + public Map overrides = new HashMap(); public T getInstance(Class type, String name) { if (String.class.isAssignableFrom(type) && overrides.containsKey(name)) { @@ -471,7 +475,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { public void removeScopeStrategy() { parent.removeScopeStrategy(); - + } public void setScopeStrategy(Strategy scopeStrategy) { diff --git a/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java b/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java index a5b3bb254..6cde3f7d6 100644 --- a/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java +++ b/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java @@ -35,6 +35,8 @@ import junit.framework.TestCase; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.dispatcher.HttpParameters; import org.apache.struts2.jasper.runtime.InstanceHelper; +import org.apache.struts2.url.StrutsUrlDecoder; +import org.apache.struts2.url.StrutsUrlEncoder; import org.apache.struts2.views.util.DefaultUrlHelper; import org.apache.struts2.views.util.UrlHelper; import org.apache.tomcat.InstanceManager; @@ -348,7 +350,9 @@ public class EmbeddedJSPResultTest extends TestCase { EasyMock.expect(container.getInstanceNames(FileManager.class)).andReturn(new HashSet<>()).anyTimes(); EasyMock.expect(container.getInstance(FileManager.class)).andReturn(fileManager).anyTimes(); - UrlHelper urlHelper = new DefaultUrlHelper(); + DefaultUrlHelper urlHelper = new DefaultUrlHelper(); + urlHelper.setDecoder(new StrutsUrlDecoder()); + urlHelper.setEncoder(new StrutsUrlEncoder()); EasyMock.expect(container.getInstance(UrlHelper.class)).andReturn(urlHelper).anyTimes(); FileManagerFactory fileManagerFactory = new DummyFileManagerFactory(); EasyMock.expect(container.getInstance(FileManagerFactory.class)).andReturn(fileManagerFactory).anyTimes(); diff --git a/plugins/embeddedjsp/src/test/resources/org/apache/struts2/complex0.jsp b/plugins/embeddedjsp/src/test/resources/org/apache/struts2/complex0.jsp index 184ce1781..440898140 100644 --- a/plugins/embeddedjsp/src/test/resources/org/apache/struts2/complex0.jsp +++ b/plugins/embeddedjsp/src/test/resources/org/apache/struts2/complex0.jsp @@ -30,7 +30,6 @@ <%@ page import="org.apache.struts2.util.ComponentUtils" %> <%@ page import="org.apache.struts2.util.ContainUtil" %> <%@ page import="org.apache.struts2.util.StrutsUtil" %> -<%@ page import="org.apache.struts2.util.URLDecoderUtil" %> <%@ page import="org.apache.struts2.views.velocity.VelocityStrutsUtil" %> <%@ taglib prefix="r" uri="http://jakarta.apache.org/taglibs/request-1.0" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> @@ -61,7 +60,7 @@ Foo - + Bar @@ -79,7 +78,7 @@ BarBar - + Bar @@ -97,7 +96,7 @@ BarBar - + Bar @@ -107,7 +106,7 @@ Foo - + Bar @@ -125,7 +124,7 @@ Foo - + Bar @@ -188,7 +187,7 @@ testvalue3 set/if worked.
    -
    + testvalue4 set/if worked.
    From 054f1f4cdbdaaf5e0c9c31897692086fab5e0440 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 2 Nov 2022 11:54:35 +0100 Subject: [PATCH 086/143] Includes apps in code Coverage scan --- Jenkinsfile | 2 +- pom.xml | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2adf56ac9..1f0fe858a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -94,7 +94,7 @@ pipeline { } steps { withCredentials([string(credentialsId: 'asf-struts-sonarcloud', variable: 'SONARCLOUD_TOKEN')]) { - sh './mvnw -B -Pcoverage -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN} sonar:sonar' + sh './mvnw -B -Pcoverage -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN} verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar' } } } diff --git a/pom.xml b/pom.xml index 5a8fa9af7..a555d664c 100644 --- a/pom.xml +++ b/pom.xml @@ -129,7 +129,6 @@ apache_struts ${project.artifactId} https://sonarcloud.io - apps/** -Duser.language=en -Duser.country=US -Duser.region=US @@ -211,9 +210,6 @@ coverage - - https://sonarcloud.io - From 4bb81d5909e93bb008a5c6f7e350cd4e1395ea04 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 2 Nov 2022 08:39:49 +0100 Subject: [PATCH 087/143] WW-5255 Fixes and and uses them across tags --- .../main/webapp/WEB-INF/decorators/main.jsp | 19 ++++--- .../struts2/interceptor/debugging/console.ftl | 8 +-- .../resources/template/css_xhtml/head.ftl | 2 +- .../resources/template/simple/combobox.ftl | 14 ++--- .../main/resources/template/simple/debug.ftl | 16 +++--- .../template/simple/doubleselect.ftl | 4 +- .../template/simple/form-close-tooltips.ftl | 11 ++-- .../resources/template/simple/form-close.ftl | 4 +- .../main/resources/template/simple/head.ftl | 2 +- .../template/simple/inputtransferselect.ftl | 2 +- .../main/resources/template/simple/link.ftl | 52 +++++++++---------- .../main/resources/template/simple/nonce.ftl | 4 +- .../template/simple/optiontransferselect.ftl | 2 +- .../main/resources/template/simple/script.ftl | 33 +++++------- .../template/simple/updownselect.ftl | 4 +- .../template/xhtml/form-close-validate.ftl | 8 +-- .../resources/template/xhtml/form-close.ftl | 4 +- .../template/xhtml/form-validate.ftl | 2 +- .../main/resources/template/xhtml/head.ftl | 2 +- .../main/resources/template/xhtml/link.ftl | 21 -------- .../main/resources/template/xhtml/script.ftl | 21 -------- .../FreemarkerResultMockedTest.java | 3 +- .../struts2/views/jsp/ui/LinkTagTest.java | 6 ++- .../views/freemarker/callActionFreeMarker.ftl | 4 +- .../freemarker/callActionFreeMarker2.ftl | 4 +- .../views/freemarker/customTextField.ftl | 2 - .../views/freemarker/dynaAttributes.ftl | 2 - .../freemarker/incompatible-improvements.ftl | 4 +- .../struts2/views/freemarker/manual-list.ftl | 2 - .../struts2/views/freemarker/nested.ftl | 4 +- .../struts2/views/freemarker/nonceTest.ftl | 2 - .../struts2/views/freemarker/something.ftl | 2 - .../struts2/views/jsp/ui/HeadTagTest-1.txt | 4 +- .../apache/struts2/views/jsp/ui/tooltip-1.txt | 2 +- .../apache/struts2/views/jsp/ui/tooltip-2.txt | 4 +- .../apache/struts2/views/jsp/ui/tooltip-3.txt | 2 +- .../config-browser/showValidators.ftl | 32 +++++++----- 37 files changed, 132 insertions(+), 182 deletions(-) delete mode 100644 core/src/main/resources/template/xhtml/link.ftl delete mode 100644 core/src/main/resources/template/xhtml/script.ftl diff --git a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp index ff1353032..77f387ace 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp @@ -64,14 +64,14 @@ <decorator:title default="Struts2 Showcase"/> - + - + - + - + $(function () { var alerts = $('ul.alert').wrap('
    '); @@ -82,19 +82,22 @@ - + - + + + jQuery(document).ready(function() { prettyPrint(); } ); + - +