001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.ade.configuration; 029 030import org.opencms.ade.containerpage.shared.CmsCntPageData.ElementDeleteMode; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProperty; 033import org.opencms.file.CmsRequestContext; 034import org.opencms.file.CmsResource; 035import org.opencms.file.CmsResourceFilter; 036import org.opencms.file.CmsVfsResourceNotFoundException; 037import org.opencms.file.types.CmsResourceTypeFunctionConfig; 038import org.opencms.file.types.I_CmsResourceType; 039import org.opencms.lock.CmsLock; 040import org.opencms.lock.CmsLockException; 041import org.opencms.main.CmsException; 042import org.opencms.main.CmsLog; 043import org.opencms.main.OpenCms; 044import org.opencms.relations.CmsCategoryService; 045import org.opencms.security.CmsPermissionSet; 046import org.opencms.security.CmsRole; 047import org.opencms.ui.util.CmsNewResourceBuilder; 048import org.opencms.util.CmsStringUtil; 049import org.opencms.util.CmsUUID; 050import org.opencms.util.CmsVfsUtil; 051import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 052import org.opencms.xml.containerpage.CmsXmlDynamicFunctionHandler; 053 054import java.util.ArrayList; 055 056import org.apache.commons.logging.Log; 057 058/** 059 * The configuration for a single resource type.<p> 060 */ 061public class CmsResourceTypeConfig implements I_CmsConfigurationObject<CmsResourceTypeConfig> { 062 063 /** 064 * Enum used to distinguish the type of menu in which a configured resource type can be displayed. 065 */ 066 public enum AddMenuType { 067 /** ADE add menu. */ 068 ade, 069 070 /** Workplace dialogs. */ 071 workplace 072 } 073 074 /** 075 * Represents the visibility status of a resource type in the 'Add' menu of the container page editor.<p> 076 */ 077 public enum AddMenuVisibility { 078 079 /** Type should not be creatable. */ 080 createDisabled, 081 082 /** Type not visible. */ 083 disabled, 084 085 /** Type does not belong to current view, but has been configured to be still visible in it. */ 086 fromOtherView, 087 088 /** Type is normally visible. */ 089 visible 090 } 091 092 /** The log instance for this class. */ 093 private static final Log LOG = CmsLog.getLog(CmsResourceTypeConfig.class); 094 095 /** The CMS object used for VFS operations. */ 096 protected CmsObject m_cms; 097 098 /** Flag which controls whether adding elements of this type using ADE is disabled. */ 099 private boolean m_addDisabled; 100 101 /** Flag which controls whether creating elements of this type using ADE is disabled. */ 102 private boolean m_createDisabled; 103 104 /** Elements of this type when used in models should be copied instead of reused. */ 105 private Boolean m_copyInModels; 106 107 /** The flag for disabling detail pages. */ 108 private boolean m_detailPagesDisabled; 109 110 /** True if this is a disabled configuration. */ 111 private boolean m_disabled; 112 113 /** The element delete mode. */ 114 private ElementDeleteMode m_elementDeleteMode; 115 116 /** The element view id. */ 117 private CmsUUID m_elementView; 118 119 /** A reference to a folder of folder name. */ 120 private CmsContentFolderDescriptor m_folderOrName; 121 122 /** The bundle to add as workplace bundle for the resource type. */ 123 private String m_localization; 124 125 /** The name pattern .*/ 126 private String m_namePattern; 127 128 /** The number used for sorting the resource type configurations. */ 129 private int m_order; 130 131 /** Flag which controls whether this type should be shown in the 'add' menu in the default view. */ 132 private Boolean m_showInDefaultView; 133 134 /** The name of the resource type. */ 135 private String m_typeName; 136 137 /** 138 * Creates a new resource type configuration.<p> 139 * 140 * @param typeName the resource type name 141 * @param disabled true if this is a disabled configuration 142 * @param folder the folder reference 143 * @param pattern the name pattern 144 */ 145 public CmsResourceTypeConfig(String typeName, boolean disabled, CmsContentFolderDescriptor folder, String pattern) { 146 147 this( 148 typeName, 149 disabled, 150 folder, 151 pattern, 152 false, 153 false, 154 false, 155 CmsElementView.DEFAULT_ELEMENT_VIEW.getId(), 156 null, 157 null, 158 null, 159 I_CmsConfigurationObject.DEFAULT_ORDER, 160 null); 161 } 162 163 /** 164 * Creates a new resource type configuration.<p> 165 * 166 * @param typeName the resource type name 167 * @param disabled true if this is a disabled configuration 168 * @param folder the folder reference 169 * @param pattern the name pattern 170 * @param detailPagesDisabled true if detail page creation should be disabled for this type 171 * @param addDisabled true if adding elements of this type via ADE should be disabled 172 * @param createDisabled true if creating elements of this type via ADE should be disabled 173 * @param elementView the element view id 174 * @param localization the base name of the bundle to add as workplace bundle for the resource type 175 * @param showInDefaultView if true, the element type should be shown in the default element view even if it doesn't belong to it 176 * @param copyInModels if elements of this type when used in models should be copied instead of reused 177 * @param elementDeleteMode the element delete mode 178 * 179 * @param order the number used for sorting resource types from modules 180 */ 181 public CmsResourceTypeConfig( 182 String typeName, 183 boolean disabled, 184 CmsContentFolderDescriptor folder, 185 String pattern, 186 boolean detailPagesDisabled, 187 boolean addDisabled, 188 boolean createDisabled, 189 CmsUUID elementView, 190 String localization, 191 Boolean showInDefaultView, 192 Boolean copyInModels, 193 int order, 194 ElementDeleteMode elementDeleteMode) { 195 196 m_typeName = typeName; 197 m_disabled = disabled; 198 m_folderOrName = folder; 199 m_namePattern = pattern; 200 m_detailPagesDisabled = detailPagesDisabled; 201 m_addDisabled = addDisabled; 202 m_createDisabled = createDisabled; 203 m_elementView = elementView; 204 m_localization = localization; 205 m_showInDefaultView = showInDefaultView; 206 m_copyInModels = copyInModels; 207 m_order = order; 208 m_elementDeleteMode = elementDeleteMode; 209 } 210 211 /** 212 * Checks if this resource type is creatable.<p> 213 * 214 * @param cms the current CMS context 215 * @param pageFolderRootPath the root path of the folder containing the current container page 216 * 217 * @return <code>true</code> if the resource type is creatable 218 * 219 * @throws CmsException if something goes wrong 220 */ 221 public boolean checkCreatable(CmsObject cms, String pageFolderRootPath) throws CmsException { 222 223 if (cms.getRequestContext().getCurrentProject().isOnlineProject()) { 224 return false; 225 } 226 if (OpenCms.getRoleManager().hasRole(cms, CmsRole.ROOT_ADMIN)) { 227 return true; 228 } 229 if (CmsXmlDynamicFunctionHandler.TYPE_FUNCTION.equals(m_typeName) 230 || CmsResourceTypeFunctionConfig.TYPE_NAME.equals(m_typeName)) { 231 return OpenCms.getRoleManager().hasRole(cms, CmsRole.DEVELOPER); 232 } 233 checkInitialized(); 234 String folderPath = getFolderPath(cms, pageFolderRootPath); 235 String oldSiteRoot = cms.getRequestContext().getSiteRoot(); 236 cms.getRequestContext().setSiteRoot(""); 237 //tryToUnlock(cms, folderPath); 238 CmsResource permissionCheckFolder = null; 239 for (String currentPath = folderPath; currentPath != null; currentPath = CmsResource.getParentFolder( 240 currentPath)) { 241 try { 242 permissionCheckFolder = cms.readResource(currentPath); 243 break; 244 } catch (CmsVfsResourceNotFoundException e) { 245 // ignore 246 } 247 } 248 try { 249 if (permissionCheckFolder == null) { 250 return false; 251 } 252 LOG.info("Using " + permissionCheckFolder + " as a permission check folder for " + folderPath); 253 CmsExplorerTypeSettings settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(m_typeName); 254 if (settings == null) { 255 return false; 256 } 257 boolean editable = settings.isEditable(cms, permissionCheckFolder); 258 boolean controlPermission = settings.getAccess().getPermissions( 259 cms, 260 permissionCheckFolder).requiresControlPermission(); 261 boolean hasWritePermission = cms.hasPermissions( 262 permissionCheckFolder, 263 CmsPermissionSet.ACCESS_WRITE, 264 false, 265 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 266 return editable && controlPermission && hasWritePermission; 267 } catch (CmsVfsResourceNotFoundException e) { 268 return false; 269 } catch (CmsException e) { 270 LOG.error(e.getLocalizedMessage(), e); 271 return false; 272 } finally { 273 cms.getRequestContext().setSiteRoot(oldSiteRoot); 274 } 275 } 276 277 /** 278 * Checks whether the object is initialized and throws an exception otherwise.<p> 279 */ 280 public void checkInitialized() { 281 282 if (m_cms == null) { 283 throw new IllegalStateException(); 284 } 285 } 286 287 /** 288 * Checks whether the cms context is in the offline project and throws an exception otherwise.<p> 289 * 290 * @param cms the cms context 291 */ 292 public void checkOffline(CmsObject cms) { 293 294 if (cms.getRequestContext().getCurrentProject().isOnlineProject()) { 295 throw new IllegalStateException(); 296 } 297 } 298 299 /** 300 * Checks if a resource type is viewable for the current user. 301 * If not, this resource type should not be available at all within the ADE 'add-wizard'.<p> 302 * 303 * @param cms the current CMS context 304 * @param referenceUri the resource URI to check permissions for 305 * 306 * @return <code>true</code> if the resource type is viewable 307 */ 308 public boolean checkViewable(CmsObject cms, String referenceUri) { 309 310 try { 311 CmsExplorerTypeSettings settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(m_typeName); 312 CmsResource referenceResource = cms.readResource(referenceUri); 313 if (settings == null) { 314 // no explorer type 315 return false; 316 } 317 return settings.getAccess().getPermissions(cms, referenceResource).requiresViewPermission(); 318 } catch (CmsException e) { 319 LOG.error(e.getLocalizedMessage(), e); 320 return false; 321 } 322 } 323 324 /** 325 * Similar to createNewElement, but just sets parameters on a resource builder instead of actually creating the resource.<p> 326 * 327 * @param cms the CMS context 328 * @param pageFolderRootPath the page folder root path 329 * @param builder the resource builder 330 * 331 * @throws CmsException if something goes wrong 332 */ 333 public void configureCreateNewElement(CmsObject cms, String pageFolderRootPath, CmsNewResourceBuilder builder) 334 throws CmsException { 335 336 checkOffline(cms); 337 checkInitialized(); 338 String folderPath = getFolderPath(cms, pageFolderRootPath); 339 CmsVfsUtil.createFolder(cms, folderPath); 340 String destination = CmsStringUtil.joinPaths(folderPath, getNamePattern(true)); 341 builder.setSiteRoot(""); 342 builder.setPatternPath(destination); 343 builder.setType(getTypeName()); 344 builder.setLocale(cms.getRequestContext().getLocale()); 345 } 346 347 /** 348 * Creates a new element.<p> 349 * 350 * @param userCms the CMS context to use 351 * @param modelResource the model resource to use 352 * @param pageFolderRootPath the root path of the folder containing the current container page 353 * 354 * @return the created resource 355 * 356 * @throws CmsException if something goes wrong 357 */ 358 public CmsResource createNewElement(CmsObject userCms, CmsResource modelResource, String pageFolderRootPath) 359 throws CmsException { 360 361 checkOffline(userCms); 362 checkInitialized(); 363 CmsObject rootCms = rootCms(userCms); 364 String folderPath = getFolderPath(userCms, pageFolderRootPath); 365 CmsVfsUtil.createFolder(userCms, folderPath); 366 String destination = CmsStringUtil.joinPaths(folderPath, getNamePattern(true)); 367 String creationPath = OpenCms.getResourceManager().getNameGenerator().getNewFileName(rootCms, destination, 5); 368 // set the content locale 369 rootCms.getRequestContext().setAttribute( 370 CmsRequestContext.ATTRIBUTE_NEW_RESOURCE_LOCALE, 371 userCms.getRequestContext().getLocale()); 372 if (modelResource != null) { 373 // set the model resource 374 rootCms.getRequestContext().setAttribute(CmsRequestContext.ATTRIBUTE_MODEL, modelResource.getRootPath()); 375 } 376 CmsResource createdResource = rootCms.createResource( 377 creationPath, 378 getType(), 379 null, 380 new ArrayList<CmsProperty>(0)); 381 if (modelResource != null) { 382 // set the model resource 383 CmsCategoryService.getInstance().copyCategories(rootCms, modelResource, creationPath); 384 } 385 try { 386 rootCms.unlockResource(creationPath); 387 } catch (CmsLockException e) { 388 // probably the parent folder is locked 389 LOG.info(e.getLocalizedMessage(), e); 390 } 391 return createdResource; 392 } 393 394 /** 395 * Creates a new element.<p> 396 * 397 * @param userCms the CMS context to use 398 * @param pageFolderRootPath root path of the folder containing the current container page 399 * 400 * @return the created resource 401 * 402 * @throws CmsException if something goes wrong 403 */ 404 public CmsResource createNewElement(CmsObject userCms, String pageFolderRootPath) throws CmsException { 405 406 return createNewElement(userCms, null, pageFolderRootPath); 407 } 408 409 /** 410 * Gets the visibility status in the 'add' menu for this type and the given element view.<p> 411 * 412 * @param elementViewId the id of the view for which to compute the visibility status 413 * @param menuType the menu type for which we want to evaluate the visibility 414 * 415 * @return the visibility status 416 */ 417 public AddMenuVisibility getAddMenuVisibility(CmsUUID elementViewId, AddMenuType menuType) { 418 419 if (isAddDisabled()) { 420 return AddMenuVisibility.disabled; 421 } 422 423 if (elementViewId.equals(getElementView())) { 424 if (isCreateDisabled() && (menuType == AddMenuType.ade)) { 425 return AddMenuVisibility.createDisabled; 426 } 427 return AddMenuVisibility.visible; 428 } 429 430 if (isShowInDefaultView() && elementViewId.equals(CmsElementView.DEFAULT_ELEMENT_VIEW.getId())) { 431 return AddMenuVisibility.fromOtherView; 432 } 433 434 return AddMenuVisibility.disabled; 435 } 436 437 /** 438 * Returns the bundle that is configured as workplace bundle for the resource type, or <code>null</code> if none is configured. 439 * @return the bundle that is configured as workplace bundle for the resource type, or <code>null</code> if none is configured. 440 */ 441 public String getConfiguredWorkplaceBundle() { 442 443 return m_localization; 444 } 445 446 /** 447 * Gets the element delete mode.<p> 448 * 449 * @return the element delete mode 450 */ 451 public ElementDeleteMode getElementDeleteMode() { 452 453 return m_elementDeleteMode; 454 } 455 456 /** 457 * Returns the element view id.<p> 458 * 459 * @return the element view id 460 */ 461 public CmsUUID getElementView() { 462 463 return m_elementView == null ? CmsElementView.DEFAULT_ELEMENT_VIEW.getId() : m_elementView; 464 } 465 466 /** 467 * Computes the folder path for this resource type.<p> 468 * 469 * @param cms the cms context to use 470 * @param pageFolderRootPath root path of the folder containing the current container page 471 * 472 * @return the folder root path for this resource type 473 */ 474 public String getFolderPath(CmsObject cms, String pageFolderRootPath) { 475 476 checkInitialized(); 477 if (m_folderOrName != null) { 478 return m_folderOrName.getFolderPath(cms, pageFolderRootPath); 479 } else { 480 String siteRoot = null; 481 if (pageFolderRootPath != null) { 482 siteRoot = OpenCms.getSiteManager().getSiteRoot(pageFolderRootPath); 483 } 484 if (siteRoot == null) { 485 siteRoot = cms.getRequestContext().getSiteRoot(); 486 } 487 return CmsStringUtil.joinPaths(siteRoot, CmsADEManager.CONTENT_FOLDER_NAME, m_typeName); 488 } 489 } 490 491 /** 492 * @see org.opencms.ade.configuration.I_CmsConfigurationObject#getKey() 493 */ 494 public String getKey() { 495 496 return m_typeName; 497 } 498 499 /** 500 * Gets the name pattern.<p> 501 * 502 * @param useDefaultIfEmpty if true, uses a default value if the name pattern isn't set directly 503 * 504 * @return the name pattern 505 */ 506 public String getNamePattern(boolean useDefaultIfEmpty) { 507 508 if (m_namePattern != null) { 509 return m_namePattern; 510 } 511 if (useDefaultIfEmpty) { 512 return m_typeName + "-%(number).xml"; 513 } 514 return null; 515 } 516 517 /** 518 * Returns the number used for sorting module resource types.<p> 519 * 520 * @return the number used for sorting module resource types 521 */ 522 public int getOrder() { 523 524 return m_order; 525 } 526 527 /** 528 * Gets the actual resource type for which this is a configuration.<p> 529 * 530 * @return the actual resource type 531 * 532 * @throws CmsException if something goes wrong 533 */ 534 public I_CmsResourceType getType() throws CmsException { 535 536 return OpenCms.getResourceManager().getResourceType(m_typeName); 537 } 538 539 /** 540 * Returns the type name.<p> 541 * 542 * @return the type name 543 */ 544 public String getTypeName() { 545 546 return m_typeName; 547 } 548 549 /** 550 * Initializes this instance.<p> 551 * 552 * @param cms the CMS context to use 553 */ 554 public void initialize(CmsObject cms) { 555 556 m_cms = cms; 557 558 } 559 560 /** 561 * Returns true if adding elements of this type via ADE should be disabled.<p> 562 * 563 * @return true if elements of this type shouldn't be added to the page 564 */ 565 public boolean isAddDisabled() { 566 567 return m_addDisabled; 568 } 569 570 /** 571 * Returns if elements of this type when used in models should be copied instead of reused.<p> 572 * 573 * @return if elements of this type when used in models should be copied instead of reused 574 */ 575 public boolean isCopyInModels() { 576 577 return (m_copyInModels == null) || m_copyInModels.booleanValue(); 578 } 579 580 /** 581 * Returns whether creating elements of this type via ADE should be disabled.<p> 582 * 583 * @return <code>true</code> if creating elements of this type via ADE should be disabled 584 */ 585 public boolean isCreateDisabled() { 586 587 return m_createDisabled; 588 } 589 590 /** 591 * True if the detail page creation should be disabled for this resource type.<p> 592 * 593 * @return true if detail page creation should be disabled for this type 594 */ 595 public boolean isDetailPagesDisabled() { 596 597 return m_detailPagesDisabled; 598 } 599 600 /** 601 * @see org.opencms.ade.configuration.I_CmsConfigurationObject#isDisabled() 602 */ 603 public boolean isDisabled() { 604 605 return m_disabled; 606 } 607 608 /** 609 * Returns true if this resource type is configured as 'page relative', i.e. elements of this type are to be stored 610 * with the container page on which they were created.<p> 611 * 612 * @return true if this is a page relative type configuration 613 */ 614 public boolean isPageRelative() { 615 616 return (m_folderOrName != null) && m_folderOrName.isPageRelative(); 617 } 618 619 /** 620 * Returns true if the type should be shown in the default view if it is not assigned to it.<p> 621 * 622 * This defaults to 'false' if not set. 623 * 624 * @return true if the type should be shown in the default view event if it doens't belong to that element view 625 */ 626 public boolean isShowInDefaultView() { 627 628 return (m_showInDefaultView != null) && m_showInDefaultView.booleanValue(); 629 } 630 631 /** 632 * @see org.opencms.ade.configuration.I_CmsConfigurationObject#merge(org.opencms.ade.configuration.I_CmsConfigurationObject) 633 */ 634 public CmsResourceTypeConfig merge(CmsResourceTypeConfig childConfig) { 635 636 CmsContentFolderDescriptor folderOrName = childConfig.m_folderOrName != null 637 ? childConfig.m_folderOrName 638 : m_folderOrName; 639 String namePattern = childConfig.m_namePattern != null ? childConfig.m_namePattern : m_namePattern; 640 CmsUUID elementView = childConfig.m_elementView != null ? childConfig.m_elementView : m_elementView; 641 Boolean showInDefaultView = childConfig.m_showInDefaultView != null 642 ? childConfig.m_showInDefaultView 643 : m_showInDefaultView; 644 Boolean copyInModels = childConfig.m_copyInModels != null ? childConfig.m_copyInModels : m_copyInModels; 645 ElementDeleteMode deleteMode = childConfig.m_elementDeleteMode != null 646 ? childConfig.m_elementDeleteMode 647 : m_elementDeleteMode; 648 649 CmsResourceTypeConfig result = new CmsResourceTypeConfig( 650 m_typeName, 651 false, 652 folderOrName, 653 namePattern, 654 isDetailPagesDisabled() || childConfig.isDetailPagesDisabled(), 655 childConfig.isAddDisabled(), 656 // a type marked as not creatable, should not be creatable in any sub site 657 isCreateDisabled() && childConfig.isCreateDisabled(), 658 elementView, 659 m_localization, 660 showInDefaultView, 661 copyInModels, 662 m_order, 663 deleteMode); 664 if (childConfig.isDisabled()) { 665 result.m_disabled = true; 666 } 667 return result; 668 } 669 670 /** 671 * Creates a shallow copy of this resource type configuration object.<p> 672 * 673 * @return a copy of the resource type configuration object 674 */ 675 protected CmsResourceTypeConfig copy() { 676 677 return copy(false); 678 } 679 680 /** 681 * Creates a shallow copy of this resource type configuration object.<p> 682 * 683 * @param disabled true if the copy should be disabled regardless of whether the original is disabled 684 * 685 * @return a copy of the resource type configuration object 686 */ 687 protected CmsResourceTypeConfig copy(boolean disabled) { 688 689 return new CmsResourceTypeConfig( 690 m_typeName, 691 m_disabled || disabled, 692 getFolderOrName(), 693 m_namePattern, 694 m_detailPagesDisabled, 695 isAddDisabled(), 696 isCreateDisabled(), 697 m_elementView, 698 m_localization, 699 m_showInDefaultView, 700 m_copyInModels, 701 m_order, 702 m_elementDeleteMode); 703 } 704 705 /** 706 * Returns the folder bean from the configuration.<p> 707 * 708 * Normally, you should use getFolderPath() instead.<p> 709 * 710 * @return the folder bean from the configuration 711 */ 712 protected CmsContentFolderDescriptor getFolderOrName() { 713 714 return m_folderOrName; 715 } 716 717 /** 718 * Gets the configured name pattern.<p> 719 * 720 * @return the configured name pattern 721 */ 722 protected String getNamePattern() { 723 724 return m_namePattern; 725 } 726 727 /** 728 * Creates a new CMS object based on existing one and changes its site root to the site root.<p> 729 * 730 * @param cms the CMS context 731 * @return the root site CMS context 732 * @throws CmsException if something goes wrong 733 */ 734 protected CmsObject rootCms(CmsObject cms) throws CmsException { 735 736 CmsObject result = OpenCms.initCmsObject(cms); 737 result.getRequestContext().setSiteRoot(""); 738 return result; 739 } 740 741 /** 742 * Tries to remove a lock on an ancestor of a given path owned by the current user.<p> 743 * 744 * @param cms the CMS context 745 * @param folderPath the path for which the lock should be removed 746 * 747 * @throws CmsException if something goes wrong 748 */ 749 protected void tryToUnlock(CmsObject cms, String folderPath) throws CmsException { 750 751 // Get path of first ancestor that actually exists 752 while (!cms.existsResource(folderPath)) { 753 folderPath = CmsResource.getParentFolder(folderPath); 754 } 755 CmsResource resource = cms.readResource(folderPath); 756 CmsLock lock = cms.getLock(resource); 757 // we are only interested in locks we can safely unlock, i.e. locks by the current user 758 if (lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) { 759 // walk up the tree until we get to the location from which the lock is inherited 760 while (lock.isInherited()) { 761 folderPath = CmsResource.getParentFolder(folderPath); 762 resource = cms.readResource(folderPath); 763 lock = cms.getLock(resource); 764 } 765 cms.unlockResource(folderPath); 766 } 767 } 768 769 /** 770 * Updates the base path for the folder information.<p> 771 * 772 * @param basePath the new base path 773 */ 774 protected void updateBasePath(String basePath) { 775 776 if (m_folderOrName != null) { 777 if (m_folderOrName.isName()) { 778 m_folderOrName = new CmsContentFolderDescriptor(basePath, m_folderOrName.getFolderName()); 779 } 780 } else { 781 m_folderOrName = new CmsContentFolderDescriptor(basePath, m_typeName); 782 } 783 } 784}