package org.gbif.ipt.action;
import org.gbif.ipt.config.AppConfig;
import org.gbif.ipt.config.Constants;
import org.gbif.ipt.model.Ipt;
import org.gbif.ipt.model.Organisation;
import org.gbif.ipt.model.User;
import org.gbif.ipt.service.admin.RegistrationManager;
import org.gbif.ipt.struts2.SimpleTextProvider;
import org.gbif.ws.util.XSSUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
/**
* The base of all IPT actions. This handles conditions such as menu items, a custom text provider, sessions, currently
* logged in user, and hosting organization information.
*/
public class BaseAction extends ActionSupport implements SessionAware, Preparable, ServletRequestAware {
// logging
private static final Logger LOG = Logger.getLogger(BaseAction.class);
private static final long serialVersionUID = -2330991910834399442L;
public static final String NOT_MODIFIED = "304";
public static final String NOT_FOUND = "404";
public static final String NOT_ALLOWED = "401";
public static final String NOT_ALLOWED_MANAGER = "401-manager";
public static final String HOME = "home";
public static final String LOCKED = "locked";
public static final String NOT_AVAILABLE = "410";
protected List<String> warnings = new ArrayList<String>();
protected Map<String, Object> session;
protected HttpServletRequest req;
// a generic identifier for loading an object BEFORE the param interceptor sets values
protected String id;
protected SimpleTextProvider textProvider;
protected AppConfig cfg;
protected RegistrationManager registrationManager;
@Inject
public BaseAction(SimpleTextProvider textProvider, AppConfig cfg, RegistrationManager registrationManager) {
this.textProvider = textProvider;
this.cfg = cfg;
this.registrationManager = registrationManager;
}
/**
* Adds an exception message, if not null, to the action warnings.
*
* @param e the exception from which the message is taken
*/
protected void addActionExceptionWarning(Exception e) {
String msg = e.getMessage();
if (msg != null) {
warnings.add(msg);
}
}
/**
* Adds a warning similar to the action errors to the user UI, but does not interact with the validation aware
* workflow interceptor, therefore no changes to the result name of the action are expected.
* This is the way to present user warnings/errors others than for form validation.
* If you want form validation with the workflow interceptor, please {@link #addActionError(String)} instead.
*/
public void addActionWarning(String anErrorMessage) {
warnings.add(anErrorMessage);
}
public void addActionWarning(String anErrorMessage, Exception e) {
warnings.add(anErrorMessage);
addActionExceptionWarning(e);
}
/**
* Return a list of action warning strings.
*
* @return list of action warning strings.
*/
public List<String> getActionWarnings() {
return warnings;
}
/**
* Easy access to the configured application root for simple use in templates.
*/
public String getBase() {
return cfg.getBaseUrl();
}
public String getBaseURL() {
return cfg.getBaseUrl();
}
public AppConfig getCfg() {
return cfg;
}
/**
* Return the currently logged in (session) user.
*
* @return the currently logged in (session) user or null if not logged in
*/
public User getCurrentUser() {
User u = null;
try {
u = (User) session.get(Constants.SESSION_USER);
} catch (Exception e) {
LOG.debug("A problem occurred retrieving current user. This can happen if the session is not yet opened");
}
return u;
}
public String getId() {
return id;
}
/**
* Return the locale language code.
* Struts2 manages the locale in the session param WW_TRANS_I18N_LOCALE via the i18n interceptor.
*
* @return locale language code, defaulting to "en" if locale was null or if locale did not match a local
* ResourceBundle
*/
public String getLocaleLanguage() {
if (getLocale() != null) {
String requestedLocale = Strings.emptyToNull(getLocale().getLanguage());
if (requestedLocale != null && !XSSUtil.containsXSS(requestedLocale)) {
ResourceBundle resourceBundle = textProvider.getTexts(new Locale(requestedLocale));
return resourceBundle.getLocale().getLanguage();
}
}
return Locale.ENGLISH.getLanguage();
}
@Override
public String getText(String key) {
return textProvider.getText(this, key, null, new String[0]);
}
@Override
public String getText(String key, List args) {
return textProvider.getText(this, key, null, args);
}
@Override
public String getText(String key, String defaultValue) {
return textProvider.getText(this, key, defaultValue, new String[0]);
}
@Override
public String getText(String key, String defaultValue, List args) {
return textProvider.getText(this, key, defaultValue, args);
}
@Override
public String getText(String key, String defaultValue, List args, ValueStack stack) {
return textProvider.getText(this, key, defaultValue, args);
}
@Override
public String getText(String key, String defaultValue, String obj) {
return textProvider.getText(this, key, defaultValue, new String[0]);
}
@Override
public String getText(String key, String defaultValue, String[] args) {
return textProvider.getText(this, key, defaultValue, args);
}
@Override
public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
return textProvider.getText(this, key, defaultValue, args);
}
@Override
public String getText(String key, String[] args) {
return textProvider.getText(this, key, null, args);
}
@Override
public ResourceBundle getTexts() {
return textProvider.getTexts(getLocale());
}
@Override
public ResourceBundle getTexts(String bundleName) {
return textProvider.getTexts(bundleName, getLocale());
}
public String getTextWithDynamicArgs(String key, String... args) {
return textProvider.getText(this, key, null, args);
}
public List<String> getWarnings() {
return warnings;
}
public boolean isAdminRights() {
User user = getCurrentUser();
if (user != null && user.hasAdminRights()) {
return true;
}
return false;
}
protected boolean isHttpPost() {
if (req.getMethod().equalsIgnoreCase("post")) {
return true;
}
return false;
}
/**
* Determine whether some user is logged in or not.
*
* @return true if some user is logged in or false otherwise
*/
public boolean isLoggedIn() {
return getCurrentUser() != null;
}
public boolean isManagerRights() {
User user = getCurrentUser();
if (user != null && user.hasManagerRights()) {
return true;
}
return false;
}
/**
* Override this method if you need to load entities based on the id value before the PARAM interceptor is called.
* You can also use this method to prepare a new, empty instance in case no id was provided. If the id parameter
* alone
* is not sufficient to load your entities, you can access the request object directly like we do here and read any
* other parameter you need to prepare the action for the param phase.
*/
public void prepare() {
// see if an id was provided in the request.
// we dont use the PARAM - PREPARE - PARAM interceptor stack
// so we investigate the request object directly BEFORE the param interceptor is called
// this allows us to load any existing instances that should be modified
id = StringUtils.trimToNull(req.getParameter("id"));
}
public void setServletRequest(HttpServletRequest req) {
this.req = req;
}
public void setSession(Map<String, Object> session) {
this.session = session;
// always keep sth in the session otherwise the session is not maintained and e.g. the message redirect interceptor
// doesnt work
if (session.isEmpty()) {
session.put("-", true);
}
}
/**
* Utility to compare 2 objects for comparison when both converted to strings useful to compare if a submitted value
* is the same as the persisted value.
*
* @return true only if o1.equals(o2)
*/
protected boolean stringEquals(Object o1, Object o2) {
// both null
if (o1 == null && o2 == null) {
return true;
}
if (o1 != null && o2 != null) {
return o1.toString().equals(o2.toString());
}
return false;
}
/**
* @return the registered IPT instance, or null if the IPT hasn't been registered yet.
*/
public Ipt getRegisteredIpt() {
return registrationManager.getIpt();
}
/**
* @return default organisation named "No organisation" or null if it doesn't exist
*/
@Nullable
public Organisation getDefaultOrganisation() {
Organisation noOrganisation = registrationManager.get(Constants.DEFAULT_ORG_KEY);
return (noOrganisation == null) ? null : noOrganisation;
}
}