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 07bb9df0b..4c94b6b46 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java @@ -203,7 +203,9 @@ public class ParametersInterceptor extends MethodFilterInterceptor { String name = entry.getKey(); Parameter value = entry.getValue(); try { - if (value.isMultiple()) { + if (value instanceof Parameter.File) { + newStack.setParameter(name, value.getObject()); + } else if (value.isMultiple()) { newStack.setParameter(name, value.getMultipleValues()); } else { newStack.setParameter(name, value.getValue()); diff --git a/core/src/main/java/org/apache/struts2/dispatcher/HttpParameters.java b/core/src/main/java/org/apache/struts2/dispatcher/HttpParameters.java index a85c9c762..5c6360eab 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/HttpParameters.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/HttpParameters.java @@ -53,10 +53,6 @@ public class HttpParameters implements Cloneable { return parameters.containsKey(name); } - public HttpParameters clone(Map newParams) { - return HttpParameters.createEmpty().withParent(this).withExtraParams(newParams).build(); - } - public Map toMap() { Map result = new HashMap<>(parameters.size()); for (Map.Entry entry : parameters.entrySet()) { @@ -65,6 +61,11 @@ public class HttpParameters implements Cloneable { return result; } + public HttpParameters appendAll(Map newParams) { + parameters.putAll(newParams); + return this; + } + public static class Builder { private Map requestParameterMap; private HttpParameters parent; diff --git a/core/src/main/java/org/apache/struts2/dispatcher/Parameter.java b/core/src/main/java/org/apache/struts2/dispatcher/Parameter.java index 7a088959c..97f7946a2 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/Parameter.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/Parameter.java @@ -3,6 +3,8 @@ package org.apache.struts2.dispatcher; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.io.File; + public interface Parameter { String getName(); @@ -82,6 +84,12 @@ public interface Parameter { } } + class File extends Request { + public File(String name, Object value) { + super(name, value); + } + } + class EmptyHttpParameter implements Parameter { private String name; diff --git a/core/src/main/java/org/apache/struts2/interceptor/CheckboxInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/CheckboxInterceptor.java index 2bb49aa75..369f81e2f 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/CheckboxInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/CheckboxInterceptor.java @@ -61,7 +61,7 @@ public class CheckboxInterceptor extends AbstractInterceptor { public String intercept(ActionInvocation ai) throws Exception { HttpParameters parameters = ai.getInvocationContext().getParameters(); - Map extraParams = new HashMap<>(); + Map extraParams = new HashMap<>(); for (String name : parameters.getNames()) { if (name.startsWith("__checkbox_")) { @@ -77,13 +77,13 @@ public class CheckboxInterceptor extends AbstractInterceptor { // is this checkbox checked/submitted? if (!parameters.contains(checkboxName)) { // if not, let's be sure to default the value to false - extraParams.put(checkboxName, new String[]{ uncheckedValue }); + extraParams.put(checkboxName, new Parameter.Request(checkboxName, uncheckedValue)); } } } - ai.getInvocationContext().setParameters(parameters.clone(extraParams)); + ai.getInvocationContext().getParameters().appendAll(extraParams); return ai.invoke(); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/DateTextFieldInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/DateTextFieldInterceptor.java index c71cf4d94..acadde2e7 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/DateTextFieldInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/DateTextFieldInterceptor.java @@ -96,7 +96,7 @@ public class DateTextFieldInterceptor implements Interceptor { } // Create all the date objects - Map newParams = new HashMap<>(); + Map newParams = new HashMap<>(); Set>> dateEntries = dates.entrySet(); for (Entry> dateEntry : dateEntries) { Set> dateFormatEntries = dateEntry.getValue().entrySet(); @@ -110,13 +110,13 @@ public class DateTextFieldInterceptor implements Interceptor { SimpleDateFormat formatter = new SimpleDateFormat(dateFormat); formatter.setLenient(false); Date value = formatter.parse(dateValue); - newParams.put(dateEntry.getKey(), value); + newParams.put(dateEntry.getKey(), new Parameter.Request(dateEntry.getKey(), value)); } catch (ParseException e) { LOG.warn("Cannot parse the parameter '{}' with format '{}' and with value '{}'", dateEntry.getKey(), dateFormat, dateValue); } } - ai.getInvocationContext().setParameters(parameters.clone(newParams)); + ai.getInvocationContext().getParameters().appendAll(newParams); return ai.invoke(); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java index 0ceacc4a4..680f8279d 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java @@ -30,6 +30,7 @@ import com.opensymphony.xwork2.util.TextParseUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; +import org.apache.struts2.dispatcher.Parameter; import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper; import org.apache.struts2.util.ContentTypeMatcher; @@ -294,11 +295,11 @@ public class FileUploadInterceptor extends AbstractInterceptor { } if (!acceptedFiles.isEmpty()) { - Map newParams = new HashMap<>(); - newParams.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()])); - newParams.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()])); - newParams.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()])); - ac.setParameters(ac.getParameters().clone(newParams)); + Map newParams = new HashMap<>(); + newParams.put(inputName, new Parameter.File(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]))); + newParams.put(contentTypeName, new Parameter.File(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]))); + newParams.put(fileNameName, new Parameter.File(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]))); + ac.getParameters().appendAll(newParams); } } } else { diff --git a/core/src/main/java/org/apache/struts2/interceptor/MultiselectInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/MultiselectInterceptor.java index 337fd0caa..a62de226d 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/MultiselectInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/MultiselectInterceptor.java @@ -23,6 +23,7 @@ package org.apache.struts2.interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import org.apache.struts2.dispatcher.HttpParameters; +import org.apache.struts2.dispatcher.Parameter; import java.util.HashMap; import java.util.Map; @@ -47,7 +48,7 @@ public class MultiselectInterceptor extends AbstractInterceptor { */ public String intercept(ActionInvocation ai) throws Exception { HttpParameters parameters = ai.getInvocationContext().getParameters(); - Map newParams = new HashMap<>(); + Map newParams = new HashMap<>(); for (String name : parameters.getNames()) { if (name.startsWith("__multiselect_")) { @@ -56,14 +57,14 @@ public class MultiselectInterceptor extends AbstractInterceptor { // is this multi-select box submitted? if (!parameters.contains(key)) { // if not, let's be sure to default the value to an empty string array - newParams.put(key, new String[0]); + newParams.put(key, new Parameter.Request(key, new String[0])); } parameters = parameters.remove(name); } } - ai.getInvocationContext().setParameters(parameters.clone(newParams)); + ai.getInvocationContext().getParameters().appendAll(newParams); return ai.invoke(); } diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPRuntime.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPRuntime.java index bd9b4a88a..1aa719ac8 100644 --- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPRuntime.java +++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/JSPRuntime.java @@ -22,12 +22,14 @@ package org.apache.struts2; import com.opensymphony.xwork2.ActionContext; import org.apache.struts2.dispatcher.HttpParameters; +import org.apache.struts2.dispatcher.Parameter; import org.apache.struts2.views.util.UrlHelper; import javax.servlet.Servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.HttpJspPage; +import java.util.HashMap; import java.util.Map; /** @@ -54,12 +56,14 @@ public abstract class JSPRuntime { int i = location.indexOf("?"); if (i > 0) { //extract params from the url and add them to the request - HttpParameters parameters = ActionContext.getContext().getParameters(); String query = location.substring(i + 1); Map queryParams = urlHelper.parseQueryString(query, true); if (queryParams != null && !queryParams.isEmpty()) { - parameters = parameters.clone(queryParams); - ActionContext.getContext().setParameters(parameters); + Map newParams = new HashMap<>(); + for (Map.Entry entry : queryParams.entrySet()) { + newParams.put(entry.getKey(), new Parameter.Request(entry.getKey(), entry.getValue())); + } + ActionContext.getContext().getParameters().appendAll(newParams); } location = location.substring(0, i); }