blob: 9fdc74e3d980b85da97775937ad7151f4a3daed1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.roller.weblogger.ui.struts2.util;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.roller.weblogger.business.UserManager;
import org.apache.roller.weblogger.business.WebloggerFactory;
import org.apache.roller.weblogger.config.WebloggerConfig;
import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
import org.apache.roller.weblogger.pojos.GlobalPermission;
import org.apache.roller.weblogger.pojos.User;
import org.apache.roller.weblogger.pojos.Weblog;
import org.apache.roller.weblogger.pojos.WeblogPermission;
import org.apache.roller.weblogger.ui.core.util.menu.Menu;
import org.apache.roller.weblogger.ui.core.util.menu.MenuHelper;
import org.apache.struts2.interceptor.RequestAware;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Extends the Struts2 ActionSupport class to add in support for handling an
* error and status success. Other actions extending this one only need to
* calle setError() and setSuccess() accordingly.
*
* NOTE: as a small convenience, all errors and messages are assumed to be keys
* which point to a success in a resource bundle, so we automatically call
* getText(key) on the param passed into setError() and setSuccess().
*/
public abstract class UIAction extends ActionSupport
implements UIActionPreparable, UISecurityEnforced, RequestAware {
// a result that sends the user to an access denied warning
public static final String DENIED = "access-denied";
// a common result name used to indicate the result should list some data
public static final String LIST = "list";
// a result for a cancel.
public static final String CANCEL = "cancel";
// the authenticated user accessing this action, or null if client is not logged in
private User authenticatedUser = null;
// the weblog this action is intended to work on, or null if no weblog specified
private Weblog actionWeblog = null;
// the weblog handle of the action weblog
private String weblog = null;
// action name (used by tabbed menu utility)
protected String actionName = null;
// the name of the menu this action wants to show, or null for no menu
protected String desiredMenu = null;
// page title, called by some Tiles JSPs (e.g., tiles-simplepage.jsp)
protected String pageTitle = null;
protected String salt = null;
public void myPrepare() {
// no-op
}
public void setRequest(Map<String, Object> map) {
this.salt = (String) map.get("salt");
}
public String getSalt() {
return salt;
}
/**
* Necessary to avoid showing up "Error setting expression 'salt' with value ...".
* See also https://issues.apache.org/jira/browse/ROL-2068
* @param salt previous salt
*/
public void setSalt(String salt) {
// no-op
}
// default action permissions, user is required
public boolean isUserRequired() {
return true;
}
// default action permissions, weblog is required
public boolean isWeblogRequired() {
return true;
}
// Default is ADMIN for safety, if a subclasser forgets to override this only admins can use.
public List<String> requiredWeblogPermissionActions() {
return Collections.singletonList(WeblogPermission.ADMIN);
}
public List<String> requiredGlobalPermissionActions() {
return Collections.singletonList(GlobalPermission.LOGIN);
}
// convenient way to tell if user being dealt with is an admin
public boolean isUserIsAdmin() {
try {
GlobalPermission adminPerm = new GlobalPermission(
Collections.singletonList(GlobalPermission.ADMIN));
UserManager umgr = WebloggerFactory.getWeblogger().getUserManager();
return umgr.checkPermission(adminPerm, getAuthenticatedUser());
} catch (Exception e) {}
return false;
}
/**
* Cancel.
*
* @return "CANCEL" string constant.
*/
public String cancel() {
return CANCEL;
}
public String getSiteURL() {
return WebloggerRuntimeConfig.getRelativeContextURL();
}
public String getAbsoluteSiteURL() {
return WebloggerRuntimeConfig.getAbsoluteContextURL();
}
public String getProp(String key) {
// first try static config
String value = WebloggerConfig.getProperty(key);
if(value == null) {
value = WebloggerRuntimeConfig.getProperty(key);
}
return (value == null) ? key : value;
}
public boolean getBooleanProp(String key) {
// first try static config
String value = WebloggerConfig.getProperty(key);
if(value == null) {
value = WebloggerRuntimeConfig.getProperty(key);
}
return (value == null) ? false : Boolean.valueOf(value);
}
public int getIntProp(String key) {
// first try static config
String value = WebloggerConfig.getProperty(key);
if(value == null) {
value = WebloggerRuntimeConfig.getProperty(key);
}
return (value == null) ? 0 : Integer.valueOf(value);
}
@Override
public String getText(String aTextName) {
return super.getText(cleanTextKey(aTextName));
}
@Override
public String getText(String aTextName, String defaultValue) {
return super.getText(cleanTextKey(aTextName), cleanTextKey(defaultValue));
}
@Override
public String getText(String aTextName, String defaultValue, String obj) {
return super.getText(cleanTextKey(aTextName), cleanTextKey(defaultValue), cleanTextArg(obj));
}
@Override
public String getText(String aTextName, List<?> args) {
List<Object> cleanedArgs = new ArrayList<Object>(args.size());
for (Object el : args) {
cleanedArgs.add(el instanceof String ? cleanTextArg((String) el) : el);
}
return super.getText(cleanTextKey(aTextName), cleanedArgs);
}
@Override
public String getText(String key, String[] args) {
String[] cleanedArgs = new String[args.length];
for (int i = 0; i < args.length; ++i) {
cleanedArgs[i] = cleanTextArg(args[i]);
}
return super.getText(cleanTextKey(key), cleanedArgs);
}
@Override
public String getText(String aTextName, String defaultValue, List<?> args) {
List<Object> cleanedArgs = new ArrayList<Object>(args.size());
for (Object el : args) {
cleanedArgs.add(el instanceof String ? cleanTextArg((String) el) : el);
}
return super.getText(cleanTextKey(aTextName), cleanTextKey(defaultValue), cleanedArgs);
}
@Override
public String getText(String key, String defaultValue, String[] args) {
String[] cleanedArgs = new String[args.length];
for (int i = 0; i < args.length; ++i) {
cleanedArgs[i] = cleanTextArg(args[i]);
}
return super.getText(cleanTextKey(key), cleanTextKey(defaultValue), cleanedArgs);
}
public void addError(String errorKey) {
addActionError(getText(errorKey));
}
public void addError(String errorKey, String param) {
addActionError(getText(errorKey, errorKey, param));
}
public void addError(String errorKey, List args) {
addActionError(getText(errorKey, args));
}
/**
* This simply returns the result of hasActionErrors() but we need it
* because without it you can't easily check if there were errors since
* you can't call a hasXXX() method via OGNL.
*/
public boolean errorsExist() {
return hasActionErrors();
}
public void addMessage(String msgKey) {
addActionMessage(getText(msgKey));
}
public void addMessage(String msgKey, String param) {
addActionMessage(getText(msgKey, msgKey, param));
}
public void addMessage(String msgKey, List args) {
addActionMessage(getText(msgKey, args));
}
/**
* This simply returns the result of hasActionMessages() but we need it
* because without it you can't easily check if there were messages since
* you can't call a hasXXX() method via OGNL.
*/
public boolean messagesExist() {
return hasActionMessages();
}
public User getAuthenticatedUser() {
return authenticatedUser;
}
public void setAuthenticatedUser(User authenticatedUser) {
this.authenticatedUser = authenticatedUser;
}
public Weblog getActionWeblog() {
return actionWeblog;
}
public void setActionWeblog(Weblog workingWeblog) {
this.actionWeblog = workingWeblog;
}
public String getWeblog() {
return weblog;
}
public void setWeblog(String weblog) {
this.weblog = weblog;
}
public String getPageTitle() {
return getText(pageTitle);
}
public void setPageTitle(String pageTitle) {
// disabled by default as it causes page titles not
// to update on chain actions defined in struts.xml
// override in subclasses where you want this to occur.
// this.pageTitle = pageTitle;
}
public String getActionName() {
return this.actionName;
}
public void setActionName(String actionName) {
this.actionName = actionName;
}
public String getDesiredMenu() {
return desiredMenu;
}
public void setDesiredMenu(String desiredMenu) {
this.desiredMenu = desiredMenu;
}
public Menu getMenu() {
return MenuHelper.getMenu(getDesiredMenu(), getActionName(), getAuthenticatedUser(), getActionWeblog());
}
public String getShortDateFormat() {
DateFormat sdf = DateFormat.getDateInstance(
DateFormat.SHORT, getLocale());
if (sdf instanceof SimpleDateFormat) {
return ((SimpleDateFormat)sdf).toPattern();
}
return "yyyy/MM/dd";
}
public String getMediumDateFormat() {
DateFormat sdf = DateFormat.getDateInstance(
DateFormat.MEDIUM, getLocale());
if (sdf instanceof SimpleDateFormat) {
return ((SimpleDateFormat)sdf).toPattern();
}
return "MMM dd, yyyy";
}
public List getLocalesList() {
return UIUtils.getLocales();
}
public List getTimeZonesList() {
return UIUtils.getTimeZones();
}
public List getHoursList() {
List ret = new ArrayList();
for (int i=0; i<24; i++) {
ret.add(i);
}
return ret;
}
public List getMinutesList() {
List ret = new ArrayList();
for (int i=0; i<60; i++) {
ret.add(i);
}
return ret;
}
public List getSecondsList() {
return getMinutesList();
}
public List<KeyValueObject> getCommentDaysList() {
List<KeyValueObject> opts = new ArrayList<>();
opts.add(new KeyValueObject(-1, getText("weblogEdit.commentsNotAllowed")));
opts.add(new KeyValueObject(0, getText("weblogEdit.unlimitedCommentDays")));
opts.add(new KeyValueObject(3, getText("weblogEdit.days3")));
opts.add(new KeyValueObject(7, getText("weblogEdit.days7")));
opts.add(new KeyValueObject(14, getText("weblogEdit.days14")));
opts.add(new KeyValueObject(30, getText("weblogEdit.days30")));
opts.add(new KeyValueObject(60, getText("weblogEdit.days60")));
opts.add(new KeyValueObject(90, getText("weblogEdit.days90")));
return opts;
}
private static String cleanExpressions(String s) {
return (s == null || s.contains("${") || s.contains("%{")) ? "" : s;
}
public static String cleanTextKey(String s) {
if (s == null || s.isEmpty()) {
return s;
}
// escape HTML
return StringEscapeUtils.escapeHtml4(cleanExpressions(s));
}
public static String cleanTextArg(String s) {
if (s == null || s.isEmpty()) {
return s;
}
return StringEscapeUtils.escapeHtml4(s);
}
}