Skip to content

Commit

Permalink
WW-4636 - File upload error message always in default language
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksandr-m committed Oct 15, 2016
1 parent 1af1887 commit 835cc7c
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 22 deletions.
104 changes: 104 additions & 0 deletions core/src/main/java/org/apache/struts2/dispatcher/LocalizedMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.struts2.dispatcher;

import java.util.Arrays;

public class LocalizedMessage {
private final Class clazz;
private final String textKey;
private final String defaultMessage;
private final Object[] args;

public LocalizedMessage(Class clazz, String textKey, String defaultMessage, Object[] args) {
this.clazz = clazz;
this.textKey = textKey;
this.defaultMessage = defaultMessage;
this.args = args;
}

public Class getClazz() {
return clazz;
}

public String getTextKey() {
return textKey;
}

public String getDefaultMessage() {
return defaultMessage;
}

public Object[] getArgs() {
return args;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(args);
result = prime * result + ((clazz == null) ? 0 : clazz.hashCode());
result = prime * result + ((defaultMessage == null) ? 0 : defaultMessage.hashCode());
result = prime * result + ((textKey == null) ? 0 : textKey.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
LocalizedMessage other = (LocalizedMessage) obj;
if (!Arrays.equals(args, other.args)) {
return false;
}
if (clazz == null) {
if (other.clazz != null) {
return false;
}
} else if (!clazz.equals(other.clazz)) {
return false;
}
if (defaultMessage == null) {
if (other.defaultMessage != null) {
return false;
}
} else if (!defaultMessage.equals(other.defaultMessage)) {
return false;
}
if (textKey == null) {
if (other.textKey != null) {
return false;
}
} else if (!textKey.equals(other.textKey)) {
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.LocalizedMessage;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
Expand All @@ -56,7 +57,7 @@ public class JakartaMultiPartRequest implements MultiPartRequest {
protected Map<String, List<String>> params = new HashMap<>();

// any errors while processing this request
protected List<String> errors = new ArrayList<>();
protected List<LocalizedMessage> errors = new ArrayList<>();

protected long maxSize;
private Locale defaultLocale = Locale.ENGLISH;
Expand Down Expand Up @@ -85,7 +86,7 @@ public void parse(HttpServletRequest request, String saveDir) throws IOException
processUpload(request, saveDir);
} catch (FileUploadException e) {
LOG.warn("Request exceeded size limit!", e);
String errorMessage = null;
LocalizedMessage errorMessage = null;

if(e instanceof FileUploadBase.SizeLimitExceededException) {
FileUploadBase.SizeLimitExceededException ex = (FileUploadBase.SizeLimitExceededException) e;
Expand All @@ -99,7 +100,7 @@ public void parse(HttpServletRequest request, String saveDir) throws IOException
}
} catch (Exception e) {
LOG.warn("Unable to parse request", e);
String errorMessage = buildErrorMessage(e, new Object[]{});
LocalizedMessage errorMessage = buildErrorMessage(e, new Object[]{});
if (!errors.contains(errorMessage)) {
errors.add(errorMessage);
}
Expand All @@ -112,10 +113,10 @@ protected void setLocale(HttpServletRequest request) {
}
}

protected String buildErrorMessage(Throwable e, Object[] args) {
protected LocalizedMessage buildErrorMessage(Throwable e, Object[] args) {
String errorKey = "struts.messages.upload.error." + e.getClass().getSimpleName();
LOG.debug("Preparing error message for key: [{}]", errorKey);
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
return new LocalizedMessage(this.getClass(), errorKey, e.getMessage(), args);
}

protected void processUpload(HttpServletRequest request, String saveDir) throws FileUploadException, UnsupportedEncodingException {
Expand Down Expand Up @@ -315,7 +316,7 @@ public String[] getParameterValues(String name) {
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getErrors()
*/
public List<String> getErrors() {
public List<LocalizedMessage> getErrors() {
return errors;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.LocalizedMessage;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
Expand Down Expand Up @@ -48,7 +49,7 @@ public class JakartaStreamMultiPartRequest implements MultiPartRequest {
/**
* Internal list of raised errors to be passed to the the Struts2 framework.
*/
private List<String> errors = new ArrayList<>();
private List<LocalizedMessage> errors = new ArrayList<>();

/**
* Internal list of non-critical messages to be passed to the Struts2 framework.
Expand Down Expand Up @@ -130,7 +131,7 @@ public String[] getContentType(String fieldName) {
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getErrors()
*/
public List<String> getErrors() {
public List<LocalizedMessage> getErrors() {
return errors;
}

Expand Down Expand Up @@ -239,7 +240,7 @@ public void parse(HttpServletRequest request, String saveDir) throws IOException
processUpload(request, saveDir);
} catch (Exception e) {
LOG.warn("Error occurred during parsing of multi part request", e);
String errorMessage = buildErrorMessage(e, new Object[]{});
LocalizedMessage errorMessage = buildErrorMessage(e, new Object[]{});
if (!errors.contains(errorMessage)) {
errors.add(errorMessage);
}
Expand Down Expand Up @@ -349,7 +350,7 @@ private long getRequestSize(HttpServletRequest request) {
private void addFileSkippedError(String fileName, HttpServletRequest request) {
String exceptionMessage = "Skipped file " + fileName + "; request size limit exceeded.";
FileSizeLimitExceededException exception = new FileUploadBase.FileSizeLimitExceededException(exceptionMessage, getRequestSize(request), maxSize);
String message = buildErrorMessage(exception, new Object[]{fileName, getRequestSize(request), maxSize});
LocalizedMessage message = buildErrorMessage(exception, new Object[]{fileName, getRequestSize(request), maxSize});
if (!errors.contains(message)) {
errors.add(message);
}
Expand Down Expand Up @@ -507,10 +508,10 @@ private String getCanonicalName(String fileName) {
* @param args arguments
* @return error message
*/
private String buildErrorMessage(Throwable e, Object[] args) {
private LocalizedMessage buildErrorMessage(Throwable e, Object[] args) {
String errorKey = "struts.message.upload.error." + e.getClass().getSimpleName();
LOG.debug("Preparing error message for key: [{}]", errorKey);
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
return new LocalizedMessage(this.getClass(), errorKey, e.getMessage(), args);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
package org.apache.struts2.dispatcher.multipart;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.dispatcher.LocalizedMessage;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
Expand Down Expand Up @@ -112,7 +115,7 @@ public interface MultiPartRequest {
*
* @return a list of Strings that represent various errors during parsing
*/
public List<String> getErrors();
public List<LocalizedMessage> getErrors();

/**
* Cleans up all uploaded file, should be called at the end of request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.dispatcher.LocalizedMessage;
import org.apache.struts2.dispatcher.StrutsRequestWrapper;

import javax.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -60,7 +61,7 @@ public class MultiPartRequestWrapper extends StrutsRequestWrapper {

protected static final Logger LOG = LogManager.getLogger(MultiPartRequestWrapper.class);

private Collection<String> errors;
private Collection<LocalizedMessage> errors;
private MultiPartRequest multi;
private Locale defaultLocale = Locale.ENGLISH;

Expand All @@ -83,7 +84,7 @@ public MultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletReq
setLocale(request);
try {
multi.parse(request, saveDir);
for (String error : multi.getErrors()) {
for (LocalizedMessage error : multi.getErrors()) {
addError(error);
}
} catch (IOException e) {
Expand All @@ -102,10 +103,10 @@ protected void setLocale(HttpServletRequest request) {
}
}

protected String buildErrorMessage(Throwable e, Object[] args) {
protected LocalizedMessage buildErrorMessage(Throwable e, Object[] args) {
String errorKey = "struts.messages.upload.error." + e.getClass().getSimpleName();
LOG.debug("Preparing error message for key: [{}]", errorKey);
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
return new LocalizedMessage(this.getClass(), errorKey, e.getMessage(), args);
}

/**
Expand Down Expand Up @@ -234,7 +235,7 @@ public boolean hasErrors() {
*
* @return the error Collection.
*/
public Collection<String> getErrors() {
public Collection<LocalizedMessage> getErrors() {
return errors;
}

Expand All @@ -243,7 +244,7 @@ public Collection<String> getErrors() {
*
* @param anErrorMessage the error message to report.
*/
protected void addError(String anErrorMessage) {
protected void addError(LocalizedMessage anErrorMessage) {
if (!errors.contains(anErrorMessage)) {
errors.add(anErrorMessage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
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.LocalizedMessage;
import org.apache.struts2.dispatcher.Parameter;
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
import org.apache.struts2.util.ContentTypeMatcher;
Expand Down Expand Up @@ -256,9 +258,9 @@ public String intercept(ActionInvocation invocation) throws Exception {
MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;

if (multiWrapper.hasErrors()) {
for (String error : multiWrapper.getErrors()) {
for (LocalizedMessage error : multiWrapper.getErrors()) {
if (validation != null) {
validation.addActionError(error);
validation.addActionError(LocalizedTextUtil.findText(error.getClazz(), error.getTextKey(), ActionContext.getContext().getLocale(), error.getDefaultMessage(), error.getArgs()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;


Expand Down Expand Up @@ -335,6 +337,44 @@ public void testMultipleAccept() throws Exception {
assertNotNull("test1.html", fileRealFilenames[0]);
}

public void testMultipartRequestLocalizedError() throws Exception {
MockHttpServletRequest req = new MockHttpServletRequest();
req.setCharacterEncoding("text/html");
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 FileUploadInterceptor" +
"\r\n" +
"-----1234--\r\n");
req.setContent(content.getBytes("US-ASCII"));

MyFileupAction action = new MyFileupAction();

MockActionInvocation mai = new MockActionInvocation();
mai.setAction(action);
mai.setResultCode("success");
mai.setInvocationContext(ActionContext.getContext());
Map<String, Object> param = new HashMap<>();
ActionContext.getContext().setParameters(HttpParameters.create(param).build());
// set German locale
ActionContext.getContext().setLocale(Locale.GERMAN);
ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequest(req, 10));

interceptor.intercept(mai);

assertTrue(action.hasActionErrors());

Collection<String> errors = action.getActionErrors();
assertEquals(1, errors.size());
String msg = errors.iterator().next();
// the error message should contain at least this test
assertTrue(msg.startsWith("Der Request übertraf die maximal erlaubte Größe"));
}

private String encodeTextFile(String bondary, String endline, String name, String filename, String contentType, String content) {
final StringBuilder sb = new StringBuilder(64);
sb.append(endline);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.apache.logging.log4j.LogManager;
import http.utils.multipartrequest.ServletMultipartRequest;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.LocalizedMessage;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
Expand Down Expand Up @@ -131,7 +132,7 @@ public String[] getParameterValues(String name) {
return values.toArray(new String[values.size()]);
}

public List<String> getErrors() {
public List<LocalizedMessage> getErrors() {
return Collections.emptyList();
}

Expand Down

0 comments on commit 835cc7c

Please sign in to comment.