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