/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software GmbH, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.workplace;
import org.opencms.db.CmsDbEntryNotFoundException;
import org.opencms.db.CmsUserSettings;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsRequestContext;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.CmsUser;
import org.opencms.i18n.CmsEncoder;
import org.opencms.i18n.CmsMessages;
import org.opencms.i18n.CmsMultiMessages;
import org.opencms.jsp.CmsJspActionElement;
import org.opencms.lock.CmsLock;
import org.opencms.lock.CmsLockType;
import org.opencms.main.CmsBroadcast;
import org.opencms.main.CmsContextInfo;
import org.opencms.main.CmsException;
import org.opencms.main.CmsIllegalStateException;
import org.opencms.main.CmsLog;
import org.opencms.main.CmsSessionInfo;
import org.opencms.main.OpenCms;
import org.opencms.security.CmsPermissionSet;
import org.opencms.security.CmsRole;
import org.opencms.security.CmsRoleViolationException;
import org.opencms.site.CmsSite;
import org.opencms.site.CmsSiteManagerImpl;
import org.opencms.util.CmsMacroResolver;
import org.opencms.util.CmsRequestUtil;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import org.opencms.workplace.help.CmsHelpTemplateBean;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.PageContext;
import org.apache.commons.collections.Buffer;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.logging.Log;
/**
* Master class for the JSP based workplace which provides default methods and
* session handling for all JSP workplace classes.<p>
*
* @since 6.0.0
*/
public abstract class CmsWorkplace {
/** The debug flag. */
public static final boolean DEBUG = false;
/** Parameter for the default locale. */
public static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
/** Parameter for the default language. */
public static final String DEFAULT_LANGUAGE = DEFAULT_LOCALE.getLanguage();
/** Helper variable to deliver the html end part. */
public static final int HTML_END = 1;
/** Helper variable to deliver the html start part. */
public static final int HTML_START = 0;
/** The request parameter for the workplace project selection. */
public static final String PARAM_WP_EXPLORER_RESOURCE = "wpExplorerResource";
/** The request parameter for the workplace project selection. */
public static final String PARAM_WP_PROJECT = "wpProject";
/** The request parameter for the workplace site selection. */
public static final String PARAM_WP_SITE = "wpSite";
/** Path for file type icons relative to the resources folder. */
public static final String RES_PATH_FILETYPES = "filetypes/";
/** Path to system folder. */
public static final String VFS_PATH_SYSTEM = "/system/";
/** Path to the workplace. */
public static final String VFS_PATH_WORKPLACE = VFS_PATH_SYSTEM + "workplace/";
/** Constant for the JSP dialogs path. */
public static final String PATH_DIALOGS = VFS_PATH_WORKPLACE + "commons/";
/** Constant for the JSP workplace path. */
public static final String PATH_WORKPLACE = VFS_PATH_WORKPLACE;
/** Path to exported system image folder. */
public static final String RFS_PATH_RESOURCES = "/resources/";
/** Directory name of content default_bodies folder. */
public static final String VFS_DIR_DEFAULTBODIES = "default_bodies/";
/** Directory name of content templates folder. */
public static final String VFS_DIR_TEMPLATES = "templates/";
/** Path to commons. */
public static final String VFS_PATH_COMMONS = VFS_PATH_WORKPLACE + "commons/";
/** Path to the workplace editors. */
public static final String VFS_PATH_EDITORS = VFS_PATH_WORKPLACE + "editors/";
/** Path to the galleries. */
public static final String VFS_PATH_GALLERIES = VFS_PATH_SYSTEM + "galleries/";
/** Path to locales. */
public static final String VFS_PATH_LOCALES = VFS_PATH_WORKPLACE + "locales/";
/** Path to modules folder. */
public static final String VFS_PATH_MODULES = VFS_PATH_SYSTEM + "modules/";
/** Path to system image folder. */
public static final String VFS_PATH_RESOURCES = VFS_PATH_WORKPLACE + "resources/";
/** Path to workplace views. */
public static final String VFS_PATH_VIEWS = VFS_PATH_WORKPLACE + "views/";
/** Constant for the JSP explorer filelist file. */
public static final String FILE_EXPLORER_FILELIST = VFS_PATH_VIEWS + "explorer/explorer_files.jsp";
/** Constant for the JSP common files (e.g. error page) path. */
public static final String DIALOG_PATH_COMMON = PATH_DIALOGS + "includes/";
/** Constant for the JSP common close dialog page. */
public static final String FILE_DIALOG_CLOSE = DIALOG_PATH_COMMON + "closedialog.jsp";
/** Constant for the JSP common confirmation dialog. */
public static final String FILE_DIALOG_SCREEN_CONFIRM = DIALOG_PATH_COMMON + "confirmation.jsp";
/** Constant for the JSP common error dialog. */
public static final String FILE_DIALOG_SCREEN_ERROR = DIALOG_PATH_COMMON + "error.jsp";
/** Constant for the JSP common error dialog. */
public static final String FILE_DIALOG_SCREEN_ERRORPAGE = DIALOG_PATH_COMMON + "errorpage.jsp";
/** Constant for the JSP common wait screen. */
public static final String FILE_DIALOG_SCREEN_WAIT = DIALOG_PATH_COMMON + "wait.jsp";
/** Constant for the JSP common report page. */
public static final String FILE_REPORT_OUTPUT = DIALOG_PATH_COMMON + "report.jsp";
/** Constant for the direct edit view JSP. */
public static final String VIEW_DIRECT_EDIT = VFS_PATH_VIEWS + "explorer/directEdit.jsp";
/** Constant for the direct edit view JSP. */
public static final String VIEW_WORKPLACE = VFS_PATH_VIEWS + "explorer/explorer_fs.jsp";
/** Key name for the request attribute to indicate a multipart request was already parsed. */
protected static final String REQUEST_ATTRIBUTE_MULTIPART = "__CmsWorkplace.MULTIPART";
/** Key name for the request attribute to reload the folder tree view. */
protected static final String REQUEST_ATTRIBUTE_RELOADTREE = "__CmsWorkplace.RELOADTREE";
/** Key name for the session workplace class. */
protected static final String SESSION_WORKPLACE_CLASS = "__CmsWorkplace.WORKPLACE_CLASS";
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(CmsWorkplace.class);
/** The link to the explorer file list (cached for performance reasons). */
private static String m_file_explorer_filelist;
/** The URI to the skin resources (cached for performance reasons). */
private static String m_skinUri;
/** The URI to the stylesheet resources (cached for performance reasons). */
private static String m_styleUri;
/** The current users OpenCms context. */
private CmsObject m_cms;
/** Helper variable to store the id of the current project. */
private CmsUUID m_currentProjectId;
/** Flag for indicating that request forwarded was. */
private boolean m_forwarded;
/** The current JSP action element. */
private CmsJspActionElement m_jsp;
/** The macro resolver, this is cached to avoid multiple instance generation. */
private CmsMacroResolver m_macroResolver;
/** The currently used message bundle. */
private CmsMultiMessages m_messages;
/** The list of multi part file items (if available). */
private List<FileItem> m_multiPartFileItems;
/** The map of parameters read from the current request. */
private Map<String, String[]> m_parameterMap;
/** The current resource URI. */
private String m_resourceUri;
/** The current OpenCms users http session. */
private HttpSession m_session;
/** The current OpenCms users workplace settings. */
private CmsWorkplaceSettings m_settings;
/**
* Public constructor.<p>
*
* @param jsp the initialized JSP context
*/
public CmsWorkplace(CmsJspActionElement jsp) {
initWorkplaceMembers(jsp);
}
/**
* Public constructor with JSP variables.<p>
*
* @param context the JSP page context
* @param req the JSP request
* @param res the JSP response
*/
public CmsWorkplace(PageContext context, HttpServletRequest req, HttpServletResponse res) {
this(new CmsJspActionElement(context, req, res));
}
/**
* Generates a html select box out of the provided values.<p>
*
* @param parameters a string that will be inserted into the initial select tag,
* if null no parameters will be inserted
* @param options the options
* @param values the option values, if null the select will have no value attributes
* @param selected the index of the pre-selected option, if -1 no option is pre-selected
* @param useLineFeed if true, adds some formatting "\n" to the output String
* @return a String representing a html select box
*/
public static String buildSelect(
String parameters,
List<String> options,
List<String> values,
int selected,
boolean useLineFeed) {
StringBuffer result = new StringBuffer(1024);
result.append("<select ");
if (parameters != null) {
result.append(parameters);
}
result.append(">");
if (useLineFeed) {
result.append("\n");
}
int length = options.size();
String value = null;
for (int i = 0; i < length; i++) {
if (values != null) {
try {
value = values.get(i);
} catch (Exception e) {
// can usually be ignored
if (LOG.isInfoEnabled()) {
LOG.info(e.getLocalizedMessage());
}
// lists are not properly initialized, just don't use the value
value = null;
}
}
if (value == null) {
result.append("<option");
if (i == selected) {
result.append(" selected=\"selected\"");
}
result.append(">");
result.append(options.get(i));
result.append("</option>");
if (useLineFeed) {
result.append("\n");
}
} else {
result.append("<option value=\"");
result.append(value);
result.append("\"");
if (i == selected) {
result.append(" selected=\"selected\"");
}
result.append(">");
result.append(options.get(i));
result.append("</option>");
if (useLineFeed) {
result.append("\n");
}
}
}
result.append("</select>");
if (useLineFeed) {
result.append("\n");
}
return result.toString();
}
/**
* Returns the full Workplace resource path to the selected resource.<p>
*
* @param resourceName the name of the resource to get the resource path for
*
* @return the full Workplace resource path to the selected resource
*/
public static String getResourceUri(String resourceName) {
StringBuffer result = new StringBuffer(256);
result.append(getSkinUri());
result.append(resourceName);
return result.toString();
}
/**
* Returns the path to the skin resources.<p>
*
* @return the path to the skin resources
*/
public static String getSkinUri() {
if (m_skinUri == null) {
m_skinUri = OpenCms.getSystemInfo().getContextPath() + RFS_PATH_RESOURCES;
}
return m_skinUri;
}
/**
* Returns the path to the cascading stylesheets.<p>
*
* @param jsp the JSP context
* @return the path to the cascading stylesheets
*/
public static String getStyleUri(CmsJspActionElement jsp) {
if (m_styleUri == null) {
CmsProject project = jsp.getCmsObject().getRequestContext().getCurrentProject();
try {
jsp.getCmsObject().getRequestContext().setCurrentProject(
jsp.getCmsObject().readProject(CmsProject.ONLINE_PROJECT_ID));
m_styleUri = jsp.link("/system/workplace/commons/style/");
} catch (CmsException e) {
LOG.error(e.getLocalizedMessage());
} finally {
jsp.getCmsObject().getRequestContext().setCurrentProject(project);
}
}
return m_styleUri;
}
/**
* Returns the path to the cascading stylesheets.<p>
*
* @param jsp the JSP context
* @param filename the name of the stylesheet
* @return the path to the cascading stylesheets
*/
public static String getStyleUri(CmsJspActionElement jsp, String filename) {
if (m_styleUri == null) {
CmsProject project = jsp.getCmsObject().getRequestContext().getCurrentProject();
try {
jsp.getCmsObject().getRequestContext().setCurrentProject(
jsp.getCmsObject().readProject(CmsProject.ONLINE_PROJECT_ID));
m_styleUri = jsp.link("/system/workplace/commons/style/");
} catch (CmsException e) {
if (LOG.isErrorEnabled()) {
LOG.error(e.getLocalizedMessage(), e);
}
} finally {
jsp.getCmsObject().getRequestContext().setCurrentProject(project);
}
}
return m_styleUri + filename;
}
/**
* Returns the temporary file name for the given resource name.<p>
*
* To create a temporary file name of a resource name, the prefix char <code>'~'</code> (tilde)
* is added to the file name after all parent folder names have been removed.<p>
*
* @param resourceName the resource name to return the temporary file name for
*
* @return the temporary file name for the given resource name
*
* @see CmsResource#isTemporaryFileName(String)
* @see #isTemporaryFile(CmsResource)
*/
public static String getTemporaryFileName(String resourceName) {
if (resourceName == null) {
return null;
}
StringBuffer result = new StringBuffer(resourceName.length() + 2);
result.append(CmsResource.getFolderPath(resourceName));
result.append(CmsResource.TEMP_FILE_PREFIX);
result.append(CmsResource.getName(resourceName));
return result.toString();
}
/**
* Updates the user settings in the given workplace settings for the current user, reading the user settings
* from the database if required.<p>
*
* @param cms the cms object for the current user
* @param settings the workplace settings to update (if <code>null</code> a new instance is created)
* @param update flag indicating if settings are only updated (user preferences)
*
* @return the current users workplace settings
*
* @see #initWorkplaceSettings(CmsObject, CmsWorkplaceSettings, boolean)
*/
public static CmsWorkplaceSettings initUserSettings(CmsObject cms, CmsWorkplaceSettings settings, boolean update) {
if (settings == null) {
settings = new CmsWorkplaceSettings();
}
// save current workplace user & user settings object
CmsUser user;
if (update) {
try {
// read the user from db to get the latest user information if required
user = cms.readUser(cms.getRequestContext().getCurrentUser().getId());
} catch (CmsException e) {
// can usually be ignored
if (LOG.isInfoEnabled()) {
LOG.info(e.getLocalizedMessage());
}
user = cms.getRequestContext().getCurrentUser();
}
} else {
user = cms.getRequestContext().getCurrentUser();
}
// store the user and it's settings in the Workplace settings
settings.setUser(user);
settings.setUserSettings(new CmsUserSettings(user));
// return the result settings
return settings;
}
/**
* Updates the given workplace settings, also re-initializing
* the state of the Workplace to the users preferences (for example setting the startup site and project).
*
* The user settings will also be updated by calling <code>{@link #initUserSettings(CmsObject, CmsWorkplaceSettings, boolean)}</code>
* before updating the workplace project, selected site etc.<p>
*
* @param cms the cms object for the current user
* @param settings the workplace settings to update (if <code>null</code> a new instance is created)
* @param update flag indicating if settings are only updated (user preferences)
*
* @return the current users initialized workplace settings
*
* @see #initUserSettings(CmsObject, CmsWorkplaceSettings, boolean)
*/
public static synchronized CmsWorkplaceSettings initWorkplaceSettings(
CmsObject cms,
CmsWorkplaceSettings settings,
boolean update) {
// init the workplace user settings
settings = initUserSettings(cms, settings, update);
// save current project
settings.setProject(cms.getRequestContext().getCurrentProject().getUuid());
// switch to users preferred site
String siteRoot = settings.getUserSettings().getStartSite();
if (siteRoot.endsWith("/")) {
// remove trailing slash
siteRoot = siteRoot.substring(0, siteRoot.length() - 1);
}
if (CmsStringUtil.isNotEmpty(siteRoot) && (OpenCms.getSiteManager().getSiteForSiteRoot(siteRoot) == null)) {
// this is not the root site and the site is not in the list
siteRoot = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartSite();
if (siteRoot.endsWith("/")) {
// remove trailing slash
siteRoot = siteRoot.substring(0, siteRoot.length() - 1);
}
}
boolean access = false;
CmsResource res = null;
String currentSite = cms.getRequestContext().getSiteRoot();
cms.getRequestContext().setSiteRoot(siteRoot);
try {
// check access to the site
res = cms.readResource("/");
access = cms.hasPermissions(res, CmsPermissionSet.ACCESS_VIEW, false, CmsResourceFilter.ONLY_VISIBLE);
} catch (CmsException e) {
// error reading site root, in this case we will use a readable default
if (LOG.isInfoEnabled()) {
LOG.info(e.getLocalizedMessage(), e);
}
} finally {
cms.getRequestContext().setSiteRoot(currentSite);
}
if ((res == null) || !access) {
List<CmsSite> sites = OpenCms.getSiteManager().getAvailableSites(cms, true);
if (sites.size() > 0) {
siteRoot = sites.get(0).getSiteRoot();
cms.getRequestContext().setSiteRoot(siteRoot);
}
}
// set the current site
settings.setSite(siteRoot);
// set the preferred folder to display
// check start folder:
String startFolder = settings.getUserSettings().getStartFolder();
if (!cms.existsResource(startFolder, CmsResourceFilter.IGNORE_EXPIRATION)) {
// self - healing:
startFolder = "/";
settings.getUserSettings().setStartFolder(startFolder);
}
if (OpenCms.getSiteManager().startsWithShared(cms.getRequestContext().getSiteRoot())) {
// For some reason, the request context of the CmsObject is different from siteRoot
// when the user changes his preferences while in the shared folder. This would lead
// to problems because setExplorerResource uses both the site from the settings and
// the site from the CmsObject. To prevent this, we temporarily set the CmsObject's site
// root to the site root from the settings.
String contextSiteRoot = cms.getRequestContext().getSiteRoot();
try {
cms.getRequestContext().setSiteRoot(siteRoot);
settings.setExplorerResource(startFolder, cms);
} finally {
cms.getRequestContext().setSiteRoot(contextSiteRoot);
}
} else {
settings.setExplorerResource(startFolder, cms);
}
// get the default view from the user settings
settings.setViewUri(OpenCms.getLinkManager().substituteLink(cms, settings.getUserSettings().getStartView()));
return settings;
}
/**
* Returns <code>true</code> if the given resource is a temporary file.<p>
*
* A resource is considered a temporary file it is a file where the
* {@link CmsResource#FLAG_TEMPFILE} flag has been set, or if the file name (without parent folders)
* starts with the prefix char <code>'~'</code> (tilde).<p>
*
* @param resource the resource name to check
*
* @return <code>true</code> if the given resource name is a temporary file
*
* @see #getTemporaryFileName(String)
* @see CmsResource#isTemporaryFileName(String)
*/
public static boolean isTemporaryFile(CmsResource resource) {
return (resource != null)
&& ((resource.isFile() && (((resource.getFlags() & CmsResource.FLAG_TEMPFILE) > 0) || (CmsResource.isTemporaryFileName(resource.getName())))));
}
/**
* Stores the settings in the given session.<p>
*
* @param session the session to store the settings in
* @param settings the settings
*/
static void storeSettings(HttpSession session, CmsWorkplaceSettings settings) {
// save the workplace settings in the session
session.setAttribute(CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS, settings);
}
/**
* Returns all parameters of the current workplace class
* as hidden field tags that can be inserted in a form.<p>
*
* @return all parameters of the current workplace class
* as hidden field tags that can be inserted in a html form
*/
public String allParamsAsHidden() {
StringBuffer result = new StringBuffer(512);
Map<String, Object> params = allParamValues();
Iterator<Entry<String, Object>> i = params.entrySet().iterator();
while (i.hasNext()) {
Entry<String, Object> entry = i.next();
result.append("<input type=\"hidden\" name=\"");
result.append(entry.getKey());
result.append("\" value=\"");
String encoded = CmsEncoder.encode(entry.getValue().toString(), getCms().getRequestContext().getEncoding());
result.append(encoded);
result.append("\">\n");
}
return result.toString();
}
/**
* Returns all present request parameters as String.<p>
*
* The String is formatted as a parameter String (<code>param1=val1¶m2=val2</code>) with UTF-8 encoded values.<p>
*
* @return all present request parameters as String
*/
public String allParamsAsRequest() {
StringBuffer retValue = new StringBuffer(512);
HttpServletRequest request = getJsp().getRequest();
@SuppressWarnings("unchecked")
Iterator<String> paramNames = request.getParameterMap().keySet().iterator();
while (paramNames.hasNext()) {
String paramName = paramNames.next();
String paramValue = request.getParameter(paramName);
retValue.append(paramName + "=" + CmsEncoder.encode(paramValue, getCms().getRequestContext().getEncoding()));
if (paramNames.hasNext()) {
retValue.append("&");
}
}
return retValue.toString();
}
/**
* Builds the end html of the body.<p>
*
* @return the end html of the body
*/
public String bodyEnd() {
return pageBody(HTML_END, null, null);
}
/**
* Builds the start html of the body.<p>
*
* @param className optional class attribute to add to the body tag
* @return the start html of the body
*/
public String bodyStart(String className) {
return pageBody(HTML_START, className, null);
}
/**
* Builds the start html of the body.<p>
*
* @param className optional class attribute to add to the body tag
* @param parameters optional parameters to add to the body tag
* @return the start html of the body
*/
public String bodyStart(String className, String parameters) {
return pageBody(HTML_START, className, parameters);
}
/**
* Generates a html select box out of the provided values.<p>
*
* @param parameters a string that will be inserted into the initial select tag,
* if null no parameters will be inserted
* @param options the options
* @param values the option values, if null the select will have no value attributes
* @param selected the index of the pre-selected option, if -1 no option is pre-selected
* @return a formatted html String representing a html select box
*/
public String buildSelect(String parameters, List<String> options, List<String> values, int selected) {
return buildSelect(parameters, options, values, selected, true);
}
/**
* Generates a button for the OpenCms workplace.<p>
*
* @param href the href link for the button, if none is given the button will be disabled
* @param target the href link target for the button, if none is given the target will be same window
* @param image the image name for the button, skin path will be automattically added as prefix
* @param label the label for the text of the button
* @param type 0: image only (default), 1: image and text, 2: text only
*
* @return a button for the OpenCms workplace
*/
public String button(String href, String target, String image, String label, int type) {
return button(href, target, image, label, type, getSkinUri() + "buttons/");
}
/**
* Generates a button for the OpenCms workplace.<p>
*
* @param href the href link for the button, if none is given the button will be disabled
* @param target the href link target for the button, if none is given the target will be same window
* @param image the image name for the button, skin path will be automattically added as prefix
* @param label the label for the text of the button
* @param type 0: image only (default), 1: image and text, 2: text only
* @param imagePath the path to the image
*
* @return a button for the OpenCms workplace
*/
public String button(String href, String target, String image, String label, int type, String imagePath) {
StringBuffer result = new StringBuffer(256);
String anchorStart = "<a href=\"";
if ((href != null) && href.toLowerCase().startsWith("javascript:")) {
anchorStart = "<a href=\"#\" onclick=\"";
}
result.append("<td style=\"vertical-align: top;\">");
switch (type) {
case 1:
// image and text
if (href != null) {
result.append(anchorStart);
result.append(href);
result.append("\" class=\"button\"");
if (target != null) {
result.append(" target=\"");
result.append(target);
result.append("\"");
}
result.append(">");
}
result.append("<span unselectable=\"on\" ");
if (href != null) {
result.append("class=\"norm\" onmouseover=\"className='over'\" onmouseout=\"className='norm'\" onmousedown=\"className='push'\" onmouseup=\"className='over'\"");
} else {
result.append("class=\"disabled\"");
}
result.append("><span unselectable=\"on\" class=\"combobutton\" ");
result.append("style=\"background-image: url('");
result.append(imagePath);
result.append(image);
if ((image != null) && (image.indexOf('.') == -1)) {
// append default suffix for button images
result.append(".png");
}
result.append("');\">");
result.append(shortKey(label));
result.append("</span></span>");
if (href != null) {
result.append("</a>");
}
break;
case 2:
// text only
if (href != null) {
result.append(anchorStart);
result.append(href);
result.append("\" class=\"button\"");
if (target != null) {
result.append(" target=\"");
result.append(target);
result.append("\"");
}
result.append(">");
}
result.append("<span unselectable=\"on\" ");
if (href != null) {
result.append("class=\"norm\" onmouseover=\"className='over'\" onmouseout=\"className='norm'\" onmousedown=\"className='push'\" onmouseup=\"className='over'\"");
} else {
result.append("class=\"disabled\"");
}
result.append("><span unselectable=\"on\" class=\"txtbutton\">");
result.append(shortKey(label));
result.append("</span></span>");
if (href != null) {
result.append("</a>");
}
break;
default:
// only image
if (href != null) {
result.append(anchorStart);
result.append(href);
result.append("\" class=\"button\"");
if (target != null) {
result.append(" target=\"");
result.append(target);
result.append("\"");
}
result.append(" title=\"");
result.append(key(label));
result.append("\">");
}
result.append("<span unselectable=\"on\" ");
if (href != null) {
result.append("class=\"norm\" onmouseover=\"className='over'\" onmouseout=\"className='norm'\" onmousedown=\"className='push'\" onmouseup=\"className='over'\"");
} else {
result.append("class=\"disabled\"");
}
result.append("><img class=\"button\" src=\"");
result.append(imagePath);
result.append(image);
if ((image != null) && (image.indexOf('.') == -1)) {
// append default suffix for button images
result.append(".png");
}
result.append("\" alt=\"");
result.append(key(label));
result.append("\">");
result.append("</span>");
if (href != null) {
result.append("</a>");
}
break;
}
result.append("</td>\n");
return result.toString();
}
/**
* Returns the html for a button bar.<p>
*
* @param segment the HTML segment (START / END)
*
* @return a button bar html start / end segment
*/
public String buttonBar(int segment) {
return buttonBar(segment, null);
}
/**
* Returns the html for a button bar.<p>
*
* @param segment the HTML segment (START / END)
* @param attributes optional attributes for the table tag
*
* @return a button bar html start / end segment
*/
public String buttonBar(int segment, String attributes) {
if (segment == HTML_START) {
String result = "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\"";
if (attributes != null) {
result += " " + attributes;
}
return result + "><tr>\n";
} else {
return "</tr></table>";
}
}
/**
* Generates a horizontal button bar separator line with maximum width.<p>
*
* @return a horizontal button bar separator line
*/
public String buttonBarHorizontalLine() {
StringBuffer result = new StringBuffer(256);
result.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"maxwidth\">\n");
result.append("<tr>\n");
result.append("\t<td class=\"horseparator\" ><img src=\"");
result.append(getSkinUri());
result.append("tree/empty.gif\" border=\"0\" width=\"1\" height=\"1\" alt=\"\"></td>\n");
result.append("</tr>\n");
result.append("</table>\n");
return result.toString();
}
/**
* Generates a button bar label.<p>
*
* @param label the label to show
*
* @return a button bar label
*/
public String buttonBarLabel(String label) {
return buttonBarLabel(label, "norm");
}
/**
* Generates a button bar label.<p>
*
* @param label the label to show
* @param className the css class name for the formatting
*
* @return a button bar label
*/
public String buttonBarLabel(String label, String className) {
StringBuffer result = new StringBuffer(128);
result.append("<td><span class=\"");
result.append(className);
result.append("\"><span unselectable=\"on\" class=\"txtbutton\">");
result.append(key(label));
result.append("</span></span></td>\n");
return result.toString();
}
/**
* Generates a variable button bar separator line.<p>
*
* @param leftPixel the amount of pixel left to the line
* @param rightPixel the amount of pixel right to the line
* @param className the css class name for the formatting
*
* @return a variable button bar separator line
*/
public String buttonBarLine(int leftPixel, int rightPixel, String className) {
StringBuffer result = new StringBuffer(512);
if (leftPixel > 0) {
result.append(buttonBarLineSpacer(leftPixel));
}
result.append("<td><span class=\"");
result.append(className);
result.append("\"></span></td>\n");
if (rightPixel > 0) {
result.append(buttonBarLineSpacer(rightPixel));
}
return result.toString();
}
/**
* Generates a variable button bar separator line spacer.<p>
*
* @param pixel the amount of pixel space
*
* @return a variable button bar separator line spacer
*/
public String buttonBarLineSpacer(int pixel) {
StringBuffer result = new StringBuffer(128);
result.append("<td><span class=\"norm\"><span unselectable=\"on\" class=\"txtbutton\" style=\"padding-right: 0px; padding-left: ");
result.append(pixel);
result.append("px;\"></span></span></td>\n");
return result.toString();
}
/**
* Generates a button bar separator.<p>
*
* @param leftPixel the amount of pixel left to the separator
* @param rightPixel the amount of pixel right to the separator
*
* @return a button bar separator
*/
public String buttonBarSeparator(int leftPixel, int rightPixel) {
return buttonBarLine(leftPixel, rightPixel, "separator");
}
/**
* Returns the html for an invisible spacer between button bar contents like buttons, labels, etc.<p>
*
* @param width the width of the invisible spacer
* @return the html for the invisible spacer
*/
public String buttonBarSpacer(int width) {
StringBuffer result = new StringBuffer(128);
result.append("<td><span class=\"norm\"><span unselectable=\"on\" class=\"txtbutton\" style=\"width: ");
result.append(width);
result.append("px;\"></span></span></td>\n");
return result.toString();
}
/**
* Generates a button bar starter tab.<p>
*
* @param leftPixel the amount of pixel left to the starter
* @param rightPixel the amount of pixel right to the starter
*
* @return a button bar starter tab
*/
public String buttonBarStartTab(int leftPixel, int rightPixel) {
StringBuffer result = new StringBuffer(512);
result.append(buttonBarLineSpacer(leftPixel));
result.append("<td><span class=\"starttab\"><span style=\"width:1px; height:1px\"></span></span></td>\n");
result.append(buttonBarLineSpacer(rightPixel));
return result.toString();
}
/**
* Checks the lock state of the resource and locks it if the autolock feature is enabled.<p>
*
* @param resource the resource name which is checked
* @throws CmsException if reading or locking the resource fails
*/
public void checkLock(String resource) throws CmsException {
checkLock(resource, CmsLockType.EXCLUSIVE);
}
/**
* Checks the lock state of the resource and locks it if the autolock feature is enabled.<p>
*
* @param resource the resource name which is checked
* @param type indicates the mode {@link CmsLockType#EXCLUSIVE} or {@link CmsLockType#TEMPORARY}
*
* @throws CmsException if reading or locking the resource fails
*/
public void checkLock(String resource, CmsLockType type) throws CmsException {
CmsResource res = getCms().readResource(resource, CmsResourceFilter.ALL);
CmsLock lock = getCms().getLock(res);
boolean lockable = lock.isLockableBy(getCms().getRequestContext().getCurrentUser());
if (OpenCms.getWorkplaceManager().autoLockResources()) {
// autolock is enabled, check the lock state of the resource
if (lockable) {
// resource is lockable, so lock it automatically
if (type == CmsLockType.TEMPORARY) {
getCms().lockResourceTemporary(resource);
} else {
getCms().lockResource(resource);
}
} else {
throw new CmsException(Messages.get().container(Messages.ERR_WORKPLACE_LOCK_RESOURCE_1, resource));
}
} else {
if (!lockable) {
throw new CmsException(Messages.get().container(Messages.ERR_WORKPLACE_LOCK_RESOURCE_1, resource));
}
}
}
/**
* First sets site and project in the workplace settings, then fills all class parameter values from the data
* provided in the current request.<p>
*
* @param settings the workplace settings
* @param request the current request
*/
public void fillParamValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
initSettings(settings, request);
fillParamValues(request);
}
/**
* Fills all class parameter values from the data provided in the current request.<p>
*
* All methods that start with "setParam" are possible candidates to be
* automatically filled. The remaining part of the method name is converted
* to lower case. Then a parameter of this name is searched in the request parameters.
* If the parameter is found, the "setParam" method is automatically invoked
* by reflection with the value of the parameter.<p>
*
* @param request the current JSP request
*/
@SuppressWarnings("unchecked")
public void fillParamValues(HttpServletRequest request) {
m_parameterMap = null;
// ensure a multipart request is parsed only once (for "forward" scenarios with reports)
if (null == request.getAttribute(REQUEST_ATTRIBUTE_MULTIPART)) {
// check if this is a multipart request
m_multiPartFileItems = CmsRequestUtil.readMultipartFileItems(request);
if (m_multiPartFileItems != null) {
// this was indeed a multipart form request
m_parameterMap = CmsRequestUtil.readParameterMapFromMultiPart(
getCms().getRequestContext().getEncoding(),
m_multiPartFileItems);
request.setAttribute(REQUEST_ATTRIBUTE_MULTIPART, Boolean.TRUE);
}
}
if (m_parameterMap == null) {
// the request was a "normal" request
m_parameterMap = request.getParameterMap();
}
List<Method> methods = paramSetMethods();
Iterator<Method> i = methods.iterator();
while (i.hasNext()) {
Method m = i.next();
String name = m.getName().substring(8).toLowerCase();
String[] values = m_parameterMap.get(name);
String value = null;
if (values != null) {
// get the parameter value from the map
value = values[0];
}
if (CmsStringUtil.isEmpty(value)) {
value = null;
}
// TODO: this is very dangerous since most of the dialogs does not send encoded data
// and by decoding not encoded data the data will get corrupted, for instance '1+2' will become '1 2'.
// we should ensure that we decode the data only if the data has been encoded
value = decodeParamValue(name, value);
try {
if (LOG.isDebugEnabled() && (value != null)) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_SET_PARAM_2, m.getName(), value));
}
m.invoke(this, new Object[] {value});
} catch (InvocationTargetException ite) {
// can usually be ignored
if (LOG.isInfoEnabled()) {
LOG.info(ite.getLocalizedMessage());
}
} catch (IllegalAccessException eae) {
// can usually be ignored
if (LOG.isInfoEnabled()) {
LOG.info(eae.getLocalizedMessage());
}
}
}
}
/**
* Returns the message String for the broadcast message alert of the workplace.<p>
*
* Caution: returns the pure message String (not escaped) or null, if no message is pending.<p>
*
* @return the message String for the broadcast message alert of the workplace
*/
public String getBroadcastMessageString() {
CmsSessionInfo sessionInfo = OpenCms.getSessionManager().getSessionInfo(getSession());
if (sessionInfo == null) {
return null;
}
String sessionId = sessionInfo.getSessionId().toString();
Buffer messageQueue = OpenCms.getSessionManager().getBroadcastQueue(sessionId);
if (!messageQueue.isEmpty()) {
// create message String
StringBuffer result = new StringBuffer(512);
// the user has pending messages, display them all
while (!messageQueue.isEmpty()) {
CmsBroadcast message = (CmsBroadcast)messageQueue.remove();
result.append('[');
result.append(getMessages().getDateTime(message.getSendTime()));
result.append("] ");
result.append(key(Messages.GUI_LABEL_BROADCASTMESSAGEFROM_0));
result.append(' ');
if (message.getUser() != null) {
result.append(message.getUser().getName());
} else {
// system message
result.append(key(Messages.GUI_LABEL_BROADCAST_FROM_SYSTEM_0));
}
result.append(":\n");
result.append(message.getMessage());
result.append("\n\n");
}
return result.toString();
}
// no message pending, return null
return null;
}
/**
* Returns the initialized cms object for the current user.<p>
*
* @return the initialized cms object for the current user
*/
public CmsObject getCms() {
return m_cms;
}
/**
* Returns the current workplace encoding.<p>
*
* @return the current workplace encoding
*/
public String getEncoding() {
return OpenCms.getWorkplaceManager().getEncoding();
}
/**
* Returns the uri (including context path) to the explorer file list.<p>
*
* @return the uri (including context path) to the explorer file list
*/
public String getExplorerFileListFullUri() {
if (m_file_explorer_filelist != null) {
return m_file_explorer_filelist;
}
synchronized (this) {
m_file_explorer_filelist = OpenCms.getLinkManager().substituteLink(getCms(), FILE_EXPLORER_FILELIST);
}
return m_file_explorer_filelist;
}
/**
* Returns the html for the frame name and source and stores this information in the workplace settings.<p>
*
* @param frameName the name of the frame
* @param uri the absolute path of the frame
* @return the html for the frame name and source
*/
public String getFrameSource(String frameName, String uri) {
String frameString = "name=\"" + frameName + "\" src=\"" + uri + "\"";
int paramIndex = uri.indexOf("?");
if (paramIndex != -1) {
// remove request parameters from URI before putting it to Map
uri = uri.substring(0, uri.indexOf("?"));
}
getSettings().getFrameUris().put(frameName, uri);
return frameString;
}
/**
* Returns the JSP action element.<p>
*
* @return the JSP action element
*/
public CmsJspActionElement getJsp() {
return m_jsp;
}
/**
* Returns the current users workplace locale settings.<p>
*
* @return the current users workplace locale setting
*/
public Locale getLocale() {
return m_settings.getUserSettings().getLocale();
}
/**
* Returns the current used macro resolver instance.<p>
*
* @return the macro resolver
*/
public CmsMacroResolver getMacroResolver() {
if (m_macroResolver == null) {
// create a new macro resolver "with everything we got"
m_macroResolver = CmsMacroResolver.newInstance()
// initialize resolver with the objects available
.setCmsObject(m_cms).setMessages(getMessages()).setJspPageContext(
(m_jsp == null) ? null : m_jsp.getJspContext());
}
return m_macroResolver;
}
/**
* Returns the current used message object.<p>
*
* @return the current used message object
*/
public CmsMessages getMessages() {
return m_messages;
}
/**
* Returns a list of FileItem instances parsed from the request, in the order that they were transmitted.<p>
*
* This list is automatically initialized from the createParameterMapFromMultiPart(HttpServletRequest) method.<p>
*
* @return list of FileItem instances parsed from the request, in the order that they were transmitted
*/
public List<FileItem> getMultiPartFileItems() {
return m_multiPartFileItems;
}
/**
* Returns the path to the workplace static resources.<p>
*
* Workplaces static resources are images, css files etc.
* These are exported during the installation of OpenCms,
* and are usually only read from this exported location to
* avoid the overhaead of accessing the database later.<p>
*
* @return the path to the workplace static resources
*/
public String getResourceUri() {
if (m_resourceUri == null) {
m_resourceUri = OpenCms.getSystemInfo().getContextPath() + CmsWorkplace.RFS_PATH_RESOURCES;
}
return m_resourceUri;
}
/**
* Returns the current user http session.<p>
*
* @return the current user http session
*/
public HttpSession getSession() {
return m_session;
}
/**
* Returns the current users workplace settings.<p>
*
* @return the current users workplace settings
*/
public CmsWorkplaceSettings getSettings() {
return m_settings;
}
/**
* Returns the path to the cascading stylesheets.<p>
*
* @param filename the name of the stylesheet
* @return the path to the cascading stylesheets
*/
public String getStyleUri(String filename) {
return getStyleUri(getJsp(), filename);
}
/**
* Builds the end html of the page.<p>
*
* @return the end html of the page
*/
public String htmlEnd() {
return pageHtml(HTML_END, null);
}
/**
* Builds the start html of the page, including setting of DOCTYPE and
* inserting a header with the content-type.<p>
*
* @param title the content for the title tag
* @return the start html of the page
*/
public String htmlStart(String title) {
return pageHtml(HTML_START, title);
}
/**
* Sets site and project in the workplace settings with the request values of parameters
* <code>{@link CmsWorkplace#PARAM_WP_SITE}</code> and <code>{@link CmsWorkplace#PARAM_WP_PROJECT}</code>.<p>
*
* @param settings the workplace settings
* @param request the current request
*
* @return true, if a reload of the main body frame is required
*/
public boolean initSettings(CmsWorkplaceSettings settings, HttpServletRequest request) {
// check if the user requested a project change
String project = request.getParameter(PARAM_WP_PROJECT);
boolean reloadRequired = false;
if (project != null) {
reloadRequired = true;
try {
getCms().readProject(new CmsUUID(project));
} catch (Exception e) {
// project not found, set online project
project = String.valueOf(CmsProject.ONLINE_PROJECT_ID);
}
try {
m_cms.getRequestContext().setCurrentProject(getCms().readProject(new CmsUUID(project)));
} catch (Exception e) {
if (LOG.isInfoEnabled()) {
LOG.info(e);
}
}
settings.setProject(new CmsUUID(project));
}
// check if the user requested a site change
String site = request.getParameter(PARAM_WP_SITE);
if (site != null) {
reloadRequired = true;
m_cms.getRequestContext().setSiteRoot(site);
settings.setSite(site);
}
// check which resource was requested
String explorerResource = request.getParameter(PARAM_WP_EXPLORER_RESOURCE);
if (explorerResource != null) {
reloadRequired = true;
settings.setExplorerResource(explorerResource, getCms());
}
return reloadRequired;
}
/**
* Returns the forwarded flag.<p>
*
* @return the forwarded flag
*/
public boolean isForwarded() {
return m_forwarded;
}
/**
* Returns true if the online help for the users current workplace language is installed.<p>
*
* @return true if the online help for the users current workplace language is installed
*/
public boolean isHelpEnabled() {
return getCms().existsResource(
resolveMacros(CmsHelpTemplateBean.PATH_HELP),
CmsResourceFilter.IGNORE_EXPIRATION);
}
/**
* Returns true if the currently processed element is an included sub element.<p>
*
* @return true if the currently processed element is an included sub element
*/
public boolean isSubElement() {
return !getJsp().getRequestContext().getUri().equals(getJsp().info("opencms.request.element.uri"));
}
/**
* Returns the localized resource string for a given message key,
* checking the workplace default resources and all module bundles.<p>
*
* If the key was not found, the return value is
* <code>"??? " + keyName + " ???"</code>.<p>
*
* If the key starts with <code>"help."</code> and is not found,
* the value <code>"index.html"</code> is returned.<p>
*
* @param keyName the key for the desired string
* @return the resource string for the given key
*
* @see CmsMessages#key(String)
*/
public String key(String keyName) {
return getMessages().key(keyName);
}
/**
* Returns the localized resource string for a given message key,
* with the provided replacement parameters.<p>
*
* If the key was found in the bundle, it will be formatted using
* a <code>{@link java.text.MessageFormat}</code> using the provided parameters.<p>
*
* If the key was not found in the bundle, the return value is
* <code>"??? " + keyName + " ???"</code>. This will also be returned
* if the bundle was not properly initialized first.
*
* @param keyName the key for the desired string
* @param params the parameters to use for formatting
* @return the resource string for the given key
*
* @see CmsMessages#key(String)
*/
public String key(String keyName, Object[] params) {
return getMessages().key(keyName, params);
}
/**
* Returns the localized resource string for the given message key,
* checking the workplace default resources and all module bundles.<p>
*
* If the key was not found, the provided default value
* is returned.<p>
*
* @param keyName the key for the desired string
* @param defaultValue the default value in case the key does not exist in the bundle
* @return the resource string for the given key it it exists, or the given default if not
*
* @see CmsMessages#keyDefault(String, String)
*/
public String keyDefault(String keyName, String defaultValue) {
return getMessages().keyDefault(keyName, defaultValue);
}
/**
* Returns the empty String "" if the provided value is null, otherwise just returns
* the provided value.<p>
*
* Use this method in forms if a getParamXXX method is used, but a String (not null)
* is required.
*
* @param value the String to check
* @return the empty String "" if the provided value is null, otherwise just returns
* the provided value
*/
public String nullToEmpty(String value) {
if (value != null) {
return value;
}
return "";
}
/**
* Builds the html of the body.<p>
*
* @param segment the HTML segment (START / END)
* @param className optional class attribute to add to the body tag
* @param parameters optional parameters to add to the body tag
* @return the html of the body
*/
public String pageBody(int segment, String className, String parameters) {
if (segment == HTML_START) {
StringBuffer result = new StringBuffer(128);
result.append("</head>\n<body unselectable=\"on\"");
if (className != null) {
result.append(" class=\"");
result.append(className);
result.append("\"");
}
if (CmsStringUtil.isNotEmpty(parameters)) {
result.append(" ");
result.append(parameters);
}
result.append(">\n");
return result.toString();
} else {
return "</body>";
}
}
/**
* Returns the default html for a workplace page, including setting of DOCTYPE and
* inserting a header with the content-type.<p>
*
* @param segment the HTML segment (START / END)
* @param title the title of the page, if null no title tag is inserted
* @return the default html for a workplace page
*/
public String pageHtml(int segment, String title) {
return pageHtmlStyle(segment, title, null);
}
/**
* Returns the default html for a workplace page, including setting of DOCTYPE and
* inserting a header with the content-type, allowing the selection of an individual style sheet.<p>
*
* @param segment the HTML segment (START / END)
* @param title the title of the page, if null no title tag is inserted
* @param stylesheet the used style sheet, if null the default stylesheet 'workplace.css' is inserted
* @return the default html for a workplace page
*/
public String pageHtmlStyle(int segment, String title, String stylesheet) {
if (segment == HTML_START) {
StringBuffer result = new StringBuffer(512);
result.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n");
result.append("<html>\n<head>\n");
if (title != null) {
result.append("<title>");
result.append(title);
result.append("</title>\n");
}
result.append("<meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=");
result.append(getEncoding());
result.append("\">\n");
result.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"");
result.append(getStyleUri(getJsp(), stylesheet == null ? "workplace.css" : stylesheet));
result.append("\">\n");
return result.toString();
} else {
return "</html>";
}
}
/**
* Returns all initialized parameters of the current workplace class
* as hidden field tags that can be inserted in a form.<p>
*
* @return all initialized parameters of the current workplace class
* as hidden field tags that can be inserted in a html form
*/
public String paramsAsHidden() {
return paramsAsHidden(null);
}
/**
* Returns all initialized parameters of the current workplace class
* that are not in the given exclusion list as hidden field tags that can be inserted in a form.<p>
*
* @param excludes the parameters to exclude
*
* @return all initialized parameters of the current workplace class
* that are not in the given exclusion list as hidden field tags that can be inserted in a form
*/
public String paramsAsHidden(Collection<String> excludes) {
StringBuffer result = new StringBuffer(512);
Map<String, Object> params = paramValues();
Iterator<Entry<String, Object>> i = params.entrySet().iterator();
while (i.hasNext()) {
Entry<String, Object> entry = i.next();
String param = entry.getKey();
if ((excludes == null) || (!excludes.contains(param))) {
result.append("<input type=\"hidden\" name=\"");
result.append(param);
result.append("\" value=\"");
String encoded = CmsEncoder.encode(
entry.getValue().toString(),
getCms().getRequestContext().getEncoding());
result.append(encoded);
result.append("\">\n");
}
}
return result.toString();
}
/**
* Returns all initialized parameters of the current workplace class in the
* form of a parameter map, i.e. the values are arrays.<p>
*
* @return all initialized parameters of the current workplace class in the
* form of a parameter map
*/
public Map<String, String[]> paramsAsParameterMap() {
return CmsRequestUtil.createParameterMap(paramValues());
}
/**
* Returns all initialized parameters of the current workplace class
* as request parameters, i.e. in the form <code>key1=value1&key2=value2</code> etc.
*
* @return all initialized parameters of the current workplace class
* as request parameters
*/
public String paramsAsRequest() {
StringBuffer result = new StringBuffer(512);
Map<String, Object> params = paramValues();
Iterator<Entry<String, Object>> i = params.entrySet().iterator();
while (i.hasNext()) {
Entry<String, Object> entry = i.next();
result.append(entry.getKey());
result.append("=");
result.append(CmsEncoder.encode(entry.getValue().toString(), getCms().getRequestContext().getEncoding()));
if (i.hasNext()) {
result.append("&");
}
}
return result.toString();
}
/**
* Resolves the macros in the given String and replaces them by their localized keys.<p>
*
* The following macro contexts are available in the Workplace:<ul>
* <li>Macros based on the current users OpenCms context (obtained from the current <code>{@link CmsObject}</code>).</li>
* <li>Localized key macros (obtained from the current <code>{@link CmsMessages}</code>).</li>
* <li>Macros from the current JSP page context (obtained by <code>{@link #getJsp()}</code>).</li>
* </ul>
*
* @param input the input String containing the macros
* @return the resolved String
*
* @see CmsMacroResolver#resolveMacros(String)
*/
public String resolveMacros(String input) {
// resolve the macros
return getMacroResolver().resolveMacros(input);
}
/**
* Sends a http redirect to the specified URI in the OpenCms VFS.<p>
*
* @param location the location the response is redirected to
* @throws IOException in case redirection fails
*/
public void sendCmsRedirect(String location) throws IOException {
// TOOD: IBM Websphere v5 has problems here, use forward instead (which has other problems)
getJsp().getResponse().sendRedirect(OpenCms.getSystemInfo().getOpenCmsContext() + location);
}
/**
* Forwards to the specified location in the OpenCms VFS.<p>
*
* @param location the location the response is redirected to
* @param params the map of parameters to use for the forwarded request
*
* @throws IOException in case the forward fails
* @throws ServletException in case the forward fails
*/
public void sendForward(String location, Map<String, ?> params) throws IOException, ServletException {
setForwarded(true);
// params must be arrays of String, ensure this is the case
Map<String, String[]> parameters = CmsRequestUtil.createParameterMap(params);
CmsRequestUtil.forwardRequest(
getJsp().link(location),
parameters,
getJsp().getRequest(),
getJsp().getResponse());
}
/**
* Sets the forwarded flag.<p>
*
* @param forwarded the forwarded flag to set
*/
public void setForwarded(boolean forwarded) {
m_forwarded = forwarded;
}
/**
* Get a localized short key value for the workplace.<p>
*
* @param keyName name of the key
* @return a localized short key value
*/
public String shortKey(String keyName) {
String value = keyDefault(keyName + CmsMessages.KEY_SHORT_SUFFIX, (String)null);
if (value == null) {
// short key value not found, return "long" key value
return key(keyName);
}
return value;
}
/**
* Auxiliary method for initialization of messages.<p>
*
* @param messages the {@link CmsMessages} to add
*/
protected void addMessages(CmsMessages messages) {
if (messages != null) {
m_messages.addMessages(messages);
}
}
/**
* Auxiliary method for initialization of messages.<p>
*
* @param bundleName the resource bundle name to add
*/
protected void addMessages(String bundleName) {
addMessages(new CmsMessages(bundleName, getLocale()));
}
/**
* Returns the values of all parameter methods of this workplace class instance.<p>
*
* @return the values of all parameter methods of this workplace class instance
*/
protected Map<String, Object> allParamValues() {
List<Method> methods = paramGetMethods();
Map<String, Object> map = new HashMap<String, Object>(methods.size());
Iterator<Method> i = methods.iterator();
while (i.hasNext()) {
Method m = i.next();
Object o = null;
try {
o = m.invoke(this, new Object[0]);
} catch (InvocationTargetException ite) {
// can usually be ignored
if (LOG.isInfoEnabled()) {
LOG.info(ite);
}
} catch (IllegalAccessException eae) {
// can usually be ignored
if (LOG.isInfoEnabled()) {
LOG.info(eae);
}
}
if (o == null) {
o = "";
}
map.put(m.getName().substring(8).toLowerCase(), o);
}
return map;
}
/**
* Checks that the current user is a workplace user.<p>
*
* @throws CmsRoleViolationException if the user does not have the required role
*/
protected void checkRole() throws CmsRoleViolationException {
OpenCms.getRoleManager().checkRole(m_cms, CmsRole.WORKPLACE_USER);
}
/**
* Decodes an individual parameter value.<p>
*
* In special cases some parameters might require a different-from-default
* encoding. This is the case if the content of the parameter was
* encoded using the JavaScript encodeURIComponent() method on the client,
* which always encodes in UTF-8.<p>
*
* @param paramName the name of the parameter
* @param paramValue the unencoded value of the parameter
*
* @return the encoded value of the parameter
*/
protected String decodeParamValue(String paramName, String paramValue) {
if ((paramName != null) && (paramValue != null)) {
return CmsEncoder.decode(paramValue, getCms().getRequestContext().getEncoding());
} else {
return null;
}
}
/**
* Returns the map of parameters read from the current request.<p>
*
* This method will also handle parameters from forms
* of type <code>multipart/form-data</code>.<p>
*
* @return the map of parameters read from the current request
*/
protected Map<String, String[]> getParameterMap() {
return m_parameterMap;
}
/**
* Initializes the message object.<p>
*
* By default the {@link CmsWorkplaceMessages} are initialized.<p>
*
* You SHOULD override this method for setting the bundles you really need,
* using the <code>{@link #addMessages(CmsMessages)}</code> or <code>{@link #addMessages(String)}</code> method.<p>
*/
protected void initMessages() {
// no bundles are added by default as all core bundles are added as part of the WorkplaceModuleMessages
}
/**
* Sets the users time warp if configured and if the current timewarp setting is different or
* clears the current time warp setting if the user has no configured timewarp.<p>
*
* Timwarping is controlled by the session attribute
* {@link CmsContextInfo#ATTRIBUTE_REQUEST_TIME} with a value of type <code>Long</code>.<p>
*
* @param settings the user settings which are configured via the preferences dialog
*
* @param session the session of the user
*/
protected void initTimeWarp(CmsUserSettings settings, HttpSession session) {
long timeWarpConf = settings.getTimeWarp();
Long timeWarpSetLong = (Long)session.getAttribute(CmsContextInfo.ATTRIBUTE_REQUEST_TIME);
long timeWarpSet = (timeWarpSetLong != null) ? timeWarpSetLong.longValue() : CmsContextInfo.CURRENT_TIME;
if (timeWarpConf == CmsContextInfo.CURRENT_TIME) {
// delete:
if (timeWarpSetLong != null) {
// we may come from direct_edit.jsp: don't remove attribute, this is
session.removeAttribute(CmsContextInfo.ATTRIBUTE_REQUEST_TIME);
}
} else {
// this is dominant: if configured we will use it
if (timeWarpSet != timeWarpConf) {
session.setAttribute(CmsContextInfo.ATTRIBUTE_REQUEST_TIME, new Long(timeWarpConf));
}
}
}
/**
* Initializes this workplace class instance.<p>
*
* This method can be used in case there a workplace class was generated using
* {@link Class#forName(java.lang.String)} to initialize the class members.<p>
*
* @param jsp the initialized JSP context
*/
protected void initWorkplaceMembers(CmsJspActionElement jsp) {
if (jsp != null) {
m_jsp = jsp;
m_cms = m_jsp.getCmsObject();
m_session = m_jsp.getRequest().getSession();
// check role
try {
checkRole();
} catch (CmsRoleViolationException e) {
throw new CmsIllegalStateException(e.getMessageContainer(), e);
}
// get / create the workplace settings
m_settings = (CmsWorkplaceSettings)m_session.getAttribute(CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS);
if (m_settings == null) {
// create the settings object
m_settings = new CmsWorkplaceSettings();
m_settings = initWorkplaceSettings(m_cms, m_settings, false);
storeSettings(m_session, m_settings);
}
// initialize messages
CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(getLocale());
// generate a new multi messages object and add the messages from the workplace
m_messages = new CmsMultiMessages(getLocale());
m_messages.addMessages(messages);
initMessages();
// check request for changes in the workplace settings
initWorkplaceRequestValues(m_settings, m_jsp.getRequest());
// set cms context accordingly
initWorkplaceCmsContext(m_settings, m_cms);
// timewarp reset logic
initTimeWarp(m_settings.getUserSettings(), m_session);
}
}
/**
* Analyzes the request for workplace parameters and adjusts the workplace
* settings accordingly.<p>
*
* @param settings the workplace settings
* @param request the current request
*/
protected abstract void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request);
/**
* Returns the values of all parameter methods of this workplace class instance.<p>
*
* @return the values of all parameter methods of this workplace class instance
*/
protected Map<String, Object> paramValues() {
List<Method> methods = paramGetMethods();
Map<String, Object> map = new HashMap<String, Object>(methods.size());
Iterator<Method> i = methods.iterator();
while (i.hasNext()) {
Method m = i.next();
Object o = null;
try {
o = m.invoke(this, new Object[0]);
} catch (InvocationTargetException ite) {
// can usually be ignored
if (LOG.isInfoEnabled()) {
LOG.info(ite.getLocalizedMessage());
}
} catch (IllegalAccessException eae) {
// can usually be ignored
if (LOG.isInfoEnabled()) {
LOG.info(eae.getLocalizedMessage());
}
}
if (o != null) {
map.put(m.getName().substring(8).toLowerCase(), o);
}
}
return map;
}
/**
* Replaces the site title, if necessary.<p>
*
* @param title the site title
*
* @return the new site title
*/
protected String substituteSiteTitle(String title) {
if (title.equals(CmsSiteManagerImpl.SHARED_FOLDER_TITLE)) {
return Messages.get().getBundle(getSettings().getUserSettings().getLocale()).key(
Messages.GUI_SHARED_TITLE_0);
}
return title;
}
/**
* Helper method to change back from the temporary project to the current project.<p>
*
* @throws CmsException if switching back fails
*/
protected void switchToCurrentProject() throws CmsException {
if (m_currentProjectId != null) {
// switch back to the current users project
getCms().getRequestContext().setCurrentProject(getCms().readProject(m_currentProjectId));
}
}
/**
* Helper method to change the current project to the temporary file project.<p>
*
* The id of the old project is stored in a member variable to switch back.<p>
*
* @return the id of the tempfileproject
* @throws CmsException if getting the tempfileproject id fails
*/
protected CmsUUID switchToTempProject() throws CmsException {
// store the current project id in member variable
m_currentProjectId = getSettings().getProject();
CmsUUID tempProjectId = OpenCms.getWorkplaceManager().getTempFileProjectId();
getCms().getRequestContext().setCurrentProject(getCms().readProject(tempProjectId));
return tempProjectId;
}
/**
* Sets the cms request context and other cms related settings to the
* values stored in the workplace settings.<p>
*
* @param settings the workplace settings
* @param cms the current cms object
*/
private void initWorkplaceCmsContext(CmsWorkplaceSettings settings, CmsObject cms) {
CmsRequestContext reqCont = cms.getRequestContext();
// check project setting
if (!settings.getProject().equals(reqCont.getCurrentProject().getUuid())) {
try {
reqCont.setCurrentProject(cms.readProject(settings.getProject()));
} catch (CmsDbEntryNotFoundException e) {
try {
// project not found, set current project and settings to online project
reqCont.setCurrentProject(cms.readProject(CmsProject.ONLINE_PROJECT_ID));
settings.setProject(CmsProject.ONLINE_PROJECT_ID);
} catch (CmsException ex) {
// log error
if (LOG.isInfoEnabled()) {
LOG.info(ex.getLocalizedMessage());
}
}
} catch (CmsException e1) {
if (LOG.isInfoEnabled()) {
LOG.info(e1.getLocalizedMessage());
}
}
}
// check site setting
if (!(settings.getSite().equals(reqCont.getSiteRoot()))) {
// site was switched, set new site root
reqCont.setSiteRoot(settings.getSite());
// removed setting explorer resource to "/" to get the stored folder
}
}
/**
* Returns a list of all methods of the current class instance that
* start with "getParam" and have no parameters.<p>
*
* @return a list of all methods of the current class instance that
* start with "getParam" and have no parameters
*/
private List<Method> paramGetMethods() {
List<Method> list = new ArrayList<Method>();
Method[] methods = this.getClass().getMethods();
int length = methods.length;
for (int i = 0; i < length; i++) {
Method method = methods[i];
if (method.getName().startsWith("getParam") && (method.getParameterTypes().length == 0)) {
if (DEBUG) {
System.err.println("getMethod: " + method.getName());
}
list.add(method);
}
}
return list;
}
/**
* Returns a list of all methods of the current class instance that
* start with "setParam" and have exactly one String parameter.<p>
*
* @return a list of all methods of the current class instance that
* start with "setParam" and have exactly one String parameter
*/
private List<Method> paramSetMethods() {
List<Method> list = new ArrayList<Method>();
Method[] methods = getClass().getMethods();
int length = methods.length;
for (int i = 0; i < length; i++) {
Method method = methods[i];
if (method.getName().startsWith("setParam")
&& (method.getParameterTypes().length == 1)
&& (method.getParameterTypes()[0].equals(java.lang.String.class))) {
if (DEBUG) {
System.err.println("setMethod: " + method.getName());
}
list.add(method);
}
}
return list;
}
}