mirror of
https://github.com/apache/struts.git
synced 2026-08-05 22:56:59 +00:00
Merge pull request #809 from apache/fix/after-rebase
Rebase struts-7-0-x branch
This commit is contained in:
+1
-1
@@ -14,5 +14,5 @@
|
||||
# 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.8.6/apache-maven-3.8.6-bin.zip
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
||||
|
||||
Vendored
+55
-56
@@ -37,14 +37,9 @@ pipeline {
|
||||
MAVEN_OPTS = "-Xmx1024m"
|
||||
}
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh './mvnw -B test'
|
||||
sh './mvnw -B -DskipAssembly verify --no-transfer-progress'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -53,49 +48,6 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Build Source & JavaDoc') {
|
||||
when {
|
||||
branch 'master'
|
||||
}
|
||||
steps {
|
||||
dir("local-snapshots-dir/") {
|
||||
deleteDir()
|
||||
}
|
||||
sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Deploy Snapshot') {
|
||||
when {
|
||||
branch 'master'
|
||||
}
|
||||
steps {
|
||||
withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) {
|
||||
sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Upload nightlies') {
|
||||
when {
|
||||
branch 'master'
|
||||
}
|
||||
steps {
|
||||
sh './mvnw -B package -DskipTests'
|
||||
sshPublisher(publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'Nightlies',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
remoteDirectory: '/struts/snapshot',
|
||||
removePrefix: 'assembly/target/assembly/out',
|
||||
sourceFiles: 'assembly/target/assembly/out/struts-*.zip',
|
||||
cleanRemote: true
|
||||
)
|
||||
],
|
||||
verbose: true
|
||||
)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -115,14 +67,9 @@ pipeline {
|
||||
MAVEN_OPTS = "-Xmx1024m"
|
||||
}
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh './mvnw -B verify -Pcoverage -DskipAssembly'
|
||||
sh './mvnw -B verify -Pcoverage -DskipAssembly --no-transfer-progress'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -133,7 +80,9 @@ pipeline {
|
||||
}
|
||||
stage('Code Quality') {
|
||||
when {
|
||||
branch 'master'
|
||||
anyOf {
|
||||
branch 'master'; branch 'release/struts-7-0-x'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withCredentials([string(credentialsId: 'asf-struts-sonarcloud', variable: 'SONARCLOUD_TOKEN')]) {
|
||||
@@ -141,6 +90,56 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Build Source & JavaDoc') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'master'; branch 'release/struts-7-0-x'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
dir("local-snapshots-dir/") {
|
||||
deleteDir()
|
||||
}
|
||||
sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Deploy Snapshot') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'master'; branch 'release/struts-7-0-x'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) {
|
||||
sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Upload nightlies') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'master'
|
||||
branch 'release/struts-7-0-x'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
sh './mvnw -B package -DskipTests'
|
||||
sshPublisher(publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'Nightlies',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
remoteDirectory: '/struts/snapshot',
|
||||
removePrefix: 'assembly/target/assembly/out',
|
||||
sourceFiles: 'assembly/target/assembly/out/struts-*.zip',
|
||||
cleanRemote: true
|
||||
)
|
||||
],
|
||||
verbose: true
|
||||
)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
|
||||
@@ -129,6 +129,12 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.htmlunit</groupId>
|
||||
<artifactId>htmlunit</artifactId>
|
||||
@@ -231,7 +237,7 @@
|
||||
<httpConnector>
|
||||
<port>8090</port>
|
||||
</httpConnector>
|
||||
<scanIntervalSeconds>10</scanIntervalSeconds>
|
||||
<scan>10</scan>
|
||||
<webAppSourceDirectory>${basedir}/src/main/webapp/</webAppSourceDirectory>
|
||||
<webApp>
|
||||
<extraClasspath>
|
||||
|
||||
@@ -19,35 +19,46 @@
|
||||
package it.org.apache.struts2.showcase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
|
||||
import org.htmlunit.WebClient;
|
||||
import org.htmlunit.html.DomElement;
|
||||
import org.htmlunit.html.HtmlFileInput;
|
||||
import org.htmlunit.html.HtmlForm;
|
||||
import org.htmlunit.html.HtmlInput;
|
||||
import org.htmlunit.html.HtmlPage;
|
||||
import org.htmlunit.html.HtmlSubmitInput;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class FileUploadTest {
|
||||
|
||||
@Test
|
||||
public void testEmptyFile() throws Exception {
|
||||
public void testSimpleFileUpload() throws Exception {
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/fileupload/doUpload.action");
|
||||
final HtmlForm form = page.getFormByName("doUpload");
|
||||
HtmlInput captionInput = form.getInputByName("caption");
|
||||
HtmlFileInput uploadInput = form.getInputByName("upload");
|
||||
captionInput.type("some caption");
|
||||
File tempFile = File.createTempFile("testEmptyFile", ".tmp");
|
||||
File tempFile = File.createTempFile("testEmptyFile", ".txt");
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
try (FileWriter writer = new FileWriter(tempFile)) {
|
||||
writer.append("Some strings");
|
||||
}
|
||||
|
||||
uploadInput.setValue(tempFile.getAbsolutePath());
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage resultPage = button.click();
|
||||
DomElement errorMessage = resultPage.getFirstByXPath("//span[@class='errorMessage']");
|
||||
Assert.assertNotNull(errorMessage);
|
||||
Assert.assertEquals("File cannot be empty", errorMessage.getVisibleText());
|
||||
|
||||
String content = resultPage.getVisibleText();
|
||||
System.out.println(content);
|
||||
assertThat(content).contains(
|
||||
"ContentType: text/plain",
|
||||
"Original FileName: " + tempFile.getName(),
|
||||
"Caption:some caption"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.action;
|
||||
|
||||
import org.apache.struts2.dispatcher.multipart.UploadedFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Actions that want to be aware of all the uploaded file should implement this interface.
|
||||
* The {@link org.apache.struts2.interceptor.ActionFileUploadInterceptor} will use the interface
|
||||
* to notify action about the multiple uploaded files.
|
||||
*/
|
||||
public interface UploadedFilesAware {
|
||||
|
||||
/**
|
||||
* Notifies action about the multiple uploaded files, when a single file is uploaded
|
||||
* the list will have just one element
|
||||
*
|
||||
* @param uploadedFiles a list of {@link UploadedFile}, cannot be null. It can be empty.
|
||||
*/
|
||||
void withUploadedFiles(List<UploadedFile> uploadedFiles);
|
||||
|
||||
}
|
||||
+2
@@ -36,6 +36,8 @@ import java.util.Locale;
|
||||
*/
|
||||
public abstract class AbstractMultiPartRequest implements MultiPartRequest {
|
||||
|
||||
protected static final String STRUTS_MESSAGES_UPLOAD_ERROR_PARAMETER_TOO_LONG_KEY = "struts.messages.upload.error.parameter.too.long";
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(AbstractMultiPartRequest.class);
|
||||
|
||||
/**
|
||||
|
||||
+36
-25
@@ -18,6 +18,22 @@
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.multipart;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.fileupload2.core.DiskFileItem;
|
||||
import org.apache.commons.fileupload2.core.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload2.core.FileItem;
|
||||
import org.apache.commons.fileupload2.core.FileUploadByteCountLimitException;
|
||||
import org.apache.commons.fileupload2.core.FileUploadContentTypeException;
|
||||
import org.apache.commons.fileupload2.core.FileUploadException;
|
||||
import org.apache.commons.fileupload2.core.FileUploadFileCountLimitException;
|
||||
import org.apache.commons.fileupload2.core.FileUploadSizeException;
|
||||
import org.apache.commons.fileupload2.core.RequestContext;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.dispatcher.LocalizedMessage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -31,22 +47,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.fileupload2.core.DiskFileItem;
|
||||
import org.apache.commons.fileupload2.core.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload2.core.FileItem;
|
||||
import org.apache.commons.fileupload2.core.FileUploadByteCountLimitException;
|
||||
import org.apache.commons.fileupload2.core.FileUploadException;
|
||||
import org.apache.commons.fileupload2.core.FileUploadFileCountLimitException;
|
||||
import org.apache.commons.fileupload2.core.FileUploadSizeException;
|
||||
import org.apache.commons.fileupload2.core.RequestContext;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.dispatcher.LocalizedMessage;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Multipart form data request adapter for Jakarta Commons Fileupload package.
|
||||
*/
|
||||
@@ -77,13 +77,24 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest {
|
||||
LocalizedMessage errorMessage;
|
||||
if (e instanceof FileUploadByteCountLimitException) {
|
||||
FileUploadByteCountLimitException ex = (FileUploadByteCountLimitException) e;
|
||||
errorMessage = buildErrorMessage(e, new Object[]{ex.getFileName(), ex.getPermitted(), ex.getActualSize()});
|
||||
errorMessage = buildErrorMessage(e, new Object[]{
|
||||
ex.getFieldName(), ex.getFileName(), ex.getPermitted(), ex.getActualSize()
|
||||
});
|
||||
} else if (e instanceof FileUploadFileCountLimitException) {
|
||||
FileUploadFileCountLimitException ex = (FileUploadFileCountLimitException) e;
|
||||
errorMessage = buildErrorMessage(e, new Object[]{ex.getPermitted()});
|
||||
errorMessage = buildErrorMessage(e, new Object[]{
|
||||
ex.getPermitted(), ex.getActualSize()
|
||||
});
|
||||
} else if (e instanceof FileUploadSizeException) {
|
||||
FileUploadSizeException ex = (FileUploadSizeException) e;
|
||||
errorMessage = buildErrorMessage(e, new Object[]{ex.getPermitted(), ex.getActualSize()});
|
||||
errorMessage = buildErrorMessage(e, new Object[]{
|
||||
ex.getPermitted(), ex.getActualSize()
|
||||
});
|
||||
} else if (e instanceof FileUploadContentTypeException) {
|
||||
FileUploadContentTypeException ex = (FileUploadContentTypeException) e;
|
||||
errorMessage = buildErrorMessage(e, new Object[]{
|
||||
ex.getContentType()
|
||||
});
|
||||
} else {
|
||||
errorMessage = buildErrorMessage(e, new Object[]{});
|
||||
}
|
||||
@@ -149,8 +160,8 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest {
|
||||
long size = item.getSize();
|
||||
if (size > maxStringLength) {
|
||||
LOG.debug("Form field {} of size {} bytes exceeds limit of {}.", sanitizeNewlines(item.getFieldName()), size, maxStringLength);
|
||||
String errorKey = "struts.messages.upload.error.parameter.too.long";
|
||||
LocalizedMessage localizedMessage = new LocalizedMessage(this.getClass(), errorKey, null,
|
||||
LocalizedMessage localizedMessage = new LocalizedMessage(this.getClass(),
|
||||
STRUTS_MESSAGES_UPLOAD_ERROR_PARAMETER_TOO_LONG_KEY, null,
|
||||
new Object[]{item.getFieldName(), maxStringLength, size});
|
||||
if (!errors.contains(localizedMessage)) {
|
||||
errors.add(localizedMessage);
|
||||
@@ -174,7 +185,7 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest {
|
||||
DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
|
||||
JakartaServletFileUpload upload = createServletFileUpload(fac);
|
||||
|
||||
|
||||
|
||||
return upload.parseRequest(createRequestContext(servletRequest));
|
||||
}
|
||||
|
||||
@@ -252,9 +263,9 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest {
|
||||
}
|
||||
}
|
||||
UploadedFile uploadedFile = StrutsUploadedFile.Builder.create(storeLocation)
|
||||
.withContentType(fileItem.getContentType())
|
||||
.withOriginalName(fileItem.getName())
|
||||
.build();
|
||||
.withContentType(fileItem.getContentType())
|
||||
.withOriginalName(fileItem.getName())
|
||||
.build();
|
||||
fileList.add(uploadedFile);
|
||||
}
|
||||
|
||||
|
||||
+3
-10
@@ -18,17 +18,12 @@
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.multipart;
|
||||
|
||||
import org.apache.commons.fileupload2.core.DiskFileItem;
|
||||
import org.apache.commons.fileupload2.core.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
|
||||
import org.apache.commons.fileupload2.core.FileUploadSizeException;
|
||||
import org.apache.commons.fileupload2.core.FileItemInputIterator;
|
||||
import org.apache.commons.fileupload2.core.FileItemInput;
|
||||
import org.apache.commons.fileupload.FileItemIterator;
|
||||
import org.apache.commons.fileupload.FileItemStream;
|
||||
import org.apache.commons.fileupload.FileUploadBase;
|
||||
import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
|
||||
import org.apache.commons.fileupload.FileUploadException;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import org.apache.commons.fileupload.util.Streams;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.dispatcher.LocalizedMessage;
|
||||
@@ -223,7 +218,7 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
|
||||
// Interface with Commons FileUpload API
|
||||
// Using the Streaming API
|
||||
JakartaServletFileUpload servletFileUpload = new JakartaServletFileUpload();
|
||||
JakartaServletFileUpload<DiskFileItem, DiskFileItemFactory> servletFileUpload = new JakartaServletFileUpload<>();
|
||||
if (maxSize != null) {
|
||||
servletFileUpload.setSizeMax(maxSize);
|
||||
}
|
||||
@@ -447,8 +442,6 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
*/
|
||||
public static class FileInfo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1083158552766906037L;
|
||||
|
||||
private final File file;
|
||||
private final String contentType;
|
||||
private final String originalName;
|
||||
|
||||
+10
-10
@@ -55,9 +55,9 @@ public class MultiPartRequestWrapper extends StrutsRequestWrapper {
|
||||
|
||||
protected static final Logger LOG = LogManager.getLogger(MultiPartRequestWrapper.class);
|
||||
|
||||
private Collection<LocalizedMessage> errors;
|
||||
private MultiPartRequest multi;
|
||||
private Locale defaultLocale = Locale.ENGLISH;
|
||||
private final Collection<LocalizedMessage> errors;
|
||||
private final MultiPartRequest multi;
|
||||
private Locale defaultLocale;
|
||||
|
||||
/**
|
||||
* Process file downloads and log any errors.
|
||||
@@ -84,7 +84,7 @@ public class MultiPartRequestWrapper extends StrutsRequestWrapper {
|
||||
} catch (IOException e) {
|
||||
LOG.warn(e.getMessage(), e);
|
||||
addError(buildErrorMessage(e, new Object[] {e.getMessage()}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir, LocaleProvider provider) {
|
||||
@@ -185,12 +185,12 @@ public class MultiPartRequestWrapper extends StrutsRequestWrapper {
|
||||
/**
|
||||
* @see jakarta.servlet.http.HttpServletRequest#getParameterMap()
|
||||
*/
|
||||
public Map getParameterMap() {
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
Map<String, String[]> map = new HashMap<>();
|
||||
Enumeration enumeration = getParameterNames();
|
||||
Enumeration<String> enumeration = getParameterNames();
|
||||
|
||||
while (enumeration.hasMoreElements()) {
|
||||
String name = (String) enumeration.nextElement();
|
||||
String name = enumeration.nextElement();
|
||||
map.put(name, this.getParameterValues(name));
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public class MultiPartRequestWrapper extends StrutsRequestWrapper {
|
||||
/**
|
||||
* @see jakarta.servlet.http.HttpServletRequest#getParameterNames()
|
||||
*/
|
||||
public Enumeration getParameterNames() {
|
||||
public Enumeration<String> getParameterNames() {
|
||||
if (multi == null) {
|
||||
return super.getParameterNames();
|
||||
} else {
|
||||
@@ -251,8 +251,8 @@ public class MultiPartRequestWrapper extends StrutsRequestWrapper {
|
||||
* @param params2 the second enumeration.
|
||||
* @return a single Enumeration of all elements from both Enumerations.
|
||||
*/
|
||||
protected Enumeration mergeParams(Enumeration params1, Enumeration params2) {
|
||||
Vector temp = new Vector();
|
||||
protected Enumeration<String> mergeParams(Enumeration<String> params1, Enumeration<String> params2) {
|
||||
Vector<String> temp = new Vector<>();
|
||||
|
||||
while (params1.hasMoreElements()) {
|
||||
temp.add(params1.nextElement());
|
||||
|
||||
@@ -21,13 +21,13 @@ package org.apache.struts2.interceptor;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.ActionProxy;
|
||||
import com.opensymphony.xwork2.interceptor.ValidationAware;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.action.UploadedFilesAware;
|
||||
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
|
||||
import org.apache.struts2.dispatcher.multipart.UploadedFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
@@ -134,7 +134,7 @@ public class ActionFileUploadInterceptor extends AbstractFileUploadInterceptor {
|
||||
*/
|
||||
public String intercept(ActionInvocation invocation) throws Exception {
|
||||
HttpServletRequest request = invocation.getInvocationContext().getServletRequest();
|
||||
if (!(request instanceof MultiPartRequestWrapper)) {
|
||||
if (!(request instanceof MultiPartRequestWrapper multiWrapper)) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
ActionProxy proxy = invocation.getProxy();
|
||||
LOG.debug(getTextMessage(STRUTS_MESSAGES_BYPASS_REQUEST_KEY, new String[]{proxy.getNamespace(), proxy.getActionName()}));
|
||||
@@ -142,15 +142,12 @@ public class ActionFileUploadInterceptor extends AbstractFileUploadInterceptor {
|
||||
return invocation.invoke();
|
||||
}
|
||||
|
||||
MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;
|
||||
|
||||
if (!(invocation.getAction() instanceof UploadedFilesAware)) {
|
||||
if (!(invocation.getAction() instanceof UploadedFilesAware action)) {
|
||||
LOG.debug("Action: {} doesn't implement: {}, ignoring file upload",
|
||||
invocation.getProxy().getActionName(),
|
||||
UploadedFilesAware.class.getSimpleName());
|
||||
return invocation.invoke();
|
||||
}
|
||||
UploadedFilesAware action = (UploadedFilesAware) invocation.getAction();
|
||||
|
||||
applyValidation(action, multiWrapper);
|
||||
|
||||
|
||||
@@ -16,24 +16,62 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# WARNING! This file is the exact copy of struts-messages.properties!
|
||||
# See https://issues.apache.org/jira/browse/WW-4195 for more details!
|
||||
|
||||
struts.messages.invalid.token=The form has already been processed or no token was supplied, please try again.
|
||||
struts.internal.invalid.token=Form token {0} does not match the session token {1}.
|
||||
|
||||
struts.messages.bypass.request=Bypassing {0}/{1}
|
||||
struts.messages.current.file=File {0} {1} {2} {3}
|
||||
# 0 - input name
|
||||
struts.messages.invalid.file=Could not find a Filename for {0}. Verify that a valid file was submitted.
|
||||
# 0 - original filename
|
||||
struts.messages.invalid.content.type=Could not find a Content-Type for {0}. Verify that a valid file was submitted.
|
||||
struts.messages.removing.file=Removing file {0} {1}
|
||||
struts.messages.error.uploading=Error uploading: {0}
|
||||
struts.messages.error.file.too.large=File {0} is too large to be uploaded. Maximum allowed size is {4} bytes!
|
||||
struts.messages.upload.error.parameter.too.long=The request parameter "{0}" was too long. Max length allowed is {1}, but found {2}!
|
||||
# 0 - input name
|
||||
# 1 - original filename
|
||||
# 2 - file name after uploading the file
|
||||
# 3 - size of the uploaded files
|
||||
# 4 - maximum allowed size
|
||||
struts.messages.error.file.too.large=The file is too large to be uploaded: {0} "{1}" "{2}" has size {3} and allowed mx size is {4}
|
||||
# 0 - field name
|
||||
# 1 - max string length
|
||||
# 2 - actual size
|
||||
struts.messages.upload.error.parameter.too.long=The request parameter "{0}" was too long. Max length allowed is {1}, but found {2}!
|
||||
# 0 - input name
|
||||
# 1 - original filename
|
||||
# 2 - file name after uploading the file
|
||||
# 3 - content type of the file
|
||||
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
|
||||
# 0 - input name
|
||||
# 1 - original filename
|
||||
# 2 - file name after uploading the file
|
||||
# 3 - content type of the file
|
||||
struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
|
||||
|
||||
# dedicated messages used to handle various problems with file upload - check {@link JakartaMultiPartRequest#parse(HttpServletRequest, String)}
|
||||
struts.messages.upload.error.FileUploadSizeException=Request exceeded allowed size limit! Max size allowed is: {0}!
|
||||
struts.messages.upload.error.FileUploadFileCountLimitException=Request exceeded allowed number of files! Max allowed files number is: {0}!
|
||||
struts.messages.upload.error.FileUploadByteCountLimitException=File in request exceeded allowed file size limit! Max file size allowed is: {1}!
|
||||
# params depend on exception being handled
|
||||
# FileUploadByteCountLimitException
|
||||
# 0 - field name
|
||||
# 1 - file name
|
||||
# 2 - permitted
|
||||
# 3 - actual size
|
||||
struts.messages.upload.error.FileUploadByteCountLimitException=File {1} assigned to {0} exceeded allowed size limit! Max size allowed is: {2} but file was: {3}!
|
||||
|
||||
# FileUploadFileCountLimitException
|
||||
# 0 - limit
|
||||
struts.messages.upload.error.FileUploadFileCountLimitException=Request exceeded allowed number of files! Permitted number of files is: {0}!
|
||||
|
||||
# FileUploadSizeException
|
||||
# 1 - permitted size
|
||||
# 2 - actual size
|
||||
struts.messages.upload.error.FileUploadSizeException=Request exceeded allowed size limit! Max size allowed is: {0} but request was: {1}!
|
||||
|
||||
# FileUploadContentTypeException
|
||||
# 0 - content type
|
||||
struts.messages.upload.error.FileUploadContentTypeException=Request has wrong content type: {0}!
|
||||
|
||||
struts.messages.upload.error.FileUploadException=Error uploading: {0}!
|
||||
|
||||
devmode.notification=Developer Notification (set struts.devMode to false to disable this message):\n{0}
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowlist() throws Exception {
|
||||
public void allowList() throws Exception {
|
||||
loadConfigurationProviders(testXml1, testXml2);
|
||||
providerAllowlist = container.getInstance(ProviderAllowlist.class);
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.ognl;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class MyCustomMap<K, V> extends HashMap<K, V> {
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
return (V) "System compromised";
|
||||
}
|
||||
}
|
||||
+52
-45
@@ -25,7 +25,9 @@ import com.opensymphony.xwork2.ValidationAwareSupport;
|
||||
import com.opensymphony.xwork2.mock.MockActionInvocation;
|
||||
import com.opensymphony.xwork2.mock.MockActionProxy;
|
||||
import com.opensymphony.xwork2.util.ClassLoaderUtil;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletDiskFileUpload;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.StrutsInternalTestCase;
|
||||
import org.apache.struts2.action.UploadedFilesAware;
|
||||
@@ -35,7 +37,6 @@ import org.apache.struts2.dispatcher.multipart.StrutsUploadedFile;
|
||||
import org.apache.struts2.dispatcher.multipart.UploadedFile;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
@@ -290,13 +291,14 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
req.addHeader("Content-type", "multipart/form-data; boundary=---1234");
|
||||
|
||||
// inspired by the unit tests for jakarta commons fileupload
|
||||
String content = ("-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" +
|
||||
"Content-Type: text/html\r\n" +
|
||||
"\r\n" +
|
||||
"Unit test of ActionFileUploadInterceptor" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n");
|
||||
String content = ("""
|
||||
-----1234\r
|
||||
Content-Disposition: form-data; name="file"; filename="deleteme.txt"\r
|
||||
Content-Type: text/html\r
|
||||
\r
|
||||
Unit test of ActionFileUploadInterceptor\r
|
||||
-----1234--\r
|
||||
""");
|
||||
req.setContent(content.getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
MyFileUploadAction action = new MyFileUploadAction();
|
||||
@@ -340,7 +342,7 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
endline;
|
||||
req.setContent(content.getBytes());
|
||||
|
||||
assertTrue(ServletFileUpload.isMultipartContent(req));
|
||||
assertTrue(JakartaServletDiskFileUpload.isMultipartContent(req));
|
||||
|
||||
MyFileUploadAction action = new MyFileUploadAction();
|
||||
container.inject(action);
|
||||
@@ -377,7 +379,7 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
endline;
|
||||
req.setContent(content.getBytes());
|
||||
|
||||
assertTrue(ServletFileUpload.isMultipartContent(req));
|
||||
assertTrue(JakartaServletFileUpload.isMultipartContent(req));
|
||||
|
||||
MyFileUploadAction action = new MyFileUploadAction();
|
||||
container.inject(action);
|
||||
@@ -392,7 +394,10 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
|
||||
assertNull(action.getUploadFiles());
|
||||
assertEquals(1, action.getActionErrors().size());
|
||||
assertEquals("Request exceeded allowed number of files! Max allowed files number is: 3!", action.getActionErrors().iterator().next());
|
||||
assertEquals(
|
||||
"Request exceeded allowed number of files! Permitted number of files is: 3!",
|
||||
action.getActionErrors().iterator().next()
|
||||
);
|
||||
}
|
||||
|
||||
public void testMultipartRequestMaxFileSize() throws Exception {
|
||||
@@ -402,13 +407,14 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
req.addHeader("Content-type", "multipart/form-data; boundary=---1234");
|
||||
|
||||
// inspired by the unit tests for jakarta commons fileupload
|
||||
String content = ("-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" +
|
||||
"Content-Type: text/html\r\n" +
|
||||
"\r\n" +
|
||||
"Unit test of ActionFileUploadInterceptor" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n");
|
||||
String content = ("""
|
||||
-----1234\r
|
||||
Content-Disposition: form-data; name="file"; filename="deleteme.txt"\r
|
||||
Content-Type: text/html\r
|
||||
\r
|
||||
Unit test of ActionFileUploadInterceptor\r
|
||||
-----1234--\r
|
||||
""");
|
||||
req.setContent(content.getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
MyFileUploadAction action = container.inject(MyFileUploadAction.class);
|
||||
@@ -427,8 +433,9 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
Collection<String> errors = action.getActionErrors();
|
||||
assertEquals(1, errors.size());
|
||||
String msg = errors.iterator().next();
|
||||
// FIXME: the expected size is 40 - length of the string
|
||||
assertEquals(
|
||||
"File in request exceeded allowed file size limit! Max file size allowed is: 10 but file deleteme.txt was: 40!",
|
||||
"File deleteme.txt assigned to file exceeded allowed size limit! Max size allowed is: 10 but file was: 10!",
|
||||
msg);
|
||||
}
|
||||
|
||||
@@ -439,23 +446,22 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
req.addHeader("Content-type", "multipart/form-data; boundary=---1234");
|
||||
|
||||
// inspired by the unit tests for jakarta commons fileupload
|
||||
String content = ("-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" +
|
||||
"Content-Type: text/html\r\n" +
|
||||
"\r\n" +
|
||||
"Unit test of ActionFileUploadInterceptor" +
|
||||
"\r\n" +
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"normalFormField1\"\r\n" +
|
||||
"\r\n" +
|
||||
"it works" +
|
||||
"\r\n" +
|
||||
"-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"normalFormField2\"\r\n" +
|
||||
"\r\n" +
|
||||
"long string should not work" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n");
|
||||
String content = ("""
|
||||
-----1234\r
|
||||
Content-Disposition: form-data; name="file"; filename="deleteme.txt"\r
|
||||
Content-Type: text/html\r
|
||||
\r
|
||||
Unit test of ActionFileUploadInterceptor\r
|
||||
-----1234\r
|
||||
Content-Disposition: form-data; name="normalFormField1"\r
|
||||
\r
|
||||
it works\r
|
||||
-----1234\r
|
||||
Content-Disposition: form-data; name="normalFormField2"\r
|
||||
\r
|
||||
long string should not work\r
|
||||
-----1234--\r
|
||||
""");
|
||||
req.setContent(content.getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
MyFileUploadAction action = container.inject(MyFileUploadAction.class);
|
||||
@@ -475,7 +481,7 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
assertEquals(1, errors.size());
|
||||
String msg = errors.iterator().next();
|
||||
assertEquals(
|
||||
"The request parameter \"normalFormField2\" was too long. Max length allowed is 20, but found 27!",
|
||||
"The request parameter \"normalFormField2\" was too long. Max length allowed is 20, but found 27!",
|
||||
msg);
|
||||
}
|
||||
|
||||
@@ -486,13 +492,14 @@ public class ActionFileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
req.addHeader("Content-type", "multipart/form-data; boundary=---1234");
|
||||
|
||||
// inspired by the unit tests for jakarta commons fileupload
|
||||
String content = ("-----1234\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" +
|
||||
"Content-Type: text/html\r\n" +
|
||||
"\r\n" +
|
||||
"Unit test of ActionFileUploadInterceptor" +
|
||||
"\r\n" +
|
||||
"-----1234--\r\n");
|
||||
String content = ("""
|
||||
-----1234\r
|
||||
Content-Disposition: form-data; name="file"; filename="deleteme.txt"\r
|
||||
Content-Type: text/html\r
|
||||
\r
|
||||
Unit test of ActionFileUploadInterceptor\r
|
||||
-----1234--\r
|
||||
""");
|
||||
req.setContent(content.getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
MyFileUploadAction action = container.inject(MyFileUploadAction.class);
|
||||
|
||||
@@ -424,7 +424,10 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
HttpParameters parameters = mai.getInvocationContext().getParameters();
|
||||
assertEquals(0, parameters.keySet().size());
|
||||
assertEquals(1, action.getActionErrors().size());
|
||||
assertEquals("Request exceeded allowed number of files! Max allowed files number is: 3!", action.getActionErrors().iterator().next());
|
||||
assertEquals(
|
||||
"Request exceeded allowed number of files! Permitted number of files is: 3!",
|
||||
action.getActionErrors().iterator().next()
|
||||
);
|
||||
}
|
||||
|
||||
public void testMultipartRequestMaxFileSize() throws Exception {
|
||||
@@ -461,8 +464,9 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
Collection<String> errors = action.getActionErrors();
|
||||
assertEquals(1, errors.size());
|
||||
String msg = errors.iterator().next();
|
||||
// FIXME: the expected size is 40 - length of the string
|
||||
assertEquals(
|
||||
"File in request exceeded allowed file size limit! Max file size allowed is: 10!",
|
||||
"File deleteme.txt assigned to file exceeded allowed size limit! Max size allowed is: 10 but file was: 10!",
|
||||
msg);
|
||||
}
|
||||
|
||||
@@ -511,7 +515,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
|
||||
assertEquals(1, errors.size());
|
||||
String msg = errors.iterator().next();
|
||||
assertEquals(
|
||||
"The request parameter \"normalFormField2\" was too long. Max length allowed is 20, but found 27!",
|
||||
"The request parameter \"normalFormField2\" was too long. Max length allowed is 20, but found 27!",
|
||||
msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
package org.apache.struts2.util;
|
||||
|
||||
import com.opensymphony.xwork2.ognl.SecurityMemberAccess;
|
||||
import jakarta.servlet.jsp.tagext.TagSupport;
|
||||
import org.apache.struts2.StrutsInternalTestCase;
|
||||
import org.apache.struts2.views.jsp.ActionTag;
|
||||
|
||||
import jakarta.servlet.jsp.tagext.TagSupport;
|
||||
import java.lang.reflect.Member;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -40,9 +40,7 @@ public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
Set<Pattern> excluded = new HashSet<Pattern>();
|
||||
excluded.add(Pattern.compile("^(?!jakarta\\.servlet\\..+)(jakarta\\..+)"));
|
||||
sma.useExcludedPackageNamePatterns(excluded);
|
||||
sma.useExcludedPackageNamePatterns("^(?!jakarta\\.servlet\\..+)(jakarta\\..+)");
|
||||
|
||||
String propertyName = "value";
|
||||
Member member = TagSupport.class.getMethod("doStartTag");
|
||||
@@ -58,9 +56,7 @@ public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
Set<Pattern> excluded = new HashSet<>();
|
||||
excluded.add(Pattern.compile("^jakarta\\..+"));
|
||||
sma.useExcludedPackageNamePatterns(excluded);
|
||||
sma.useExcludedPackageNamePatterns("^jakarta\\..+");
|
||||
|
||||
String propertyName = "value";
|
||||
Member member = TagSupport.class.getMethod("doStartTag");
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
<?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">
|
||||
<struts>
|
||||
<package name="allow2">
|
||||
<result-types>
|
||||
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult" default="true"/>
|
||||
</result-types>
|
||||
|
||||
<interceptors>
|
||||
<interceptor name="noop" class="org.apache.struts2.interceptor.NoOpInterceptor"/>
|
||||
</interceptors>
|
||||
|
||||
<action name="WildCard" class="com.opensymphony.xwork2.ActionSupport">
|
||||
<result name="*" type="chain"/>
|
||||
<interceptor-ref name="noop"/>
|
||||
</action>
|
||||
|
||||
</package>
|
||||
</struts>
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
<?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">
|
||||
<struts>
|
||||
<package name="allow">
|
||||
<result-types>
|
||||
<result-type name="mock" class="com.opensymphony.xwork2.mock.MockResult"/>
|
||||
</result-types>
|
||||
|
||||
<interceptors>
|
||||
<interceptor name="test" class="com.opensymphony.xwork2.mock.MockInterceptor">
|
||||
<param name="foo">fooDefault</param>
|
||||
</interceptor>
|
||||
|
||||
<interceptor-stack name="defaultStack">
|
||||
<interceptor-ref name="test"/>
|
||||
</interceptor-stack>
|
||||
</interceptors>
|
||||
|
||||
<action name="Foo" class="com.opensymphony.xwork2.SimpleAction">
|
||||
<param name="foo">18</param>
|
||||
<param name="bar">24</param>
|
||||
<result name="success" type="mock"/>
|
||||
<interceptor-ref name="defaultStack"/>
|
||||
</action>
|
||||
</package>
|
||||
</struts>
|
||||
@@ -21,6 +21,7 @@ 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;
|
||||
|
||||
Reference in New Issue
Block a user