Compare commits

..

1 Commits

Author SHA1 Message Date
Lukasz Lenart 52628432a9 [maven-release-plugin] prepare release STRUTS_6_11_0 2026-08-01 12:28:14 +02:00
65 changed files with 399 additions and 1010 deletions
BIN
View File
Binary file not shown.
+18 -4
View File
@@ -1,4 +1,18 @@
wrapperVersion=3.3.4
distributionType=bin
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar
# 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.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
+2 -2
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
<name>Struts 2 Rest Showcase Webapp</name>
<description>Struts 2 Rest Showcase Example</description>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-showcase</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-assembly</artifactId>
+3 -3
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-bom</artifactId>
@@ -43,7 +43,7 @@
</licenses>
<properties>
<struts-version.version>6.12.0-SNAPSHOT</struts-version.version>
<struts-version.version>6.11.0</struts-version.version>
<maven.site.skip>true</maven.site.skip>
<maven.site.deploy.skip>true</maven.site.deploy.skip>
</properties>
@@ -189,7 +189,7 @@
</dependencyManagement>
<scm>
<tag>STRUTS_6_9_0</tag>
<tag>STRUTS_6_11_0</tag>
<connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection>
<url>https://github.com/apache/struts/</url>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-osgi-admin-bundle</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-osgi-demo-bundle</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-osgi-bundles</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-core</artifactId>
<packaging>jar</packaging>
@@ -61,7 +61,7 @@ public class CollectionConverter extends DefaultTypeConverter {
for (Object anObjArray : objArray) {
Object convertedValue = converter.convertValue(context, target, member, propertyName, anObjArray, memberType);
if (convertedValue != TypeConverter.NO_CONVERSION_POSSIBLE) {
if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) {
result.add(convertedValue);
}
}
@@ -72,7 +72,7 @@ public class CollectionConverter extends DefaultTypeConverter {
for (Object aCol : col) {
Object convertedValue = converter.convertValue(context, target, member, propertyName, aCol, memberType);
if (convertedValue != TypeConverter.NO_CONVERSION_POSSIBLE) {
if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) {
result.add(convertedValue);
}
}
@@ -80,7 +80,7 @@ public class CollectionConverter extends DefaultTypeConverter {
result = createCollection(toType, memberType, -1);
TypeConverter converter = getTypeConverter(context);
Object convertedValue = converter.convertValue(context, target, member, propertyName, value, memberType);
if (convertedValue != TypeConverter.NO_CONVERSION_POSSIBLE) {
if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) {
result.add(convertedValue);
}
}
@@ -36,18 +36,6 @@ import java.util.Objects;
public class StringConverter extends DefaultTypeConverter {
/**
* Upper bound on the number of fraction digits emitted when formatting a number.
* <p>
* Covers every {@code double} and {@code float} value in full - the widest is
* {@link Double#MIN_VALUE} at 325 fraction digits - so the round-trip precision
* introduced by WW-4871 is preserved. Beyond that bound the length of the output
* would follow the scale of the value rather than its precision, so a
* {@link BigDecimal} scaled past this limit is rounded to it.
*/
private static final int MAX_FRACTION_DIGITS = 340;
@Override
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) {
String result;
@@ -98,7 +86,7 @@ public class StringConverter extends DefaultTypeConverter {
// TODO: delete this variable and corresponding if statement when jdk fixed java.text.NumberFormat.format's behavior with Float
Object fixedValue = value;
if (BigDecimal.class.isInstance(value) || Double.class.isInstance(value) || Float.class.isInstance(value)) {
format.setMaximumFractionDigits(MAX_FRACTION_DIGITS);
format.setMaximumFractionDigits(Integer.MAX_VALUE);
if (Float.class.isInstance(value)) {
fixedValue = Double.valueOf(value.toString());
}
@@ -20,7 +20,6 @@ package com.opensymphony.xwork2.ognl.accessor;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
import com.opensymphony.xwork2.conversion.TypeConverter;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.ognl.OgnlUtil;
@@ -30,8 +29,6 @@ import ognl.OgnlException;
import ognl.PropertyAccessor;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Collection;
import java.util.List;
@@ -46,8 +43,6 @@ import java.util.Map;
*/
public class XWorkListPropertyAccessor extends ListPropertyAccessor {
private static final Logger LOG = LogManager.getLogger(XWorkListPropertyAccessor.class);
private XWorkCollectionPropertyAccessor _sAcc = new XWorkCollectionPropertyAccessor();
private XWorkConverter xworkConverter;
@@ -172,10 +167,6 @@ public class XWorkListPropertyAccessor extends ListPropertyAccessor {
}
Object realValue = getRealValue(context, value, convertToClass);
if (realValue == TypeConverter.NO_CONVERSION_POSSIBLE) {
LOG.debug("Unable to convert value for index [{}] to the declared element type, skipping assignment", name);
return;
}
if (target instanceof List && name instanceof Number) {
//make sure there are enough spaces in the List to set
@@ -20,7 +20,6 @@ package com.opensymphony.xwork2.ognl.accessor;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
import com.opensymphony.xwork2.conversion.TypeConverter;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
@@ -127,17 +126,8 @@ public class XWorkMapPropertyAccessor extends MapPropertyAccessor {
LOG.trace("Entering setProperty({},{},{},{})", context, target, name, value);
Object key = getKey(context, name);
if (key == TypeConverter.NO_CONVERSION_POSSIBLE) {
LOG.debug("Unable to convert key [{}] to the declared key type, skipping assignment", name);
return;
}
Object convertedValue = getValue(context, value);
if (convertedValue == TypeConverter.NO_CONVERSION_POSSIBLE) {
LOG.debug("Unable to convert value for key [{}] to the declared element type, skipping assignment", key);
return;
}
Map map = (Map) target;
map.put(key, convertedValue);
map.put(key, getValue(context, value));
}
private Object getValue(Map context, Object value) {
@@ -33,11 +33,7 @@ import java.util.StringTokenizer;
/**
* Extended version of {@link RestfulActionMapper}, see documentation for more details
* <a href="https://struts.apache.org/core-developers/restful-action-mapper.html">Restful2ActionMapper</a>
*
* @deprecated since 6.12.0, this legacy mapper predates the Struts REST plugin, which is the maintained
* way to build REST-style applications with Struts. Scheduled for removal in the next major release.
*/
@Deprecated
public class Restful2ActionMapper extends DefaultActionMapper {
private static final Logger LOG = LogManager.getLogger(Restful2ActionMapper.class);
@@ -23,55 +23,29 @@ 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.StrutsConstants;
import org.apache.struts2.url.UrlDecoder;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
/**
* Simple Restfull Action Mapper to support REST application
* See docs for more information
* <a href="https://struts.apache.org/core-developers/restful-action-mapper.html">RestfulActionMapper</a>
*
* @deprecated since 6.12.0, this legacy mapper predates the Struts REST plugin, which is the maintained
* way to build REST-style applications with Struts. Scheduled for removal in the next major release.
*/
@Deprecated
public class RestfulActionMapper implements ActionMapper {
protected static final Logger LOG = LogManager.getLogger(RestfulActionMapper.class);
private UrlDecoder decoder;
/**
* Matches action names allowed in the request URI, aligned with {@link DefaultActionMapper}.
*/
private Pattern allowedActionNames = Pattern.compile("[a-zA-Z0-9._!/\\-]*");
/**
* Action name used when the name extracted from the URI is not allowed, aligned with {@link DefaultActionMapper}.
*/
private String defaultActionName = "index";
@Inject
public void setDecoder(UrlDecoder decoder) {
this.decoder = decoder;
}
@Inject(value = StrutsConstants.STRUTS_ALLOWED_ACTION_NAMES, required = false)
public void setAllowedActionNames(String allowedActionNames) {
this.allowedActionNames = Pattern.compile(allowedActionNames);
}
@Inject(value = StrutsConstants.STRUTS_DEFAULT_ACTION_NAME, required = false)
public void setDefaultActionName(String defaultActionName) {
this.defaultActionName = defaultActionName;
}
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.mapper.ActionMapper#getMapping(javax.servlet.http.HttpServletRequest)
*/
@@ -83,7 +57,7 @@ public class RestfulActionMapper implements ActionMapper {
return null;
}
String actionName = cleanupActionName(uri.substring(1, nextSlash));
String actionName = uri.substring(1, nextSlash);
Map<String, Object> parameters = new HashMap<>();
try {
StringTokenizer st = new StringTokenizer(uri.substring(nextSlash), "/");
@@ -122,22 +96,6 @@ public class RestfulActionMapper implements ActionMapper {
return new ActionMapping(actionName, null, null, null);
}
/**
* Checks action name against the allowed pattern; if it does not match, returns the default action name.
* Mirrors {@link DefaultActionMapper#cleanupActionName(String)}.
*
* @param rawActionName action name extracted from the URI
* @return safe action name
*/
protected String cleanupActionName(final String rawActionName) {
if (allowedActionNames.matcher(rawActionName).matches()) {
return rawActionName;
} else {
LOG.warn("{} did not match allowed action names {} - default action {} will be used!", rawActionName, allowedActionNames, defaultActionName);
return defaultActionName;
}
}
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.mapper.ActionMapper#getUriFromActionMapping(org.apache.struts2.dispatcher.mapper.ActionMapping)
*/
-2
View File
@@ -79,8 +79,6 @@
class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper"/>
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="prefix"
class="org.apache.struts2.dispatcher.mapper.PrefixBasedActionMapper"/>
<!-- Deprecated for removal: the legacy "restful" and "restful2" mappers predate the Struts REST
plugin, which is the maintained way to build REST-style applications. -->
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful"
class="org.apache.struts2.dispatcher.mapper.RestfulActionMapper"/>
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful2"
@@ -1,128 +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.conversion.impl;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.XWorkTestCase;
import com.opensymphony.xwork2.conversion.TypeConverter;
import com.opensymphony.xwork2.util.ValueStack;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class CollectionConverterTest extends XWorkTestCase {
/**
* WW-5701: the marker constant's value is ordinary text, so an element that genuinely holds
* that text converts successfully and must be kept.
* <p>
* The value is built at runtime rather than written as a literal on purpose: a literal would be
* interned to the very same instance as the constant's value, which no request-derived
* parameter ever is. A servlet container builds parameter values from the request bytes.
*/
public void testElementWhoseTextEqualsTheMarkerIsKept() {
String asSubmittedByAUser = new String("ognl.NoConversionPossible".toCharArray());
assertNotSame("fixture must not be interned", TypeConverter.NO_CONVERSION_POSSIBLE, asSubmittedByAUser);
Holder holder = new Holder();
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(holder);
vs.setValue("names", new String[]{"alpha", asSubmittedByAUser, "omega"});
assertEquals(Arrays.asList("alpha", "ognl.NoConversionPossible", "omega"), holder.getNames());
}
/**
* The guard must still do its job: a genuinely unconvertible element is dropped.
*/
public void testUnconvertibleElementIsStillDropped() {
Holder holder = new Holder();
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(holder);
vs.setValue("numbers", new String[]{"1", "not-a-number", "3"});
assertEquals(Arrays.asList(1L, 3L), holder.getNumbers());
}
/**
* The same guard on the path taken when the submitted value is itself a collection rather than
* an array - here a List feeding a Set-typed property.
*/
public void testUnconvertibleElementIsDroppedFromACollectionSource() {
Holder holder = new Holder();
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(holder);
vs.setValue("numberSet", Arrays.asList("1", "not-a-number", "3"));
assertEquals(new HashSet<>(Arrays.asList(1L, 3L)), holder.getNumberSet());
}
/**
* The same guard on the path taken when a single value is assigned to a collection property.
* The property is seeded first so that a setter which is never called cannot pass vacuously.
*/
public void testUnconvertibleSingleValueIsDropped() {
Holder holder = new Holder();
holder.setNumbers(new ArrayList<>(Arrays.asList(99L)));
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(holder);
vs.setValue("numbers", "not-a-number");
assertEquals(Collections.emptyList(), holder.getNumbers());
}
public static class Holder {
private List<String> names = new ArrayList<>();
private List<Long> numbers = new ArrayList<>();
private Set<Long> numberSet = new LinkedHashSet<>();
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
public List<Long> getNumbers() {
return numbers;
}
public void setNumbers(List<Long> numbers) {
this.numbers = numbers;
}
public Set<Long> getNumberSet() {
return numberSet;
}
public void setNumberSet(Set<Long> numberSet) {
this.numberSet = numberSet;
}
}
}
@@ -22,7 +22,6 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.StrutsInternalTestCase;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Locale;
import java.util.Map;
@@ -103,18 +102,6 @@ public class StringConverterTest extends StrutsInternalTestCase {
assertEquals(aBitBiggerThanDouble.substring(0, 309) + "," + aBitBiggerThanDouble.substring(310), value);
}
public void testBigDecimalFractionDigitsAreBounded() throws Exception {
// given
StringConverter converter = new StringConverter();
Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));
// when the scale of the value exceeds the supported number of fraction digits
Object value = converter.convertValue(context, null, null, null, new BigDecimal(BigInteger.ONE, 100_000), null);
// then the length of the output is bounded by the converter, not by the scale of the value
assertEquals("0", value);
}
public void testStringArrayToStringConversion() {
// given
StringConverter converter = new StringConverter();
@@ -64,22 +64,6 @@ public class XWorkListPropertyAccessorTest extends XWorkTestCase {
assertEquals(myList.size(), vs.findValue("strings.size"));
}
public void testUnconvertibleElementIsNotStored() {
ValueStack vs = ActionContext.getContext().getValueStack();
ListHolder listHolder = new ListHolder();
listHolder.setLongs(new ArrayList<>());
vs.push(listHolder);
vs.setValue("longs[0]", "1");
vs.setValue("longs[1]", "not-a-number");
assertEquals(Long.valueOf(1), listHolder.getLongs().get(0));
for (Object element : (List) listHolder.getLongs()) {
assertTrue("list must not hold a non-Long element: " + element,
element == null || element instanceof Long);
}
}
public void testAutoGrowthCollectionLimit() {
PropertyAccessor accessor = container.getInstance(PropertyAccessor.class, ArrayList.class.getName());
((XWorkListPropertyAccessor) accessor).setAutoGrowCollectionLimit("2");
@@ -25,7 +25,6 @@ import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class XWorkMapPropertyAccessorTest extends XWorkTestCase {
@@ -58,50 +57,6 @@ public class XWorkMapPropertyAccessorTest extends XWorkTestCase {
assertNull(vs.findValue("map['key']"));
}
public void testUnconvertibleValueIsNotStored() {
TypedMapHolder holder = new TypedMapHolder();
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(holder);
vs.setValue("counts[1]", "5");
vs.setValue("counts[2]", "not-a-number");
assertEquals(Integer.valueOf(5), holder.getCounts().get(1L));
assertOnlyDeclaredTypes(holder.getCounts());
}
public void testUnconvertibleKeyIsNotStored() {
TypedMapHolder holder = new TypedMapHolder();
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(holder);
vs.setValue("counts[1]", "5");
vs.setValue("counts['abc']", "6");
assertEquals(Integer.valueOf(5), holder.getCounts().get(1L));
assertOnlyDeclaredTypes(holder.getCounts());
}
/**
* A Map declared to hold Long keys and Integer values must never be left holding anything else.
*/
private static void assertOnlyDeclaredTypes(Map<Long, Integer> map) {
for (Object o : ((Map) map).entrySet()) {
Map.Entry entry = (Map.Entry) o;
assertTrue("key is not a Long: " + entry.getKey(), entry.getKey() instanceof Long);
assertTrue("value is not an Integer: " + entry.getValue(), entry.getValue() instanceof Integer);
}
}
public static class TypedMapHolder {
@Element(value = Integer.class)
private final Map<Long, Integer> counts = new HashMap<>();
public Map<Long, Integer> getCounts() {
return counts;
}
}
private static class MapHolder {
private final Map map;
@@ -105,22 +105,6 @@ public class RestfulActionMapperTest extends StrutsInternalTestCase {
assertEquals("europe", am.getParams().get("region"));
}
public void testGetMappingRejectsActionNameWithDisallowedCharacters() {
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
request.setupGetServletPath("/%{1+1}/x");
ActionMapping am = mapper.getMapping(request, null);
assertEquals("index", am.getName());
}
public void testGetMappingAcceptsRegularActionName() {
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
request.setupGetServletPath("/my-app.action/x");
ActionMapping am = mapper.getMapping(request, null);
assertEquals("my-app.action", am.getName());
}
protected void setUp() throws Exception {
super.setUp();
mapper = new RestfulActionMapper();
@@ -38,7 +38,6 @@ import com.opensymphony.xwork2.ognl.OgnlValueStack;
import com.opensymphony.xwork2.ognl.OgnlValueStackFactory;
import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
import com.opensymphony.xwork2.ognl.accessor.RootAccessor;
import com.opensymphony.xwork2.util.Element;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
@@ -1013,44 +1012,6 @@ public class ParametersInterceptorTest extends XWorkTestCase {
container.inject(config.getInterceptors().get(0).getInterceptor());
}
/**
* WW-5700: a value that cannot be converted to the map's element type must not be stored.
* An unchecked s:checkbox with submitUnchecked="true" submits the CheckboxInterceptor's
* uncheckedValue, "false", which cannot become an Integer.
*/
public void testUnconvertibleValueIsNotBoundIntoTypedMap() {
CheckboxAction action = new CheckboxAction();
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(action);
ParametersInterceptor pi = new ParametersInterceptor();
container.inject(pi);
Map<String, Object> params = new HashMap<>();
params.put("capDeferral[100]", "1");
params.put("capDeferral[200]", "false");
pi.applyParameters(action, vs, HttpParameters.create(params).build());
Map<Long, Integer> capDeferral = action.getCapDeferral();
assertEquals("sanity: the convertible value must still bind", Integer.valueOf(1), capDeferral.get(100L));
for (Object entry : ((Map) capDeferral).entrySet()) {
Map.Entry e = (Map.Entry) entry;
assertTrue("key is not a Long: " + e.getKey(), e.getKey() instanceof Long);
assertTrue("value is not an Integer: " + e.getValue(), e.getValue() instanceof Integer);
}
}
public static class CheckboxAction {
@Element(value = Integer.class)
private final Map<Long, Integer> capDeferral = new HashMap<>();
@StrutsParameter(depth = 1)
public Map<Long, Integer> getCapDeferral() {
return capDeferral;
}
}
}
class ValidateAction implements ValidationAware {
Vendored
+116 -146
View File
@@ -19,7 +19,7 @@
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.4
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
@@ -33,84 +33,75 @@
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ]; then
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ]; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ]; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ]; then
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false
darwin=false
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true ;;
Darwin*)
darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"
export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"
export JAVA_HOME
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
fi
;;
;;
esac
if [ -z "$JAVA_HOME" ]; then
if [ -r /etc/gentoo-release ]; then
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin; then
[ -n "$JAVA_HOME" ] \
&& JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] \
&& CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \
&& JAVA_HOME="$(
cd "$JAVA_HOME" || (
echo "cannot cd into $JAVA_HOME." >&2
exit 1
)
pwd
)"
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin; then
javaHome="$(dirname "$javaExecutable")"
javaExecutable="$(cd "$javaHome" && pwd -P)/javac"
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "$javaExecutable")"
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "$javaExecutable")"
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
@@ -118,60 +109,52 @@ if [ -z "$JAVA_HOME" ]; then
fi
fi
if [ -z "$JAVACMD" ]; then
if [ -n "$JAVA_HOME" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(
\unset -f command 2>/dev/null
\command -v java
)"
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ]; then
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ]; then
echo "Warning: JAVA_HOME environment variable is not set." >&2
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]; then
echo "Path not specified to find_maven_basedir" >&2
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ]; do
if [ -d "$wdir"/.mvn ]; then
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(
cd "$wdir/.." || exit 1
pwd
)
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(
cd "$basedir" || exit 1
pwd
)"
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
@@ -182,7 +165,7 @@ concat_lines() {
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' <"$1"
tr -s '\r\n' ' ' < "$1"
fi
}
@@ -194,85 +177,75 @@ log() {
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
export MAVEN_PROJECTBASEDIR
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar"
fi
while IFS="=" read -r key value; do
case "$key" in wrapperUrl)
wrapperUrl=$(trim "${value-}")
break
;;
esac
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget >/dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget ${QUIET:+"$QUIET"} "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wget ${QUIET:+"$QUIET"} --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
elif command -v curl >/dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl ${QUIET:+"$QUIET"} -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl ${QUIET:+"$QUIET"} --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
fi
##########################################################################################
# End of extension
@@ -281,25 +254,22 @@ fi
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in wrapperSha256Sum)
wrapperSha256Sum=$(trim "${value-}")
break
;;
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum >/dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c - >/dev/null 2>&1; then
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
@@ -314,12 +284,12 @@ MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] \
&& JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] \
&& CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] \
&& MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
Vendored
+205 -206
View File
@@ -1,206 +1,205 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.4
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo. >&2
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo. >&2
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo. >&2
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo. >&2
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-async-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-cdi-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-config-browser-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-convention-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-dwr-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-embeddedjsp-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-gxp-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-jasperreports-plugin</artifactId>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-javatemplates-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-jfreechart-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-json-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-junit-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-osgi-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-oval-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-pell-multipart-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-plexus-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-plugins</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-portlet-junit-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-portlet-mocks-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-portlet-tiles-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-portlet-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-rest-plugin</artifactId>
@@ -351,7 +351,6 @@ public class RestActionMapper extends DefaultActionMapper {
Configuration config = configManager.getConfiguration();
String prefix = uri.substring(0, lastSlash);
namespace = "";
boolean rootAvailable = false;
// Find the longest matching namespace, defaulting to the default
for (Object o : config.getPackageConfigs().values()) {
String ns = ((PackageConfig) o).getNamespace();
@@ -360,19 +359,9 @@ public class RestActionMapper extends DefaultActionMapper {
namespace = ns;
}
}
if ("/".equals(ns)) {
rootAvailable = true;
}
}
// must be read before the root namespace is selected below, as it is relative to ""
name = uri.substring(namespace.length() + 1);
// WW-5688, WW-2461: still none found, use the root namespace if it is declared, so that
// an id-bearing uri lands in the same namespace as the one without an id
if (rootAvailable && namespace.isEmpty()) {
namespace = "/";
}
}
mapping.setNamespace(cleanupNamespaceName(namespace));
@@ -1,85 +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.rest;
import com.opensymphony.xwork2.XWorkTestCase;
import org.apache.struts2.config.StrutsXmlConfigurationProvider;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.springframework.mock.web.MockHttpServletRequest;
/**
* WW-5688: an action declared in the root namespace has to stay reachable whether or not the
* request URI carries an id, so that {@code index} and {@code show} resolve to the same action.
*
* <p>These assertions go all the way to the {@code ActionConfig} rather than stopping at the
* mapping, because the reported symptom is a 404 - the mapper handing back a namespace that
* the configuration cannot resolve.</p>
*/
public class RestActionMapperRootNamespaceTest extends XWorkTestCase {
private RestActionMapper mapper;
@Override
protected void setUp() throws Exception {
super.setUp();
loadConfigurationProviders(new StrutsXmlConfigurationProvider("ww-5688.xml"));
mapper = new RestActionMapper();
}
private ActionMapping map(String servletPath, String httpMethod) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContextPath("/myapp");
request.setMethod(httpMethod);
request.setRequestURI("/myapp" + servletPath);
request.setServletPath(servletPath);
return mapper.getMapping(request, configurationManager);
}
private void assertResolves(String servletPath, String httpMethod, String expectedMethod) {
ActionMapping mapping = map(servletPath, httpMethod);
assertNotNull(httpMethod + " " + servletPath + " produced no mapping", mapping);
assertEquals("dog", mapping.getName());
assertEquals(expectedMethod, mapping.getMethod());
assertNotNull(httpMethod + " " + servletPath + " must resolve to the action declared in the root namespace,"
+ " but namespace '" + mapping.getNamespace() + "' does not hold it",
configurationManager.getConfiguration().getRuntimeConfiguration()
.getActionConfig(mapping.getNamespace(), mapping.getName()));
}
public void testIndexResolvesInRootNamespace() {
assertResolves("/dog", "GET", "index");
}
public void testShowResolvesInRootNamespace() {
assertResolves("/dog/1", "GET", "show");
}
public void testUpdateResolvesInRootNamespace() {
assertResolves("/dog/1", "PUT", "update");
}
public void testDestroyResolvesInRootNamespace() {
assertResolves("/dog/1", "DELETE", "destroy");
}
public void testIdIsStillExtracted() {
ActionMapping mapping = map("/dog/1", "GET");
assertEquals("1", ((String[]) mapping.getParams().get("id"))[0]);
}
}
@@ -261,23 +261,6 @@ public class RestActionMapperTest extends TestCase {
tryUri("/my/foo/23;edit", "/my", "foo/23;edit");
}
/**
* WW-5688: when a package declares the root namespace, a uri that matches no more specific
* namespace belongs to that root rather than to the default namespace, so that "/foo" and
* "/foo/23" agree on where the action lives. Without a root package the default namespace
* still wins - see {@link #testParseNameAndNamespace()}.
*/
public void testParseNameAndNamespaceWithRootPackage() {
config.addPackageConfig("root", new PackageConfig.Builder("root").namespace("/").build());
tryUri("/foo/23", "/", "foo/23");
tryUri("/foo/", "/", "foo/");
tryUri("/", "/", "");
// a longer declared namespace still outranks the root
tryUri("/my/foo/23", "/my", "foo/23");
}
public void testShouldAllowExclamation() throws Exception {
req.setRequestURI("/myapp/animals/dog/fido!edit");
req.setServletPath("/animals/dog/fido!edit");
@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
/*
* 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.
*/
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
"https://struts.apache.org/dtds/struts-6.0.dtd">
<!-- WW-5688: the only declared package sits at the root namespace -->
<struts>
<package name="ww-5688-root" namespace="/">
<action name="dog" class="org.apache.struts2.ActionSupport"/>
</package>
</struts>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-sitemesh-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-spring-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-testng-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-tiles-plugin</artifactId>
@@ -26,6 +26,7 @@ import org.apache.tiles.request.ApplicationContext;
import org.apache.tiles.request.ApplicationResource;
import org.apache.tiles.request.locale.LocaleUtil;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
@@ -52,13 +53,6 @@ public class CachingLocaleUrlDefinitionDAO extends BaseLocaleUrlDefinitionDAO im
*/
public static final String CHECK_REFRESH_INIT_PARAMETER = "org.apache.tiles.definition.dao.LocaleUrlDefinitionDAO.CHECK_REFRESH";
/**
* Default upper bound on the number of customization keys (locales) whose definitions are cached at once. Since the
* customization key is derived from the request locale, this bounds the cache so it cannot grow without limit as
* distinct locales are encountered.
*/
public static final int DEFAULT_MAX_CACHED_LOCALES = 1000;
/**
* The locale-specific set of definitions objects.
*
@@ -66,12 +60,6 @@ public class CachingLocaleUrlDefinitionDAO extends BaseLocaleUrlDefinitionDAO im
*/
protected Map<Locale, Map<String, Definition>> locale2definitionMap;
/**
* Maximum number of customization keys (locales) retained in {@link #locale2definitionMap}. When exceeded, the
* eldest entry is evicted (and reloaded on demand if requested again).
*/
protected int maxCachedLocales = DEFAULT_MAX_CACHED_LOCALES;
/**
* Flag that, when <code>true</code>, enables automatic checking of URLs
* changing.
@@ -94,29 +82,7 @@ public class CachingLocaleUrlDefinitionDAO extends BaseLocaleUrlDefinitionDAO im
*/
public CachingLocaleUrlDefinitionDAO(ApplicationContext applicationContext) {
super(applicationContext);
locale2definitionMap = new LinkedHashMap<Locale, Map<String, Definition>>(16, 0.75f, false) {
@Override
protected boolean removeEldestEntry(Map.Entry<Locale, Map<String, Definition>> eldest) {
if (size() <= maxCachedLocales) {
return false;
}
if (definitionResolver != null) {
definitionResolver.removePatternPaths(eldest.getKey());
}
return true;
}
};
}
/**
* Sets the maximum number of customization keys (locales) whose definitions are cached. When more distinct keys are
* requested, the eldest cached entry is evicted so the cache cannot grow without bound. Evicted entries are reloaded
* on demand if requested again, so eviction never changes rendering, only re-incurs a load.
*
* @param maxCachedLocales the maximum number of cached customization keys; values below 1 are treated as 1
*/
public void setMaxCachedLocales(int maxCachedLocales) {
this.maxCachedLocales = Math.max(1, maxCachedLocales);
locale2definitionMap = new HashMap<>();
}
/**
@@ -21,9 +21,9 @@ package org.apache.tiles.core.definition.pattern;
import org.apache.tiles.api.Definition;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* A pattern definition resolver that stores {@link DefinitionPatternMatcher}
@@ -39,7 +39,7 @@ public abstract class AbstractPatternDefinitionResolver<T> implements PatternDef
/**
* Stores patterns depending on the locale they refer to.
*/
private final Map<T, List<DefinitionPatternMatcher>> localePatternPaths = new ConcurrentHashMap<>();
private final Map<T, List<DefinitionPatternMatcher>> localePatternPaths = new HashMap<>();
/** {@inheritDoc} */
public Definition resolveDefinition(String name, T customizationKey) {
@@ -103,10 +103,4 @@ public abstract class AbstractPatternDefinitionResolver<T> implements PatternDef
if (localePatternPaths.get(customizationKey) != null)
localePatternPaths.get(customizationKey).clear();
}
/** {@inheritDoc} */
@Override
public void removePatternPaths(T customizationKey) {
localePatternPaths.remove(customizationKey);
}
}
@@ -60,12 +60,4 @@ public interface PatternDefinitionResolver<T> {
* @param customizationKey customization key
*/
void clearPatternPaths(T customizationKey);
/**
* Removes the stored patterns for a specific customization key entirely, including the key itself. Used when the
* owning definitions cache evicts a customization key so that the pattern store cannot grow without bound.
*
* @param customizationKey customization key
*/
void removePatternPaths(T customizationKey);
}
@@ -34,7 +34,6 @@ import org.apache.tiles.request.ApplicationResource;
import org.apache.tiles.request.locale.URLApplicationResource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -369,40 +368,4 @@ public class CachingLocaleUrlDefinitionDAOTest extends TestCase {
assertEquals(1, attributes.size());
verify(applicationContext);
}
/**
* The definitions cache is keyed by locale, so it must not grow beyond the configured bound as distinct
* locales are requested; the eldest entry is evicted instead, and the eviction is propagated to the pattern
* resolver so its per-locale store cannot grow without bound either.
*/
public void testLocaleCacheIsBounded() {
List<ApplicationResource> sourceURLs = new ArrayList<>();
sourceURLs.add(url1);
sourceURLs.add(url2);
sourceURLs.add(url3);
definitionDao.setSources(sourceURLs);
definitionDao.setReader(new DigesterDefinitionsReader());
List<Locale> evicted = new ArrayList<>();
WildcardDefinitionPatternMatcherFactory factory = new WildcardDefinitionPatternMatcherFactory();
PatternDefinitionResolver<Locale> recordingResolver = new BasicPatternDefinitionResolver<Locale>(factory, factory) {
@Override
public void removePatternPaths(Locale customizationKey) {
evicted.add(customizationKey);
super.removePatternPaths(customizationKey);
}
};
definitionDao.setPatternDefinitionResolver(recordingResolver);
definitionDao.setMaxCachedLocales(2);
for (Locale locale : new Locale[]{Locale.US, Locale.FRENCH, Locale.CANADA_FRENCH, Locale.CHINA}) {
assertNotNull("Definitions for " + locale + " were not loaded.",
definitionDao.getDefinitions(locale));
}
assertEquals("Definitions cache must not grow beyond the configured bound",
2, definitionDao.locale2definitionMap.size());
assertEquals("Evicted locales must be removed from the pattern resolver in lockstep",
Arrays.asList(Locale.US, Locale.FRENCH), evicted);
}
}
@@ -79,35 +79,6 @@ public class AbstractPatternDefinitionResolverTest {
testResolveDefinitionImpl();
}
/**
* Test method for
* {@link AbstractPatternDefinitionResolver#removePatternPaths(Object)}: the key and its patterns are dropped
* entirely, so nothing resolves for that key afterwards.
*/
@Test
public void testRemovePatternPaths() {
firstMatcher = createMock(DefinitionPatternMatcher.class);
thirdMatcher = createMock(DefinitionPatternMatcher.class);
Definition firstDefinition = new Definition("first", null, null);
Definition firstTransformedDefinition = new Definition("firstTransformed", null, null);
expect(firstMatcher.createDefinition("firstTransformed")).andReturn(firstTransformedDefinition);
replay(firstMatcher, thirdMatcher);
Map<String, Definition> localeDefsMap = new LinkedHashMap<>();
localeDefsMap.put("first", firstDefinition);
resolver.storeDefinitionPatterns(localeDefsMap, 1);
assertEquals(firstTransformedDefinition, resolver.resolveDefinition("firstTransformed", 1));
resolver.removePatternPaths(1);
assertNull("removePatternPaths must drop the entry so nothing resolves for the key",
resolver.resolveDefinition("firstTransformed", 1));
verify(firstMatcher, thirdMatcher);
}
private void testResolveDefinitionImpl() {
firstMatcher = createMock(DefinitionPatternMatcher.class);
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-velocity-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
</parent>
<artifactId>struts2-xslt-plugin</artifactId>
+9 -9
View File
@@ -29,7 +29,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>struts2-parent</artifactId>
<version>6.12.0-SNAPSHOT</version>
<version>6.11.0</version>
<packaging>pom</packaging>
<name>Struts 2</name>
<url>https://struts.apache.org/</url>
@@ -51,7 +51,7 @@
<connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection>
<url>https://github.com/apache/struts/</url>
<tag>STRUTS_6_9_0</tag>
<tag>STRUTS_6_11_0</tag>
</scm>
<issueManagement>
@@ -104,13 +104,13 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.outputTimestamp>2026-08-01T10:28:23Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2026-08-01T10:22:19Z</project.build.outputTimestamp>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- dependency versions in alphanumeric order -->
<asm.version>9.10.1</asm.version>
<jackson.version>2.22.2</jackson.version>
<jackson.version>2.22.1</jackson.version>
<log4j2.version>2.26.1</log4j2.version>
<ognl.version>3.3.5</ognl.version>
<slf4j.version>2.0.18</slf4j.version>
@@ -119,7 +119,7 @@
<tiles-request.version>1.0.7</tiles-request.version>
<maven-surefire-plugin.version>3.5.6</maven-surefire-plugin.version>
<hibernate-validator.version>6.2.4.Final</hibernate-validator.version>
<freemarker.version>2.3.35</freemarker.version>
<freemarker.version>2.3.34</freemarker.version>
<!-- Site generation -->
<fluido-skin.version>1.9</fluido-skin.version>
@@ -341,7 +341,7 @@
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>13.0.0</version>
<version>12.2.2</version>
<configuration>
<suppressionFiles>
<suppressionFile>src/etc/project-suppression.xml</suppressionFile>
@@ -770,7 +770,7 @@
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>5.7.0</version>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
@@ -851,7 +851,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.6.0</version>
<version>4.5.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
@@ -892,7 +892,7 @@
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.11.0</version>
<version>1.10.1</version>
</dependency>
<!-- Mocks for unit testing (by Spring) -->