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