Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WW-4636 - File upload error message always in default language #113

Merged
merged 1 commit into from
Nov 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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