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.configuration.CmsADEConfigDataInternal.ConfigReference; 031import org.opencms.ade.configuration.CmsADEConfigDataInternal.ConfigReferenceMeta; 032import org.opencms.ade.configuration.formatters.CmsFormatterChangeSet; 033import org.opencms.ade.configuration.formatters.CmsFormatterConfigurationCache; 034import org.opencms.ade.containerpage.shared.CmsCntPageData.ElementDeleteMode; 035import org.opencms.ade.detailpage.CmsDetailPageInfo; 036import org.opencms.ade.galleries.CmsAddContentRestriction; 037import org.opencms.file.CmsFile; 038import org.opencms.file.CmsObject; 039import org.opencms.file.CmsResource; 040import org.opencms.file.CmsResourceFilter; 041import org.opencms.file.types.I_CmsResourceType; 042import org.opencms.gwt.CmsIconUtil; 043import org.opencms.i18n.CmsLocaleManager; 044import org.opencms.main.CmsException; 045import org.opencms.main.CmsLog; 046import org.opencms.main.CmsRuntimeException; 047import org.opencms.main.OpenCms; 048import org.opencms.module.CmsModule; 049import org.opencms.relations.CmsLink; 050import org.opencms.util.CmsFileUtil; 051import org.opencms.util.CmsStringUtil; 052import org.opencms.util.CmsUUID; 053import org.opencms.xml.containerpage.CmsFormatterBean; 054import org.opencms.xml.containerpage.CmsXmlDynamicFunctionHandler; 055import org.opencms.xml.containerpage.I_CmsFormatterBean; 056import org.opencms.xml.content.CmsXmlContent; 057import org.opencms.xml.content.CmsXmlContentFactory; 058import org.opencms.xml.content.CmsXmlContentProperty; 059import org.opencms.xml.content.CmsXmlContentProperty.Visibility; 060import org.opencms.xml.content.CmsXmlContentRootLocation; 061import org.opencms.xml.content.I_CmsXmlContentLocation; 062import org.opencms.xml.content.I_CmsXmlContentValueLocation; 063import org.opencms.xml.types.CmsXmlVarLinkValue; 064import org.opencms.xml.types.CmsXmlVfsFileValue; 065 066import java.util.ArrayList; 067import java.util.HashSet; 068import java.util.LinkedHashMap; 069import java.util.LinkedHashSet; 070import java.util.List; 071import java.util.Locale; 072import java.util.Map; 073import java.util.Set; 074 075import org.apache.commons.logging.Log; 076 077import com.google.common.collect.Lists; 078 079/** 080 * A class to parse ADE sitemap or module configuration files and create configuration objects from them.<p> 081 */ 082public class CmsConfigurationReader { 083 084 /** 085 * Enum describing how to deal with inherited properties. 086 */ 087 enum DiscardPropertiesMode { 088 089 /** Remove properties from parent sitemaps. */ 090 discard("true"), 091 092 /** Inherit properties from parent sitemaps. */ 093 keep("false"), 094 095 /** Remove properties from parent sitemaps, and mark properties defined in this sitemap as 'top', which moves them over the properties which are only defined in opencms-workplace.xml/opencms-modules.xml. */ 096 top("top"); 097 098 /** The value representing the mode in an actual sitemap configuration content. */ 099 private String m_stringValue; 100 101 /** 102 * Creates the enum value. 103 * 104 * @param stringValue the string value from the configuration 105 */ 106 private DiscardPropertiesMode(String stringValue) { 107 108 m_stringValue = stringValue; 109 110 } 111 112 /** 113 * Gets the string value occurring in the sitemap configuration. 114 * 115 * @return the string value 116 */ 117 public String getStringValue() { 118 119 return m_stringValue; 120 } 121 } 122 123 /** The default locale for configuration objects. */ 124 public static final Locale DEFAULT_LOCALE = CmsLocaleManager.getLocale("en"); 125 126 /** The AddContentReplacements node name. */ 127 public static final String N_ADD_CONTENT_RESTRICTION = "AddContentRestriction"; 128 129 /** Node name for added formatters. */ 130 public static final String N_ADD_FORMATTER = "AddFormatter"; 131 132 /** Node name for the nested content with the added formatters. */ 133 public static final String N_ADD_FORMATTERS = "AddFormatters"; 134 135 /** The AddPlugin node name. */ 136 public static final String N_ADD_PLUGIN = "AddPlugin"; 137 138 /** The AddPlugins node name. */ 139 public static final String N_ADD_PLUGINS = "AddPlugins"; 140 141 /** The Attribute node name. */ 142 public static final String N_ATTRIBUTE = "Attribute"; 143 144 /** Node name for the attribute editor configuration reference. */ 145 public static final String N_ATTRIBUTE_EDITOR_CONFIG = "AttributeEditorConfig"; 146 147 /** The CopyInModels node name. */ 148 public static final String N_COPY_IN_MODELS = "CopyInModels"; 149 150 /** The create content locally node name. */ 151 public static final String N_CREATE_CONTENTS_LOCALLY = "CreateContentsLocally"; 152 153 /** The default node name. */ 154 public static final String N_DEFAULT = "Default"; 155 156 /** The description node name. */ 157 public static final String N_DESCRIPTION = "Description"; 158 159 /** The detail page node name. */ 160 public static final String N_DETAIL_PAGE = "DetailPage"; 161 162 /** The detail pages disabled node name. */ 163 public static final String N_DETAIL_PAGES_DISABLED = "DetailPagesDisabled"; 164 165 /** The disabled node name. */ 166 public static final String N_DISABLED = "Disabled"; 167 168 /** The DisabledFunctionsMode node name. */ 169 public static final String N_DISABLED_FUNCTIONS_MODE = "DisabledFunctionsMode"; 170 171 /** The DisabledTypesMode node name. */ 172 public static final String N_DISABLED_TYPES_MODE = "DisabledTypesMode"; 173 174 /** The discard model pages node name. */ 175 public static final String N_DISCARD_MODEL_PAGES = "DiscardModelPages"; 176 177 /** The discard properties node name. */ 178 public static final String N_DISCARD_PROPERTIES = "DiscardProperties"; 179 180 /** The discard types node name. */ 181 public static final String N_DISCARD_TYPES = "DiscardTypes"; 182 183 /** The display name node name. */ 184 public static final String N_DISPLAY_NAME = "DisplayName"; 185 186 /** The element view node name. */ 187 public static final String N_ELEMENT_VIEW = "ElementView"; 188 189 /** The error node name. */ 190 public static final String N_ERROR = "Error"; 191 192 /** The 'exclude external detail contents' node name. */ 193 public static final String N_EXCLUDE_EXTERNAL_DETAIL_CONTENTS = "ExcludeExternalDetailContents"; 194 195 /** The folder node name. */ 196 public static final String N_FOLDER = "Folder"; 197 198 /** The formatter node name. */ 199 public static final String N_FORMATTER = "Formatter"; 200 201 /** The function node name. */ 202 public static final String N_FUNCTION = "Function"; 203 204 /** The function node name. */ 205 public static final String N_FUNCTION_DEFAULT_PAGE = "FunctionDefaultPage"; 206 207 /** The function reference node name. */ 208 public static final String N_FUNCTION_REF = "FunctionRef"; 209 210 /** The 'include in site selector' node name. */ 211 public static final String N_INCLUDE_IN_SITE_SELECTOR = "IncludeInSiteSelector"; 212 213 /** The IncludeName node name. */ 214 public static final String N_INCLUDE_NAME = "IncludeName"; 215 216 /** The is default node name. */ 217 public static final String N_IS_DEFAULT = "IsDefault"; 218 219 /** The is preview node name. */ 220 public static final String N_IS_PREVIEW = "IsPreview"; 221 222 /** The JSP node name. */ 223 public static final String N_JSP = "Jsp"; 224 225 /** The Key node name. */ 226 public static final String N_KEY = "Key"; 227 228 /** The localization node name. */ 229 public static final String N_LOCALIZATION = "Localization"; 230 231 /** The master configuration node name. */ 232 public static final String N_MASTER_CONFIG = "MasterConfig"; 233 234 /** The max width node name. */ 235 public static final String N_MAX_WIDTH = "MaxWidth"; 236 237 /** The min width node name. */ 238 public static final String N_MIN_WIDTH = "MinWidth"; 239 240 /** The model page node name. */ 241 public static final String N_MODEL_PAGE = "ModelPage"; 242 243 /** The folder name node name. */ 244 public static final String N_NAME = "Name"; 245 246 /** The name pattern node name. */ 247 public static final String N_NAME_PATTERN = "NamePattern"; 248 249 /** The order node name. */ 250 public static final String N_ORDER = "Order"; 251 252 /** The page node name. */ 253 public static final String N_PAGE = "Page"; 254 255 /** The PageRelative node name. */ 256 public static final String N_PAGE_RELATIVE = "PageRelative"; 257 258 /** The folder path node name. */ 259 public static final String N_PATH = "Path"; 260 261 /** The Plugin node name. */ 262 public static final String N_PLUGIN = "Plugin"; 263 264 /** The PreferDetailPagesForLocalContents node name. */ 265 public static final String N_PREFER_DETAIL_PAGES_FOR_LOCAL_CONTENTS = "PreferDetailPagesForLocalContents"; 266 267 /** The prefer folder node name. */ 268 public static final String N_PREFER_FOLDER = "PreferFolder"; 269 270 /** The property node name. */ 271 public static final String N_PROPERTY = "Property"; 272 273 /** The property name node name. */ 274 public static final String N_PROPERTY_NAME = "PropertyName"; 275 276 /** XML node name. */ 277 public static final String N_PROPERTY_NAME_ALIAS = "PropertyNameAlias"; 278 279 /** Node name for the "Remove all formatters"-option. */ 280 public static final String N_REMOVE_ALL_FORMATTERS = "RemoveAllFormatters"; 281 282 /** Field name for the 'Remove all functions' setting. */ 283 public static final String N_REMOVE_ALL_FUNCTIONS = "RemoveAllFunctions"; 284 285 /** The RemoveAllPlugins node name. */ 286 public static final String N_REMOVE_ALL_PLUGINS = "RemoveAllPlugins"; 287 288 /** The RemoveAllSharedSettingOverrides node name. */ 289 public static final String N_REMOVE_ALL_SHARED_SETTING_OVERRIDES = "RemoveAllSharedSettingOverrides"; 290 291 /** Node name for removed formatters. */ 292 public static final String N_REMOVE_FORMATTER = "RemoveFormatter"; 293 294 /** Node name for the nested content with the removed formatters. */ 295 public static final String N_REMOVE_FORMATTERS = "RemoveFormatters"; 296 297 /** The remove function node name. */ 298 public static final String N_REMOVE_FUNCTIONS = "RemoveFunctions"; 299 300 /** The RemovePlugin node name. */ 301 public static final String N_REMOVE_PLUGIN = "RemovePlugin"; 302 303 /** The RemovePlugins node name. */ 304 public static final String N_REMOVE_PLUGINS = "RemovePlugins"; 305 306 /** The resource type node name. */ 307 public static final String N_RESOURCE_TYPE = "ResourceType"; 308 309 /** The regex rule node name. */ 310 public static final String N_RULE_REGEX = "RuleRegex"; 311 312 /** The rule type node name. */ 313 public static final String N_RULE_TYPE = "RuleType"; 314 315 /** The SharedSettingOverride node name. */ 316 public static final String N_SHARED_SETTING_OVERRIDE = "SharedSettingOverride"; 317 318 /** The ShowInDefaultView node name. */ 319 public static final String N_SHOW_IN_DEFAULT_VIEW = "ShowInDefaultView"; 320 321 /** The type node name. */ 322 public static final String N_TYPE = "Type"; 323 324 /** The type name node name. */ 325 public static final String N_TYPE_NAME = "TypeName"; 326 327 /** The node name for the type ordering mode. */ 328 public static final String N_TYPE_ORDERING_MODE = "TypeOrderingMode"; 329 330 /** Node name. */ 331 public static final String N_USE_FORMATTER_KEYS = "UseFormatterKeys"; 332 333 /** The Value node name. */ 334 public static final String N_VALUE = "Value"; 335 336 /** XML node name. */ 337 public static final String N_VALUE_TRANSLATION = "ValueTranslation"; 338 339 /** The widget node name. */ 340 public static final String N_VISIBILITY = "Visibility"; 341 342 /** The widget node name. */ 343 public static final String N_WIDGET = "Widget"; 344 345 /** The widget configuration node name. */ 346 public static final String N_WIDGET_CONFIG = "WidgetConfig"; 347 348 /** Scheme for explorer type view links. */ 349 public static final String VIEW_SCHEME = "view://"; 350 351 /** The log object for this class. */ 352 private static final Log LOG = CmsLog.getLog(CmsConfigurationReader.class); 353 354 /** The ElementDeleteMode node name. */ 355 private static final String N_ELEMENT_DELETE_MODE = "ElementDeleteMode"; 356 357 /** The CMS context used for reading the configuration data. */ 358 private CmsObject m_cms; 359 360 /** The parsed detail page configuration elements. */ 361 private List<CmsDetailPageInfo> m_detailPageConfigs = new ArrayList<CmsDetailPageInfo>(); 362 363 /** The list of configured function references. */ 364 private List<CmsFunctionReference> m_functionReferences = new ArrayList<CmsFunctionReference>(); 365 366 /** The parsed model page configuration elements. */ 367 private List<CmsModelPageConfigWithoutResource> m_modelPageConfigs = new ArrayList<CmsModelPageConfigWithoutResource>(); 368 369 /** The parsed property configuration elements. */ 370 private List<CmsPropertyConfig> m_propertyConfigs = new ArrayList<CmsPropertyConfig>(); 371 372 /** The resource type configuration objects. */ 373 private List<CmsResourceTypeConfig> m_resourceTypeConfigs = new ArrayList<CmsResourceTypeConfig>(); 374 375 /** 376 * Creates a new configuration reader.<p> 377 * 378 * @param cms the CMS context which should be used to read the configuration data.<p> 379 */ 380 public CmsConfigurationReader(CmsObject cms) { 381 382 m_cms = cms; 383 } 384 385 /** 386 * Gets the string value of an XML content location.<p> 387 * 388 * @param cms the CMS context to use 389 * @param location an XML content location 390 * 391 * @return the string value of that XML content location 392 */ 393 public static String getString(CmsObject cms, I_CmsXmlContentValueLocation location) { 394 395 if (location == null) { 396 return null; 397 } 398 return location.asString(cms); 399 } 400 401 /** 402 * Helper method to parse a property.<p> 403 * 404 * @param cms the CMS context to use 405 * @param field the location of the parent value 406 * 407 * @return the parsed property configuration 408 */ 409 public static CmsPropertyConfig parseProperty(CmsObject cms, I_CmsXmlContentLocation field) { 410 411 String name = getString(cms, field.getSubValue(N_PROPERTY_NAME)); 412 String includeName = getString(cms, field.getSubValue(N_INCLUDE_NAME)); 413 String widget = getString(cms, field.getSubValue(N_WIDGET)); 414 String widgetConfig = getString(cms, field.getSubValue(N_WIDGET_CONFIG)); 415 String ruleRegex = getString(cms, field.getSubValue(N_RULE_REGEX)); 416 String ruleType = getString(cms, field.getSubValue(N_RULE_TYPE)); 417 String default1 = getString(cms, field.getSubValue(N_DEFAULT)); 418 String error = getString(cms, field.getSubValue(N_ERROR)); 419 String niceName = getString(cms, field.getSubValue(N_DISPLAY_NAME)); 420 String description = getString(cms, field.getSubValue(N_DESCRIPTION)); 421 String preferFolder = getString(cms, field.getSubValue(N_PREFER_FOLDER)); 422 String aliasName = getString(cms, field.getSubValue(N_PROPERTY_NAME_ALIAS)); 423 String valueTranslations = getString(cms, field.getSubValue(N_VALUE_TRANSLATION)); 424 425 String disabledStr = getString(cms, field.getSubValue(N_DISABLED)); 426 boolean disabled = ((disabledStr != null) && Boolean.parseBoolean(disabledStr)); 427 428 String orderStr = getString(cms, field.getSubValue(N_ORDER)); 429 int order = I_CmsConfigurationObject.DEFAULT_ORDER; 430 431 try { 432 order = Integer.parseInt(orderStr); 433 } catch (NumberFormatException e) { 434 // noop 435 } 436 437 Visibility visibility; 438 String visibilityStr = getString(cms, field.getSubValue(N_VISIBILITY)); 439 try { 440 // to stay compatible with former visibility option values 441 if ("both".equals(visibilityStr)) { 442 visibilityStr = Visibility.elementAndParentIndividual.name(); 443 } else if ("parent".equals(visibilityStr)) { 444 visibilityStr = Visibility.parentShared.name(); 445 } 446 visibility = Visibility.valueOf(visibilityStr); 447 } catch (Exception e) { 448 visibility = null; 449 } 450 CmsXmlContentProperty prop = new CmsXmlContentProperty( 451 name, 452 aliasName, 453 "string", 454 visibility, 455 widget, 456 widgetConfig, 457 ruleRegex, 458 ruleType, 459 default1, 460 niceName, 461 description, 462 error, 463 preferFolder, 464 valueTranslations).withIncludeName(includeName); 465 // since these are real properties, using type vfslist makes no sense, so we always use the "string" type 466 CmsPropertyConfig propConfig = new CmsPropertyConfig(prop, disabled, order); 467 return propConfig; 468 469 } 470 471 /** 472 * Returns the list of function references.<p> 473 * 474 * @return the list of function references 475 */ 476 public List<CmsFunctionReference> getFunctionReferences() { 477 478 return new ArrayList<CmsFunctionReference>(m_functionReferences); 479 } 480 481 /** 482 * Returns the modelPageConfigs.<p> 483 * 484 * @return the modelPageConfigs 485 */ 486 public List<CmsModelPageConfigWithoutResource> getModelPageConfigs() { 487 488 return m_modelPageConfigs; 489 } 490 491 /** 492 * Parses the formatters to add.<p> 493 * 494 * @param node the parent node 495 * @return the set of keys of the formatters to add 496 */ 497 public Set<String> parseAddFormatters(I_CmsXmlContentLocation node) { 498 499 Set<String> addFormatters = new HashSet<String>(); 500 for (I_CmsXmlContentValueLocation addLoc : node.getSubValues(N_ADD_FORMATTERS + "/" + N_ADD_FORMATTER)) { 501 CmsXmlVfsFileValue value = (CmsXmlVfsFileValue)addLoc.getValue(); 502 CmsLink link = value.getLink(m_cms); 503 if (link != null) { 504 CmsUUID structureId = link.getStructureId(); 505 if (structureId != null) { 506 addFormatters.add(structureId.toString()); 507 } 508 } 509 } 510 return addFormatters; 511 } 512 513 /** 514 * Parses a configuration XML content and creates a configuration object from it.<p> 515 * 516 * @param basePath the base path 517 * @param content the XML content 518 * 519 * @return the created configuration object with the data from the XML content 520 * @throws CmsException if something goes wrong 521 */ 522 public CmsADEConfigDataInternal parseConfiguration(String basePath, CmsXmlContent content) throws CmsException { 523 524 m_detailPageConfigs = Lists.newArrayList(); 525 m_functionReferences = Lists.newArrayList(); 526 m_modelPageConfigs = Lists.newArrayList(); 527 m_propertyConfigs = Lists.newArrayList(); 528 m_resourceTypeConfigs = Lists.newArrayList(); 529 530 if (!content.hasLocale(DEFAULT_LOCALE)) { 531 return CmsADEConfigDataInternal.emptyConfiguration(basePath); 532 } 533 CmsXmlContentRootLocation root = new CmsXmlContentRootLocation(content, DEFAULT_LOCALE); 534 for (I_CmsXmlContentValueLocation node : root.getSubValues(N_RESOURCE_TYPE)) { 535 try { 536 parseResourceTypeConfig(basePath, node); 537 } catch (CmsException e) { 538 LOG.warn(e.getLocalizedMessage(), e); 539 } 540 } 541 for (I_CmsXmlContentValueLocation node : root.getSubValues(N_MODEL_PAGE)) { 542 try { 543 parseModelPage(node); 544 } catch (Exception e) { 545 LOG.warn(e.getLocalizedMessage(), e); 546 } 547 } 548 for (I_CmsXmlContentLocation node : root.getSubValues(N_DETAIL_PAGE)) { 549 try { 550 parseDetailPage(node); 551 } catch (Exception e) { 552 LOG.warn(e.getLocalizedMessage(), e); 553 } 554 } 555 556 for (I_CmsXmlContentLocation node : root.getSubValues(N_FUNCTION_REF)) { 557 parseFunctionReference(node); 558 } 559 560 CmsUUID sharedSettingOverride = null; 561 for (I_CmsXmlContentValueLocation node : root.getSubValues(N_SHARED_SETTING_OVERRIDE)) { 562 sharedSettingOverride = ((CmsXmlVfsFileValue)node.getValue()).getLink(m_cms).getStructureId(); 563 } 564 565 boolean removeSharedSettingOverrides = getBoolean(root, N_REMOVE_ALL_SHARED_SETTING_OVERRIDES); 566 567 boolean removeFunctions = false; 568 removeFunctions = getBoolean(root, N_REMOVE_ALL_FUNCTIONS); 569 570 Set<CmsUUID> functions = new LinkedHashSet<>(); 571 for (I_CmsXmlContentValueLocation node : root.getSubValues(N_FUNCTION)) { 572 CmsXmlVfsFileValue value = (CmsXmlVfsFileValue)node.getValue(); 573 CmsLink link = value.getLink(m_cms); 574 if (link != null) { 575 CmsUUID structureId = link.getStructureId(); 576 if (structureId != null) { 577 functions.add(link.getStructureId()); 578 } 579 } 580 } 581 582 Set<CmsUUID> functionsToRemove = new LinkedHashSet<>(); 583 for (I_CmsXmlContentValueLocation parent : root.getSubValues(N_REMOVE_FUNCTIONS)) { 584 for (I_CmsXmlContentValueLocation node : parent.getSubValues(N_FUNCTION)) { 585 CmsXmlVfsFileValue value = (CmsXmlVfsFileValue)node.getValue(); 586 CmsLink link = value.getLink(m_cms); 587 if (link != null) { 588 CmsUUID structureId = link.getStructureId(); 589 if (structureId != null) { 590 functionsToRemove.add(link.getStructureId()); 591 } 592 } 593 } 594 } 595 596 boolean removeAllPlugins = getBoolean(root, N_REMOVE_ALL_PLUGINS); 597 Set<CmsUUID> pluginsToRemove = readInternalLinkListTargetIds(root, N_REMOVE_PLUGINS, N_PLUGIN); 598 Set<CmsUUID> pluginsToAdd = readInternalLinkListTargetIds(root, N_ADD_PLUGINS, N_PLUGIN); 599 600 boolean removeAllFormatters = getBoolean(root, N_REMOVE_ALL_FORMATTERS); 601 CmsFormatterChangeSet formatterChangeSet = parseFormatterChangeSet( 602 basePath, 603 root, 604 removeAllFormatters, 605 removeFunctions, 606 functions, 607 functionsToRemove); 608 boolean discardInheritedTypes = getBoolean(root, N_DISCARD_TYPES); 609 // boolean discardInheritedProperties = getBoolean(root, N_DISCARD_PROPERTIES); 610 I_CmsXmlContentValueLocation discardPropertiesLoc = root.getSubValue(N_DISCARD_PROPERTIES); 611 DiscardPropertiesMode discardPropertiesMode = DiscardPropertiesMode.keep; 612 if (discardPropertiesLoc != null) { 613 String discardPropertiesStr = discardPropertiesLoc.getValue().getStringValue(m_cms); 614 for (DiscardPropertiesMode discardMode : DiscardPropertiesMode.values()) { 615 if (discardMode.getStringValue().contentEquals(discardPropertiesStr)) { 616 discardPropertiesMode = discardMode; 617 } 618 } 619 } 620 for (I_CmsXmlContentLocation node : root.getSubValues(N_PROPERTY)) { 621 parseProperty(node, discardPropertiesMode); 622 } 623 624 boolean discardInheritedModelPages = getBoolean(root, N_DISCARD_MODEL_PAGES); 625 626 boolean createContentsLocally = getBoolean(root, N_CREATE_CONTENTS_LOCALLY); 627 boolean preferDetailPagesForLocalContents = getBoolean(root, N_PREFER_DETAIL_PAGES_FOR_LOCAL_CONTENTS); 628 boolean exludeExternalDetailContents = getBoolean(root, N_EXCLUDE_EXTERNAL_DETAIL_CONTENTS); 629 boolean includeInSiteSelector = getBoolean(root, N_INCLUDE_IN_SITE_SELECTOR); 630 631 String galleryDisabledTypesStr = getString(root.getSubValue(N_DISABLED_TYPES_MODE)); 632 CmsGalleryDisabledTypesMode galleryDisabledTypesMode = null; 633 if (galleryDisabledTypesStr != null) { 634 galleryDisabledTypesMode = CmsGalleryDisabledTypesMode.valueOf(galleryDisabledTypesStr); 635 } 636 637 String galleryDisabledFunctionsStr = getString(root.getSubValue(N_DISABLED_FUNCTIONS_MODE)); 638 CmsGalleryDisabledTypesMode galleryDisabledFunctionsMode = null; 639 if (galleryDisabledFunctionsStr != null) { 640 galleryDisabledFunctionsMode = CmsGalleryDisabledTypesMode.valueOf(galleryDisabledFunctionsStr); 641 } 642 643 I_CmsXmlContentValueLocation typeOrderingLoc = root.getSubValue(N_TYPE_ORDERING_MODE); 644 CmsTypeOrderingMode typeOrderingMode = null; 645 if (typeOrderingLoc != null) { 646 boolean byDisplayOrder = Boolean.parseBoolean(typeOrderingLoc.getValue().getStringValue(m_cms)); 647 typeOrderingMode = byDisplayOrder ? CmsTypeOrderingMode.byDisplayOrder : CmsTypeOrderingMode.latestOnTop; 648 } 649 650 I_CmsXmlContentValueLocation useFormatterKeysLoc = root.getSubValue(N_USE_FORMATTER_KEYS); 651 Boolean useFormatterKeys = null; 652 if (useFormatterKeysLoc != null) { 653 useFormatterKeys = Boolean.valueOf(useFormatterKeysLoc.getValue().getStringValue(m_cms)); 654 } 655 656 boolean isModuleConfig = OpenCms.getResourceManager().getResourceType( 657 content.getFile().getTypeId()).getTypeName().equals(CmsADEManager.MODULE_CONFIG_TYPE); 658 659 List<ConfigReference> masterConfigIds = new ArrayList<>(); 660 for (I_CmsXmlContentValueLocation masterConfigLoc : root.getSubValues(N_MASTER_CONFIG)) { 661 CmsXmlVfsFileValue value = (CmsXmlVfsFileValue)masterConfigLoc.getValue(); 662 CmsLink link = value.getUncheckedLink(); 663 ConfigReferenceMeta meta = null; 664 if (link != null) { 665 meta = new ConfigReferenceMeta(link.getParameterMap()); 666 } 667 CmsUUID id = masterConfigLoc.asId(m_cms); 668 if (id != null) { 669 masterConfigIds.add(new ConfigReference(id, meta)); 670 } 671 } 672 673 Map<String, String> attributes = new LinkedHashMap<>(); 674 for (I_CmsXmlContentValueLocation mappingLoc : root.getSubValues(N_ATTRIBUTE)) { 675 String key = getString(mappingLoc.getSubValue(N_KEY)).trim(); 676 String value = getString(mappingLoc.getSubValue(N_VALUE)).trim(); 677 attributes.put(key, value); 678 } 679 680 I_CmsXmlContentValueLocation attributeEditorConfigLoc = root.getSubValue(N_ATTRIBUTE_EDITOR_CONFIG); 681 CmsUUID attributeEditorConfigId = null; 682 if (attributeEditorConfigLoc != null) { 683 attributeEditorConfigId = attributeEditorConfigLoc.asId(m_cms); 684 } 685 686 CmsAddContentRestriction addContentRestriction = CmsAddContentRestriction.read( 687 m_cms, 688 root, 689 N_ADD_CONTENT_RESTRICTION); 690 691 CmsADEConfigDataInternal result = new CmsADEConfigDataInternal( 692 m_cms, 693 content.getFile(), 694 isModuleConfig, 695 basePath, 696 masterConfigIds, 697 m_resourceTypeConfigs, 698 galleryDisabledTypesMode, 699 galleryDisabledFunctionsMode, 700 discardInheritedTypes, 701 m_propertyConfigs, 702 discardPropertiesMode, 703 m_detailPageConfigs, 704 m_modelPageConfigs, 705 m_functionReferences, 706 discardInheritedModelPages, 707 createContentsLocally, 708 preferDetailPagesForLocalContents, 709 exludeExternalDetailContents, 710 includeInSiteSelector, 711 formatterChangeSet, 712 removeFunctions, 713 functions, 714 functionsToRemove, 715 removeAllPlugins, 716 pluginsToAdd, 717 pluginsToRemove, 718 useFormatterKeys, 719 typeOrderingMode, 720 addContentRestriction, 721 sharedSettingOverride, 722 removeSharedSettingOverrides, 723 attributeEditorConfigId, 724 attributes); 725 return result; 726 } 727 728 /** 729 * Parses a folder which may either be given as a path or as a folder name.<p> 730 * 731 * @param basePath the base path for the configuration 732 * @param location the XML content node from which to parse the folder 733 * @return the folder bean 734 * 735 * @throws CmsException if something goes wrong 736 */ 737 public CmsContentFolderDescriptor parseFolderOrName(String basePath, I_CmsXmlContentLocation location) 738 throws CmsException { 739 740 if (location == null) { 741 return null; 742 } 743 I_CmsXmlContentValueLocation nameLoc = location.getSubValue(N_NAME); 744 I_CmsXmlContentValueLocation pathLoc = location.getSubValue(N_PATH); 745 I_CmsXmlContentValueLocation pageRelativeLoc = location.getSubValue(N_PAGE_RELATIVE); 746 if (nameLoc != null) { 747 String name = nameLoc.asString(m_cms); 748 return new CmsContentFolderDescriptor( 749 basePath == null ? null : CmsStringUtil.joinPaths(basePath, CmsADEManager.CONTENT_FOLDER_NAME), 750 name); 751 } else if (pathLoc != null) { 752 String path = pathLoc.asString(m_cms); 753 CmsResource folder = m_cms.readResource(path); 754 return new CmsContentFolderDescriptor(folder); 755 } else if (pageRelativeLoc != null) { 756 return CmsContentFolderDescriptor.createPageRelativeFolderDescriptor(); 757 } else { 758 return null; 759 } 760 } 761 762 /** 763 * Parses a formatter bean.<p> 764 * 765 * @param typeName the type name for which the formatter is being parsed 766 * @param node the node from which to parse the formatter data 767 * 768 * @return the formatter bean from the XML 769 */ 770 public CmsFormatterBean parseFormatter(String typeName, I_CmsXmlContentLocation node) { 771 772 String type = getString(node.getSubValue(N_TYPE)); 773 String minWidth = getString(node.getSubValue(N_MIN_WIDTH)); 774 String maxWidth = getString(node.getSubValue(N_MAX_WIDTH)); 775 boolean preview = false; 776 I_CmsXmlContentValueLocation previewLoc = node.getSubValue(N_IS_PREVIEW); 777 preview = (previewLoc != null) && Boolean.parseBoolean(previewLoc.asString(m_cms)); 778 String jsp = m_cms.getRequestContext().addSiteRoot(getString(node.getSubValue(N_JSP))); 779 boolean searchContent = true; 780 CmsFormatterBean formatterBean = new CmsFormatterBean( 781 type, 782 jsp, 783 minWidth, 784 maxWidth, 785 "" + preview, 786 "" + searchContent, 787 null); 788 return formatterBean; 789 790 } 791 792 /** 793 * Parses model page data from the XML content.<p> 794 * 795 * @param node the XML content node 796 */ 797 public void parseModelPage(I_CmsXmlContentLocation node) { 798 799 CmsXmlVfsFileValue pageValue = (CmsXmlVfsFileValue)node.getSubValue(N_PAGE).getValue(); 800 CmsLink link = pageValue.getUncheckedLink(); 801 if ((link == null) || (link.getStructureId() == null)) { 802 return; 803 } 804 I_CmsXmlContentValueLocation disabledLoc = node.getSubValue(N_DISABLED); 805 boolean disabled = (disabledLoc != null) && Boolean.parseBoolean(disabledLoc.asString(m_cms)); 806 I_CmsXmlContentValueLocation defaultLoc = node.getSubValue(N_IS_DEFAULT); 807 boolean isDefault = (defaultLoc != null) && Boolean.parseBoolean(defaultLoc.asString(m_cms)); 808 CmsModelPageConfigWithoutResource modelPage = new CmsModelPageConfigWithoutResource( 809 link.getStructureId(), 810 isDefault, 811 disabled); 812 m_modelPageConfigs.add(modelPage); 813 814 } 815 816 /** 817 * Parses the set of formatters to remove.<p> 818 * 819 * @param node the parent node 820 * @return the set of formatters to remove 821 */ 822 public Set<String> parseRemoveFormatters(I_CmsXmlContentLocation node) { 823 824 Set<String> removeFormatters = new HashSet<String>(); 825 for (I_CmsXmlContentValueLocation removeLoc : node.getSubValues( 826 N_REMOVE_FORMATTERS + "/" + N_REMOVE_FORMATTER)) { 827 CmsXmlVfsFileValue value = (CmsXmlVfsFileValue)removeLoc.getValue(); 828 CmsLink link = value.getLink(m_cms); 829 if (link != null) { 830 CmsUUID structureId = link.getStructureId(); 831 if (structureId != null) { 832 removeFormatters.add(structureId.toString()); 833 } 834 } 835 } 836 return removeFormatters; 837 } 838 839 /** 840 * Parses a resource type configuration element from the XML content.<p> 841 * 842 * @param basePath the base path of the configuration 843 * @param node the XML configuration node 844 * @throws CmsException if something goes wrong 845 */ 846 public void parseResourceTypeConfig(String basePath, I_CmsXmlContentLocation node) throws CmsException { 847 848 I_CmsXmlContentValueLocation typeNameLoc = node.getSubValue(N_TYPE_NAME); 849 String typeName = typeNameLoc.asString(m_cms); 850 CmsContentFolderDescriptor folderOrName = parseFolderOrName(basePath, node.getSubValue(N_FOLDER)); 851 I_CmsXmlContentValueLocation disabledLoc = node.getSubValue(N_DISABLED); 852 boolean disabled = false; 853 boolean addDisabled = false; 854 boolean createDisabled = false; 855 boolean editDisabled = false; 856 boolean listsOnly = false; 857 String disabledStr = disabledLoc == null ? null : disabledLoc.asString(m_cms); 858 boolean availabilityNotSet = false; 859 if (disabledStr != null) { 860 if ("add".equalsIgnoreCase(disabledStr.trim())) { 861 addDisabled = true; 862 } else if ("create".equalsIgnoreCase(disabledStr.trim())) { 863 createDisabled = true; 864 } else if ("createOrEdit".equalsIgnoreCase(disabledStr.trim())) { 865 createDisabled = true; 866 editDisabled = true; 867 } else if ("listsOnly".equalsIgnoreCase(disabledStr.trim())) { 868 listsOnly = true; 869 addDisabled = true; 870 } else { 871 disabled = Boolean.parseBoolean(disabledStr); 872 } 873 } else { 874 availabilityNotSet = true; 875 } 876 877 I_CmsXmlContentValueLocation namePatternLoc = node.getSubValue(N_NAME_PATTERN); 878 String namePattern = null; 879 if (namePatternLoc != null) { 880 namePattern = namePatternLoc.asString(m_cms); 881 } 882 883 boolean detailPagesDisabled = false; 884 I_CmsXmlContentValueLocation detailDisabledLoc = node.getSubValue(N_DETAIL_PAGES_DISABLED); 885 if (detailDisabledLoc != null) { 886 String detailPagesDisabledStr = detailDisabledLoc.asString(m_cms); 887 detailPagesDisabled = Boolean.parseBoolean(detailPagesDisabledStr); 888 } 889 890 Integer order = null; 891 I_CmsXmlContentValueLocation orderLoc = node.getSubValue(N_ORDER); 892 if (orderLoc != null) { 893 try { 894 String orderStr = orderLoc.asString(m_cms); 895 order = Integer.valueOf(orderStr); 896 } catch (NumberFormatException e) { 897 // noop 898 } 899 } 900 901 I_CmsXmlContentValueLocation elementViewLoc = node.getSubValue(N_ELEMENT_VIEW); 902 CmsUUID elementView = null; 903 if (elementViewLoc != null) { 904 try { 905 CmsXmlVarLinkValue elementViewValue = (CmsXmlVarLinkValue)elementViewLoc.getValue(); 906 String stringValue = elementViewValue.getStringValue(m_cms); 907 if ("".equals(stringValue)) { 908 elementView = CmsUUID.getNullUUID(); 909 } else if (stringValue.startsWith(VIEW_SCHEME)) { 910 elementView = new CmsUUID(stringValue.substring(VIEW_SCHEME.length())); 911 } else { 912 elementView = elementViewValue.getLink(m_cms).getStructureId(); 913 } 914 } catch (Exception e) { 915 // in case parsing the link fails, the default element view will be used 916 } 917 } 918 919 I_CmsXmlContentValueLocation locationLoc = node.getSubValue(N_LOCALIZATION); 920 String localization = null; 921 if (locationLoc != null) { 922 CmsXmlVfsFileValue locationValue = (CmsXmlVfsFileValue)locationLoc.getValue(); 923 CmsLink link = locationValue.getLink(m_cms); 924 if (null != link) { 925 String stringValue = link.getSitePath(m_cms); 926 // extract bundle base name from the path to the bundle file 927 int lastSlashIndex = stringValue.lastIndexOf("/"); 928 String fileName = stringValue.substring(lastSlashIndex + 1); 929 if (CmsFileUtil.getExtension(fileName).equals(".properties")) { 930 fileName = fileName.substring(0, fileName.length() - ".properties".length()); 931 } 932 String localeSuffix = CmsStringUtil.getLocaleSuffixForName(fileName); 933 if ((localeSuffix != null) && fileName.endsWith(localeSuffix)) { 934 fileName = fileName.substring(0, fileName.length() - localeSuffix.length() - 1); 935 } 936 localization = fileName; 937 } 938 } 939 940 I_CmsXmlContentValueLocation showDefaultViewLoc = node.getSubValue(N_SHOW_IN_DEFAULT_VIEW); 941 Boolean showInDefaultView = null; 942 if (showDefaultViewLoc != null) { 943 showInDefaultView = Boolean.valueOf( 944 Boolean.parseBoolean(showDefaultViewLoc.getValue().getStringValue(m_cms))); 945 } 946 947 I_CmsXmlContentValueLocation copyInModelsLoc = node.getSubValue(N_COPY_IN_MODELS); 948 Boolean copyInModels = null; 949 if (copyInModelsLoc != null) { 950 copyInModels = Boolean.valueOf(Boolean.parseBoolean(copyInModelsLoc.getValue().getStringValue(m_cms))); 951 } 952 953 I_CmsXmlContentValueLocation elementDeleteModeLoc = node.getSubValue(N_ELEMENT_DELETE_MODE); 954 ElementDeleteMode elementDeleteMode = null; 955 if (elementDeleteModeLoc != null) { 956 try { 957 elementDeleteMode = ElementDeleteMode.valueOf(elementDeleteModeLoc.getValue().getStringValue(m_cms)); 958 } catch (Exception e) { 959 LOG.warn(e.getLocalizedMessage(), e); 960 } 961 } 962 963 List<I_CmsFormatterBean> formatters = new ArrayList<I_CmsFormatterBean>(); 964 for (I_CmsXmlContentValueLocation formatterLoc : node.getSubValues(N_FORMATTER)) { 965 CmsFormatterBean formatter = parseFormatter(typeName, formatterLoc); 966 formatters.add(formatter); 967 } 968 969 CmsResourceTypeConfig typeConfig = new CmsResourceTypeConfig( 970 typeName, 971 disabled, 972 folderOrName, 973 namePattern, 974 detailPagesDisabled, 975 addDisabled, 976 createDisabled, 977 editDisabled, 978 listsOnly, 979 availabilityNotSet, 980 elementView, 981 localization, 982 showInDefaultView, 983 copyInModels, 984 order, 985 elementDeleteMode); 986 m_resourceTypeConfigs.add(typeConfig); 987 } 988 989 /** 990 * Parses the sitemap configuration given the configuration file and base path.<p> 991 * 992 * @param basePath the base path 993 * @param configRes the configuration file resource 994 * @return the parsed configuration data 995 * @throws CmsException if something goes wrong 996 */ 997 public CmsADEConfigDataInternal parseSitemapConfiguration(String basePath, CmsResource configRes) 998 throws CmsException { 999 1000 LOG.info("Parsing configuration " + configRes.getRootPath()); 1001 CmsFile configFile = m_cms.readFile(configRes); 1002 CmsXmlContent content = CmsXmlContentFactory.unmarshal(m_cms, configFile); 1003 return parseConfiguration(basePath, content); 1004 } 1005 1006 /** 1007 * Reads the configurations of all modules and combines them into a single configuration object.<p> 1008 * 1009 * @return the combined configuration object 1010 */ 1011 public List<CmsADEConfigDataInternal> readModuleConfigurations() { 1012 1013 List<CmsADEConfigDataInternal> configurations = new ArrayList<CmsADEConfigDataInternal>(); 1014 List<CmsModule> modules = OpenCms.getModuleManager().getAllInstalledModules(); 1015 long beginTime = System.currentTimeMillis(); 1016 for (CmsModule module : modules) { 1017 String configPath = module.getConfigurationPath(); 1018 if (m_cms.existsResource(configPath)) { 1019 try { 1020 CmsResource configFile = m_cms.readResource(configPath); 1021 LOG.info("Found module configuration " + configPath + " for module " + module.getName()); 1022 CmsADEConfigDataInternal config = parseSitemapConfiguration(null, configFile); 1023 configurations.add(config); 1024 } catch (CmsException e) { 1025 // errors while parsing configuration 1026 LOG.error(e.getLocalizedMessage(), e); 1027 } catch (CmsRuntimeException e) { 1028 // may happen during import of org.opencms.ade.configuration module 1029 LOG.warn(e.getLocalizedMessage(), e); 1030 } catch (Throwable e) { 1031 LOG.error(e.getLocalizedMessage(), e); 1032 } 1033 } 1034 } 1035 long endTime = System.currentTimeMillis(); 1036 LOG.debug("readModuleConfiguations took " + (endTime - beginTime) + "ms"); 1037 return configurations; 1038 } 1039 1040 /** 1041 * Helper method to read a boolean value from the XML.<p> 1042 * 1043 * If the element is not found in the XML, false is returned.<p> 1044 * 1045 * @param parent the parent node 1046 * @param name the name of the XML content value 1047 * @return the boolean value 1048 */ 1049 protected boolean getBoolean(I_CmsXmlContentLocation parent, String name) { 1050 1051 I_CmsXmlContentValueLocation location = parent.getSubValue(name); 1052 if (location == null) { 1053 return false; 1054 } 1055 String value = location.getValue().getStringValue(m_cms); 1056 return Boolean.parseBoolean(value); 1057 } 1058 1059 /** 1060 * Gets the string value of an XML content location.<p> 1061 * 1062 * @param location an XML content location 1063 * 1064 * @return the string value of that XML content location 1065 */ 1066 protected String getString(I_CmsXmlContentValueLocation location) { 1067 1068 return getString(m_cms, location); 1069 } 1070 1071 /** 1072 * Parses the detail pages from an XML content node.<p> 1073 * 1074 * @param node the XML content node 1075 */ 1076 protected void parseDetailPage(I_CmsXmlContentLocation node) { 1077 1078 I_CmsXmlContentValueLocation pageLoc = node.getSubValue(N_PAGE); 1079 String typeName = getString(node.getSubValue(N_TYPE)); 1080 int qualifierPos = typeName.indexOf(CmsDetailPageInfo.QUALIFIER_SEPARATOR); 1081 String qualifier = null; 1082 if (qualifierPos != -1) { 1083 qualifier = typeName.substring(qualifierPos + 1); 1084 typeName = typeName.substring(0, qualifierPos); 1085 } 1086 CmsXmlVfsFileValue detailPageValue = (CmsXmlVfsFileValue)pageLoc.getValue(); 1087 CmsLink uncheckedLink = detailPageValue.getUncheckedLink(); 1088 if (uncheckedLink == null) { 1089 LOG.warn( 1090 "Missing detail page link in " + CmsLog.eval(LOG, () -> node.getDocument().getFile().getRootPath())); 1091 return; 1092 } 1093 String page = uncheckedLink.getTarget(); 1094 CmsUUID structureId = uncheckedLink.getStructureId(); 1095 if (structureId == null) { 1096 return; 1097 } 1098 1099 String iconClasses; 1100 if (typeName.startsWith(CmsDetailPageInfo.FUNCTION_PREFIX)) { 1101 iconClasses = CmsIconUtil.getIconClasses(CmsXmlDynamicFunctionHandler.TYPE_FUNCTION, null, false); 1102 } else { 1103 iconClasses = CmsIconUtil.getIconClasses(typeName, null, false); 1104 } 1105 1106 CmsDetailPageInfo detailPage = new CmsDetailPageInfo(structureId, page, typeName, qualifier, iconClasses); 1107 m_detailPageConfigs.add(detailPage); 1108 1109 } 1110 1111 /** 1112 * Parses the formatter change set.<p> 1113 * 1114 * @param basePath the configuration base path 1115 * @param node the parent node 1116 * @param removeAllFormatters flag, indicating if all formatters that are not explicitly added should be removed 1117 * @param removeFunctions if true, remove functions 1118 * @param functions the functions to add 1119 * @param functionsToRemove the functions to remove 1120 * 1121 * @return the formatter change set 1122 */ 1123 protected CmsFormatterChangeSet parseFormatterChangeSet( 1124 String basePath, 1125 I_CmsXmlContentLocation node, 1126 boolean removeAllFormatters, 1127 boolean removeFunctions, 1128 Set<CmsUUID> functions, 1129 Set<CmsUUID> functionsToRemove) { 1130 1131 Set<String> addFormatters = parseAddFormatters(node); 1132 addFormatters.addAll(readLocalFormatters(node)); 1133 Set<String> removeFormatters = removeAllFormatters ? new HashSet<String>() : parseRemoveFormatters(node); 1134 String siteRoot = null; 1135 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(basePath)) { 1136 siteRoot = OpenCms.getSiteManager().getSiteRoot(basePath); 1137 } 1138 CmsFormatterChangeSet result = new CmsFormatterChangeSet( 1139 removeFormatters, 1140 addFormatters, 1141 siteRoot, 1142 removeAllFormatters, 1143 removeFunctions, 1144 functions, 1145 functionsToRemove); 1146 return result; 1147 } 1148 1149 /** 1150 * Parses a function reference node.<p> 1151 * 1152 * @param node the function reference node 1153 */ 1154 protected void parseFunctionReference(I_CmsXmlContentLocation node) { 1155 1156 String name = node.getSubValue(N_NAME).asString(m_cms); 1157 CmsUUID functionId = node.getSubValue(N_FUNCTION).asId(m_cms); 1158 CmsUUID functionDefaultPageId = null; 1159 I_CmsXmlContentValueLocation defaultPageValue = node.getSubValue(N_FUNCTION_DEFAULT_PAGE); 1160 if (defaultPageValue != null) { 1161 functionDefaultPageId = defaultPageValue.asId(m_cms); 1162 } 1163 I_CmsXmlContentValueLocation orderNode = node.getSubValue(N_ORDER); 1164 int order = I_CmsConfigurationObject.DEFAULT_ORDER; 1165 if (orderNode != null) { 1166 String orderStr = orderNode.asString(m_cms); 1167 try { 1168 order = Integer.parseInt(orderStr); 1169 } catch (NumberFormatException e) { 1170 // noop 1171 } 1172 } 1173 m_functionReferences.add(new CmsFunctionReference(name, functionId, functionDefaultPageId, order)); 1174 } 1175 1176 /** 1177 * Parses a single field definition from a content value.<p> 1178 * 1179 * @param field the content value to parse the field from 1180 * @param mode the property discard mode 1181 */ 1182 private void parseProperty(I_CmsXmlContentLocation field, DiscardPropertiesMode mode) { 1183 1184 CmsPropertyConfig propConfig = parseProperty(m_cms, field); 1185 if (CmsStringUtil.isEmptyOrWhitespaceOnly(propConfig.getName())) { 1186 return; 1187 } 1188 if (mode == DiscardPropertiesMode.top) { 1189 propConfig = propConfig.cloneWithTop(true); 1190 } 1191 m_propertyConfigs.add(propConfig); 1192 } 1193 1194 /** 1195 * Helper method for reading the target ids from a list of internal links two levels nested. 1196 * 1197 * @param root the parent location 1198 * @param childName the node name for the children 1199 * @param grandchildName the node name for the grandchildren 1200 * 1201 * @return the set of target ids collected from the grandchildren 1202 */ 1203 private Set<CmsUUID> readInternalLinkListTargetIds( 1204 I_CmsXmlContentLocation root, 1205 String childName, 1206 String grandchildName) { 1207 1208 Set<CmsUUID> result = new LinkedHashSet<>(); 1209 for (I_CmsXmlContentValueLocation parent : root.getSubValues(childName)) { 1210 for (I_CmsXmlContentValueLocation node : parent.getSubValues(grandchildName)) { 1211 CmsXmlVfsFileValue value = (CmsXmlVfsFileValue)node.getValue(); 1212 CmsLink link = value.getLink(m_cms); 1213 if (link != null) { 1214 CmsUUID structureId = link.getStructureId(); 1215 if (structureId != null) { 1216 result.add(link.getStructureId()); 1217 } 1218 } 1219 } 1220 } 1221 return result; 1222 } 1223 1224 /** 1225 * Reads the local macro or flex formatters from the .formatters folder if present.<p> 1226 * 1227 * @param node the xml content node 1228 * 1229 * @return the local formatters 1230 */ 1231 private Set<String> readLocalFormatters(I_CmsXmlContentLocation node) { 1232 1233 Set<String> addFormatters = new HashSet<String>(); 1234 String path = m_cms.getSitePath(node.getDocument().getFile()); 1235 path = CmsStringUtil.joinPaths(CmsResource.getParentFolder(path), ".formatters"); 1236 try { 1237 if (m_cms.existsResource(path, CmsResourceFilter.IGNORE_EXPIRATION)) { 1238 I_CmsResourceType macroType = OpenCms.getResourceManager().getResourceType( 1239 CmsFormatterConfigurationCache.TYPE_MACRO_FORMATTER); 1240 CmsResourceFilter filter = CmsResourceFilter.IGNORE_EXPIRATION.addRequireType(macroType); 1241 List<CmsResource> macroFormatters = m_cms.readResources(path, filter); 1242 for (CmsResource formatter : macroFormatters) { 1243 addFormatters.add(formatter.getStructureId().toString()); 1244 } 1245 I_CmsResourceType flexType = OpenCms.getResourceManager().getResourceType( 1246 CmsFormatterConfigurationCache.TYPE_FLEX_FORMATTER); 1247 CmsResourceFilter filterFlex = CmsResourceFilter.IGNORE_EXPIRATION.addRequireType(flexType); 1248 List<CmsResource> flexFormatters = m_cms.readResources(path, filterFlex); 1249 for (CmsResource formatter : flexFormatters) { 1250 addFormatters.add(formatter.getStructureId().toString()); 1251 } 1252 } 1253 } catch (CmsException e) { 1254 LOG.warn(e.getMessage(), e); 1255 } 1256 return addFormatters; 1257 } 1258 1259}