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) throws JspException { 134 135 if (editPermissions == null) { 136 // we do not have direct edit permissions 137 return null; 138 } 139 140 ServletRequest req = context.getRequest(); 141 ServletResponse res = context.getResponse(); 142 CmsFlexController controller = CmsFlexController.getController(req); 143 144 // append "direct edit" permissions to element 145 element = element + "_" + editPermissions; 146 147 // set request parameters required by the included direct edit JSP 148 Map<String, String[]> parameterMap = new HashMap<String, String[]>(); 149 CmsJspTagInclude.addParameter(parameterMap, I_CmsResourceLoader.PARAMETER_ELEMENT, element, true); 150 CmsJspTagInclude.addParameter(parameterMap, DIRECT_EDIT_PARAM_TARGET, editTarget, true); 151 CmsJspTagInclude.addParameter( 152 parameterMap, 153 DIRECT_EDIT_PARAM_LOCALE, 154 controller.getCmsObject().getRequestContext().getLocale().toString(), 155 true); 156 CmsUserSettings settings = new CmsUserSettings(controller.getCmsObject()); 157 CmsJspTagInclude.addParameter( 158 parameterMap, 159 DIRECT_EDIT_PARAM_BUTTONSTYLE, 160 String.valueOf(settings.getDirectEditButtonStyle()), 161 true); 162 if (editElement != null) { 163 CmsJspTagInclude.addParameter(parameterMap, DIRECT_EDIT_PARAM_ELEMENT, editElement, true); 164 } 165 if (editOptions != null) { 166 CmsJspTagInclude.addParameter(parameterMap, DIRECT_EDIT_PARAM_OPTIONS, editOptions, true); 167 } 168 if (createLink != null) { 169 CmsJspTagInclude.addParameter(parameterMap, DIRECT_EDIT_PARAM_NEWLINK, CmsEncoder.encode(createLink), true); 170 } 171 172 // save old parameters from current request 173 Map<String, String[]> oldParameterMap = controller.getCurrentRequest().getParameterMap(); 174 175 try { 176 controller.getCurrentRequest().addParameterMap(parameterMap); 177 context.getOut().print(CmsFlexResponse.FLEX_CACHE_DELIMITER); 178 controller.getCurrentResponse().addToIncludeList( 179 jspIncludeFile, 180 parameterMap, 181 CmsRequestUtil.getAtrributeMap(req)); 182 controller.getCurrentRequest().getRequestDispatcher(jspIncludeFile).include(req, res); 183 } catch (ServletException e) { 184 Throwable t; 185 if (e.getRootCause() != null) { 186 t = e.getRootCause(); 187 } else { 188 t = e; 189 } 190 t = controller.setThrowable(t, jspIncludeFile); 191 throw new JspException(t); 192 } catch (IOException e) { 193 Throwable t = controller.setThrowable(e, jspIncludeFile); 194 throw new JspException(t); 195 } finally { 196 // restore old parameter map (if required) 197 if (oldParameterMap != null) { 198 controller.getCurrentRequest().setParameterMap(oldParameterMap); 199 } 200 } 201 202 return editPermissions; 203 } 204 205 /** 206 * @see org.opencms.workplace.editors.directedit.A_CmsDirectEditProvider#init(org.opencms.file.CmsObject, org.opencms.workplace.editors.directedit.CmsDirectEditMode, java.lang.String) 207 */ 208 @Override 209 public void init(CmsObject cms, CmsDirectEditMode mode, String fileName) { 210 211 m_cms = cms; 212 m_fileName = fileName; 213 if (CmsStringUtil.isEmpty(m_fileName)) { 214 m_fileName = DIRECT_EDIT_INCLUDE_FILE_URI_DEFAULT; 215 } 216 m_mode = mode != null ? mode : CmsDirectEditMode.AUTO; 217 } 218 219 /** 220 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditEnd(javax.servlet.jsp.PageContext) 221 */ 222 public void insertDirectEditEnd(PageContext context) throws JspException { 223 224 if (m_editTarget != null) { 225 // otherwise no valid direct edit element has been opened 226 includeDirectEditElement( 227 context, 228 m_fileName, 229 DIRECT_EDIT_AREA_END, 230 m_editTarget, 231 m_editElement, 232 null, 233 m_permissions, 234 null); 235 m_editTarget = null; 236 m_permissions = null; 237 m_editElement = null; 238 } 239 } 240 241 /** 242 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditIncludes(javax.servlet.jsp.PageContext, org.opencms.workplace.editors.directedit.CmsDirectEditParams) 243 */ 244 public void insertDirectEditIncludes(PageContext context, CmsDirectEditParams params) throws JspException { 245 246 try { 247 CmsJspTagInclude.includeTagAction( 248 context, 249 m_fileName, 250 DIRECT_EDIT_INCLUDES, 251 false, 252 null, 253 null, 254 context.getRequest(), 255 context.getResponse()); 256 } catch (Throwable t) { 257 // should never happen 258 throw new JspException(t); 259 } 260 } 261 262 /** 263 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditStart(javax.servlet.jsp.PageContext, org.opencms.workplace.editors.directedit.CmsDirectEditParams) 264 */ 265 public boolean insertDirectEditStart(PageContext context, CmsDirectEditParams params) throws JspException { 266 267 String result = null; 268 CmsDirectEditPermissions permissions = getResourceInfo(params.getResourceName()).getPermissions(); 269 if (permissions.getPermission() > 0) { 270 // permission to direct edit is granted 271 m_permissions = permissions.toString(); 272 m_editTarget = params.getResourceName(); 273 m_editElement = params.getElement(); 274 275 result = includeDirectEditElement( 276 context, 277 m_fileName, 278 DIRECT_EDIT_AREA_START, 279 m_editTarget, 280 m_editElement, 281 params.getButtonSelection().toString(), 282 m_permissions, 283 params.getLinkForNew()); 284 285 } else { 286 // no direct edit permissions 287 m_editTarget = null; 288 m_permissions = null; 289 m_editElement = null; 290 } 291 return result != null; 292 } 293 294 /** 295 * Returns <code>false</code> because the JSP include provider does not support manual button placement.<p> 296 * 297 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#isManual(org.opencms.workplace.editors.directedit.CmsDirectEditMode) 298 */ 299 @Override 300 public boolean isManual(CmsDirectEditMode mode) { 301 302 return false; 303 } 304 305 /** 306 * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#newInstance() 307 */ 308 public I_CmsDirectEditProvider newInstance() { 309 310 CmsDirectEditJspIncludeProvider result = new CmsDirectEditJspIncludeProvider(); 311 result.m_configurationParameters = m_configurationParameters; 312 return result; 313 } 314}