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, 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.workplace.editors.directedit; 029 030import org.opencms.db.CmsUserSettings; 031import org.opencms.file.CmsObject; 032import org.opencms.flex.CmsFlexController; 033import org.opencms.flex.CmsFlexResponse; 034import org.opencms.i18n.CmsEncoder; 035import org.opencms.jsp.CmsJspTagInclude; 036import org.opencms.loader.I_CmsResourceLoader; 037import org.opencms.util.CmsRequestUtil; 038import org.opencms.util.CmsStringUtil; 039 040import java.io.IOException; 041import java.util.HashMap; 042import java.util.Map; 043 044import javax.servlet.ServletException; 045import javax.servlet.ServletRequest; 046import javax.servlet.ServletResponse; 047import javax.servlet.jsp.JspException; 048import javax.servlet.jsp.PageContext; 049 050/** 051 * Direct edit provider that uses the same JSP include based logic that has been 052 * the default before the 6.2.3 release.<p> 053 * 054 * Even though placing the HTML of the direct edit buttons appears to be more "flexible" at first, 055 * there is a large overhead invloved using this provider as compared to an implementation 056 * like {@link CmsDirectEditDefaultProvider}. For every direct edit button on a page, 057 * a JSP include is processed <i>twice</i> using this provider, 058 * one include for the opening and one for the closing HTML. A JSP include is a costly operation, which means 059 * the performance of a website is be impacted if many content managers work on the system that makes great 060 * use of direct edit with a lot of elements on a page. In order to avoid this performance impact, 061 * OpenCms since version 6.2.3 uses the {@link CmsDirectEditDefaultProvider} by default.<p> 062 * 063 * This provider DOES NOT support {@link CmsDirectEditMode#MANUAL} mode.<p> 064 * 065 * @since 6.2.3 066 */ 067public class CmsDirectEditJspIncludeProvider extends A_CmsDirectEditProvider { 068 069 /** Prefix for direct edit end elements, used on JPS pages that supply the direct edit html. */ 070 public static final String DIRECT_EDIT_AREA_END = "end_directedit"; 071 072 /** Prefix for direct edit start elements, used on JPS pages that supply the direct edit html. */ 073 public static final String DIRECT_EDIT_AREA_START = "start_directedit"; 074 075 /** Default direct edit include file URI. */ 076 public static final String DIRECT_EDIT_INCLUDE_FILE_URI_DEFAULT = "/system/workplace/editors/direct_edit.jsp"; 077 078 /** Element name for direct edit includes. */ 079 public static final String DIRECT_EDIT_INCLUDES = "directedit_includes"; 080 081 /** Key to identify the edit button style, used on JPS pages that supply the direct edit html. */ 082 public static final String DIRECT_EDIT_PARAM_BUTTONSTYLE = "__directEditButtonStyle"; 083 084 /** Key to identify the edit element, used on JPS pages that supply the direct edit html. */ 085 public static final String DIRECT_EDIT_PARAM_ELEMENT = "__directEditElement"; 086 087 /** Key to identify the edit language, used on JPS pages that supply the direct edit html. */ 088 public static final String DIRECT_EDIT_PARAM_LOCALE = "__directEditLocale"; 089 090 /** Key to identify the link to use for the "new" button (if enabled). */ 091 public static final String DIRECT_EDIT_PARAM_NEWLINK = "__directEditNewLink"; 092 093 /** Key to identify additional direct edit options, used e.g. to control which direct edit buttons are displayed */ 094 public static final String DIRECT_EDIT_PARAM_OPTIONS = "__directEditOptions"; 095 096 /** Key to identify the edit target, used on JPS pages that supply the direct edit html. */ 097 public static final String DIRECT_EDIT_PARAM_TARGET = "__directEditTarget"; 098 099 /** The last direct edit element. */ 100 protected String m_editElement; 101 102 /** The last direct edit target. */ 103 protected String m_editTarget; 104 105 /** The last calculated direct edit permissions. */ 106 protected String m_permissions; 107 108 /** 109 * Includes the "direct edit" element that adds HTML for the editable area to 110 * the output page.<p> 111 * 112 * @param context the current JSP page context 113 * @param jspIncludeFile the VFS path of the JSP that contains the direct edit HTML fragments 114 * @param element the editor element to include 115 * @param editTarget the direct edit target 116 * @param editElement the direct edit element 117 * @param editOptions the direct edit options 118 * @param editPermissions the direct edit permissions 119 * @param createLink the direct edit create link 120 * 121 * @throws JspException in case something goes wrong 122 * 123 * @return the direct edit permissions 124 */ 125 public static String includeDirectEditElement( 126 PageContext context, 127 String jspIncludeFile, 128 String element, 129 String editTarget, 130 String editElement, 131 String editOptions, 132 String editPermissions, 133 String createLink) 134 throws JspException { 135 136 if (editPermissions == null) { 137 // we do not have direct edit permissions 138 return null; 139 } 140 141 ServletRequest req = context.getRequest(); 142 ServletResponse res = context.getResponse(); 143 CmsFlexController controller = CmsFlexController.getController(req); 144 145 // append "direct edit" permissions to element 146 element = element + "_" + editPermissions; 147 148 // set request parameters required by the included direct edit JSP 149 Map<String, String[]> parameterMap = new HashMap<String, String[]>(); 150 CmsJspTagInclude.addParameter(parameterMap, I_CmsResourceLoader.PARAMETER_ELEMENT, element, true); 151 CmsJspTagInclude.addParameter(parameterMap, DIRECT_EDIT_PARAM_TARGET, editTarget, true); 152 CmsJspTagInclude.addParameter( 153 parameterMap, 154 DIRECT_EDIT_PARAM_LOCALE, 155 controller.getCmsObject().getRequestContext().getLocale().toString(), 156 true); 157 CmsUserSettings settings = new CmsUserSettings(controller.getCmsObject()); 158 CmsJspTagInclude.addParameter( 159 parameterMap, 160 DIRECT_EDIT_PARAM_BUTTONSTYLE, 161 String.valueOf(settings.getDirectEditButtonStyle()), 162 true); 163 if (editElement != null) { 164 CmsJspTagInclude.addParameter(parameterMap, DIRECT_EDIT_PARAM_ELEMENT, editElement, true); 165 } 166 if (editOptions != null) { 167 CmsJspTagInclude.addParameter(parameterMap, DIRECT_EDIT_PARAM_OPTIONS, editOptions, true); 168 } 169 if (createLink != null) { 170 CmsJspTagInclude.addParameter(parameterMap, DIRECT_EDIT_PARAM_NEWLINK, CmsEncoder.encode(createLink), true); 171 } 172 173 // save old parameters from current request 174 Map<String, String[]> oldParameterMap = controller.getCurrentRequest().getParameterMap(); 175 176 try { 177 controller.getCurrentRequest().addParameterMap(parameterMap); 178 context.getOut().print(CmsFlexResponse.FLEX_CACHE_DELIMITER); 179 controller.getCurrentResponse().addToIncludeList( 180 jspIncludeFile, 181 parameterMap, 182 CmsRequestUtil.getAtrributeMap(req)); 183 controller.getCurrentRequest().getRequestDispatcher(jspIncludeFile).include(req, res); 184 } catch (ServletException e) { 185 Throwable t; 186 if (e.getRootCause() != null) { 187 t = e.getRootCause(); 188 } else { 189 t = e; 190 } 191 t = controller.setThrowable(t, jspIncludeFile); 192 throw new JspException(t); 193 } catch (IOException e) { 194 Throwable t = controller.setThrowable(e, jspIncludeFile); 195 throw new JspException(t); 196 } finally { 197 // restore old parameter map (if required) 198 if (oldParameterMap != null) { 199 controller.getCurrentRequest().setParameterMap(oldParameterMap); 200 } 201 } 202 203 return editPermissions; 204 } 205 206 /** 207 * @see org.opencms.workplace.editors.directedit.A_CmsDirectEditProvider#init(org.opencms.file.CmsObject, org.opencms.workplace.editors.directedit.CmsDirectEditMode, java.lang.String) 208 */ 209 @Override 210 public void init(CmsObject cms, CmsDirectEditMode mode, String fileName) { 211 212 m_cms = cms; 213 m_fileName = fileName; 214 if (CmsStringUtil.isEmpty(m_fileName)) { 215 m_fileName = DIRECT_EDIT_INCLUDE_FILE_URI_DEFAULT; 216 } 217 m_mode = mode != null ? mode : CmsDirectEditMode.AUTO; 218 } 219 220 /** 221 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditEnd(javax.servlet.jsp.PageContext) 222 */ 223 public void insertDirectEditEnd(PageContext context) throws JspException { 224 225 if (m_editTarget != null) { 226 // otherwise no valid direct edit element has been opened 227 includeDirectEditElement( 228 context, 229 m_fileName, 230 DIRECT_EDIT_AREA_END, 231 m_editTarget, 232 m_editElement, 233 null, 234 m_permissions, 235 null); 236 m_editTarget = null; 237 m_permissions = null; 238 m_editElement = null; 239 } 240 } 241 242 /** 243 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditIncludes(javax.servlet.jsp.PageContext, org.opencms.workplace.editors.directedit.CmsDirectEditParams) 244 */ 245 public void insertDirectEditIncludes(PageContext context, CmsDirectEditParams params) throws JspException { 246 247 try { 248 CmsJspTagInclude.includeTagAction( 249 context, 250 m_fileName, 251 DIRECT_EDIT_INCLUDES, 252 false, 253 null, 254 null, 255 context.getRequest(), 256 context.getResponse()); 257 } catch (Throwable t) { 258 // should never happen 259 throw new JspException(t); 260 } 261 } 262 263 /** 264 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditStart(javax.servlet.jsp.PageContext, org.opencms.workplace.editors.directedit.CmsDirectEditParams) 265 */ 266 public boolean insertDirectEditStart(PageContext context, CmsDirectEditParams params) throws JspException { 267 268 String result = null; 269 CmsDirectEditPermissions permissions = getResourceInfo(params, params.getResourceName()).getPermissions(); 270 if (permissions.getPermission() > 0) { 271 // permission to direct edit is granted 272 m_permissions = permissions.toString(); 273 m_editTarget = params.getResourceName(); 274 m_editElement = params.getElement(); 275 276 result = includeDirectEditElement( 277 context, 278 m_fileName, 279 DIRECT_EDIT_AREA_START, 280 m_editTarget, 281 m_editElement, 282 params.getButtonSelection().toString(), 283 m_permissions, 284 params.getLinkForNew()); 285 286 } else { 287 // no direct edit permissions 288 m_editTarget = null; 289 m_permissions = null; 290 m_editElement = null; 291 } 292 return result != null; 293 } 294 295 /** 296 * Returns <code>false</code> because the JSP include provider does not support manual button placement.<p> 297 * 298 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#isManual(org.opencms.workplace.editors.directedit.CmsDirectEditMode) 299 */ 300 @Override 301 public boolean isManual(CmsDirectEditMode mode) { 302 303 return false; 304 } 305 306 /** 307 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#newInstance() 308 */ 309 public I_CmsDirectEditProvider newInstance() { 310 311 CmsDirectEditJspIncludeProvider result = new CmsDirectEditJspIncludeProvider(); 312 result.m_configurationParameters = m_configurationParameters; 313 return result; 314 } 315}