org.opencms.jsp.util.CmsJspStatusBean Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (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 & Co. KG, 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.jsp.util;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.flex.CmsFlexController;
import org.opencms.flex.CmsFlexRequest;
import org.opencms.flex.CmsFlexResponse;
import org.opencms.i18n.CmsAcceptLanguageHeaderParser;
import org.opencms.i18n.CmsMessages;
import org.opencms.jsp.CmsJspActionElement;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.security.CmsRole;
import org.opencms.site.CmsSite;
import org.opencms.staticexport.CmsLinkManager;
import org.opencms.util.CmsRequestUtil;
import org.opencms.util.CmsStringUtil;
import org.opencms.workplace.CmsWorkplace;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import org.apache.commons.logging.Log;
/**
* This bean provides methods to generate customized http status error pages, e.g. to handle 404 (not found) errors.
*
* The JSPs using this bean are placed in the OpenCms VFS folder /system/handler/.
*
* @since 6.0
*/
public class CmsJspStatusBean extends CmsJspActionElement {
/** Request attribute key for the error message. */
public static final String ERROR_MESSAGE = "javax.servlet.error.message";
/** Request attribute key for the error request URI. */
public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
/** Request attribute key for the error servlet name. */
public static final String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
/** Request attribute key for the error status code. */
public static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";
/** Default name for an unknown error status code. */
public static final String UNKKNOWN_STATUS_CODE = "unknown";
/** The OpenCms VFS path containing the handler files. */
public static final String VFS_FOLDER_HANDLER = CmsWorkplace.VFS_PATH_SYSTEM + "handler/";
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(CmsJspStatusBean.class);
/** The error message. */
private String m_errorMessage;
/** The thrown exception. */
private Throwable m_exception;
/** The Locale to use for displayed messages. */
private Locale m_locale;
/** Contains all possible parameters usable by localized messages. */
private Object[] m_localizeParameters;
/** The localized messages to use on the page. */
private CmsMessages m_messages;
/** The request URI. */
private String m_requestUri;
/** The servlet name. */
private String m_servletName;
/** The site root of the requested resource. */
private String m_siteRoot;
/** The status code. */
private Integer m_statusCode;
/** The status code as message. */
private String m_statusCodeMessage;
/** The URI used for template part inclusion. */
private String m_templateUri;
/**
* Empty constructor, required for every JavaBean.
*/
public CmsJspStatusBean() {
super();
}
/**
* Constructor, with parameters.
*
* @param context the JSP page context object
* @param req the JSP request
* @param res the JSP response
*/
public CmsJspStatusBean(PageContext context, HttpServletRequest req, HttpServletResponse res) {
super(context, req, res);
initMembers(req, null);
}
/**
* Constructor, with parameters.
*
* @param context the JSP page context object
* @param req the JSP request
* @param res the JSP response
* @param t the exception that lead to the error
*/
public CmsJspStatusBean(PageContext context, HttpServletRequest req, HttpServletResponse res, Throwable t) {
super(context, req, res);
initMembers(req, t);
}
/**
* Tries to forward to the configured error page for the current site root if present.
*
* @param rootPath the resource to be used as error page
*
* @return true
if the forward was successful performed, false
otherwise
*
* @deprecated will not work for container pages and other pages using cms:include tags
*/
@Deprecated
public boolean forwardToErrorPage(String rootPath) {
try {
// get the site of the the error page resource
CmsSite site = OpenCms.getSiteManager().getSiteForRootPath(rootPath);
// initialize a CMS object for the given resource
CmsObject clone = OpenCms.initCmsObject(getCmsObject());
if (site != null) {
clone.getRequestContext().setSiteRoot(site.getSiteRoot());
}
String relPath = clone.getRequestContext().removeSiteRoot(rootPath);
clone.getRequestContext().setUri(relPath);
// create a new flex controller together with its flex request/response
// initialized with the context of the error page
CmsFlexController ori = CmsFlexController.getController(getRequest());
CmsFlexController controller = new CmsFlexController(
clone,
clone.readResource(relPath),
ori.getCmsCache(),
getRequest(),
getResponse(),
false,
false);
// controller.setForwardMode(true);
CmsFlexController.setController(getRequest(), controller);
CmsFlexRequest f_req = new CmsFlexRequest(getRequest(), controller);
CmsFlexResponse f_res = new CmsFlexResponse(getResponse(), controller, false, false);
controller.push(f_req, f_res);
// send the forward
CmsRequestUtil.forwardRequest(
OpenCms.getStaticExportManager().getVfsPrefix() + relPath,
getRequest(),
getResponse());
} catch (Throwable e) {
// something went wrong log the exception and return false
LOG.error(e.getMessage(), e);
return false;
}
// return success flag
return true;
}
/**
* Returns the error message.
*
* @return the error message
*/
public String getErrorMessage() {
return m_errorMessage;
}
/**
* Returns the exception.
*
* @return the exception
*/
public Throwable getException() {
return m_exception;
}
/**
* Returns the locale to use for the error page.
*
* @return the locale to use for the error page
*/
public Locale getLocale() {
return m_locale;
}
/**
* Returns the processed output of the specified element of an OpenCms page.
*
* The page to get the content from is looked up in the property value "template-elements".
* If no value is found, the page is read from the "contents/" subfolder of the handler folder.
*
* For each status code, an individual page can be created by naming it "content${STATUSCODE}.html".
* If the individual page can not be found, the content is read from "contentunknown.html".
*
* @param element name of the element
* @return the processed output of the specified element of an OpenCms page
*/
public String getPageContent(String element) {
// Determine the folder to read the contents from
String contentFolder = property(CmsPropertyDefinition.PROPERTY_TEMPLATE_ELEMENTS, "search", "");
if (CmsStringUtil.isEmpty(contentFolder)) {
contentFolder = VFS_FOLDER_HANDLER + "contents/";
}
// determine the file to read the contents from
String fileName = "content" + getStatusCodeMessage() + ".html";
if (!getCmsObject().existsResource(contentFolder + fileName)) {
// special file does not exist, use generic one
fileName = "content" + UNKKNOWN_STATUS_CODE + ".html";
}
// get the content
return getContent(contentFolder + fileName, element, getLocale());
}
/**
* Returns the absolute path of the requested resource in the VFS of OpenCms.
*
* @return the absolute path of the requested resource in the VFS of OpenCms
*/
public String getRequestResourceName() {
if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getRequestUri())) {
return CmsLinkManager.removeOpenCmsContext(getRequestUri());
}
return getRequestUri();
}
/**
* Returns the request Uri.
*
* @return the request Uri
*/
public String getRequestUri() {
return m_requestUri;
}
/**
* Returns the full Workplace resource path to the selected resource.
*
* @param resourceName the name of the resource to get the resource path for
*
* @return the full Workplace resource path to the selected resource
*/
public String getResourceUri(String resourceName) {
return CmsWorkplace.getResourceUri(resourceName);
}
/**
* Returns the servlet name.
*
* @return the servlet name
*/
public String getServletName() {
return m_servletName;
}
/**
* Returns the site root of the requested resource.
*
* @return the site root of the requested resource
*/
public String getSiteRoot() {
return m_siteRoot;
}
/**
* Returns the status code.
*
* @return the status code
*/
public Integer getStatusCode() {
return m_statusCode;
}
/**
* Returns the status code message.
*
* @return the status code message
*/
public String getStatusCodeMessage() {
return m_statusCodeMessage;
}
/**
* Returns the URI used for template part inclusion.
*
* @return the URI used for template part inclusion
*/
public String getTemplateUri() {
if (CmsStringUtil.isEmptyOrWhitespaceOnly(m_templateUri)) {
m_templateUri = "/";
}
return m_templateUri;
}
/**
* Include a template part to display on the error page.
*
* @param target the target uri of the file in the OpenCms VFS (can be relative or absolute)
* @param element the element (template selector) to display from the target
*
* @throws JspException in case there were problems including the target
*/
public void includeTemplatePart(String target, String element) throws JspException {
includeTemplatePart(target, element, null);
}
/**
* Include a template part to display on the error page.
*
* @param target the target uri of the file in the OpenCms VFS (can be relative or absolute)
* @param element the element (template selector) to display from the target
* @param parameterMap a map of the request parameters
*
* @throws JspException in case there were problems including the target
*/
public void includeTemplatePart(String target, String element, Map parameterMap)
throws JspException {
// store current site root and URI
String currentSiteRoot = getRequestContext().getSiteRoot();
String currentUri = getRequestContext().getUri();
try {
// set site root and URI to display template part correct
getRequestContext().setSiteRoot(getSiteRoot());
getRequestContext().setUri(getTemplateUri());
// include the template part
include(target, element, parameterMap);
} finally {
// reset site root and requested URI to status JSP
getRequestContext().setSiteRoot(currentSiteRoot);
getRequestContext().setUri(currentUri);
}
}
/**
* Returns the localized resource string for a given message key.
*
* If the key was not found in the bundle, the return value is
* "??? " + keyName + " ???"
.
*
* The key can use the following parameters for formatting:
*
* - 0: the HTTP status code
* - 1: the requested URI
* - 2: the generated error message
* - 3: the servlet name
* - 4: the date of the request
*
*
* @param keyName the key for the desired string
* @return the resource string for the given key
*/
public String key(String keyName) {
return key(keyName, null);
}
/**
* Returns the localized resource string for a given message key.
*
* For a detailed parameter description, see {@link CmsJspStatusBean#key(String)}.
*
* @param keyName the key for the desired string
* @param defaultKeyName the default key for the desired string, used if the keyName delivered no resource string
* @return the resource string for the given key
*/
public String key(String keyName, String defaultKeyName) {
String value = getMessages().key(keyName, getLocalizeParameters());
if (value.startsWith(CmsMessages.UNKNOWN_KEY_EXTENSION) && CmsStringUtil.isNotEmpty(defaultKeyName)) {
value = getMessages().key(defaultKeyName, getLocalizeParameters());
}
return CmsStringUtil.escapeHtml(value);
}
/**
* Returns the localized resource string for a given message key depending on the HTTP status.
*
* Automatically adds a status suffix for the key to get, eg. "keyname" gets the suffix "_404" for a 404 status.
* For a detailed parameter description, see {@link CmsJspStatusBean#key(String)}.
*
* @param keyName the key for the desired string
* @return the resource string for the given key
*/
public String keyStatus(String keyName) {
keyName += "_";
return key(keyName + getStatusCodeMessage(), keyName + UNKKNOWN_STATUS_CODE);
}
/**
* Writes the exception into the 'opencms.log', if the exception is not null
.
*/
public void logException() {
if (m_exception != null) {
LOG.error(m_exception.getMessage(), m_exception);
}
}
/**
* Sets the URI used for template part inclusion.
*
* @param templateUri the URI used for template part inclusion
*/
public void setTemplateUri(String templateUri) {
m_templateUri = templateUri;
}
/**
* Returns true if the current user has the "DEVELOPER" role and can view the exception stacktrace.
*
* @return true if the current user has the "DEVELOPER" role and can view the exception stacktrace
*/
public boolean showException() {
return OpenCms.getRoleManager().hasRole(getCmsObject(), CmsRole.DEVELOPER);
}
/**
* Returns the parameter object for localization.
*
* @return the parameter object for localization
*
* @see #key(String) for a more detailed object description
*/
protected Object[] getLocalizeParameters() {
if (m_localizeParameters == null) {
m_localizeParameters = new Object[] {
getStatusCodeMessage(),
getRequestUri(),
getErrorMessage(),
getServletName(),
new Date(getRequestContext().getRequestTime())};
}
return m_localizeParameters;
}
/**
* Returns the initialized messages object to read localized messages from.
*
* @return the initialized messages object to read localized messages from
*/
protected CmsMessages getMessages() {
if (m_messages == null) {
// initialize the localized messages
m_messages = new CmsMessages(Messages.get().getBundleName(), getLocale().toString());
}
return m_messages;
}
/**
* Initializes the members of this bean with the information retrieved from the current request.
*
* @param req the JSP request
* @param t the exception that lead to the error
*/
protected void initMembers(HttpServletRequest req, Throwable t) {
// get the status error attribute values from the request
m_servletName = (String)req.getAttribute(ERROR_SERVLET_NAME);
m_errorMessage = (String)req.getAttribute(ERROR_MESSAGE);
m_requestUri = (String)req.getAttribute(ERROR_REQUEST_URI);
m_statusCode = (Integer)req.getAttribute(ERROR_STATUS_CODE);
if ((m_statusCode == null) || (m_requestUri == null)) {
// check if the error request is invoked via Apache/HTTPd ErrorDocument and mod_jk
// to use this you need to add the following to "jk.conf":
// JkEnvVar REDIRECT_URL none
// JkEnvVar REDIRECT_STATUS none
// JkEnvVar REDIRECT_SERVLET_NAME OpenCmsServlet
String jkUri = (String)req.getAttribute("REDIRECT_URL");
String jkStatusCode = (String)req.getAttribute("REDIRECT_STATUS");
String jkServletName = (String)req.getAttribute("REDIRECT_SERVLET_NAME");
try {
if (!"none".equals(jkStatusCode) && !"none".equals(jkUri)) {
m_servletName = jkServletName;
m_requestUri = jkUri;
m_statusCode = new Integer(jkStatusCode);
}
} catch (NullPointerException e) {
// attibute not set, ignore
} catch (NumberFormatException e) {
// status code not a number, ignore
}
}
// get the status code as String
if (m_statusCode != null) {
m_statusCodeMessage = String.valueOf(m_statusCode.intValue());
} else {
m_statusCodeMessage = UNKKNOWN_STATUS_CODE;
}
m_exception = t;
// determine the best locale to use from the users browser settings
CmsAcceptLanguageHeaderParser parser = new CmsAcceptLanguageHeaderParser(
req,
OpenCms.getWorkplaceManager().getDefaultLocale());
List acceptedLocales = parser.getAcceptedLocales();
List workplaceLocales = OpenCms.getWorkplaceManager().getLocales();
m_locale = OpenCms.getLocaleManager().getFirstMatchingLocale(acceptedLocales, workplaceLocales);
if (m_locale == null) {
// no match found - use OpenCms default locale
m_locale = OpenCms.getWorkplaceManager().getDefaultLocale();
}
getCmsObject().getRequestContext().setLocale(m_locale);
// store the site root of the request
m_siteRoot = OpenCms.getSiteManager().matchRequest(req).getSiteRoot();
}
/**
* Sets the error message.
*
* @param errorMessage the error message to set
*/
protected void setErrorMessage(String errorMessage) {
m_errorMessage = errorMessage;
}
/**
* Sets the exception.
*
* @param exception the exception to set
*/
protected void setException(Throwable exception) {
m_exception = exception;
}
/**
* Sets the locale to use for the error page.
*
* @param locale the locale to use for the error page
*/
protected void setLocale(Locale locale) {
m_locale = locale;
getCmsObject().getRequestContext().setLocale(m_locale);
}
/**
* Sets the parameter object for localization.
*
* @param localizeParameters the parameter object for localization
*/
protected void setLocalizeParameters(Object[] localizeParameters) {
m_localizeParameters = localizeParameters;
}
/**
* Sets the initialized messages object to read localized messages from.
*
* @param messages the initialized messages object to read localized messages from
*/
protected void setMessages(CmsMessages messages) {
m_messages = messages;
}
/**
* Sets the request Uri.
*
* @param requestUri the request Uri to set
*/
protected void setRequestUri(String requestUri) {
m_requestUri = requestUri;
}
/**
* Sets the servlet name.
*
* @param servletName the servlet name to set
*/
protected void setServletName(String servletName) {
m_servletName = servletName;
}
/**
* Sets the site root of the requested resource.
*
* @param siteRoot the site root of the requested resource
*/
protected void setSiteRoot(String siteRoot) {
m_siteRoot = siteRoot;
}
/**
* Sets the status code.
*
* @param statusCode the status code to set
*/
protected void setStatusCode(Integer statusCode) {
m_statusCode = statusCode;
}
/**
* Sets the status code message.
*
* @param statusCodeMessage the status code message to set
*/
protected void setStatusCodeMessage(String statusCodeMessage) {
m_statusCodeMessage = statusCodeMessage;
}
}