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.workplace.commons; 029 030import org.opencms.configuration.CmsParameterConfiguration; 031import org.opencms.file.CmsResource; 032import org.opencms.file.CmsResource.CmsResourceDeleteMode; 033import org.opencms.file.CmsResourceFilter; 034import org.opencms.jsp.CmsJspActionElement; 035import org.opencms.main.CmsException; 036import org.opencms.main.CmsLog; 037import org.opencms.main.OpenCms; 038import org.opencms.security.CmsPermissionSet; 039import org.opencms.security.CmsRole; 040import org.opencms.util.CmsStringUtil; 041import org.opencms.workplace.CmsDialogSelector; 042import org.opencms.workplace.CmsMultiDialog; 043import org.opencms.workplace.CmsWorkplaceSettings; 044import org.opencms.workplace.I_CmsDialogHandler; 045import org.opencms.workplace.list.CmsListExplorerColumn; 046 047import java.io.IOException; 048import java.util.ArrayList; 049import java.util.Iterator; 050import java.util.List; 051 052import javax.servlet.ServletException; 053import javax.servlet.http.HttpServletRequest; 054import javax.servlet.http.HttpServletResponse; 055import javax.servlet.jsp.JspException; 056import javax.servlet.jsp.PageContext; 057 058import org.apache.commons.logging.Log; 059 060/** 061 * Provides methods for the delete resources dialog.<p> 062 * 063 * The following files use this class: 064 * <ul> 065 * <li>/commons/delete_standard.jsp 066 * </ul> 067 * <p> 068 * 069 * @since 6.0.0 070 */ 071public class CmsDelete extends CmsMultiDialog implements I_CmsDialogHandler { 072 073 /** Value for the action: delete the resource. */ 074 public static final int ACTION_DELETE = 100; 075 076 /** The dialog type. */ 077 public static final String DIALOG_TYPE = "delete"; 078 079 /** The log object for this class. */ 080 public static final Log LOG = CmsLog.getLog(CmsDelete.class); 081 082 /** Request parameter name for the deletesiblings parameter. */ 083 public static final String PARAM_DELETE_SIBLINGS = "deletesiblings"; 084 085 /** The delete dialog URI. */ 086 public static final String URI_DELETE_DIALOG = PATH_DIALOGS + "delete_standard.jsp"; 087 088 /** The delete siblings parameter value. */ 089 private String m_deleteSiblings; 090 091 /** 092 * Default constructor needed for dialog handler implementation.<p> 093 */ 094 public CmsDelete() { 095 096 super(null); 097 } 098 099 /** 100 * Public constructor with JSP action element.<p> 101 * 102 * @param jsp an initialized JSP action element 103 */ 104 public CmsDelete(CmsJspActionElement jsp) { 105 106 super(jsp); 107 } 108 109 /** 110 * Public constructor with JSP variables.<p> 111 * 112 * @param context the JSP page context 113 * @param req the JSP request 114 * @param res the JSP response 115 */ 116 public CmsDelete(PageContext context, HttpServletRequest req, HttpServletResponse res) { 117 118 this(new CmsJspActionElement(context, req, res)); 119 } 120 121 /** 122 * Performs the delete action, will be called by the JSP page.<p> 123 * 124 * @throws JspException if problems including sub-elements occur 125 */ 126 public void actionDelete() throws JspException { 127 128 // save initialized instance of this class in request attribute for included sub-elements 129 getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); 130 try { 131 boolean isFolder = false; 132 if (!isMultiOperation()) { 133 isFolder = getCms().readResource(getParamResource(), CmsResourceFilter.ALL).isFolder(); 134 } 135 if (performDialogOperation()) { 136 // if no exception is caused and "true" is returned delete operation was successful 137 if (isMultiOperation() || isFolder) { 138 // set request attribute to reload the explorer tree view 139 List<String> folderList = new ArrayList<String>(1); 140 folderList.add(CmsResource.getParentFolder(getResourceList().get(0))); 141 getJsp().getRequest().setAttribute(REQUEST_ATTRIBUTE_RELOADTREE, folderList); 142 } 143 actionCloseDialog(); 144 } else { 145 // "false" returned, display "please wait" screen 146 getJsp().include(FILE_DIALOG_SCREEN_WAIT); 147 } 148 } catch (Throwable e) { 149 // prepare common message part 150 includeErrorpage(this, e); 151 } 152 } 153 154 /** 155 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String) 156 */ 157 @Override 158 public void addConfigurationParameter(String paramName, String paramValue) { 159 160 // not implemented yet 161 162 } 163 164 /** 165 * Returns the html for the confirmation message.<p> 166 * 167 * @return the html for the confirmation message 168 */ 169 public String buildConfirmation() { 170 171 StringBuffer result = new StringBuffer(512); 172 boolean isFolder = false; 173 if (!isMultiOperation()) { 174 try { 175 isFolder = getCms().readResource(getParamResource(), CmsResourceFilter.ALL).isFolder(); 176 } catch (CmsException e) { 177 // ignore 178 } 179 } 180 result.append("<div id='conf-msg'>\n"); 181 if (isMultiOperation() || isFolder || (hasSiblings() && hasCorrectLockstate())) { 182 result.append(key(Messages.GUI_DELETE_MULTI_CONFIRMATION_0)); 183 } else { 184 result.append(key(Messages.GUI_DELETE_CONFIRMATION_0)); 185 } 186 result.append("\n</div>\n"); 187 return result.toString(); 188 } 189 190 /** 191 * Returns the html for the "delete siblings" options when deleting a a resource with siblings.<p> 192 * 193 * @return the html for the "delete siblings" options 194 */ 195 public String buildDeleteSiblings() { 196 197 StringBuffer result = new StringBuffer(512); 198 if (isMultiOperation() || (hasSiblings() && hasCorrectLockstate())) { 199 // show only for multi resource operation or if resource has siblings and correct lock state 200 CmsResourceDeleteMode defaultMode = Boolean.valueOf(getParamDeleteSiblings()).booleanValue() 201 ? CmsResource.DELETE_REMOVE_SIBLINGS 202 : CmsResource.DELETE_PRESERVE_SIBLINGS; 203 if (!isMultiOperation()) { 204 result.append(key(Messages.GUI_DELETE_WARNING_SIBLINGS_0)); 205 result.append("<p>"); 206 } 207 result.append("<input type=\"radio\" name=\""); 208 result.append(PARAM_DELETE_SIBLINGS); 209 result.append("radio\" value=\"false\""); 210 if (defaultMode == CmsResource.DELETE_PRESERVE_SIBLINGS) { 211 result.append(" checked=\"checked\""); 212 } 213 result.append(" onclick='reloadDialog(false);'> "); 214 result.append(key(Messages.GUI_DELETE_PRESERVE_SIBLINGS_0)); 215 result.append("<br>"); 216 result.append("<input type=\"radio\" name=\""); 217 result.append(PARAM_DELETE_SIBLINGS); 218 result.append("radio\" value=\"true\""); 219 if (defaultMode == CmsResource.DELETE_REMOVE_SIBLINGS) { 220 result.append(" checked=\"checked\""); 221 } 222 result.append(" onclick='reloadDialog(true);'> "); 223 result.append(key(Messages.GUI_DELETE_ALL_SIBLINGS_0)); 224 result.append("<p>"); 225 } 226 return result.toString(); 227 } 228 229 /** 230 * Returns html code for the possible broken relations.<p> 231 * 232 * @return html code for the possible broken relations 233 * 234 * @throws JspException if dialog actions fail 235 * @throws IOException in case of errros forwarding to the required result page 236 * @throws ServletException in case of errros forwarding to the required result page 237 */ 238 public String buildReport() throws JspException, ServletException, IOException { 239 240 CmsDeleteBrokenRelationsList list = new CmsDeleteBrokenRelationsList( 241 getJsp(), 242 getResourceList(), 243 Boolean.valueOf(getParamDeleteSiblings()).booleanValue()); 244 list.actionDialog(); 245 246 StringBuffer result = new StringBuffer(512); 247 list.getList().setBoxed(false); 248 result.append("<input type='hidden' name='result' value='"); 249 result.append(list.getList().getTotalSize()).append("'>\n"); 250 result.append(CmsListExplorerColumn.getExplorerStyleDef()); 251 result.append("<div style='height:150px; overflow: auto;'>\n"); 252 result.append(list.getList().listHtml()); 253 result.append("</div>\n"); 254 return result.toString(); 255 } 256 257 /** 258 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration() 259 */ 260 @Override 261 public CmsParameterConfiguration getConfiguration() { 262 263 return CmsParameterConfiguration.EMPTY_PARAMETERS; 264 } 265 266 /** 267 * @see org.opencms.workplace.I_CmsDialogHandler#getDialogHandler() 268 */ 269 @Override 270 public String getDialogHandler() { 271 272 return CmsDialogSelector.DIALOG_DELETE; 273 } 274 275 /** 276 * @see org.opencms.workplace.I_CmsDialogHandler#getDialogUri(java.lang.String, CmsJspActionElement) 277 */ 278 @Override 279 public String getDialogUri(String resource, CmsJspActionElement jsp) { 280 281 return URI_DELETE_DIALOG; 282 } 283 284 /** 285 * Returns the value of the boolean option to delete siblings.<p> 286 * 287 * @return the value of the boolean option to delete siblings as a lower case string 288 */ 289 public String getParamDeleteSiblings() { 290 291 return m_deleteSiblings; 292 } 293 294 /** 295 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration() 296 */ 297 @Override 298 public void initConfiguration() { 299 300 // not implemented yet 301 302 } 303 304 /** 305 * Returns <code>true</code> if the current user is allowed 306 * to delete the selected resources.<p> 307 * 308 * @return <code>true</code> if the current user is allowed 309 * to delete the selected resources 310 */ 311 public boolean isCanDelete() { 312 313 return OpenCms.getWorkplaceManager().getDefaultUserSettings().isAllowBrokenRelations() 314 || OpenCms.getRoleManager().hasRole(getCms(), CmsRole.VFS_MANAGER); 315 } 316 317 /** 318 * Sets the value of the boolean option to delete siblings.<p> 319 * 320 * @param value the value of the boolean option to delete siblings 321 */ 322 public void setParamDeleteSiblings(String value) { 323 324 m_deleteSiblings = value; 325 } 326 327 /** 328 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 329 */ 330 @Override 331 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 332 333 // fill the parameter values in the get/set methods 334 fillParamValues(request); 335 336 if (CmsStringUtil.isEmptyOrWhitespaceOnly(getParamDeleteSiblings())) { 337 setParamDeleteSiblings(Boolean.toString( 338 getSettings().getUserSettings().getDialogDeleteFileMode() == CmsResource.DELETE_REMOVE_SIBLINGS)); 339 } 340 // check the required permissions to delete the resource 341 if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) { 342 // no write permissions for the resource, set cancel action to close dialog 343 setParamAction(DIALOG_CANCEL); 344 } 345 346 // set the dialog type 347 setParamDialogtype(DIALOG_TYPE); 348 // set the action for the JSP switch 349 if (DIALOG_TYPE.equals(getParamAction())) { 350 setAction(ACTION_DELETE); 351 } else if (DIALOG_LOCKS_CONFIRMED.equals(getParamAction())) { 352 setAction(ACTION_LOCKS_CONFIRMED); 353 } else if (DIALOG_WAIT.equals(getParamAction())) { 354 setAction(ACTION_WAIT); 355 } else if (DIALOG_CANCEL.equals(getParamAction())) { 356 setAction(ACTION_CANCEL); 357 } else { 358 setAction(ACTION_DEFAULT); 359 // build title for delete dialog 360 setDialogTitle(Messages.GUI_DELETE_RESOURCE_1, Messages.GUI_DELETE_MULTI_2); 361 } 362 } 363 364 /** 365 * Performs the resource deletion.<p> 366 * 367 * @return true, if the resource(s) was/were deleted, otherwise false 368 * @throws CmsException if deletion is not successful 369 */ 370 @Override 371 protected boolean performDialogOperation() throws CmsException { 372 373 // check if the current resource is a folder for single operation 374 boolean isFolder = isOperationOnFolder(); 375 // on folder deletion or multi operation display "please wait" screen, not for simple file deletion 376 if ((isMultiOperation() || isFolder) && !DIALOG_WAIT.equals(getParamAction())) { 377 // return false, this will trigger the "please wait" screen 378 return false; 379 } 380 381 // determine the correct delete option 382 CmsResourceDeleteMode deleteOption = Boolean.valueOf(getParamDeleteSiblings()).booleanValue() 383 ? CmsResource.DELETE_REMOVE_SIBLINGS 384 : CmsResource.DELETE_PRESERVE_SIBLINGS; 385 386 Iterator<String> i = getResourceList().iterator(); 387 // iterate the resources to delete 388 while (i.hasNext()) { 389 String resName = i.next(); 390 try { 391 performSingleDeleteOperation(resName, deleteOption); 392 } catch (CmsException e) { 393 if (isMultiOperation()) { 394 // collect exceptions to create a detailed output 395 addMultiOperationException(e); 396 } else { 397 // for single operation, throw the exception immediately 398 throw e; 399 } 400 } 401 } 402 // check if exceptions occurred 403 checkMultiOperationException(Messages.get(), Messages.ERR_DELETE_MULTI_0); 404 405 return true; 406 } 407 408 /** 409 * Performs the delete operation for a single VFS resource.<p> 410 * 411 * @param resource the resource VFS path 412 * @param deleteOption the delete option for sibling deletion 413 * @throws CmsException if deleting the resource fails 414 */ 415 protected void performSingleDeleteOperation(String resource, CmsResourceDeleteMode deleteOption) 416 throws CmsException { 417 418 // lock resource if autolock is enabled 419 checkLock(resource); 420 // delete the resource 421 getCms().deleteResource(resource, deleteOption); 422 } 423 424}