001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.jsp; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsRequestContext; 032import org.opencms.flex.CmsFlexController; 033import org.opencms.i18n.CmsMessageContainer; 034import org.opencms.main.CmsLog; 035import org.opencms.main.CmsRuntimeException; 036import org.opencms.util.CmsRequestUtil; 037 038import javax.servlet.http.HttpServletRequest; 039import javax.servlet.http.HttpServletResponse; 040import javax.servlet.jsp.PageContext; 041 042import org.apache.commons.logging.Log; 043 044/** 045 * Superclass for OpenCms JSP beans that provides convient access 046 * to OpenCms core and VFS functionality.<p> 047 * 048 * If you have large chunks of code on your JSP that you want to 049 * move to a Class file, consider creating a subclass of this bean. 050 * 051 * Initialize this bean at the beginning of your JSP like this: 052 * <pre> 053 * <jsp:useBean id="cmsbean" class="org.opencms.jsp.CmsJspBean"> 054 * <% cmsbean.init(pageContext, request, response); %> 055 * </jsp:useBean> 056 * </pre> 057 * <p> 058 * 059 * @since 6.0.0 060 */ 061public class CmsJspBean { 062 063 /** The log object for this class. */ 064 private static final Log LOG = CmsLog.getLog(CmsJspBean.class); 065 066 /** JSP page context. */ 067 private PageContext m_context; 068 069 /** OpenCms core CmsObject. */ 070 private CmsFlexController m_controller; 071 072 /** Flag to indicate that this bean was properly initialized. */ 073 private boolean m_isNotInitialized; 074 075 /** Flag to indicate if we want default or custom Exception handling. */ 076 private boolean m_isSupressingExceptions; 077 078 /** OpenCms JSP request. */ 079 private HttpServletRequest m_request; 080 081 /** OpenCms JSP response. */ 082 private HttpServletResponse m_response; 083 084 /** 085 * Empty constructor, required for every JavaBean.<p> 086 */ 087 public CmsJspBean() { 088 089 // noop, call init() to get going 090 m_isSupressingExceptions = true; 091 m_isNotInitialized = true; 092 } 093 094 /** 095 * Returns the CmsObject from the wrapped request.<p> 096 * 097 * This is a convenience method in case you need access to 098 * the CmsObject in your JSP scriplets.<p> 099 * 100 * @return the CmsObject from the wrapped request 101 */ 102 public CmsObject getCmsObject() { 103 104 if (m_isNotInitialized) { 105 return null; 106 } 107 return m_controller.getCmsObject(); 108 } 109 110 /** 111 * Returns the JSP page context this bean was initialized with.<p> 112 * 113 * @return the JSP page context this bean was initialized with 114 */ 115 public PageContext getJspContext() { 116 117 return m_context; 118 } 119 120 /** 121 * Returns the request this bean was initialized with.<p> 122 * 123 * @return the request this bean was initialized with 124 */ 125 public HttpServletRequest getRequest() { 126 127 return m_request; 128 } 129 130 /** 131 * Returns the current users OpenCms request context.<p> 132 * 133 * @return the current users OpenCms request context 134 */ 135 public CmsRequestContext getRequestContext() { 136 137 return getCmsObject().getRequestContext(); 138 } 139 140 /** 141 * Returns the response wrapped by this element.<p> 142 * 143 * @return the response wrapped by this element 144 */ 145 public HttpServletResponse getResponse() { 146 147 return m_response; 148 } 149 150 /** 151 * Initialize this bean with the current page context, request and response.<p> 152 * 153 * It is required to call one of the init() methods before you can use the 154 * instance of this bean. 155 * 156 * @param context the JSP page context object 157 * @param req the JSP request 158 * @param res the JSP response 159 */ 160 public void init(PageContext context, HttpServletRequest req, HttpServletResponse res) { 161 162 m_controller = CmsFlexController.getController(req); 163 if (m_controller == null) { 164 handleMissingFlexController(); 165 } 166 m_context = context; 167 m_request = req; 168 m_response = res; 169 m_isNotInitialized = false; 170 } 171 172 /** 173 * Returns <code>true</code> if Exceptions are handled by the class instance and suppressed on the 174 * output page, or <code>false</code> if they will be thrown and have to be handled by the calling class.<p> 175 * 176 * The default is <code>true</code>. 177 * If set to <code>false</code> Exceptions that occur internally will be wrapped into 178 * a RuntimeException and thrown to the calling class instance.<p> 179 * 180 * @return <code>true</code> if Exceptions are suppressed, or 181 * <code>false</code> if they will be thrown and have to be handled by the calling class 182 */ 183 public boolean isSupressingExceptions() { 184 185 return m_isSupressingExceptions; 186 } 187 188 /** 189 * Sets the content type for the HTTP response.<p> 190 * 191 * This method is required since JSP's are handled in a special way for included template elements, 192 * so {@link javax.servlet.ServletResponse#setContentType(java.lang.String)} won't work.<p> 193 * 194 * Please note that the content type set this way is never cached in the Flex cache, 195 * so you must make sure to not cache the element when you use this method.<p> 196 * 197 * @param type the type to set 198 * 199 * @see javax.servlet.ServletResponse#setContentType(java.lang.String) 200 */ 201 public void setContentType(String type) { 202 203 // set the content type on the top level response 204 m_controller.getTopResponse().setContentType(type); 205 } 206 207 /** 208 * Sets the status code for the HTTP response.<p> 209 * 210 * This method is required since JSP's are handled in a special way for included template elements, 211 * so {@link javax.servlet.http.HttpServletResponseWrapper#setStatus(int)} won't work.<p> 212 * 213 * Please note that the status code set this way is never cached in the Flex cache, 214 * so you must make sure to not cache the element when you use this method.<p> 215 * 216 * @param status the status code to set 217 * 218 * @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int) 219 */ 220 public void setStatus(int status) { 221 222 // use the request attribute to store the status 223 m_request.setAttribute(CmsRequestUtil.ATTRIBUTE_ERRORCODE, Integer.valueOf(status)); 224 } 225 226 /** 227 * Controls if Exceptions that occur in methods of this class are suppressed (true) 228 * or not (false).<p> 229 * 230 * The default is <code>true</code>. If set to <code>false</code> all Exceptions that 231 * occur internally will be wrapped into a RuntimeException and thrown to the calling 232 * class instance.<p> 233 * 234 * @param value the value to set the Exception handing to 235 */ 236 public void setSupressingExceptions(boolean value) { 237 238 m_isSupressingExceptions = value; 239 } 240 241 /** 242 * Returns the Flex controller derived from the request this bean was initialized with.<p> 243 * 244 * This is protected since the CmsFlexController this is really an internal OpenCms 245 * helper function, not part of the public OpenCms API. It must not be used on JSP pages, 246 * only from subclasses of this bean.<p> 247 * 248 * @return the Flex controller derived from the request this bean was initialized with 249 */ 250 protected CmsFlexController getController() { 251 252 return m_controller; 253 } 254 255 /** 256 * Internally localizes the given <code>CmsMessageContainer</code> to a String. <p> 257 * 258 * If the user request context is at hand, the user's locale will be chosen. If 259 * no user request context is available, the default locale is used. <p> 260 * 261 * @param container the message container that allows localization of the represented message. 262 * 263 * @return the message String of the container argument localized to the user's locale (if available) or 264 * to the default locale. 265 */ 266 protected String getMessage(CmsMessageContainer container) { 267 268 CmsObject cms = getCmsObject(); 269 String result; 270 if ((cms == null) || (cms.getRequestContext().getLocale() == null)) { 271 result = container.key(); 272 } else { 273 result = container.key(cms.getRequestContext().getLocale()); 274 } 275 return result; 276 } 277 278 /** 279 * Handles any exception that might occur in the context of this element to 280 * ensure that templates are not disturbed.<p> 281 * 282 * @param t the Throwable that was caught 283 */ 284 protected void handleException(Throwable t) { 285 286 if (LOG.isErrorEnabled()) { 287 LOG.error(Messages.get().getBundle().key(Messages.LOG_ERR_JSP_BEAN_0), t); 288 } 289 if (!(m_isSupressingExceptions || getRequestContext().getCurrentProject().isOnlineProject())) { 290 if (LOG.isDebugEnabled()) { 291 // no stack trace needed since it was already logged with the "error" log message above 292 LOG.debug( 293 Messages.get().getBundle().key(Messages.LOG_DEBUG_INTERRUPTED_EXCEPTION_1, getClass().getName())); 294 } 295 String uri = null; 296 Throwable u = getController().getThrowable(); 297 if (u != null) { 298 uri = getController().getThrowableResourceUri(); 299 } else { 300 uri = getRequestContext().getUri(); 301 } 302 throw new CmsRuntimeException( 303 Messages.get().container(Messages.ERR_RUNTIME_1, (uri != null) ? uri : getClass().getName()), 304 t); 305 } 306 } 307 308 /** 309 * This method is called when the flex controller can not be found during initialization.<p> 310 * 311 * Override this if you are reusing old workplace classes in a context where no flex controller is available. 312 */ 313 protected void handleMissingFlexController() { 314 315 // controller not found - this request was not initialized properly 316 throw new CmsRuntimeException( 317 Messages.get().container(Messages.ERR_MISSING_CMS_CONTROLLER_1, CmsJspBean.class.getName())); 318 } 319 320 /** 321 * Returns true if this bean has not been initialized (i.e. init() has not been called so far), false otherwise.<p> 322 * 323 * @return true if this bean has not been initialized 324 */ 325 protected boolean isNotInitialized() { 326 327 return m_isNotInitialized; 328 } 329}