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.CmsObject; 032import org.opencms.file.CmsResource; 033import org.opencms.file.CmsResourceFilter; 034import org.opencms.jsp.CmsJspActionElement; 035import org.opencms.lock.CmsLockFilter; 036import org.opencms.main.CmsException; 037import org.opencms.main.CmsLog; 038import org.opencms.relations.CmsRelation; 039import org.opencms.relations.CmsRelationFilter; 040import org.opencms.security.CmsPermissionSet; 041import org.opencms.util.CmsStringUtil; 042import org.opencms.workplace.CmsDialog; 043import org.opencms.workplace.CmsDialogSelector; 044import org.opencms.workplace.CmsMultiDialog; 045import org.opencms.workplace.CmsWorkplace; 046import org.opencms.workplace.CmsWorkplaceSettings; 047import org.opencms.workplace.I_CmsDialogHandler; 048import org.opencms.workplace.list.CmsListExplorerColumn; 049 050import java.io.IOException; 051import java.util.ArrayList; 052import java.util.Collections; 053import java.util.HashMap; 054import java.util.HashSet; 055import java.util.Iterator; 056import java.util.List; 057import java.util.Map; 058import java.util.Set; 059 060import javax.servlet.ServletException; 061import javax.servlet.http.HttpServletRequest; 062import javax.servlet.http.HttpServletResponse; 063import javax.servlet.jsp.JspException; 064import javax.servlet.jsp.PageContext; 065 066import org.apache.commons.logging.Log; 067 068/** 069 * Creates the dialogs for locking, unlocking or steal lock operations on a resource.<p> 070 * 071 * The following files use this class: 072 * <ul> 073 * <li>/commons/lock_standard.jsp 074 * <li>/commons/lockchange_standard.jsp 075 * <li>/commons/unlock_standard.jsp 076 * <li>/commons/locks.jsp 077 * </ul> 078 * <p> 079 * 080 * @since 6.0.0 081 */ 082public class CmsLock extends CmsMultiDialog implements I_CmsDialogHandler { 083 084 /** Value for the action: confirmed. */ 085 public static final int ACTION_SUBMIT_NOCONFIRMATION = 200; 086 087 /** Request parameter value for the action: submit form without user interaction. */ 088 public static final String DIALOG_SUBMIT_NOCONFIRMATION = "submitnoconfirmation"; 089 090 /** The dialog type: lock a resource. */ 091 public static final String DIALOG_TYPE_LOCK = "lock"; 092 093 /** The dialog type: Steal a lock. */ 094 public static final String DIALOG_TYPE_LOCKCHANGE = "lockchange"; 095 096 /** The dialog type: locked subresources. */ 097 public static final String DIALOG_TYPE_LOCKS = "locks"; 098 099 /** The dialog type: unlock a resource. */ 100 public static final String DIALOG_TYPE_UNLOCK = "unlock"; 101 102 /** Request parameter name for the 'include unpublished related resources' flag. */ 103 public static final String PARAM_INCLUDERELATED = "includerelated"; 104 105 /** Request parameter name for the project id. */ 106 public static final String PARAM_PROJECT_ID = "projectid"; 107 108 /** Request parameter name for the publishsiblings parameter. */ 109 public static final String PARAM_PUBLISHSIBLINGS = "publishsiblings"; 110 111 /** Request parameter name for the 'show own locked resources' flag. */ 112 public static final String PARAM_SHOWOWNLOCKS = "showownlocks"; 113 114 /** Request parameter name for the source dialog uri. */ 115 public static final String PARAM_SOURCE_DIALOG = "sourcedialog"; 116 117 /** Request parameter name for the subresources parameter. */ 118 public static final String PARAM_SUBRESOURCES = "subresources"; 119 120 /** Type of the operation which is performed: lock resource. */ 121 public static final int TYPE_LOCK = 1; 122 123 /** Type of the operation which is performed: steal a lock. */ 124 public static final int TYPE_LOCKCHANGE = 2; 125 126 /** Type of the operation which is performed: locked subresources. */ 127 public static final int TYPE_LOCKS = 4; 128 129 /** Type of the operation which is performed: unlock resource. */ 130 public static final int TYPE_UNLOCK = 3; 131 132 /** The lock dialog URI. */ 133 public static final String URI_LOCK_DIALOG = PATH_DIALOGS + "lock_standard.jsp"; 134 135 /** The steal lock dialog URI. */ 136 public static final String URI_LOCKCHANGE_DIALOG = PATH_DIALOGS + "lockchange_standard.jsp"; 137 138 /** The locks dialog URI. */ 139 public static final String URI_LOCKS_DIALOG = PATH_DIALOGS + "locks.jsp"; 140 141 /** The unlock dialog URI. */ 142 public static final String URI_UNLOCK_DIALOG = PATH_DIALOGS + "unlock_standard.jsp"; 143 144 /** The log object for this class. */ 145 private static final Log LOG = CmsLog.getLog(CmsLock.class); 146 147 /** the filter to get all blocking locks. */ 148 private CmsLockFilter m_blockingFilter; 149 150 /** the nunmber of blocking locked resources. */ 151 private int m_blockingLocks = -1; 152 153 /** The list of locked resources. */ 154 private List<String> m_lockedResources; 155 156 /** the filter to get all non blocking locks. */ 157 private CmsLockFilter m_nonBlockingFilter; 158 159 /** The 'include unpublished related resources' parameter value. */ 160 private String m_paramIncluderelated; 161 162 /** The project id parameter value. */ 163 private String m_paramProjectid; 164 165 /** The 'show own locked resources' parameter value. */ 166 private String m_paramShowownlocks; 167 168 /** 169 * Default constructor needed for dialog handler implementation.<p> 170 */ 171 public CmsLock() { 172 173 super(null); 174 } 175 176 /** 177 * Public constructor.<p> 178 * 179 * @param jsp an initialized JSP action element 180 */ 181 public CmsLock(CmsJspActionElement jsp) { 182 183 super(jsp); 184 } 185 186 /** 187 * Public constructor with JSP variables.<p> 188 * 189 * @param context the JSP page context 190 * @param req the JSP request 191 * @param res the JSP response 192 */ 193 public CmsLock(PageContext context, HttpServletRequest req, HttpServletResponse res) { 194 195 this(new CmsJspActionElement(context, req, res)); 196 } 197 198 /** 199 * Returns the html code to build the lock dialog.<p> 200 * 201 * @return html code 202 * 203 * @throws CmsException if something goes wrong 204 */ 205 public static String buildLockDialog(CmsDialog dialog) throws CmsException { 206 207 return buildLockDialog(dialog, null, null, 2000, false); 208 } 209 210 /** 211 * Returns the html code to build the lock dialog.<p> 212 * 213 * @param nonBlockingFilter the filter to get all non blocking locks 214 * @param blockingFilter the filter to get all blocking locks 215 * @param hiddenTimeout the maximal number of milliseconds the dialog will be hidden 216 * @param includeRelated indicates if the report should include related resources 217 * 218 * @return html code 219 * 220 * @throws CmsException if something goes wrong 221 */ 222 public static String buildLockDialog( 223 CmsDialog dialog, 224 CmsLockFilter nonBlockingFilter, 225 CmsLockFilter blockingFilter, 226 int hiddenTimeout, 227 boolean includeRelated) throws CmsException { 228 229 dialog.setParamAction(CmsDialog.DIALOG_LOCKS_CONFIRMED); 230 CmsLock lockwp = new CmsLock(dialog.getJsp()); 231 lockwp.setBlockingFilter(blockingFilter); 232 lockwp.setNonBlockingFilter(nonBlockingFilter); 233 234 StringBuffer html = new StringBuffer(512); 235 html.append(dialog.htmlStart("help.explorer.contextmenu.lock")); 236 html.append(lockwp.buildIncludeJs()); 237 html.append(dialog.buildLockConfirmationMessageJS()); 238 html.append(dialog.bodyStart("dialog")); 239 html.append("<div id='lock-body-id' class='hide'>\n"); 240 html.append(dialog.dialogStart()); 241 html.append(dialog.dialogContentStart(dialog.getParamTitle())); 242 html.append(dialog.buildLockHeaderBox()); 243 html.append(dialog.dialogSpacer()); 244 html.append("<form name='main' action='"); 245 html.append(dialog.getDialogUri()); 246 html.append("' method='post' class='nomargin' onsubmit=\"return submitAction('"); 247 html.append(CmsDialog.DIALOG_OK); 248 html.append("', null, 'main');\">\n"); 249 html.append(dialog.paramsAsHidden()); 250 html.append("<input type='hidden' name='"); 251 html.append(CmsDialog.PARAM_FRAMENAME); 252 html.append("' value=''>\n"); 253 html.append( 254 dialog.buildAjaxResultContainer( 255 dialog.key(org.opencms.workplace.commons.Messages.GUI_LOCK_RESOURCES_TITLE_0))); 256 html.append("<div id='conf-msg'></div>\n"); 257 html.append(dialog.buildLockAdditionalOptions()); 258 html.append(dialog.dialogContentEnd()); 259 html.append(dialog.dialogLockButtons()); 260 html.append("</form>\n"); 261 html.append(dialog.dialogEnd()); 262 html.append("</div>\n"); 263 html.append(dialog.bodyEnd()); 264 html.append(lockwp.buildLockRequest(hiddenTimeout, includeRelated)); 265 html.append(dialog.htmlEnd()); 266 return html.toString(); 267 } 268 269 /** 270 * Determines if the resource should be locked, unlocked or if the lock should be stolen.<p> 271 * 272 * @param cms the CmsObject 273 * @return the dialog action: lock, change lock (steal) or unlock 274 */ 275 public static int getDialogAction(CmsObject cms) { 276 277 String fileName = CmsResource.getName(cms.getRequestContext().getUri()); 278 if (fileName == null) { 279 // file name could not be determined, return "see locked subresources" action 280 return TYPE_LOCKS; 281 } else if (fileName.equalsIgnoreCase("lock.jsp")) { 282 // a "lock" action is requested 283 return TYPE_LOCK; 284 } else if (fileName.indexOf("change") != -1) { 285 // a "steal lock" action is requested 286 return TYPE_LOCKCHANGE; 287 } else if (fileName.indexOf("unlock") != -1) { 288 // an "unlock" action is requested 289 return TYPE_UNLOCK; 290 } else { 291 // an "see locked subresources" action is requested 292 return TYPE_LOCKS; 293 } 294 } 295 296 /** 297 * Performs the lock/unlock operation, will be called by the JSP page.<p> 298 * 299 * @throws JspException if problems including sub-elements occur 300 */ 301 public void actionToggleLock() throws JspException { 302 303 // save initialized instance of this class in request attribute for included sub-elements 304 getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); 305 306 try { 307 if (performDialogOperation()) { 308 // if no exception is caused and "true" is returned the lock/unlock operation was successful 309 actionCloseDialog(); 310 } else { 311 // "false" returned, display "please wait" screen 312 getJsp().include(FILE_DIALOG_SCREEN_WAIT); 313 } 314 } catch (Throwable e) { 315 // exception occurred, show error dialog 316 includeErrorpage(this, e); 317 } 318 } 319 320 /** 321 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String) 322 */ 323 @Override 324 public void addConfigurationParameter(String paramName, String paramValue) { 325 326 // not implemented yet 327 328 } 329 330 /** 331 * Returns the html code to build the dialogs default confirmation message js.<p> 332 * 333 * @return html code 334 */ 335 public String buildDefaultConfirmationJS() { 336 337 StringBuffer html = new StringBuffer(512); 338 html.append("<script ><!--\n"); 339 html.append("function setConfirmationMessage(locks, blockinglocks) {\n"); 340 html.append("\tvar confMsg = document.getElementById('conf-msg');\n"); 341 html.append("\tif (locks > -1) {\n"); 342 if (!getSettings().getUserSettings().getDialogShowLock() 343 && (CmsLock.getDialogAction(getCms()) != CmsLock.TYPE_LOCKS)) { 344 // auto commit if lock dialog disabled 345 html.append("\t\tif (blockinglocks == 0) {\n"); 346 html.append("\t\t\tsubmitAction('"); 347 html.append(CmsDialog.DIALOG_OK); 348 html.append("', null, 'main');\n"); 349 html.append("\t\t\tdocument.forms['main'].submit();\n"); 350 html.append("\t\t\treturn;\n"); 351 html.append("\t\t}\n"); 352 } 353 html.append("\t\tdocument.getElementById('lock-body-id').className = '';\n"); 354 html.append("\t\tif (locks > '0') {\n"); 355 html.append("\t\t\tshowAjaxReportContent();\n"); 356 html.append("\t\t\tconfMsg.innerHTML = '"); 357 html.append(getConfirmationMessage(false)); 358 html.append("';\n"); 359 html.append("\t\t} else {\n"); 360 html.append("\t\t\tshowAjaxOk();\n"); 361 html.append("\t\t\tconfMsg.innerHTML = '"); 362 html.append(getConfirmationMessage(true)); 363 html.append("';\n"); 364 html.append("\t\t}\n"); 365 html.append("\t} else {\n"); 366 html.append("\t\tconfMsg.innerHTML = '"); 367 html.append(key(org.opencms.workplace.Messages.GUI_AJAX_REPORT_WAIT_0)); 368 html.append("';\n"); 369 html.append("\t}\n"); 370 html.append("}\n"); 371 html.append("// -->\n"); 372 html.append("</script>\n"); 373 return html.toString(); 374 } 375 376 /** 377 * Returns the html code to include the needed js code.<p> 378 * 379 * @return html code 380 */ 381 public String buildIncludeJs() { 382 383 StringBuffer html = new StringBuffer(512); 384 html.append("<script src='"); 385 html.append(CmsWorkplace.getSkinUri()); 386 html.append("commons/ajax.js'></script>\n"); 387 html.append("<script src='"); 388 html.append(CmsWorkplace.getSkinUri()); 389 html.append("editors/xmlcontent/help.js'></script>\n"); 390 html.append("<script src='"); 391 html.append(CmsWorkplace.getSkinUri()); 392 html.append("admin/javascript/general.js'></script>\n"); 393 html.append("<script src='"); 394 html.append(CmsWorkplace.getSkinUri()); 395 html.append("admin/javascript/list.js'></script>\n"); 396 html.append("<script ><!--\n"); 397 html.append("function showAjaxOk() {\n"); 398 html.append("\tdocument.getElementById('ajaxreport-img').src = '"); 399 html.append(CmsWorkplace.getSkinUri()); 400 html.append("commons/ok.png';\n"); 401 html.append("\tdocument.getElementById('ajaxreport-txt').innerHTML = '"); 402 html.append(key(Messages.GUI_OPERATION_NO_LOCKS_0)); 403 html.append("';\n"); 404 html.append("}\n"); 405 html.append("var ajaxReportContent = '';\n"); 406 html.append("var ajaxWaitMessage = '"); 407 html.append(CmsStringUtil.escapeJavaScript(buildAjaxWaitMessage())); 408 html.append("';\n"); 409 html.append("function showAjaxReportContent() {\n"); 410 html.append("\tif (ajaxReportContent != '') {\n"); 411 html.append("\t\tdocument.getElementById('ajaxreport').innerHTML = ajaxReportContent;\n"); 412 html.append("\t}\n"); 413 html.append("}\n"); 414 html.append("function doReportUpdate(msg, state) {\n"); 415 html.append("\tvar img = state + '.png';\n"); 416 html.append("\tvar txt = '';\n"); 417 html.append("\tvar locks = -1;\n"); 418 html.append("\tvar blockinglocks = -1;\n"); 419 html.append("\tvar elem = document.getElementById('ajaxreport');\n"); 420 html.append("\tif (state != 'ok') {\n"); 421 html.append("\t\tif (state != 'wait') {\n"); 422 html.append("\t\t\tdocument.getElementById('lock-body-id').className = '';\n"); 423 html.append("\t\t}\n"); 424 html.append("\t\tvar img = state + '.png';\n"); 425 html.append("\t\tvar txt = msg;\n"); 426 html.append("\t\tif (state == 'fatal') {\n"); 427 html.append("\t\t\timg = 'error.png';\n"); 428 html.append("\t\t\ttxt = '"); 429 html.append(key(org.opencms.workplace.Messages.GUI_AJAX_REPORT_GIVEUP_0)); 430 html.append("';\n"); 431 html.append("\t\t} else if (state == 'wait') {\n"); 432 html.append("\t\t\timg = 'wait.gif';\n"); 433 html.append("\t\t\ttxt = '"); 434 html.append(key(org.opencms.workplace.Messages.GUI_AJAX_REPORT_WAIT_0)); 435 html.append("'\n"); 436 html.append("\t\t} else if (state == 'error') {\n"); 437 html.append("\t\t\ttxt = '"); 438 html.append(key(org.opencms.workplace.Messages.GUI_AJAX_REPORT_ERROR_0)); 439 html.append("' + msg;\n"); 440 html.append("\t\t}\n"); 441 html.append("\t\tdocument.getElementById('ajaxreport-img').src = '"); 442 html.append(CmsWorkplace.getSkinUri()); 443 html.append("commons/' + img;\n"); 444 html.append("\t\tdocument.getElementById('ajaxreport-txt').innerHTML = txt;\n"); 445 html.append("\t} else {\n"); 446 html.append("\t\telem.innerHTML = elem.innerHTML + msg.substring(0, 120);\n"); 447 html.append("\t\tajaxReportContent = msg;\n"); 448 html.append("\t}\n"); 449 html.append("\tif (txt != '') {\n"); 450 html.append("\t}\n"); 451 html.append("\tif (state == 'ok') {\n"); 452 html.append("\t\tlocks = document.forms['main'].locks.value;\n"); 453 html.append("\t\tblockinglocks = document.forms['main'].blockinglocks.value;\n"); 454 html.append("\t}\n"); 455 html.append("\tsetConfirmationMessage(locks, blockinglocks);\n"); 456 html.append("}\n"); 457 html.append("// -->\n"); 458 html.append("</script>\n"); 459 return html.toString(); 460 } 461 462 /** 463 * Returns the html code to build the lock request.<p> 464 * 465 * @return html code 466 */ 467 public String buildLockRequest() { 468 469 return buildLockRequest(0, false); 470 } 471 472 /** 473 * Returns the html code to build the lock request.<p> 474 * 475 * @param hiddenTimeout the maximal number of millis the dialog will be hidden 476 * @param includeRelated indicates if the report should include related resources 477 * 478 * @return html code 479 */ 480 public String buildLockRequest(int hiddenTimeout, boolean includeRelated) { 481 482 StringBuffer html = new StringBuffer(512); 483 html.append("<script ><!--\n"); 484 html.append("makeRequest('"); 485 html.append(getJsp().link("/system/workplace/commons/report-locks.jsp")); 486 html.append("', '"); 487 html.append(CmsWorkplace.PARAM_RESOURCELIST); 488 html.append("="); 489 html.append(getParamResourcelist()); 490 html.append("&"); 491 html.append(CmsDialog.PARAM_RESOURCE); 492 html.append("="); 493 html.append(getParamResource()); 494 html.append("&"); 495 html.append(CmsLock.PARAM_INCLUDERELATED); 496 html.append("="); 497 html.append(includeRelated); 498 html.append("', 'doReportUpdate');\n"); 499 html.append("function showLockDialog() {\n"); 500 html.append("\tdocument.getElementById('lock-body-id').className = '';\n"); 501 html.append("}\n"); 502 html.append("setTimeout('showLockDialog()', " + hiddenTimeout + ");\n"); 503 html.append("// -->\n"); 504 html.append("</script>\n"); 505 return html.toString(); 506 } 507 508 /** 509 * Returns the report of all locked subresources.<p> 510 * 511 * @return the report of all locked subresources 512 * 513 * @throws JspException if dialog actions fail 514 * @throws IOException in case of errros forwarding to the required result page 515 * @throws ServletException in case of errros forwarding to the required result page 516 */ 517 public String buildReport() throws JspException, ServletException, IOException { 518 519 List<String> lockedResources; 520 if (Boolean.valueOf(getParamShowownlocks()).booleanValue()) { 521 lockedResources = getLockedResources(); 522 } else { 523 lockedResources = new ArrayList<String>(getBlockingLockedResources()); 524 } 525 Collections.sort(lockedResources); 526 Map<String, String> lockParams = new HashMap<String, String>(); 527 if (getParamResource() != null) { 528 lockParams.put(PARAM_RESOURCE, getParamResource()); 529 } 530 if (getParamResourcelist() != null) { 531 lockParams.put(PARAM_RESOURCELIST, getParamResourcelist()); 532 } 533 if (getParamShowownlocks() != null) { 534 lockParams.put(PARAM_SHOWOWNLOCKS, getParamShowownlocks()); 535 } 536 if (getParamIncluderelated() != null) { 537 lockParams.put(PARAM_INCLUDERELATED, getParamIncluderelated()); 538 } 539 540 CmsLockedResourcesList list = new CmsLockedResourcesList( 541 getJsp(), 542 lockedResources, 543 CmsResource.getParentFolder(getResourceList().get(0)), 544 lockParams); 545 list.actionDialog(); 546 list.getList().setBoxed(false); 547 548 StringBuffer result = new StringBuffer(512); 549 result.append("<input type='hidden' name='locks' value='"); 550 result.append(getLockedResources().size()).append("'>\n"); 551 result.append("<input type='hidden' name='blockinglocks' value='"); 552 result.append(getBlockingLockedResources().size()).append("'>\n"); 553 result.append(CmsStringUtil.padLeft("", 120 - result.length())); 554 result.append(CmsListExplorerColumn.getExplorerStyleDef()); 555 result.append("<div style='height:150px; overflow: auto;'>\n"); 556 result.append(list.getList().listHtml()); 557 result.append("</div>\n"); 558 return result.toString(); 559 } 560 561 /** 562 * Builds the necessary button row.<p> 563 * 564 * @return the button row 565 */ 566 public String dialogButtons() { 567 568 if (CmsLock.getDialogAction(getCms()) != CmsLock.TYPE_LOCKS) { 569 return dialogButtonsOkCancel(); 570 } else { 571 return dialogButtonsClose(); 572 } 573 } 574 575 /** 576 * Returns the filter to get all blocking locks.<p> 577 * 578 * @return the filter to get all blocking locks 579 */ 580 public CmsLockFilter getBlockingFilter() { 581 582 if (m_blockingFilter == null) { 583 m_blockingFilter = CmsLockFilter.FILTER_ALL; 584 m_blockingFilter = m_blockingFilter.filterNotLockableByUser(getCms().getRequestContext().getCurrentUser()); 585 } 586 return m_blockingFilter; 587 } 588 589 /** 590 * Returns locked resources that do not belong to the current user.<p> 591 * 592 * @return the locked Resources 593 */ 594 public Set<String> getBlockingLockedResources() { 595 596 Set<String> blockingResources = new HashSet<String>(); 597 Iterator<String> i = getResourceList().iterator(); 598 while (i.hasNext()) { 599 String resName = i.next(); 600 try { 601 blockingResources.addAll(getCms().getLockedResources(resName, getBlockingFilter())); 602 } catch (CmsException e) { 603 // error reading a resource, should usually never happen 604 if (LOG.isErrorEnabled()) { 605 LOG.error(e.getLocalizedMessage(), e); 606 } 607 } 608 if (Boolean.valueOf(getParamIncluderelated()).booleanValue()) { 609 addLockedRelatedResources(resName, getBlockingFilter(), blockingResources); 610 } 611 } 612 m_blockingLocks = blockingResources.size(); 613 return blockingResources; 614 } 615 616 /** 617 * Returns the number of blocking locks.<p> 618 * 619 * @return the number of blocking locks 620 */ 621 public int getBlockingLocks() { 622 623 if (m_blockingLocks == -1) { 624 // to initialize the blocking locks flag 625 getLockedResources(); 626 } 627 return m_blockingLocks; 628 } 629 630 /** 631 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration() 632 */ 633 @Override 634 public CmsParameterConfiguration getConfiguration() { 635 636 return CmsParameterConfiguration.EMPTY_PARAMETERS; 637 } 638 639 /** 640 * Returns the confirmation message.<p> 641 * 642 * @param state if <code>true</code> everything is ok 643 * 644 * @return the confirmation message 645 */ 646 public String getConfirmationMessage(boolean state) { 647 648 if (getDialogAction(getCms()) == TYPE_LOCKS) { 649 return ""; 650 } 651 if (state) { 652 if (isMultiOperation()) { 653 return key(Messages.GUI_LOCK_MULTI_LOCK_CONFIRMATION_0); 654 } else { 655 return key(Messages.GUI_LOCK_CONFIRMATION_0); 656 } 657 } 658 switch (getDialogAction(getCms())) { 659 case TYPE_LOCK: 660 if (isMultiOperation()) { 661 return key(Messages.GUI_LOCK_MULTI_INFO_LOCKEDSUBRESOURCES_0); 662 } else { 663 return key(Messages.GUI_LOCK_INFO_LOCKEDSUBRESOURCES_0); 664 } 665 case TYPE_LOCKCHANGE: 666 return key(Messages.GUI_LOCK_CHANGE_CONFIRMATION_0); 667 case TYPE_UNLOCK: 668 if (isMultiOperation()) { 669 return key(Messages.GUI_LOCK_MULTI_UNLOCK_CONFIRMATION_0); 670 } else { 671 return key(Messages.GUI_LOCK_UNLOCK_CONFIRMATION_0); 672 } 673 case TYPE_LOCKS: 674 default: 675 return ""; 676 } 677 } 678 679 /** 680 * @see org.opencms.workplace.I_CmsDialogHandler#getDialogHandler() 681 */ 682 @Override 683 public String getDialogHandler() { 684 685 return CmsDialogSelector.DIALOG_LOCK; 686 } 687 688 /** 689 * @see org.opencms.workplace.I_CmsDialogHandler#getDialogUri(java.lang.String, CmsJspActionElement) 690 */ 691 @Override 692 public String getDialogUri(String resource, CmsJspActionElement jsp) { 693 694 switch (getDialogAction(jsp.getCmsObject())) { 695 case TYPE_LOCK: 696 return URI_LOCK_DIALOG; 697 case TYPE_LOCKCHANGE: 698 return URI_LOCKCHANGE_DIALOG; 699 case TYPE_UNLOCK: 700 return URI_UNLOCK_DIALOG; 701 case TYPE_LOCKS: 702 default: 703 return URI_LOCKS_DIALOG; 704 } 705 } 706 707 /** 708 * Returns all the locked Resources.<p> 709 * 710 * @return all the locked Resources 711 */ 712 public List<String> getLockedResources() { 713 714 if (m_lockedResources == null) { 715 // collect my locked resources 716 Set<String> lockedResources = new HashSet<String>(); 717 Iterator<String> i = getResourceList().iterator(); 718 while (i.hasNext()) { 719 String resName = i.next(); 720 try { 721 lockedResources.addAll(getCms().getLockedResources(resName, getNonBlockingFilter())); 722 } catch (CmsException e) { 723 // error reading a resource, should usually never happen 724 if (LOG.isErrorEnabled()) { 725 LOG.error(e.getLocalizedMessage(getLocale()), e); 726 } 727 } 728 if (Boolean.valueOf(getParamIncluderelated()).booleanValue()) { 729 addLockedRelatedResources(resName, getNonBlockingFilter(), lockedResources); 730 } 731 } 732 // get blocking resources needs the locked resources 733 m_lockedResources = new ArrayList<String>(lockedResources); 734 lockedResources.addAll(getBlockingLockedResources()); 735 // create the locked resources list again, with the blocking locked resources 736 m_lockedResources = new ArrayList<String>(lockedResources); 737 Collections.sort(m_lockedResources); 738 } 739 return m_lockedResources; 740 } 741 742 /** 743 * Returns the filter to get all non blocking locks.<p> 744 * 745 * @return the filter to get all non blocking locks 746 */ 747 public CmsLockFilter getNonBlockingFilter() { 748 749 if (m_nonBlockingFilter == null) { 750 m_nonBlockingFilter = CmsLockFilter.FILTER_ALL; 751 m_nonBlockingFilter = m_nonBlockingFilter.filterLockableByUser( 752 getCms().getRequestContext().getCurrentUser()); 753 m_nonBlockingFilter = m_nonBlockingFilter.filterSharedExclusive(); 754 } 755 return m_nonBlockingFilter; 756 } 757 758 /** 759 * Returns the 'include unpublished related resources' parameter value.<p> 760 * 761 * @return the 'include unpublished related resources' parameter value 762 */ 763 public String getParamIncluderelated() { 764 765 return m_paramIncluderelated; 766 } 767 768 /** 769 * Returns the project id parameter value.<p> 770 * 771 * @return the project id parameter value 772 */ 773 public String getParamProjectid() { 774 775 return m_paramProjectid; 776 } 777 778 /** 779 * Returns the 'show own locked resources' parameter value.<p> 780 * 781 * @return the 'show own locked resources' parameter value 782 */ 783 public String getParamShowownlocks() { 784 785 return m_paramShowownlocks; 786 } 787 788 /** 789 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration() 790 */ 791 @Override 792 public void initConfiguration() { 793 794 // not implemented yet 795 796 } 797 798 /** 799 * Sets the filter to get all blocking locks.<p> 800 * 801 * @param blockingFilter the filter to set 802 */ 803 public void setBlockingFilter(CmsLockFilter blockingFilter) { 804 805 m_blockingFilter = blockingFilter; 806 // reset blocking locks count 807 m_blockingLocks = -1; 808 // reset locked resources 809 m_lockedResources = null; 810 } 811 812 /** 813 * Sets the filter to get all non blocking locks.<p> 814 * 815 * @param nonBlockingFilter the filter to set 816 */ 817 public void setNonBlockingFilter(CmsLockFilter nonBlockingFilter) { 818 819 m_nonBlockingFilter = nonBlockingFilter; 820 // reset locked resources 821 m_lockedResources = null; 822 } 823 824 /** 825 * Sets the 'include unpublished related resources' parameter value.<p> 826 * 827 * @param paramIncluderelated the 'include unpublished related resources' parameter value to set 828 */ 829 public void setParamIncluderelated(String paramIncluderelated) { 830 831 m_paramIncluderelated = paramIncluderelated; 832 } 833 834 /** 835 * Sets the project id parameter value.<p> 836 * 837 * @param projectid the project id parameter value to set 838 */ 839 public void setParamProjectid(String projectid) { 840 841 m_paramProjectid = projectid; 842 } 843 844 /** 845 * Sets the 'show own locked resources' parameter value.<p> 846 * 847 * @param paramShowownlocks the 'show own locked resources' parameter value to set 848 */ 849 public void setParamShowownlocks(String paramShowownlocks) { 850 851 m_paramShowownlocks = paramShowownlocks; 852 } 853 854 /** 855 * Determines whether to show the lock dialog depending on the users settings and the dilaog type.<p> 856 * 857 * In case of locking a folder, a confirmation dialog is needed if any sub resources are already locked.<p> 858 * 859 * @return true if dialogs should be shown, otherwise false 860 */ 861 public boolean showConfirmation() { 862 863 boolean showConfirmation = getSettings().getUserSettings().getDialogShowLock(); 864 if (DIALOG_TYPE_LOCK.equals(getParamDialogtype())) { 865 // in case of locking resources, check if there are locked sub resources in the selected folder(s) 866 showConfirmation = showConfirmation || (getLockedResources().size() > 0); 867 } 868 return showConfirmation; 869 } 870 871 /** 872 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 873 */ 874 @Override 875 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 876 877 // fill the parameter values in the get/set methods 878 fillParamValues(request); 879 880 // set the action for the JSP switch 881 if (DIALOG_CONFIRMED.equals(getParamAction())) { 882 setAction(ACTION_CONFIRMED); 883 } else if (DIALOG_CANCEL.equals(getParamAction())) { 884 setAction(ACTION_CANCEL); 885 } else if (DIALOG_WAIT.equals(getParamAction())) { 886 setAction(ACTION_WAIT); 887 } else { 888 switch (getDialogAction(getCms())) { 889 case TYPE_LOCK: 890 setDialogTitle(Messages.GUI_LOCK_RESOURCE_1, Messages.GUI_LOCK_MULTI_LOCK_2); 891 setParamDialogtype(DIALOG_TYPE_LOCK); 892 // check the required permissions to lock/unlock 893 if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) { 894 // no write permissions for the resource, set cancel action to close dialog 895 setAction(ACTION_CANCEL); 896 return; 897 } 898 break; 899 case TYPE_LOCKCHANGE: 900 setDialogTitle(Messages.GUI_LOCK_STEAL_1, Messages.GUI_LOCK_MULTI_STEAL_2); 901 setParamDialogtype(DIALOG_TYPE_UNLOCK); 902 break; 903 case TYPE_UNLOCK: 904 setDialogTitle(Messages.GUI_LOCK_UNLOCK_1, Messages.GUI_LOCK_MULTI_UNLOCK_2); 905 setParamDialogtype(DIALOG_TYPE_UNLOCK); 906 break; 907 case TYPE_LOCKS: 908 default: 909 setDialogTitle(Messages.GUI_LOCK_LOCKS_1, Messages.GUI_LOCK_MULTI_LOCKS_2); 910 setParamDialogtype(DIALOG_TYPE_LOCKS); 911 } 912 // set action depending on user settings 913 if ((getDialogAction(getCms()) == TYPE_LOCKS) || showConfirmation()) { 914 // show confirmation dialog 915 setAction(ACTION_DEFAULT); 916 } else { 917 // lock/unlock resource without confirmation 918 setAction(ACTION_SUBMIT_NOCONFIRMATION); 919 } 920 } 921 922 if ((getParamResource() == null) && (getParamResourcelist() == null)) { 923 // this if in case of publish project 924 setParamResource("/"); 925 } 926 927 } 928 929 /** 930 * Performs the lock/unlock/steal lock operation.<p> 931 * 932 * @return true, if the operation was performed, otherwise false 933 * @throws CmsException if operation is not successful 934 */ 935 @Override 936 protected boolean performDialogOperation() throws CmsException { 937 938 //on multi resource operation display "please wait" screen 939 if (isMultiOperation() && !DIALOG_WAIT.equals(getParamAction())) { 940 return false; 941 } 942 // determine action to perform (lock, unlock, change lock) 943 int dialogAction = getDialogAction(getCms()); 944 945 // now perform the operation on the resource(s) 946 Iterator<String> i = getResourceList().iterator(); 947 while (i.hasNext()) { 948 String resName = i.next(); 949 try { 950 performSingleResourceOperation(resName, dialogAction); 951 } catch (CmsException e) { 952 // collect exceptions to create a detailed output 953 addMultiOperationException(e); 954 } 955 } 956 // generate the error message for exception 957 String message; 958 if (dialogAction == TYPE_LOCK) { 959 message = Messages.ERR_LOCK_MULTI_0; 960 } else { 961 message = Messages.ERR_UNLOCK_MULTI_0; 962 } 963 checkMultiOperationException(Messages.get(), message); 964 965 return true; 966 } 967 968 /** 969 * Performs the lock state operation on a single resource.<p> 970 * 971 * @param resourceName the resource name to perform the operation on 972 * @param dialogAction the lock action: lock, unlock or change lock 973 * @throws CmsException if the operation fails 974 */ 975 protected void performSingleResourceOperation(String resourceName, int dialogAction) throws CmsException { 976 977 // store original name to use for lock action 978 String originalResourceName = resourceName; 979 CmsResource res = getCms().readResource(resourceName, CmsResourceFilter.ALL); 980 if (res.isFolder() && !resourceName.endsWith("/")) { 981 resourceName += "/"; 982 } 983 org.opencms.lock.CmsLock lock = getCms().getLock(res); 984 // perform action depending on dialog uri 985 switch (dialogAction) { 986 case TYPE_LOCKCHANGE: 987 case TYPE_LOCK: 988 if (lock.isNullLock()) { 989 getCms().lockResource(originalResourceName); 990 } else if (!lock.isDirectlyOwnedInProjectBy(getCms())) { 991 getCms().changeLock(resourceName); 992 } 993 break; 994 case TYPE_UNLOCK: 995 default: 996 if (lock.isNullLock()) { 997 break; 998 } 999 if (lock.isOwnedBy(getCms().getRequestContext().getCurrentUser())) { 1000 getCms().unlockResource(resourceName); 1001 } 1002 } 1003 } 1004 1005 /** 1006 * Returns a set of locked unpublished related resources.<p> 1007 * 1008 * @param resName the resource to check the related resources for 1009 * @param filter the lock filter to use 1010 * @param lockedResources a set of site relative paths, of locked resources to exclude 1011 */ 1012 private void addLockedRelatedResources(String resName, CmsLockFilter filter, Set<String> lockedResources) { 1013 1014 try { 1015 // get and iterate over all related resources 1016 Iterator<CmsRelation> itRelations = getCms().getRelationsForResource( 1017 resName, 1018 CmsRelationFilter.TARGETS.filterStrong().filterIncludeChildren()).iterator(); 1019 while (itRelations.hasNext()) { 1020 CmsRelation relation = itRelations.next(); 1021 CmsResource target = null; 1022 try { 1023 target = relation.getTarget(getCms(), CmsResourceFilter.ALL); 1024 } catch (CmsException e) { 1025 // error reading a resource, should usually never happen 1026 if (LOG.isDebugEnabled()) { 1027 LOG.debug(e.getLocalizedMessage(getLocale()), e); 1028 } 1029 continue; 1030 } 1031 // we are interested just in unpublished resources 1032 if (target.getState().isUnchanged()) { 1033 continue; 1034 } 1035 String targetName = getCms().getSitePath(target); 1036 // if already selected 1037 if (lockedResources.contains(targetName) || lockedResources.contains(targetName + "*")) { 1038 continue; 1039 } 1040 if (m_lockedResources != null) { 1041 if (m_lockedResources.contains(targetName) || m_lockedResources.contains(targetName + "*")) { 1042 continue; 1043 } 1044 } 1045 try { 1046 org.opencms.lock.CmsLock lock = getCms().getLock(targetName); 1047 if (!lock.isUnlocked() && filter.match("/", lock)) { 1048 // just add resources that may come in question 1049 lockedResources.add(targetName + "*"); 1050 } 1051 } catch (CmsException e) { 1052 // error reading a lock, should usually never happen 1053 if (LOG.isErrorEnabled()) { 1054 LOG.error(e.getLocalizedMessage(getLocale()), e); 1055 } 1056 continue; 1057 } 1058 } 1059 } catch (CmsException e) { 1060 // error reading the relations, should usually never happen 1061 if (LOG.isErrorEnabled()) { 1062 LOG.error(e.getLocalizedMessage(getLocale()), e); 1063 } 1064 } 1065 } 1066}