/**
* Copyright (c) 2009--2014 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.frontend.struts;
import com.redhat.rhn.common.util.Asserts;
import com.redhat.rhn.common.util.DatePicker;
import com.redhat.rhn.common.util.ServletUtils;
import com.redhat.rhn.common.validator.ValidationMessage;
import com.redhat.rhn.common.validator.ValidatorError;
import com.redhat.rhn.common.validator.ValidatorResult;
import com.redhat.rhn.common.validator.ValidatorWarning;
import com.redhat.rhn.frontend.context.Context;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.DynaActionForm;
import org.apache.struts.upload.FormFile;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* StrutsDelegate defines a set of helper operations for working with the Struts API.
* Implementations should conform to the same design as servlets an actions classes
* in that they should be thread-safe and should not maintain client state.
*
* @version $Rev$
*/
public class StrutsDelegate {
private static final Logger LOG = Logger.getLogger(StrutsDelegate.class);
private static final StrutsDelegate INSTANCE = new StrutsDelegate();
/**
* Retuns an instance of the struts delegate factory
* @return an instance
*/
public static StrutsDelegate getInstance() {
return INSTANCE;
}
protected StrutsDelegate() {
}
/**
* Take an action forward and toss on a form variable.
* @param base Base ActionForward
*
* @param param Parameter to be added to the ActionForward url.
*
* @param value Value of parameter to be added.
*
* @return a new ActionForward with the path of the base appended with the
* param and value.
*/
public ActionForward forwardParam(ActionForward base, String param, String value) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(param, value);
return forwardParams(base, params);
}
/**
* Take an action forward and toss on a set of form variables.
*
* @param base Base ActionForward
*
* @param params Parameters to be added to the ActionForward url.
*
* @return a new ActionForward with the path of the base appended with the
* param and value.
*/
public ActionForward forwardParams(ActionForward base, Map params) {
Asserts.assertNotNull(base, "base");
String newPath = ServletUtils.pathWithParams(base.getPath(), params);
ActionForward af = new ActionForward(newPath, base.getRedirect());
af.setName(base.getName());
return af;
}
/**
* Add a message to an existing set of ActionErrors. Useful to add stuff to
* an already populated ActionErrors instance
* @param msgKey to add
* @param errors to add too
*/
// TODO Write unit tests for addError(String, ActionErrors)
public void addError(String msgKey, ActionErrors errors) {
addError(errors, msgKey, new Object[0]);
}
/**
* Add a message to an existing set of ActionErrors. Useful to add stuff to
* an already populated ActionErrors instance
* @param errors to add too
* @param msgKey to add
* @param params key params
*/
// TODO Write unit tests for addError(String, ActionErrors)
public void addError(ActionErrors errors, String msgKey, Object...params) {
ActionMessages msg = new ActionMessages();
msg.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(msgKey,
params));
errors.add(msg);
}
/**
* Add a UI message to the Request.
* @param msgKey of the string you want to display
* @param req used to store the message in.
*/
public void saveMessage(String msgKey, HttpServletRequest req) {
saveMessage(msgKey, null, req);
}
/**
* Add a UI message to the Request.
* @param msgKey of the string you want to display
* @param params formatted params for the localized message
* @param req used to store the message in.
*/
// TODO Write unit tests for saveMessage(String, String[], HttpServletRequest)
public void saveMessage(String msgKey, String[] params, HttpServletRequest req) {
if (params == null) {
params = new String[0];
}
ActionMessages msg = new ActionMessages();
msg.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage(msgKey, params));
saveMessages(req, msg);
}
/**
* Add messages to the request
* @param request Request where messages will be saved.
* @param messages Messages to be saved.
*/
// TODO Write unit tests for saveMessages(HttpServletRequest, ActionMessages)
public void saveMessages(HttpServletRequest request, ActionMessages messages) {
HttpSession session = request.getSession();
if ((messages == null) || messages.isEmpty()) {
session.removeAttribute(Globals.ERROR_KEY);
session.removeAttribute(Globals.MESSAGE_KEY);
return;
}
String key = Globals.MESSAGE_KEY;
if (messages instanceof ActionErrors) {
key = Globals.ERROR_KEY;
}
ActionMessages newMessages = new ActionMessages();
// Check for existing messages
ActionMessages sessionExisting =
(ActionMessages) session.getAttribute(key);
if (sessionExisting != null) {
newMessages.add(sessionExisting);
}
newMessages.add(messages);
session.setAttribute(key, newMessages);
request.setAttribute(key, newMessages);
}
/**
* Add messages to the request
* @param request Request where messages will be saved.
* @param errors List of ValidatorError objects.
* @param warnings List of ValidatorWarning objects.
*/
public void saveMessages(HttpServletRequest request,
List<ValidatorError> errors,
List<ValidatorWarning> warnings) {
bindMessage(request, Globals.ERROR_KEY, errors, new ActionErrors());
bindMessage(request, Globals.MESSAGE_KEY, warnings, new ActionMessages());
}
/**
* Add messages to the request
* @param request Request where messages will bed saved.
* @param result the validator result object..
*/
public void saveMessages(HttpServletRequest request, ValidatorResult result) {
saveMessages(request, result.getErrors(), result.getWarnings());
}
/**
* Util to get the String file name of a file upload form.
*
* @param form to get the contents from
* @param paramName of the FormFile
* @return String file name of the upload.
*/
public String getFormFileName(DynaActionForm form, String paramName) {
if (form.getDynaClass().getDynaProperty(paramName) == null) {
return "";
}
FormFile f = (FormFile)form.get(paramName);
return f.getFileName();
}
/**
* Util to get the String version of a file upload form. Not useful if the
* upload is binary.
*
* @param form to get the contents from
* @param paramName of the FormFile
* @return String version of the upload.
*/
// TODO Write unit tests for getFormFileString(DynaActionForm, String)
public String getFormFileString(DynaActionForm form, String paramName) {
if (form.getDynaClass().getDynaProperty(paramName) == null) {
return "";
}
FormFile f = (FormFile)form.get(paramName);
return extractString(f);
}
/**
* Util to get the String version of a file upload form. Not useful if the
* upload is binary.
* @param f the formfile to extract data off....
* @return String version of the upload.
*/
public String extractString(FormFile f) {
String retval = null;
try {
if (f != null && f.getFileData() != null) {
String fileString = new String(f.getFileData(), "UTF-8");
if (!StringUtils.isEmpty(fileString)) {
retval = fileString;
}
}
}
catch (UnsupportedEncodingException e) {
LOG.error(e);
throw new RuntimeException(e);
}
catch (FileNotFoundException e) {
LOG.error(e);
throw new RuntimeException(e);
}
catch (IOException e) {
LOG.error(e);
throw new RuntimeException(e);
}
return retval;
}
/**
* Use this for every textarea that we use in our UI. Otherwise you will get ^M
* in your file showing up.
* @param form to fetch from
* @param name of value in form
* @return String without CR in them.
*/
public String getTextAreaValue(DynaActionForm form, String name) {
String value = form.getString(name);
return StringUtils.replaceChars(value, "\r", "");
}
/**
* Reads the earliest date from a form populated by a datepicker.
* Your dyna action picker must either be a struts datePickerForm, or
* possess all of datePickerForm's fields.
* @param form The datePickerForm
* @param name The prefix for the date picker form fields, usually "date"
* @param yearDirection One of DatePicker's year range static variables.
* @return The earliest date to schedule actions.
* @see com.redhat.rhn.common.util.DatePicker
*/
public Date readDatePicker(DynaActionForm form, String name, int yearDirection) {
//use date is not required for date picker forms.
//if it is not there, then that means we should always evaluate the
//date picker. Otherwise, we evaluate if it tells us to do so.
if (!form.getMap().containsKey(DatePicker.USE_DATE) ||
form.get(DatePicker.USE_DATE) == null ||
((Boolean)form.get(DatePicker.USE_DATE)).booleanValue()) {
DatePicker p = getDatePicker(name, yearDirection);
p.readForm(form);
return p.getDate();
}
return new Date();
}
/**
* Writes the values of a date picker form to the <code>requestParams</code>
* for remembering form values across requests.
* Your dyna action picker must either be a struts datePickerForm, or
* possess all of datePickerForm's fields.
* @param requestParams The map to which to copy form fields
* @param form The datePickerForm
* @param name The prefix for the date picker form fields, usually "date"
* @param yearDirection One of DatePicker's year range static variables.
* @see com.redhat.rhn.common.util.DatePicker
*/
public void rememberDatePicker(Map requestParams,
DynaActionForm form, String name, int yearDirection) {
//Write the option use_date field if it is there.
if (form.get(DatePicker.USE_DATE) != null) {
requestParams.put(DatePicker.USE_DATE,
form.get(DatePicker.USE_DATE));
}
//The datepicker itself can write the rest.
DatePicker p = getDatePicker(name, yearDirection);
p.readForm(form);
p.writeToMap(requestParams);
}
/**
* Creates a date picker object with the given name and prepopulates the date
* with values from the given request's parameters. Prepopulates the form with
* these values as well.
* Your dyna action picker must either be a struts datePickerForm, or
* possess all of datePickerForm's fields.
* @param request The request from which to get initial form field values.
* @param form The datePickerForm
* @param name The prefix for the date picker form fields, usually "date"
* @param yearDirection One of DatePicker's year range static variables.
* @return The created and prepopulated date picker object
* @see com.redhat.rhn.common.util.DatePicker
*/
public DatePicker prepopulateDatePicker(HttpServletRequest request, DynaActionForm form,
String name, int yearDirection) {
//Create the date picker.
DatePicker p = getDatePicker(name, yearDirection);
//prepopulate the date for this picker
p.readMap(request.getParameterMap());
//prepopulate the form for this picker
p.writeToForm(form);
if (!StringUtils.isEmpty(request.getParameter(DatePicker.USE_DATE))) {
Boolean preset = Boolean.valueOf(request.getParameter(DatePicker.USE_DATE));
form.set(DatePicker.USE_DATE, preset);
}
else if (form.getMap().containsKey(DatePicker.USE_DATE)) {
form.set(DatePicker.USE_DATE, Boolean.FALSE);
}
request.setAttribute(name, p);
//give back the date picker
return p;
}
private DatePicker getDatePicker(String name, int yearDirection) {
Context ctx = Context.getCurrentContext();
if (ctx == null) {
return new DatePicker(name, TimeZone.getDefault(), Locale.getDefault(),
yearDirection);
}
return new DatePicker(name, ctx.getTimezone(), ctx.getLocale(), yearDirection);
}
private void bindMessage(HttpServletRequest request, String key,
List<? extends ValidationMessage> messages,
ActionMessages actMsgs) {
if (!messages.isEmpty()) {
for (ValidationMessage msg : messages) {
actMsgs.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage(msg.getKey(), msg.getValues()));
}
ActionMessages requestMsg = (ActionMessages)request.
getAttribute(key);
if (requestMsg == null) {
requestMsg = new ActionMessages();
}
requestMsg.add(actMsgs);
if (requestMsg.isEmpty()) {
request.removeAttribute(key);
}
else {
request.setAttribute(key, requestMsg);
request.getSession().setAttribute(key, requestMsg);
}
}
}
}