001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, 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.jsp.util; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.configuration.CmsADEManager; 032import org.opencms.ade.configuration.CmsFunctionReference; 033import org.opencms.ade.configuration.plugins.CmsTemplatePlugin; 034import org.opencms.ade.configuration.plugins.CmsTemplatePluginFinder; 035import org.opencms.ade.containerpage.CmsContainerpageService; 036import org.opencms.ade.containerpage.CmsDetailOnlyContainerUtil; 037import org.opencms.ade.containerpage.CmsModelGroupHelper; 038import org.opencms.ade.containerpage.shared.CmsFormatterConfig; 039import org.opencms.ade.containerpage.shared.CmsInheritanceInfo; 040import org.opencms.ade.detailpage.CmsDetailPageInfo; 041import org.opencms.ade.detailpage.CmsDetailPageResourceHandler; 042import org.opencms.file.CmsFile; 043import org.opencms.file.CmsObject; 044import org.opencms.file.CmsProperty; 045import org.opencms.file.CmsPropertyDefinition; 046import org.opencms.file.CmsRequestContext; 047import org.opencms.file.CmsResource; 048import org.opencms.file.CmsResourceFilter; 049import org.opencms.file.CmsVfsResourceNotFoundException; 050import org.opencms.file.history.CmsHistoryResourceHandler; 051import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 052import org.opencms.file.types.I_CmsResourceType; 053import org.opencms.flex.CmsFlexController; 054import org.opencms.flex.CmsFlexRequest; 055import org.opencms.gwt.shared.CmsGwtConstants; 056import org.opencms.i18n.CmsEncoder; 057import org.opencms.i18n.CmsLocaleGroupService; 058import org.opencms.i18n.CmsMessageToBundleIndex; 059import org.opencms.i18n.CmsResourceBundleLoader; 060import org.opencms.i18n.CmsVfsResourceBundle; 061import org.opencms.jsp.CmsJspBean; 062import org.opencms.jsp.CmsJspResourceWrapper; 063import org.opencms.jsp.CmsJspTagContainer; 064import org.opencms.jsp.CmsJspTagEditable; 065import org.opencms.jsp.Messages; 066import org.opencms.jsp.jsonpart.CmsJsonPartFilter; 067import org.opencms.jsp.search.config.parser.simplesearch.CmsConfigParserUtils; 068import org.opencms.loader.CmsLoaderException; 069import org.opencms.loader.CmsTemplateContextManager; 070import org.opencms.main.CmsException; 071import org.opencms.main.CmsLog; 072import org.opencms.main.CmsRuntimeException; 073import org.opencms.main.CmsSystemInfo; 074import org.opencms.main.OpenCms; 075import org.opencms.main.OpenCmsServlet; 076import org.opencms.relations.CmsCategory; 077import org.opencms.relations.CmsCategoryService; 078import org.opencms.search.galleries.CmsGalleryNameMacroResolver; 079import org.opencms.site.CmsSite; 080import org.opencms.ui.CmsVaadinUtils; 081import org.opencms.ui.apps.A_CmsWorkplaceApp; 082import org.opencms.ui.apps.CmsEditor; 083import org.opencms.ui.apps.CmsEditorConfiguration; 084import org.opencms.ui.editors.messagebundle.CmsMessageBundleEditor; 085import org.opencms.util.CmsCollectionsGenericWrapper; 086import org.opencms.util.CmsFileUtil; 087import org.opencms.util.CmsMacroResolver; 088import org.opencms.util.CmsStringUtil; 089import org.opencms.util.CmsUUID; 090import org.opencms.workplace.galleries.CmsAjaxDownloadGallery; 091import org.opencms.workplace.galleries.CmsAjaxImageGallery; 092import org.opencms.xml.containerpage.CmsADESessionCache; 093import org.opencms.xml.containerpage.CmsContainerBean; 094import org.opencms.xml.containerpage.CmsContainerElementBean; 095import org.opencms.xml.containerpage.CmsContainerPageBean; 096import org.opencms.xml.containerpage.CmsDynamicFunctionBean; 097import org.opencms.xml.containerpage.CmsDynamicFunctionParser; 098import org.opencms.xml.containerpage.CmsFormatterConfiguration; 099import org.opencms.xml.containerpage.CmsMetaMapping; 100import org.opencms.xml.containerpage.CmsXmlContainerPage; 101import org.opencms.xml.containerpage.CmsXmlContainerPageFactory; 102import org.opencms.xml.containerpage.I_CmsFormatterBean; 103import org.opencms.xml.content.CmsXmlContent; 104import org.opencms.xml.content.CmsXmlContentFactory; 105import org.opencms.xml.content.CmsXmlContentProperty; 106import org.opencms.xml.templatemapper.CmsTemplateMapper; 107import org.opencms.xml.types.I_CmsXmlContentValue; 108 109import java.lang.reflect.Constructor; 110import java.lang.reflect.Method; 111import java.util.ArrayList; 112import java.util.Arrays; 113import java.util.Collections; 114import java.util.HashMap; 115import java.util.List; 116import java.util.Locale; 117import java.util.Map; 118import java.util.ResourceBundle; 119import java.util.Set; 120import java.util.function.Predicate; 121 122import javax.servlet.ServletRequest; 123import javax.servlet.http.HttpServletRequest; 124 125import org.apache.commons.collections.Transformer; 126import org.apache.commons.lang3.LocaleUtils; 127import org.apache.commons.logging.Log; 128 129import com.google.common.collect.Multimap; 130 131/** 132 * Allows convenient access to the most important OpenCms functions on a JSP page, 133 * indented to be used from a JSP with the JSTL or EL.<p> 134 * 135 * This bean is available by default in the context of an OpenCms managed JSP.<p> 136 * 137 * @since 8.0 138 */ 139public final class CmsJspStandardContextBean { 140 141 /** 142 * Container element wrapper to add some API methods.<p> 143 */ 144 public class CmsContainerElementWrapper extends CmsContainerElementBean { 145 146 /** Cache for the wrapped element parent. */ 147 private CmsContainerElementWrapper m_parent; 148 149 /** Cache for the wrapped element type name. */ 150 private String m_resourceTypeName; 151 152 /** The wrapped element instance. */ 153 private CmsContainerElementBean m_wrappedElement; 154 155 /** Cache for the wrapped element settings. */ 156 private Map<String, CmsJspElementSettingValueWrapper> m_wrappedSettings; 157 158 /** 159 * Constructor.<p> 160 * 161 * @param element the element to wrap 162 */ 163 protected CmsContainerElementWrapper(CmsContainerElementBean element) { 164 165 m_wrappedElement = element; 166 167 } 168 169 /** 170 * @see org.opencms.xml.containerpage.CmsContainerElementBean#clone() 171 */ 172 @Override 173 public CmsContainerElementBean clone() { 174 175 return m_wrappedElement.clone(); 176 } 177 178 /** 179 * @see org.opencms.xml.containerpage.CmsContainerElementBean#editorHash() 180 */ 181 @Override 182 public String editorHash() { 183 184 return m_wrappedElement.editorHash(); 185 } 186 187 /** 188 * @see org.opencms.xml.containerpage.CmsContainerElementBean#equals(java.lang.Object) 189 */ 190 @Override 191 public boolean equals(Object obj) { 192 193 return m_wrappedElement.equals(obj); 194 } 195 196 /** 197 * @see org.opencms.xml.containerpage.CmsContainerElementBean#getFormatterId() 198 */ 199 @Override 200 public CmsUUID getFormatterId() { 201 202 return m_wrappedElement.getFormatterId(); 203 } 204 205 /** 206 * @see org.opencms.xml.containerpage.CmsContainerElementBean#getId() 207 */ 208 @Override 209 public CmsUUID getId() { 210 211 return m_wrappedElement.getId(); 212 } 213 214 /** 215 * @see org.opencms.xml.containerpage.CmsContainerElementBean#getIndividualSettings() 216 */ 217 @Override 218 public Map<String, String> getIndividualSettings() { 219 220 return m_wrappedElement.getIndividualSettings(); 221 } 222 223 /** 224 * @see org.opencms.xml.containerpage.CmsContainerElementBean#getInheritanceInfo() 225 */ 226 @Override 227 public CmsInheritanceInfo getInheritanceInfo() { 228 229 return m_wrappedElement.getInheritanceInfo(); 230 } 231 232 /** 233 * @see org.opencms.xml.containerpage.CmsContainerElementBean#getInstanceId() 234 */ 235 @Override 236 public String getInstanceId() { 237 238 return m_wrappedElement.getInstanceId(); 239 } 240 241 /** 242 * Returns the parent element if present.<p> 243 * 244 * @return the parent element or <code>null</code> if not available 245 */ 246 public CmsContainerElementWrapper getParent() { 247 248 if (m_parent == null) { 249 CmsContainerElementBean parent = getParentElement(m_wrappedElement); 250 m_parent = (parent != null) ? new CmsContainerElementWrapper(getParentElement(m_wrappedElement)) : null; 251 } 252 return m_parent; 253 } 254 255 /** 256 * @see org.opencms.xml.containerpage.CmsContainerElementBean#getResource() 257 */ 258 @Override 259 public CmsResource getResource() { 260 261 return m_wrappedElement.getResource(); 262 } 263 264 /** 265 * Returns the resource type name of the element resource.<p> 266 * 267 * @return the resource type name 268 */ 269 public String getResourceTypeName() { 270 271 if (m_resourceTypeName == null) { 272 m_resourceTypeName = ""; 273 try { 274 m_resourceTypeName = OpenCms.getResourceManager().getResourceType( 275 m_wrappedElement.getResource()).getTypeName(); 276 } catch (Exception e) { 277 CmsJspStandardContextBean.LOG.error(e.getLocalizedMessage(), e); 278 } 279 } 280 return m_resourceTypeName; 281 } 282 283 /** 284 * Returns a lazy initialized setting map.<p> 285 * 286 * The values returned in the map are instances of {@link A_CmsJspValueWrapper}. 287 * 288 * @return the wrapped settings 289 */ 290 public Map<String, CmsJspElementSettingValueWrapper> getSetting() { 291 292 if (m_wrappedSettings == null) { 293 m_wrappedSettings = CmsCollectionsGenericWrapper.createLazyMap( 294 new SettingsTransformer(m_wrappedElement)); 295 } 296 return m_wrappedSettings; 297 } 298 299 /** 300 * @see org.opencms.xml.containerpage.CmsContainerElementBean#getSettings() 301 */ 302 @Override 303 public Map<String, String> getSettings() { 304 305 return m_wrappedElement.getSettings(); 306 } 307 308 /** 309 * @see org.opencms.xml.containerpage.CmsContainerElementBean#getSitePath() 310 */ 311 @Override 312 public String getSitePath() { 313 314 return m_wrappedElement.getSitePath(); 315 } 316 317 /** 318 * @see org.opencms.xml.containerpage.CmsContainerElementBean#hashCode() 319 */ 320 @Override 321 public int hashCode() { 322 323 return m_wrappedElement.hashCode(); 324 } 325 326 /** 327 * @see org.opencms.xml.containerpage.CmsContainerElementBean#initResource(org.opencms.file.CmsObject) 328 */ 329 @Override 330 public void initResource(CmsObject cms) throws CmsException { 331 332 m_wrappedElement.initResource(cms); 333 } 334 335 /** 336 * @see org.opencms.xml.containerpage.CmsContainerElementBean#initSettings(org.opencms.file.CmsObject, org.opencms.ade.configuration.CmsADEConfigData, org.opencms.xml.containerpage.I_CmsFormatterBean, java.util.Locale, javax.servlet.ServletRequest, java.util.Map) 337 */ 338 @Override 339 public void initSettings( 340 CmsObject cms, 341 CmsADEConfigData config, 342 I_CmsFormatterBean formatterBean, 343 Locale locale, 344 ServletRequest request, 345 Map<String, String> settingPresets) { 346 347 m_wrappedElement.initSettings(cms, config, formatterBean, locale, request, settingPresets); 348 } 349 350 /** 351 * @see org.opencms.xml.containerpage.CmsContainerElementBean#isCreateNew() 352 */ 353 @Override 354 public boolean isCreateNew() { 355 356 return m_wrappedElement.isCreateNew(); 357 } 358 359 /** 360 * @see org.opencms.xml.containerpage.CmsContainerElementBean#isGroupContainer(org.opencms.file.CmsObject) 361 */ 362 @Override 363 public boolean isGroupContainer(CmsObject cms) throws CmsException { 364 365 return m_wrappedElement.isGroupContainer(cms); 366 } 367 368 /** 369 * @see org.opencms.xml.containerpage.CmsContainerElementBean#isHistoryContent() 370 */ 371 @Override 372 public boolean isHistoryContent() { 373 374 return m_wrappedElement.isHistoryContent(); 375 } 376 377 /** 378 * @see org.opencms.xml.containerpage.CmsContainerElementBean#isInheritedContainer(org.opencms.file.CmsObject) 379 */ 380 @Override 381 public boolean isInheritedContainer(CmsObject cms) throws CmsException { 382 383 return m_wrappedElement.isInheritedContainer(cms); 384 } 385 386 /** 387 * @see org.opencms.xml.containerpage.CmsContainerElementBean#isInMemoryOnly() 388 */ 389 @Override 390 public boolean isInMemoryOnly() { 391 392 return m_wrappedElement.isInMemoryOnly(); 393 } 394 395 /** 396 * @see org.opencms.xml.containerpage.CmsContainerElementBean#isReleasedAndNotExpired() 397 */ 398 @Override 399 public boolean isReleasedAndNotExpired() { 400 401 return m_wrappedElement.isReleasedAndNotExpired(); 402 } 403 404 /** 405 * @see org.opencms.xml.containerpage.CmsContainerElementBean#isTemporaryContent() 406 */ 407 @Override 408 public boolean isTemporaryContent() { 409 410 return m_wrappedElement.isTemporaryContent(); 411 } 412 413 /** 414 * @see org.opencms.xml.containerpage.CmsContainerElementBean#setFormatterId(org.opencms.util.CmsUUID) 415 */ 416 @Override 417 public void setFormatterId(CmsUUID formatterId) { 418 419 m_wrappedElement.setFormatterId(formatterId); 420 } 421 422 /** 423 * @see org.opencms.xml.containerpage.CmsContainerElementBean#setHistoryFile(org.opencms.file.CmsFile) 424 */ 425 @Override 426 public void setHistoryFile(CmsFile file) { 427 428 m_wrappedElement.setHistoryFile(file); 429 } 430 431 /** 432 * @see org.opencms.xml.containerpage.CmsContainerElementBean#setInheritanceInfo(org.opencms.ade.containerpage.shared.CmsInheritanceInfo) 433 */ 434 @Override 435 public void setInheritanceInfo(CmsInheritanceInfo inheritanceInfo) { 436 437 m_wrappedElement.setInheritanceInfo(inheritanceInfo); 438 } 439 440 /** 441 * @see org.opencms.xml.containerpage.CmsContainerElementBean#setTemporaryFile(org.opencms.file.CmsFile) 442 */ 443 @Override 444 public void setTemporaryFile(CmsFile elementFile) { 445 446 m_wrappedElement.setTemporaryFile(elementFile); 447 } 448 449 /** 450 * @see org.opencms.xml.containerpage.CmsContainerElementBean#toString() 451 */ 452 @Override 453 public String toString() { 454 455 return m_wrappedElement.toString(); 456 } 457 } 458 459 /** 460 * Provides a lazy initialized Map that provides the detail page link as a value when given the name of a 461 * (named) dynamic function or resource type as a key.<p> 462 */ 463 public class CmsDetailLookupTransformer implements Transformer { 464 465 /** The selected prefix. */ 466 private String m_prefix; 467 468 /** 469 * Constructor with a prefix.<p> 470 * 471 * The prefix is used to distinguish between type detail pages and function detail pages.<p> 472 * 473 * @param prefix the prefix to use 474 */ 475 public CmsDetailLookupTransformer(String prefix) { 476 477 m_prefix = prefix; 478 } 479 480 /** 481 * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) 482 */ 483 @Override 484 public Object transform(Object input) { 485 486 String prefix = m_prefix; 487 CmsObject cms = m_cms; 488 String inputStr = String.valueOf(input); 489 490 return getFunctionDetailLink(cms, prefix, inputStr, false); 491 } 492 493 } 494 495 /** 496 * The element setting transformer.<p> 497 */ 498 public class SettingsTransformer implements Transformer { 499 500 /** The element formatter config. */ 501 private I_CmsFormatterBean m_formatter; 502 503 /** The configured formatter settings. */ 504 private Map<String, CmsXmlContentProperty> m_formatterSettingsConfig; 505 506 /** The element. */ 507 private CmsContainerElementBean m_transformElement; 508 509 /** 510 * Constructor.<p> 511 * 512 * @param element the element 513 */ 514 SettingsTransformer(CmsContainerElementBean element) { 515 516 m_transformElement = element; 517 m_formatter = getElementFormatter(element); 518 } 519 520 /** 521 * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) 522 */ 523 @Override 524 public Object transform(Object settingName) { 525 526 boolean exists; 527 if (m_formatter != null) { 528 if (m_formatterSettingsConfig == null) { 529 m_formatterSettingsConfig = OpenCms.getADEManager().getFormatterSettings( 530 m_cms, 531 m_config, 532 m_formatter, 533 m_transformElement.getResource(), 534 getLocale(), 535 m_request); 536 } 537 exists = m_formatterSettingsConfig.get(settingName) != null; 538 } else { 539 exists = m_transformElement.getSettings().get(settingName) != null; 540 } 541 return new CmsJspElementSettingValueWrapper( 542 CmsJspStandardContextBean.this, 543 m_transformElement.getSettings().get(settingName), 544 exists); 545 } 546 } 547 548 /** 549 * Bean containing a template name and URI.<p> 550 */ 551 public static class TemplateBean { 552 553 /** True if the template context was manually selected. */ 554 private boolean m_forced; 555 556 /** The template name. */ 557 private String m_name; 558 559 /** The template resource. */ 560 private CmsResource m_resource; 561 562 /** The template uri, if no resource is set. */ 563 private String m_uri; 564 565 /** 566 * Creates a new instance.<p> 567 * 568 * @param name the template name 569 * @param resource the template resource 570 */ 571 public TemplateBean(String name, CmsResource resource) { 572 573 m_resource = resource; 574 m_name = name; 575 } 576 577 /** 578 * Creates a new instance with an URI instead of a resoure.<p> 579 * 580 * @param name the template name 581 * @param uri the template uri 582 */ 583 public TemplateBean(String name, String uri) { 584 585 m_name = name; 586 m_uri = uri; 587 } 588 589 /** 590 * Gets the template name.<p> 591 * 592 * @return the template name 593 */ 594 public String getName() { 595 596 return m_name; 597 } 598 599 /** 600 * Gets the template resource.<p> 601 * 602 * @return the template resource 603 */ 604 public CmsResource getResource() { 605 606 return m_resource; 607 } 608 609 /** 610 * Gets the template uri.<p> 611 * 612 * @return the template URI. 613 */ 614 public String getUri() { 615 616 if (m_resource != null) { 617 return m_resource.getRootPath(); 618 } else { 619 return m_uri; 620 } 621 } 622 623 /** 624 * Returns true if the template context was manually selected.<p> 625 * 626 * @return true if the template context was manually selected 627 */ 628 public boolean isForced() { 629 630 return m_forced; 631 } 632 633 /** 634 * Sets the 'forced' flag to a new value.<p> 635 * 636 * @param forced the new value 637 */ 638 public void setForced(boolean forced) { 639 640 m_forced = forced; 641 } 642 643 } 644 645 /** 646 * The meta mappings transformer.<p> 647 */ 648 class MetaLookupTranformer implements Transformer { 649 650 /** 651 * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) 652 */ 653 public Object transform(Object arg0) { 654 655 String result = null; 656 if ((m_metaMappings != null) && m_metaMappings.containsKey(arg0)) { 657 MetaMapping mapping = m_metaMappings.get(arg0); 658 CmsGalleryNameMacroResolver resolver = null; 659 try { 660 CmsResourceFilter filter = getIsEditMode() 661 ? CmsResourceFilter.IGNORE_EXPIRATION 662 : CmsResourceFilter.DEFAULT; 663 CmsResource res = m_cms.readResource(mapping.m_contentId, filter); 664 CmsXmlContent content = CmsXmlContentFactory.unmarshal(m_cms, res, m_request); 665 resolver = new CmsGalleryNameMacroResolver(m_cms, content, getLocale()); 666 if (content.hasLocale(getLocale())) { 667 I_CmsXmlContentValue val = content.getValue(mapping.m_elementXPath, getLocale()); 668 if (val != null) { 669 result = val.getStringValue(m_cms); 670 } 671 } 672 673 } catch (CmsException e) { 674 LOG.error(e.getLocalizedMessage(), e); 675 } 676 if (result == null) { 677 result = mapping.m_defaultValue; 678 } 679 if ((resolver != null) && (result != null)) { 680 result = resolver.resolveMacros(result); 681 } 682 } 683 return result; 684 } 685 686 } 687 688 /** The meta mapping data. */ 689 class MetaMapping { 690 691 /** The mapping content structure id. */ 692 CmsUUID m_contentId; 693 694 /** The default value. */ 695 String m_defaultValue; 696 697 /** The mapping value xpath. */ 698 String m_elementXPath; 699 700 /** The mapping key. */ 701 String m_key; 702 703 /** The mapping order. */ 704 int m_order; 705 } 706 707 /** The attribute name of the cms object.*/ 708 public static final String ATTRIBUTE_CMS_OBJECT = "__cmsObject"; 709 710 /** The attribute name of the standard JSP context bean. */ 711 public static final String ATTRIBUTE_NAME = "cms"; 712 713 /** The logger instance for this class. */ 714 protected static final Log LOG = CmsLog.getLog(CmsJspStandardContextBean.class); 715 716 /** OpenCms user context. */ 717 protected CmsObject m_cms; 718 719 /** The sitemap configuration. */ 720 protected CmsADEConfigData m_config; 721 722 /** The meta mapping configuration. */ 723 Map<String, MetaMapping> m_metaMappings; 724 725 /** The current request. */ 726 ServletRequest m_request; 727 728 /** Lazily initialized map from a category path to all sub-categories of that category. */ 729 private Map<String, CmsJspCategoryAccessBean> m_allSubCategories; 730 731 /** Lazily initialized nested map for reading either attributes or properties (first key: file name, second key: attribute / property name). */ 732 private Map<String, Map<String, CmsJspObjectValueWrapper>> m_attributesOrProperties; 733 734 /** Lazily initialized map from a category path to the path's category object. */ 735 private Map<String, CmsCategory> m_categories; 736 737 /** The container the currently rendered element is part of. */ 738 private CmsContainerBean m_container; 739 740 /** The current detail content resource if available. */ 741 private CmsResource m_detailContentResource; 742 743 /** The detail function page. */ 744 private CmsResource m_detailFunctionPage; 745 746 /** The detail only page references containers that are only displayed in detail view. */ 747 private CmsContainerPageBean m_detailOnlyPage; 748 749 /** Flag to indicate if element was just edited. */ 750 private boolean m_edited; 751 752 /** The currently rendered element. */ 753 private CmsContainerElementBean m_element; 754 755 /** The elements of the current page. */ 756 private Map<String, CmsContainerElementBean> m_elementInstances; 757 758 /** Flag to force edit mode to be disabled. */ 759 private boolean m_forceDisableEditMode; 760 761 /** The lazy initialized map which allows access to the dynamic function beans. */ 762 private Map<String, CmsDynamicFunctionBeanWrapper> m_function; 763 764 /** The lazy initialized map for the function detail pages. */ 765 private Map<String, String> m_functionDetailPage; 766 767 /** The lazy initialized map for the function detail pages. */ 768 private Map<String, String> m_functionDetailPageExact; 769 770 /** Indicates if in drag mode. */ 771 private boolean m_isDragMode; 772 773 /** Stores the edit mode info. */ 774 private Boolean m_isEditMode; 775 776 /** Lazily initialized map from the locale to the localized title property. */ 777 private Map<String, String> m_localeTitles; 778 779 /** The currently displayed container page. */ 780 private CmsContainerPageBean m_page; 781 782 /** The current container page resource, lazy initialized. */ 783 private CmsJspResourceWrapper m_pageResource; 784 785 /** The parent containers to the given element instance ids. */ 786 private Map<String, CmsContainerBean> m_parentContainers; 787 788 /** Lazily initialized map from a category path to all categories on that path. */ 789 private Map<String, List<CmsCategory>> m_pathCategories; 790 791 /** Lazily initialized map from the root path of a resource to all categories assigned to the resource. */ 792 private Map<String, CmsJspCategoryAccessBean> m_resourceCategories; 793 794 /** Map from root paths to site relative paths. */ 795 private Map<String, String> m_sitePaths; 796 797 /** The template plugins. */ 798 private Map<String, List<CmsTemplatePluginWrapper>> m_templatePlugins; 799 800 /** The lazy initialized map for the detail pages. */ 801 private Map<String, String> m_typeDetailPage; 802 803 /** The VFS content access bean. */ 804 private CmsJspVfsAccessBean m_vfsBean; 805 806 /** 807 * Creates an empty instance.<p> 808 */ 809 private CmsJspStandardContextBean() { 810 811 } 812 813 /** 814 * Creates a new standard JSP context bean. 815 * 816 * @param req the current servlet request 817 */ 818 private CmsJspStandardContextBean(ServletRequest req) { 819 820 this(); 821 CmsFlexController controller = CmsFlexController.getController(req); 822 m_request = req; 823 CmsObject cms; 824 if (controller != null) { 825 cms = controller.getCmsObject(); 826 } else { 827 cms = (CmsObject)req.getAttribute(ATTRIBUTE_CMS_OBJECT); 828 } 829 if (cms == null) { 830 // cms object unavailable - this request was not initialized properly 831 throw new CmsRuntimeException( 832 Messages.get().container(Messages.ERR_MISSING_CMS_CONTROLLER_1, CmsJspBean.class.getName())); 833 } 834 updateCmsObject(cms); 835 m_detailContentResource = CmsDetailPageResourceHandler.getDetailResource(req); 836 m_detailFunctionPage = CmsDetailPageResourceHandler.getDetailFunctionPage(req); 837 } 838 839 /** 840 * Gets the link to a function detail page. 841 * 842 * @param cms the CMS context 843 * @param prefix the function detail prefix 844 * @param functionName the function name 845 * @param fullLink true if links should be generated with server prefix 846 * 847 * @return the link 848 */ 849 public static String getFunctionDetailLink(CmsObject cms, String prefix, String functionName, boolean fullLink) { 850 851 String type = prefix + functionName; 852 853 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration( 854 cms, 855 cms.addSiteRoot(cms.getRequestContext().getUri())); 856 List<CmsDetailPageInfo> detailPages = config.getDetailPagesForType(type); 857 CmsDetailPageInfo detailPage = null; 858 if ((detailPages == null) || (detailPages.size() == 0)) { 859 detailPage = config.getDefaultDetailPage(); 860 } else { 861 detailPage = detailPages.get(0); 862 } 863 if (detailPage == null) { 864 return "[No detail page configured for type =" + type + "=]"; 865 } 866 867 CmsUUID id = detailPage.getId(); 868 try { 869 CmsResource r = cms.readResource(id); 870 boolean originalForceAbsoluteLinks = cms.getRequestContext().isForceAbsoluteLinks(); 871 try { 872 cms.getRequestContext().setForceAbsoluteLinks(fullLink || originalForceAbsoluteLinks); 873 String link = OpenCms.getLinkManager().substituteLink(cms, r); 874 return link; 875 } finally { 876 cms.getRequestContext().setForceAbsoluteLinks(originalForceAbsoluteLinks); 877 } 878 } catch (CmsException e) { 879 LOG.warn(e.getLocalizedMessage(), e); 880 return "[Error reading detail page for type =" + type + "=]"; 881 } 882 } 883 884 /** 885 * Gets the link to a function detail page. 886 * 887 * <p>This just returns null if no function detail page is defined, it does not use the default detail page as a fallback. 888 * 889 * @param cms the CMS context 890 * @param functionName the function name 891 * 892 * @return the link 893 */ 894 public static String getFunctionDetailLinkExact(CmsObject cms, String functionName) { 895 896 String type = CmsDetailPageInfo.FUNCTION_PREFIX + functionName; 897 898 CmsADEConfigData config = OpenCms.getADEManager().lookupConfigurationWithCache( 899 cms, 900 cms.addSiteRoot(cms.getRequestContext().getUri())); 901 List<CmsDetailPageInfo> detailPages = config.getDetailPagesForType(type); 902 903 CmsDetailPageInfo detailPage = null; 904 if ((detailPages == null) || (detailPages.size() == 0)) { 905 return null; 906 } 907 detailPage = detailPages.get(0); 908 if (detailPage.isDefaultDetailPage()) { 909 return null; 910 } 911 912 CmsUUID id = detailPage.getId(); 913 try { 914 CmsResource r = cms.readResource(id); 915 String link = OpenCms.getLinkManager().substituteLink(cms, r); 916 return link; 917 } catch (CmsException e) { 918 LOG.warn(e.getLocalizedMessage(), e); 919 return null; 920 } 921 922 } 923 924 /** 925 * Creates a new instance of the standard JSP context bean.<p> 926 * 927 * To prevent multiple creations of the bean during a request, the OpenCms request context 928 * attributes are used to cache the created VFS access utility bean.<p> 929 * 930 * @param req the current servlet request 931 * 932 * @return a new instance of the standard JSP context bean 933 */ 934 public static CmsJspStandardContextBean getInstance(ServletRequest req) { 935 936 Object attribute = req.getAttribute(ATTRIBUTE_NAME); 937 CmsJspStandardContextBean result; 938 if ((attribute != null) && (attribute instanceof CmsJspStandardContextBean)) { 939 result = (CmsJspStandardContextBean)attribute; 940 } else { 941 result = new CmsJspStandardContextBean(req); 942 req.setAttribute(ATTRIBUTE_NAME, result); 943 } 944 return result; 945 } 946 947 /** 948 * Returns a copy of this JSP context bean.<p> 949 * 950 * @return a copy of this JSP context bean 951 */ 952 public CmsJspStandardContextBean createCopy() { 953 954 CmsJspStandardContextBean result = new CmsJspStandardContextBean(); 955 result.m_container = m_container; 956 if (m_detailContentResource != null) { 957 result.m_detailContentResource = m_detailContentResource.getCopy(); 958 } 959 result.m_element = m_element; 960 result.m_forceDisableEditMode = m_forceDisableEditMode; 961 result.setPage(m_page); 962 return result; 963 } 964 965 /** 966 * Uses the default text encryption method to decrypt an encrypted string. 967 * 968 * @param text the encrypted stirng 969 * @return the decrypted string 970 */ 971 public String decrypt(String text) { 972 973 try { 974 return OpenCms.getTextEncryptions().get("default").decrypt(text); 975 } catch (Exception e) { 976 return null; 977 } 978 979 } 980 981 /** 982 * Returns a caching hash specific to the element, it's properties and the current container width.<p> 983 * 984 * @return the caching hash 985 */ 986 public String elementCachingHash() { 987 988 String result = ""; 989 if (m_element != null) { 990 result = m_element.editorHash(); 991 if (m_container != null) { 992 result += "w:" 993 + m_container.getWidth() 994 + "cName:" 995 + m_container.getName() 996 + "cType:" 997 + m_container.getType(); 998 } 999 } 1000 return result; 1001 } 1002 1003 /** 1004 * Uses the default text encryption to encrypt an input text. 1005 * 1006 * @param text the input text 1007 * @return the encrypted text 1008 */ 1009 public String encrypt(String text) { 1010 1011 try { 1012 return OpenCms.getTextEncryptions().get("default").encrypt(text); 1013 } catch (Exception e) { 1014 return null; 1015 } 1016 } 1017 1018 /** 1019 * Returns the locales available for the currently requested URI. 1020 * 1021 * @return the locales available for the currently requested URI. 1022 */ 1023 public List<Locale> getAvailableLocales() { 1024 1025 return OpenCms.getLocaleManager().getAvailableLocales(m_cms, getRequestContext().getUri()); 1026 } 1027 1028 /** 1029 * Helper for easy instantiation and initialization of custom context beans that returns 1030 * an instance of the class specified via <code>className</code>, with the current context already set. 1031 * 1032 * @param className name of the class to instantiate. Must be a subclass of {@link A_CmsJspCustomContextBean}. 1033 * @return an instance of the provided class with the current context already set. 1034 */ 1035 public Object getBean(String className) { 1036 1037 try { 1038 Class<?> clazz = Class.forName(className); 1039 if (A_CmsJspCustomContextBean.class.isAssignableFrom(clazz)) { 1040 Constructor<?> constructor = clazz.getConstructor(); 1041 Object instance = constructor.newInstance(); 1042 Method setContextMethod = clazz.getMethod("setContext", CmsJspStandardContextBean.class); 1043 setContextMethod.invoke(instance, this); 1044 return instance; 1045 } else { 1046 throw new Exception(); 1047 } 1048 } catch (Exception e) { 1049 LOG.error(Messages.get().container(Messages.ERR_NO_CUSTOM_BEAN_1, className)); 1050 } 1051 return null; 1052 1053 } 1054 1055 /** 1056 * Finds the folder to use for binary uploads, based on the list configuration given as an argument or 1057 * the current sitemap configuration. 1058 * 1059 * @param content the list configuration content 1060 * 1061 * @return the binary upload folder 1062 */ 1063 public String getBinaryUploadFolder(CmsJspContentAccessBean content) { 1064 1065 String keyToFind = CmsADEConfigData.ATTR_BINARY_UPLOAD_TARGET; 1066 String baseValue = null; 1067 if (content != null) { 1068 for (CmsJspContentAccessValueWrapper wrapper : content.getValueList().get( 1069 CmsConfigParserUtils.N_PARAMETER)) { 1070 String paramKey = wrapper.getValue().get(CmsConfigParserUtils.N_KEY).getToString(); 1071 String paramValue = wrapper.getValue().get(CmsConfigParserUtils.N_VALUE).getToString(); 1072 if (paramKey.equals(keyToFind)) { 1073 LOG.debug("Found upload folder in configuration: " + paramValue); 1074 baseValue = paramValue; 1075 break; 1076 } 1077 } 1078 1079 if (baseValue == null) { 1080 List<CmsJspContentAccessValueWrapper> folderEntries = content.getValueList().get( 1081 CmsConfigParserUtils.N_SEARCH_FOLDER); 1082 if (folderEntries.size() == 1) { 1083 CmsResource resource = folderEntries.get(0).getToResource(); 1084 List<String> galleryTypes = Arrays.asList( 1085 CmsAjaxDownloadGallery.GALLERYTYPE_NAME, 1086 CmsAjaxImageGallery.GALLERYTYPE_NAME); 1087 if ((resource != null) && (null != findAncestor(m_cms, resource, (ancestor) -> { 1088 return galleryTypes.stream().anyMatch( 1089 type -> OpenCms.getResourceManager().matchResourceType(type, ancestor.getTypeId())); 1090 }))) { 1091 baseValue = m_cms.getSitePath(resource); 1092 LOG.debug( 1093 "Using single download gallery from search folder configuration as upload folder: " 1094 + baseValue); 1095 1096 } 1097 } 1098 } 1099 } 1100 1101 if (baseValue == null) { 1102 baseValue = m_config.getAttribute(keyToFind, null); 1103 if (baseValue != null) { 1104 LOG.debug("Found upload folder in sitemap configuration: " + baseValue); 1105 } 1106 } 1107 1108 CmsMacroResolver resolver = new CmsMacroResolver(); 1109 resolver.setCmsObject(getCmsObject()); 1110 resolver.addMacro("subsitepath", CmsFileUtil.removeTrailingSeparator(getSubSitePath())); 1111 resolver.addMacro("sitepath", "/"); 1112 1113 // if baseValue is still null, then resolveMacros will just return null 1114 String result = resolver.resolveMacros(baseValue); 1115 1116 LOG.debug("Final value for upload folder : " + result); 1117 return result; 1118 } 1119 1120 /** 1121 * Generates a link to the bundle editor to edit the provided message key. 1122 * The back link for the editor is the current uri. 1123 * 1124 * If the bundle for the key could not be found, <code>null</code> is returned. 1125 * 1126 * @param messageKey the message key to open the bundle editor for. 1127 * 1128 * @return a link to the bundle editor for editing the provided key, or <code>null</code> if the bundle for the key could not be found. 1129 */ 1130 public String getBundleEditorLink(String messageKey) { 1131 1132 return getBundleEditorLink(messageKey, null); 1133 } 1134 1135 /** 1136 * Generates a link to the bundle editor to edit the provided message key. 1137 * The back link for the editor is the current uri with the provided backLinkAnchor added as anchor.. 1138 * 1139 * If the bundle for the key could not be found, <code>null</code> is returned. 1140 * 1141 * @param messageKey the message key to open the bundle editor for. 1142 * @param backLinkAnchor the anchor id to add to the backlink to the page. If <code>null</code> no anchor is added to the backlink. 1143 * 1144 * @return a link to the bundle editor for editing the provided key, or <code>null</code> if the bundle for the key could not be found. 1145 */ 1146 public String getBundleEditorLink(String messageKey, String backLinkAnchor) { 1147 1148 return getBundleEditorLink(messageKey, backLinkAnchor, null); 1149 } 1150 1151 /** 1152 * Generates a link to the bundle editor to edit the provided message key. 1153 * The back link for the editor is the current uri with the provided backLinkAnchor added as anchor. 1154 * 1155 * If the bundle resource for the key could not be found, <code>null</code> is returned. 1156 * 1157 * @param messageKey the message key to open the bundle editor for. 1158 * @param backLinkAnchor the anchor id to add to the backlink to the page. If <code>null</code> no anchor is added to the backlink. 1159 * @param backLinkParams request parameters to add to the backlink without leading '?', e.g. "param1=a¶m2=b". 1160 * 1161 * @return a link to the bundle editor for editing the provided key, or <code>null</code> if the bundle for the key could not be found. 1162 */ 1163 public String getBundleEditorLink(String messageKey, String backLinkAnchor, String backLinkParams) { 1164 1165 return getBundleEditorLink(messageKey, backLinkAnchor, backLinkParams, null); 1166 } 1167 1168 /** 1169 * Generates a link to the bundle editor to edit the provided message key. 1170 * The back link for the editor is the current uri with the provided backLinkAnchor added as anchor. 1171 * 1172 * If the bundle resource for the key could not be found, <code>null</code> is returned. 1173 * 1174 * @param messageKey the message key to open the bundle editor for. 1175 * @param backLinkAnchor the anchor id to add to the backlink to the page. If <code>null</code> no anchor is added to the backlink. 1176 * @param backLinkParams request parameters to add to the backlink without leading '?', e.g. "param1=a¶m2=b". 1177 * @param bundleName the name of the bundle to search the key in. If <code>null</code> the bundle is detected automatically. 1178 * 1179 * @return a link to the bundle editor for editing the provided key, or <code>null</code> if the bundle for the key could not be found. 1180 */ 1181 public String getBundleEditorLink( 1182 String messageKey, 1183 String backLinkAnchor, 1184 String backLinkParams, 1185 String bundleName) { 1186 1187 if (!m_cms.getRequestContext().getCurrentProject().isOnlineProject()) { 1188 String filePath = null; 1189 if (null == bundleName) { 1190 filePath = getBundleRootPath(messageKey); 1191 } else { 1192 ResourceBundle bundle = CmsResourceBundleLoader.getBundle( 1193 bundleName, 1194 m_cms.getRequestContext().getLocale()); 1195 if (bundle instanceof CmsVfsResourceBundle) { 1196 CmsVfsResourceBundle vfsBundle = (CmsVfsResourceBundle)bundle; 1197 filePath = vfsBundle.getParameters().getBasePath(); 1198 } 1199 } 1200 try { 1201 if (null == filePath) { 1202 throw new Exception("Could not determine the VFS root path of the bundle."); 1203 } 1204 CmsUUID structureId = m_cms.readResource(filePath).getStructureId(); 1205 String backLink = OpenCms.getLinkManager().getServerLink(m_cms, m_cms.getRequestContext().getUri()); 1206 if (!((null == backLinkParams) || backLinkParams.isEmpty())) { 1207 backLink = backLink + "?" + backLinkParams; 1208 } 1209 if (!((null == backLinkAnchor) || backLinkAnchor.isEmpty())) { 1210 backLink = backLink + "#" + backLinkAnchor; 1211 } 1212 String appState = CmsEditor.getEditState(structureId, false, backLink); 1213 if (null != messageKey) { 1214 appState = A_CmsWorkplaceApp.addParamToState( 1215 appState, 1216 CmsMessageBundleEditor.PARAM_KEYFILTER, 1217 messageKey); 1218 } 1219 String link = CmsVaadinUtils.getWorkplaceLink(CmsEditorConfiguration.APP_ID, appState); 1220 return link; 1221 } catch (Throwable t) { 1222 if (LOG.isWarnEnabled()) { 1223 String message = "Failed to open bundle editor for key '" 1224 + messageKey 1225 + "' and bundle with name '" 1226 + bundleName 1227 + "'."; 1228 if (LOG.isDebugEnabled()) { 1229 LOG.debug(message, t); 1230 } else { 1231 LOG.warn(message); 1232 } 1233 } 1234 } 1235 } 1236 return null; 1237 } 1238 1239 /** 1240 * Gets the root path for the VFS-based message bundle containing the given message key. 1241 * 1242 * <p>If no VFS-based message bundle contains the given key, null is returned. If multiple message bundles contain it, 1243 * one of them is arbitrarily chosen (but a warning is logged). 1244 * 1245 * <p>Note: This uses the online (published) state of message bundles, so if you have unpublished bundle changes, they will not be reflected in 1246 * the result. 1247 * 1248 * @param messageKey the message key 1249 * @return the root path of the bundle containing the message key 1250 */ 1251 public String getBundleRootPath(String messageKey) { 1252 1253 CmsObject cms = getCmsObject(); 1254 try { 1255 CmsMessageToBundleIndex bundleIndex = null; 1256 OpenCmsServlet.RequestCache context = OpenCmsServlet.getRequestCache(); 1257 if (context != null) { 1258 bundleIndex = (CmsMessageToBundleIndex)context.getAttribute( 1259 CmsMessageToBundleIndex.class.getName() + "_" + cms.getRequestContext().getLocale(), 1260 k -> { 1261 try { 1262 CmsMessageToBundleIndex result = CmsMessageToBundleIndex.read(getCmsObject()); 1263 return result; 1264 } catch (Exception e) { 1265 throw new RuntimeException(e); 1266 } 1267 }); 1268 1269 } else { 1270 bundleIndex = CmsMessageToBundleIndex.read(getCmsObject()); 1271 } 1272 return bundleIndex.getBundlePathForKey(messageKey); 1273 } catch (Exception e) { 1274 LOG.error(e.getLocalizedMessage(), e); 1275 return null; 1276 } 1277 } 1278 1279 /** 1280 * Returns the container the currently rendered element is part of.<p> 1281 * 1282 * @return the container the currently rendered element is part of 1283 */ 1284 public CmsContainerBean getContainer() { 1285 1286 return m_container; 1287 } 1288 1289 /** 1290 * Gets information about a given container type. 1291 * 1292 * @param containerType the container type 1293 * 1294 * @return the bean with the information about the container type 1295 */ 1296 public CmsContainerTypeInfoWrapper getContainerTypeInfo(String containerType) { 1297 1298 return new CmsContainerTypeInfoWrapper(m_cms, m_config, containerType); 1299 } 1300 1301 /** 1302 * Gets the CmsObject from the current Flex controller. 1303 * 1304 * @return the CmsObject from the current Flex controller 1305 */ 1306 public CmsObject getControllerCms() { 1307 1308 return CmsFlexController.getController(m_request).getCmsObject(); 1309 } 1310 1311 /** 1312 * Returns the current detail content, or <code>null</code> if no detail content is requested.<p> 1313 * 1314 * @return the current detail content, or <code>null</code> if no detail content is requested.<p> 1315 */ 1316 public CmsJspResourceWrapper getDetailContent() { 1317 1318 return CmsJspResourceWrapper.wrap(m_cms, m_detailContentResource); 1319 } 1320 1321 /** 1322 * Returns the structure id of the current detail content, or <code>null</code> if no detail content is requested.<p> 1323 * 1324 * @return the structure id of the current detail content, or <code>null</code> if no detail content is requested.<p> 1325 */ 1326 public CmsUUID getDetailContentId() { 1327 1328 return m_detailContentResource == null ? null : m_detailContentResource.getStructureId(); 1329 } 1330 1331 /** 1332 * Returns the detail content site path, or <code>null</code> if not available.<p> 1333 * 1334 * @return the detail content site path 1335 */ 1336 public String getDetailContentSitePath() { 1337 1338 return ((m_cms == null) || (m_detailContentResource == null)) 1339 ? null 1340 : m_cms.getSitePath(m_detailContentResource); 1341 } 1342 1343 /** 1344 * Returns the detail function page.<p> 1345 * 1346 * @return the detail function page 1347 */ 1348 public CmsJspResourceWrapper getDetailFunctionPage() { 1349 1350 return CmsJspResourceWrapper.wrap(m_cms, m_detailFunctionPage); 1351 } 1352 1353 /** 1354 * Returns the detail only page.<p> 1355 * 1356 * @return the detail only page 1357 */ 1358 public CmsContainerPageBean getDetailOnlyPage() { 1359 1360 if ((null == m_detailOnlyPage) && (null != m_detailContentResource)) { 1361 String pageRootPath = m_cms.getRequestContext().addSiteRoot(m_cms.getRequestContext().getUri()); 1362 m_detailOnlyPage = CmsDetailOnlyContainerUtil.getDetailOnlyPage(m_cms, m_request, pageRootPath, false); 1363 } 1364 return m_detailOnlyPage; 1365 } 1366 1367 /** 1368 * Returns the currently rendered element.<p> 1369 * 1370 * @return the currently rendered element 1371 */ 1372 public CmsContainerElementWrapper getElement() { 1373 1374 return m_element != null ? new CmsContainerElementWrapper(m_element) : null; 1375 } 1376 1377 /** 1378 * Returns a lazy initialized map of wrapped container elements beans by container name suffix.<p> 1379 * 1380 * So in case there is more than one container where the name end with the given suffix, 1381 * a joined list of container elements beans is returned.<p> 1382 * 1383 * @return a lazy initialized map of wrapped container elements beans by container name suffix 1384 * 1385 * @see #getElementsInContainer() 1386 */ 1387 public Map<String, List<CmsContainerElementWrapper>> getElementBeansInContainers() { 1388 1389 return CmsCollectionsGenericWrapper.createLazyMap(obj -> { 1390 if (obj instanceof String) { 1391 List<CmsContainerElementBean> containerElements = new ArrayList<>(); 1392 for (CmsContainerBean container : getPage().getContainers().values()) { 1393 if (container.getName().endsWith("-" + obj)) { 1394 for (CmsContainerElementBean element : container.getElements()) { 1395 try { 1396 element.initResource(m_cms); 1397 containerElements.add(new CmsContainerElementWrapper(element)); 1398 } catch (Exception e) { 1399 LOG.error(e.getLocalizedMessage(), e); 1400 } 1401 } 1402 } 1403 } 1404 return containerElements; 1405 } else { 1406 return null; 1407 } 1408 }); 1409 1410 } 1411 1412 /** 1413 * Returns a lazy initialized map of wrapped element resources by container name.<p> 1414 * 1415 * @return the lazy map of element resource wrappers 1416 */ 1417 public Map<String, List<CmsJspResourceWrapper>> getElementsInContainer() { 1418 1419 return CmsCollectionsGenericWrapper.createLazyMap(obj -> { 1420 if (obj instanceof String) { 1421 List<CmsJspResourceWrapper> elements = new ArrayList<>(); 1422 CmsContainerBean container = getPage().getContainers().get(obj); 1423 if (container != null) { 1424 for (CmsContainerElementBean element : container.getElements()) { 1425 try { 1426 element.initResource(m_cms); 1427 elements.add(CmsJspResourceWrapper.wrap(m_cms, element.getResource())); 1428 } catch (Exception e) { 1429 LOG.error(e.getLocalizedMessage(), e); 1430 } 1431 } 1432 } 1433 return elements; 1434 } else { 1435 return null; 1436 } 1437 }); 1438 1439 } 1440 1441 /** 1442 * Returns a lazy initialized map of wrapped element resources by container name suffix.<p> 1443 * 1444 * So in case there is more than one container where the name end with the given suffix, 1445 * a joined list of elements is returned.<p> 1446 * 1447 * @return the lazy map of element resource wrappers 1448 * 1449 * @see #getElementBeansInContainers() 1450 */ 1451 public Map<String, List<CmsJspResourceWrapper>> getElementsInContainers() { 1452 1453 return CmsCollectionsGenericWrapper.createLazyMap(obj -> { 1454 if (obj instanceof String) { 1455 List<CmsJspResourceWrapper> elements = new ArrayList<>(); 1456 for (CmsContainerBean container : getPage().getContainers().values()) { 1457 if (container.getName().endsWith("-" + obj)) { 1458 for (CmsContainerElementBean element : container.getElements()) { 1459 try { 1460 element.initResource(m_cms); 1461 elements.add(CmsJspResourceWrapper.wrap(m_cms, element.getResource())); 1462 } catch (Exception e) { 1463 LOG.error(e.getLocalizedMessage(), e); 1464 } 1465 } 1466 } 1467 } 1468 return elements; 1469 } else { 1470 return null; 1471 } 1472 }); 1473 1474 } 1475 1476 /** 1477 * Alternative method name for getReloadMarker(). 1478 * 1479 * @see org.opencms.jsp.util.CmsJspStandardContextBean#getReloadMarker() 1480 * 1481 * @return the reload marker 1482 */ 1483 public String getEnableReload() { 1484 1485 return getReloadMarker(); 1486 } 1487 1488 /** 1489 * Gets the formatter info wrapper for the given formatter key. 1490 * 1491 * @param formatterKey a formatter key 1492 * @return the formatter information for the formatter key, or null if no formatter was found 1493 */ 1494 public CmsFormatterInfoWrapper getFormatterInfo(String formatterKey) { 1495 1496 CmsObject cms = m_cms; 1497 CmsADEConfigData config = m_config; 1498 I_CmsFormatterBean formatter = config.findFormatter(formatterKey); 1499 if (formatter == null) { 1500 return null; 1501 } 1502 return new CmsFormatterInfoWrapper(cms, config, formatter); 1503 1504 } 1505 1506 /** 1507 * Returns a lazy initialized Map which allows access to the dynamic function beans using the JSP EL.<p> 1508 * 1509 * When given a key, the returned map will look up the corresponding dynamic function bean in the module configuration.<p> 1510 * 1511 * @return a lazy initialized Map which allows access to the dynamic function beans using the JSP EL 1512 */ 1513 public Map<String, CmsDynamicFunctionBeanWrapper> getFunction() { 1514 1515 if (m_function == null) { 1516 1517 Transformer transformer = new Transformer() { 1518 1519 @Override 1520 public Object transform(Object input) { 1521 1522 try { 1523 CmsDynamicFunctionBean dynamicFunction = readDynamicFunctionBean((String)input); 1524 CmsDynamicFunctionBeanWrapper wrapper = new CmsDynamicFunctionBeanWrapper( 1525 m_cms, 1526 dynamicFunction); 1527 return wrapper; 1528 1529 } catch (CmsException e) { 1530 LOG.debug(e.getLocalizedMessage(), e); 1531 return new CmsDynamicFunctionBeanWrapper(m_cms, null); 1532 } 1533 } 1534 }; 1535 m_function = CmsCollectionsGenericWrapper.createLazyMap(transformer); 1536 } 1537 return m_function; 1538 1539 } 1540 1541 /** 1542 * Deprecated method to access function detail pages using the EL.<p> 1543 * 1544 * @return a lazy initialized Map that provides the detail page link as a value when given the name of a 1545 * (named) dynamic function as a key 1546 * 1547 * @deprecated use {@link #getFunctionDetailPage()} instead 1548 */ 1549 @Deprecated 1550 public Map<String, String> getFunctionDetail() { 1551 1552 return getFunctionDetailPage(); 1553 } 1554 1555 /** 1556 * Returns a lazy initialized Map that provides the detail page link as a value when given the name of a 1557 * (named) dynamic function as a key.<p> 1558 * 1559 * The provided Map key is assumed to be a String that represents a named dynamic function.<p> 1560 * 1561 * Usage example on a JSP with the JSTL:<pre> 1562 * <a href=${cms.functionDetailPage['search']} /> 1563 * </pre> 1564 * 1565 * @return a lazy initialized Map that provides the detail page link as a value when given the name of a 1566 * (named) dynamic function as a key 1567 * 1568 * @see #getTypeDetailPage() 1569 */ 1570 public Map<String, String> getFunctionDetailPage() { 1571 1572 if (m_functionDetailPage == null) { 1573 m_functionDetailPage = CmsCollectionsGenericWrapper.createLazyMap( 1574 new CmsDetailLookupTransformer(CmsDetailPageInfo.FUNCTION_PREFIX)); 1575 } 1576 return m_functionDetailPage; 1577 } 1578 1579 /** 1580 * Returns a lazy initialized Map that provides the detail page link as a value when given the name of a 1581 * (named) dynamic function as a key.<p> 1582 * 1583 * The provided Map key is assumed to be a String that represents a named dynamic function.<p> 1584 * 1585 * Usage example on a JSP with the JSTL:<pre> 1586 * <a href=${cms.functionDetailPage['search']} /> 1587 * </pre> 1588 * 1589 * @return a lazy initialized Map that provides the detail page link as a value when given the name of a 1590 * (named) dynamic function as a key 1591 * 1592 * @see #getTypeDetailPage() 1593 */ 1594 public Map<String, String> getFunctionDetailPageExact() { 1595 1596 if (m_functionDetailPageExact == null) { 1597 m_functionDetailPageExact = CmsCollectionsGenericWrapper.createLazyMap( 1598 name -> getFunctionDetailLinkExact(m_cms, (String)name)); 1599 } 1600 return m_functionDetailPageExact; 1601 } 1602 1603 /** 1604 * Returns a lazy map which creates a wrapper object for a dynamic function format when given an XML content 1605 * as a key.<p> 1606 * 1607 * @return a lazy map for accessing function formats for a content 1608 */ 1609 public Map<CmsJspContentAccessBean, CmsDynamicFunctionFormatWrapper> getFunctionFormatFromContent() { 1610 1611 Transformer transformer = new Transformer() { 1612 1613 @Override 1614 public Object transform(Object contentAccess) { 1615 1616 CmsXmlContent content = (CmsXmlContent)(((CmsJspContentAccessBean)contentAccess).getRawContent()); 1617 CmsDynamicFunctionParser parser = new CmsDynamicFunctionParser(); 1618 CmsDynamicFunctionBean functionBean = null; 1619 try { 1620 functionBean = parser.parseFunctionBean(m_cms, content); 1621 } catch (CmsException e) { 1622 LOG.debug(e.getLocalizedMessage(), e); 1623 return new CmsDynamicFunctionFormatWrapper(m_cms, null); 1624 } 1625 String type = getContainer().getType(); 1626 String width = getContainer().getWidth(); 1627 int widthNum = -1; 1628 try { 1629 widthNum = Integer.parseInt(width); 1630 } catch (NumberFormatException e) { 1631 LOG.debug(e.getLocalizedMessage(), e); 1632 } 1633 CmsDynamicFunctionBean.Format format = functionBean.getFormatForContainer(m_cms, type, widthNum); 1634 CmsDynamicFunctionFormatWrapper wrapper = new CmsDynamicFunctionFormatWrapper(m_cms, format); 1635 return wrapper; 1636 } 1637 }; 1638 return CmsCollectionsGenericWrapper.createLazyMap(transformer); 1639 } 1640 1641 /** 1642 * Returns <code>true</code> if the current page is a detail page.<p> 1643 * 1644 * @return <code>true</code> if the current page is a detail page 1645 */ 1646 public boolean getIsDetailPage() { 1647 1648 CmsJspResourceWrapper page = getPageResource(); 1649 return OpenCms.getADEManager().isDetailPage(m_cms, page); 1650 } 1651 1652 /** 1653 * Returns <code>true</code> if the current request is direct edit enabled.<p> 1654 * 1655 * Online-, history-requests, previews and temporary files will not be editable.<p> 1656 * 1657 * @return <code>true</code> if the current request is direct edit enabled 1658 */ 1659 public boolean getIsEditMode() { 1660 1661 if (m_isEditMode == null) { 1662 m_isEditMode = Boolean.valueOf(CmsJspTagEditable.isEditableRequest(m_request)); 1663 } 1664 return m_isEditMode.booleanValue() && !m_forceDisableEditMode; 1665 } 1666 1667 /** 1668 * Returns <code>true</code> if the current request is a JSON request.<p> 1669 * 1670 * @return <code>true</code> if we are in a JSON request 1671 */ 1672 public boolean getIsJSONRequest() { 1673 1674 return CmsJsonPartFilter.isJsonRequest(m_request); 1675 } 1676 1677 /** 1678 * Returns <code>true</code> if the current project is the online project.<p> 1679 * 1680 * @return <code>true</code> if the current project is the online project 1681 */ 1682 public boolean getIsOnlineProject() { 1683 1684 return m_cms.getRequestContext().getCurrentProject().isOnlineProject(); 1685 } 1686 1687 /** 1688 * Returns true if the current request is in direct edit preview mode.<p> 1689 * 1690 * This is the case if the request is not in edit mode and in the online project.<p> 1691 * 1692 * @return <code>true</code> if the current request is in direct edit preview mode 1693 */ 1694 public boolean getIsPreviewMode() { 1695 1696 return !getIsOnlineProject() && !getIsEditMode(); 1697 } 1698 1699 /** 1700 * Returns the current locale.<p> 1701 * 1702 * @return the current locale 1703 */ 1704 public Locale getLocale() { 1705 1706 return getRequestContext().getLocale(); 1707 } 1708 1709 /** 1710 * Gets a map providing access to the locale variants of the current page.<p> 1711 * 1712 * Note that all available locales for the site / subsite are used as keys, not just the ones for which a locale 1713 * variant actually exists. 1714 * 1715 * Usage in JSPs: ${cms.localeResource['de']] 1716 * 1717 * @return the map from locale strings to locale variant resources 1718 */ 1719 public Map<String, CmsJspResourceWrapper> getLocaleResource() { 1720 1721 Map<String, CmsJspResourceWrapper> result = getPageResource().getLocaleResource(); 1722 List<Locale> locales = CmsLocaleGroupService.getPossibleLocales(m_cms, getPageResource()); 1723 for (Locale locale : locales) { 1724 if (!result.containsKey(locale.toString())) { 1725 result.put(locale.toString(), null); 1726 } 1727 } 1728 return result; 1729 } 1730 1731 /** 1732 * Gets the main locale for the current page's locale group.<p> 1733 * 1734 * @return the main locale for the current page's locale group 1735 */ 1736 public Locale getMainLocale() { 1737 1738 return getPageResource().getMainLocale(); 1739 } 1740 1741 /** 1742 * Returns the meta mappings map.<p> 1743 * 1744 * @return the meta mappings 1745 */ 1746 public Map<String, String> getMeta() { 1747 1748 initMetaMappings(); 1749 return CmsCollectionsGenericWrapper.createLazyMap(new MetaLookupTranformer()); 1750 } 1751 1752 /** 1753 * Returns the currently displayed container page.<p> 1754 * 1755 * @return the currently displayed container page 1756 */ 1757 public CmsContainerPageBean getPage() { 1758 1759 if (null == m_page) { 1760 try { 1761 initPage(); 1762 } catch (CmsException e) { 1763 if (LOG.isWarnEnabled()) { 1764 LOG.warn(e, e); 1765 } 1766 } 1767 } 1768 return m_page; 1769 } 1770 1771 /** 1772 * Returns the container page bean for the give page and locale.<p> 1773 * 1774 * @param page the container page resource as id, path or already as resource 1775 * @param locale the content locale as locale or string 1776 * 1777 * @return the container page bean 1778 */ 1779 public CmsContainerPageBean getPage(Object page, Object locale) { 1780 1781 CmsResource pageResource = null; 1782 CmsContainerPageBean result = null; 1783 if (m_cms != null) { 1784 try { 1785 pageResource = CmsJspElFunctions.convertRawResource(m_cms, page); 1786 Locale l = CmsJspElFunctions.convertLocale(locale); 1787 result = getPage(pageResource); 1788 if (result != null) { 1789 CmsADEConfigData adeConfig = OpenCms.getADEManager().lookupConfiguration( 1790 m_cms, 1791 pageResource.getRootPath()); 1792 for (CmsContainerBean container : result.getContainers().values()) { 1793 for (CmsContainerElementBean element : container.getElements()) { 1794 boolean isGroupContainer = element.isGroupContainer(m_cms); 1795 boolean isInheritedContainer = element.isInheritedContainer(m_cms); 1796 I_CmsFormatterBean formatterConfig = null; 1797 if (!isGroupContainer && !isInheritedContainer) { 1798 element.initResource(m_cms); 1799 // ensure that the formatter configuration id is added to the element settings, so it will be persisted on save 1800 formatterConfig = CmsJspTagContainer.getFormatterConfigurationForElement( 1801 m_cms, 1802 element, 1803 adeConfig, 1804 container.getName(), 1805 "", 1806 0); 1807 if (formatterConfig != null) { 1808 element.initSettings(m_cms, adeConfig, formatterConfig, l, m_request, null); 1809 } 1810 } 1811 } 1812 } 1813 } 1814 } catch (Exception e) { 1815 LOG.warn(e.getLocalizedMessage(), e); 1816 } 1817 1818 } 1819 return result; 1820 } 1821 1822 /** 1823 * Returns the current container page resource.<p> 1824 * 1825 * @return the current container page resource 1826 */ 1827 public CmsJspResourceWrapper getPageResource() { 1828 1829 try { 1830 if (m_pageResource == null) { 1831 // get the container page itself, checking the history first 1832 m_pageResource = CmsJspResourceWrapper.wrap( 1833 m_cms, 1834 (CmsResource)CmsHistoryResourceHandler.getHistoryResource(m_request)); 1835 if (m_pageResource == null) { 1836 m_pageResource = CmsJspResourceWrapper.wrap( 1837 m_cms, 1838 m_cms.readResource( 1839 m_cms.getRequestContext().getUri(), 1840 CmsResourceFilter.ignoreExpirationOffline(m_cms))); 1841 } 1842 } 1843 } catch (CmsException e) { 1844 LOG.error(e.getLocalizedMessage(), e); 1845 } 1846 return m_pageResource; 1847 } 1848 1849 /** 1850 * Returns the parent container to the current container if available.<p> 1851 * 1852 * @return the parent container 1853 */ 1854 public CmsContainerBean getParentContainer() { 1855 1856 CmsContainerBean result = null; 1857 if ((getContainer() != null) && (getContainer().getParentInstanceId() != null)) { 1858 result = m_parentContainers.get(getContainer().getParentInstanceId()); 1859 } 1860 return result; 1861 } 1862 1863 /** 1864 * Returns the instance id parent container mapping.<p> 1865 * 1866 * @return the instance id parent container mapping 1867 */ 1868 public Map<String, CmsContainerBean> getParentContainers() { 1869 1870 if (m_parentContainers == null) { 1871 initPageData(); 1872 } 1873 return Collections.unmodifiableMap(m_parentContainers); 1874 } 1875 1876 /** 1877 * Returns the parent element to the current element if available.<p> 1878 * 1879 * @return the parent element or null 1880 */ 1881 public CmsContainerElementBean getParentElement() { 1882 1883 return getParentElement(getElement()); 1884 } 1885 1886 /** 1887 * Gets the set of plugin group names. 1888 * 1889 * @return the set of plugin group names 1890 */ 1891 public Set<String> getPluginGroups() { 1892 1893 return getPlugins().keySet(); 1894 } 1895 1896 /** 1897 * Gets the map of plugins by group. 1898 * 1899 * @return the map of active plugins by group 1900 */ 1901 public Map<String, List<CmsTemplatePluginWrapper>> getPlugins() { 1902 1903 if (m_templatePlugins == null) { 1904 final Multimap<String, CmsTemplatePlugin> templatePluginsMultimap = new CmsTemplatePluginFinder( 1905 this).getTemplatePlugins(); 1906 Map<String, List<CmsTemplatePluginWrapper>> templatePlugins = new HashMap<>(); 1907 for (String key : templatePluginsMultimap.keySet()) { 1908 List<CmsTemplatePluginWrapper> wrappers = new ArrayList<>(); 1909 for (CmsTemplatePlugin plugin : templatePluginsMultimap.get(key)) { 1910 wrappers.add(new CmsTemplatePluginWrapper(m_cms, plugin)); 1911 } 1912 templatePlugins.put(key, Collections.unmodifiableList(wrappers)); 1913 } 1914 m_templatePlugins = templatePlugins; 1915 } 1916 return m_templatePlugins; 1917 } 1918 1919 /** 1920 * JSP EL accessor method for retrieving the preview formatters.<p> 1921 * 1922 * @return a lazy map for accessing preview formatters 1923 */ 1924 public Map<String, String> getPreviewFormatter() { 1925 1926 Transformer transformer = new Transformer() { 1927 1928 @Override 1929 public Object transform(Object uri) { 1930 1931 try { 1932 String rootPath = m_cms.getRequestContext().addSiteRoot((String)uri); 1933 CmsResource resource = m_cms.readResource((String)uri); 1934 CmsADEManager adeManager = OpenCms.getADEManager(); 1935 CmsADEConfigData configData = adeManager.lookupConfiguration(m_cms, rootPath); 1936 CmsFormatterConfiguration formatterConfig = configData.getFormatters(m_cms, resource); 1937 if (formatterConfig == null) { 1938 return ""; 1939 } 1940 I_CmsFormatterBean previewFormatter = formatterConfig.getPreviewFormatter(); 1941 if (previewFormatter == null) { 1942 return ""; 1943 } 1944 CmsUUID structureId = previewFormatter.getJspStructureId(); 1945 m_cms.readResource(structureId); 1946 CmsResource formatterResource = m_cms.readResource(structureId); 1947 String formatterSitePath = m_cms.getRequestContext().removeSiteRoot( 1948 formatterResource.getRootPath()); 1949 return formatterSitePath; 1950 } catch (CmsException e) { 1951 LOG.warn(e.getLocalizedMessage(), e); 1952 return ""; 1953 } 1954 } 1955 }; 1956 return CmsCollectionsGenericWrapper.createLazyMap(transformer); 1957 } 1958 1959 /** 1960 * Reads all sub-categories below the provided category. 1961 * @return The map from the provided category to it's sub-categories in a {@link CmsJspCategoryAccessBean}. 1962 */ 1963 public Map<String, CmsJspCategoryAccessBean> getReadAllSubCategories() { 1964 1965 if (null == m_allSubCategories) { 1966 m_allSubCategories = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 1967 1968 @Override 1969 public Object transform(Object categoryPath) { 1970 1971 try { 1972 List<CmsCategory> categories = CmsCategoryService.getInstance().readCategories( 1973 m_cms, 1974 (String)categoryPath, 1975 true, 1976 m_cms.getRequestContext().getUri()); 1977 CmsJspCategoryAccessBean result = new CmsJspCategoryAccessBean( 1978 m_cms, 1979 categories, 1980 (String)categoryPath); 1981 return result; 1982 } catch (CmsException e) { 1983 LOG.warn(e.getLocalizedMessage(), e); 1984 return null; 1985 } 1986 } 1987 1988 }); 1989 } 1990 return m_allSubCategories; 1991 } 1992 1993 /** 1994 * Lazily reads the given attribute from the current sitemap or a property of the same name from the given resource. 1995 * 1996 * <p>Usage example: ${cms.readAttributeOrProperty['/index.html']['attr']} 1997 * 1998 * @return a lazy loading map for accessing attributes / properties 1999 */ 2000 public Map<String, Map<String, CmsJspObjectValueWrapper>> getReadAttributeOrProperty() { 2001 2002 if (m_attributesOrProperties == null) { 2003 m_attributesOrProperties = CmsCollectionsGenericWrapper.createLazyMap(pathObj -> { 2004 return CmsCollectionsGenericWrapper.createLazyMap(keyObj -> { 2005 2006 String path = (String)pathObj; 2007 String key = (String)keyObj; 2008 2009 CmsObject cms = getCmsObject(); 2010 String result = m_config.getAttribute(key, null); 2011 if (result == null) { 2012 try { 2013 CmsProperty prop = cms.readPropertyObject(path, key, /*search=*/true); 2014 result = prop.getValue(); 2015 } catch (CmsVfsResourceNotFoundException e) { 2016 LOG.info(e.getLocalizedMessage(), e); 2017 } catch (Exception e) { 2018 LOG.error(e.getLocalizedMessage(), e); 2019 } 2020 } 2021 return CmsJspObjectValueWrapper.createWrapper(cms, result); 2022 }); 2023 }); 2024 } 2025 return m_attributesOrProperties; 2026 } 2027 2028 /** 2029 * Reads the categories assigned to the currently requested URI. 2030 * @return the categories assigned to the currently requested URI. 2031 */ 2032 public CmsJspCategoryAccessBean getReadCategories() { 2033 2034 return getReadResourceCategories().get(getRequestContext().getRootUri()); 2035 } 2036 2037 /** 2038 * Transforms the category path of a category to the category. 2039 * @return a map from root or site path to category. 2040 */ 2041 public Map<String, CmsCategory> getReadCategory() { 2042 2043 if (null == m_categories) { 2044 m_categories = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 2045 2046 public Object transform(Object categoryPath) { 2047 2048 try { 2049 CmsCategoryService catService = CmsCategoryService.getInstance(); 2050 return catService.localizeCategory( 2051 m_cms, 2052 catService.readCategory(m_cms, (String)categoryPath, getRequestContext().getUri()), 2053 m_cms.getRequestContext().getLocale()); 2054 } catch (CmsException e) { 2055 LOG.warn(e.getLocalizedMessage(), e); 2056 return null; 2057 } 2058 } 2059 2060 }); 2061 } 2062 return m_categories; 2063 } 2064 2065 /** 2066 * Transforms the category path to the list of all categories on that path.<p> 2067 * 2068 * Example: For path <code>"location/europe/"</code> 2069 * the list <code>[getReadCategory.get("location/"),getReadCategory.get("location/europe/")]</code> 2070 * is returned. 2071 * @return a map from a category path to list of categories on that path. 2072 */ 2073 public Map<String, List<CmsCategory>> getReadPathCategories() { 2074 2075 if (null == m_pathCategories) { 2076 m_pathCategories = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 2077 2078 public Object transform(Object categoryPath) { 2079 2080 List<CmsCategory> result = new ArrayList<CmsCategory>(); 2081 2082 String path = (String)categoryPath; 2083 2084 if ((null == path) || (path.length() <= 1)) { 2085 return result; 2086 } 2087 2088 //cut last slash 2089 path = path.substring(0, path.length() - 1); 2090 2091 List<String> pathParts = Arrays.asList(path.split("/")); 2092 2093 String currentPath = ""; 2094 for (String part : pathParts) { 2095 currentPath += part + "/"; 2096 CmsCategory category = getReadCategory().get(currentPath); 2097 if (null != category) { 2098 result.add(category); 2099 } 2100 } 2101 return CmsCategoryService.getInstance().localizeCategories( 2102 m_cms, 2103 result, 2104 m_cms.getRequestContext().getLocale()); 2105 } 2106 2107 }); 2108 } 2109 return m_pathCategories; 2110 } 2111 2112 /** 2113 * Reads the categories assigned to a resource. 2114 * 2115 * @return map from the resource path (root path) to the assigned categories 2116 */ 2117 public Map<String, CmsJspCategoryAccessBean> getReadResourceCategories() { 2118 2119 if (null == m_resourceCategories) { 2120 m_resourceCategories = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 2121 2122 public Object transform(Object resourceName) { 2123 2124 try { 2125 CmsResource resource = m_cms.readResource( 2126 getRequestContext().removeSiteRoot((String)resourceName)); 2127 return new CmsJspCategoryAccessBean(m_cms, resource); 2128 } catch (CmsException e) { 2129 LOG.warn(e.getLocalizedMessage(), e); 2130 return null; 2131 } 2132 } 2133 }); 2134 } 2135 return m_resourceCategories; 2136 } 2137 2138 /** 2139 * Returns a HTML comment string that will cause the container page editor to reload the page if the element or its settings 2140 * were edited.<p> 2141 * 2142 * @return the reload marker 2143 */ 2144 public String getReloadMarker() { 2145 2146 if (m_cms.getRequestContext().getCurrentProject().isOnlineProject()) { 2147 return ""; // reload marker is not needed in Online mode 2148 } else { 2149 return CmsGwtConstants.FORMATTER_RELOAD_MARKER; 2150 } 2151 } 2152 2153 /** 2154 * Gets the stored request. 2155 * 2156 * @return the stored request 2157 */ 2158 public ServletRequest getRequest() { 2159 2160 return m_request; 2161 } 2162 2163 /** 2164 * Returns the request context.<p> 2165 * 2166 * @return the request context 2167 */ 2168 public CmsRequestContext getRequestContext() { 2169 2170 return m_cms.getRequestContext(); 2171 } 2172 2173 /** 2174 * Gets information about a specific resource type for use in JSPs. 2175 * 2176 * <p>If no type with the given name exists, null is returned. 2177 * 2178 * @param typeName the type name 2179 * @return the bean representing the resource type 2180 */ 2181 public CmsResourceTypeInfoWrapper getResourceTypeInfo(String typeName) { 2182 2183 try { 2184 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(typeName); 2185 return new CmsResourceTypeInfoWrapper(m_cms, m_config, type); 2186 } catch (CmsLoaderException e) { 2187 LOG.info(e.getLocalizedMessage(), e); 2188 return null; 2189 } 2190 } 2191 2192 /** 2193 * Returns the current site.<p> 2194 * 2195 * @return the current site 2196 */ 2197 public CmsSite getSite() { 2198 2199 return OpenCms.getSiteManager().getSiteForSiteRoot(m_cms.getRequestContext().getSiteRoot()); 2200 } 2201 2202 /** 2203 * Gets the wrapper for the sitemap configuration. 2204 * 2205 * @return the wrapper object for the sitemap configuration 2206 */ 2207 public CmsJspSitemapConfigWrapper getSitemapConfig() { 2208 2209 return new CmsJspSitemapConfigWrapper(this); 2210 } 2211 2212 /** 2213 * Transforms root paths to site paths. 2214 * 2215 * @return lazy map from root paths to site paths. 2216 * 2217 * @see CmsRequestContext#removeSiteRoot(String) 2218 */ 2219 public Map<String, String> getSitePath() { 2220 2221 if (m_sitePaths == null) { 2222 m_sitePaths = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 2223 2224 public Object transform(Object rootPath) { 2225 2226 if (rootPath instanceof String) { 2227 return getRequestContext().removeSiteRoot((String)rootPath); 2228 } 2229 return null; 2230 } 2231 }); 2232 } 2233 return m_sitePaths; 2234 } 2235 2236 /** 2237 * Returns the subsite path for the currently requested URI.<p> 2238 * 2239 * @return the subsite path 2240 */ 2241 public String getSubSitePath() { 2242 2243 return m_cms.getRequestContext().removeSiteRoot( 2244 OpenCms.getADEManager().getSubSiteRoot(m_cms, m_cms.getRequestContext().getRootUri())); 2245 } 2246 2247 /** 2248 * Returns the system information.<p> 2249 * 2250 * @return the system information 2251 */ 2252 public CmsSystemInfo getSystemInfo() { 2253 2254 return OpenCms.getSystemInfo(); 2255 } 2256 2257 /** 2258 * Gets a bean containing information about the current template.<p> 2259 * 2260 * @return the template information bean 2261 */ 2262 public TemplateBean getTemplate() { 2263 2264 TemplateBean templateBean = getRequestAttribute(CmsTemplateContextManager.ATTR_TEMPLATE_BEAN); 2265 if (templateBean == null) { 2266 templateBean = new TemplateBean("", ""); 2267 } 2268 return templateBean; 2269 } 2270 2271 /** 2272 * Returns the title of a page delivered from OpenCms, usually used for the <code><title></code> tag of 2273 * a HTML page.<p> 2274 * 2275 * If no title information has been found, the empty String "" is returned.<p> 2276 * 2277 * @return the title of the current page 2278 */ 2279 public String getTitle() { 2280 2281 return getLocaleSpecificTitle(null); 2282 2283 } 2284 2285 /** 2286 * Get the title and read the Title property according the provided locale. 2287 * @return The map from locales to the locale specific titles. 2288 */ 2289 public Map<String, String> getTitleLocale() { 2290 2291 if (m_localeTitles == null) { 2292 m_localeTitles = CmsCollectionsGenericWrapper.createLazyMap(new Transformer() { 2293 2294 public Object transform(Object inputLocale) { 2295 2296 Locale locale = null; 2297 if (null != inputLocale) { 2298 if (inputLocale instanceof Locale) { 2299 locale = (Locale)inputLocale; 2300 } else if (inputLocale instanceof String) { 2301 try { 2302 locale = LocaleUtils.toLocale((String)inputLocale); 2303 } catch (IllegalArgumentException | NullPointerException e) { 2304 // do nothing, just go on without locale 2305 } 2306 } 2307 } 2308 return getLocaleSpecificTitle(locale); 2309 } 2310 2311 }); 2312 } 2313 return m_localeTitles; 2314 } 2315 2316 /** 2317 * Returns a lazy initialized Map that provides the detail page link as a value when given the name of a 2318 * resource type as a key.<p> 2319 * 2320 * The provided Map key is assumed to be the name of a resource type that has a detail page configured.<p> 2321 * 2322 * Usage example on a JSP with the JSTL:<pre> 2323 * <a href=${cms.typeDetailPage['bs-blog']} /> 2324 * </pre> 2325 * 2326 * @return a lazy initialized Map that provides the detail page link as a value when given the name of a 2327 * resource type as a key 2328 * 2329 * @see #getFunctionDetailPage() 2330 */ 2331 public Map<String, String> getTypeDetailPage() { 2332 2333 if (m_typeDetailPage == null) { 2334 m_typeDetailPage = CmsCollectionsGenericWrapper.createLazyMap(new CmsDetailLookupTransformer("")); 2335 } 2336 return m_typeDetailPage; 2337 } 2338 2339 /** 2340 * Returns an initialized VFS access bean.<p> 2341 * 2342 * @return an initialized VFS access bean 2343 */ 2344 public CmsJspVfsAccessBean getVfs() { 2345 2346 if (m_vfsBean == null) { 2347 // create a new VVFS access bean 2348 m_vfsBean = CmsJspVfsAccessBean.create(m_cms); 2349 } 2350 return m_vfsBean; 2351 } 2352 2353 /** 2354 * Returns the workplace locale from the current user's settings.<p> 2355 * 2356 * @return returns the workplace locale from the current user's settings 2357 */ 2358 public Locale getWorkplaceLocale() { 2359 2360 return OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms); 2361 } 2362 2363 /** 2364 * Returns an EL access wrapper map for the given object.<p> 2365 * 2366 * If the object is a {@link CmsResource}, then a {@link CmsJspResourceWrapper} is returned. 2367 * Otherwise the object is wrapped in a {@link CmsJspObjectValueWrapper}.<p> 2368 * 2369 * If the object is already is a wrapper, it is returned unchanged.<p> 2370 * 2371 * @return an EL access wrapper map for the given object 2372 */ 2373 public Map<Object, Object> getWrap() { 2374 2375 return CmsCollectionsGenericWrapper.createLazyMap(obj -> { 2376 2377 if ((obj instanceof A_CmsJspValueWrapper) || (obj instanceof CmsJspResourceWrapper)) { 2378 return obj; 2379 } else if (obj instanceof CmsResource) { 2380 return CmsJspResourceWrapper.wrap(m_cms, (CmsResource)obj); 2381 } else { 2382 return CmsJspObjectValueWrapper.createWrapper(m_cms, obj); 2383 } 2384 }); 2385 } 2386 2387 /** 2388 * Initializes the requested container page.<p> 2389 * 2390 * @throws CmsException in case reading the requested resource fails 2391 */ 2392 public void initPage() throws CmsException { 2393 2394 if ((m_page == null) && (m_cms != null)) { 2395 String requestUri = m_cms.getRequestContext().getUri(); 2396 // get the container page itself, checking the history first 2397 CmsResource pageResource = (CmsResource)CmsHistoryResourceHandler.getHistoryResource(m_request); 2398 if (pageResource == null) { 2399 pageResource = m_cms.readResource(requestUri, CmsResourceFilter.ignoreExpirationOffline(m_cms)); 2400 } 2401 m_config = OpenCms.getADEManager().lookupConfigurationWithCache(m_cms, pageResource.getRootPath()); 2402 m_page = getPage(pageResource); 2403 m_page = CmsTemplateMapper.get(m_request).transformContainerpageBean( 2404 m_cms, 2405 m_page, 2406 pageResource.getRootPath()); 2407 2408 } 2409 } 2410 2411 /** 2412 * Returns <code>true</code in case a detail page is available for the current element.<p> 2413 * 2414 * @return <code>true</code in case a detail page is available for the current element 2415 */ 2416 public boolean isDetailPageAvailable() { 2417 2418 boolean result = false; 2419 if ((m_cms != null) 2420 && (m_element != null) 2421 && !m_element.isInMemoryOnly() 2422 && (m_element.getResource() != null)) { 2423 try { 2424 String detailPage = OpenCms.getADEManager().getDetailPageHandler().getDetailPage( 2425 m_cms, 2426 m_element.getResource().getRootPath(), 2427 m_cms.getRequestContext().getUri(), 2428 null); 2429 result = detailPage != null; 2430 } catch (Exception e) { 2431 LOG.warn(e.getLocalizedMessage(), e); 2432 } 2433 } 2434 return result; 2435 } 2436 2437 /** 2438 * Returns <code>true</code> if this is a request to a detail resource, <code>false</code> otherwise.<p> 2439 * 2440 * Same as to check if {@link #getDetailContent()} is <code>null</code>.<p> 2441 * 2442 * @return <code>true</code> if this is a request to a detail resource, <code>false</code> otherwise 2443 */ 2444 public boolean isDetailRequest() { 2445 2446 return m_detailContentResource != null; 2447 } 2448 2449 /** 2450 * Returns if the page is in drag mode.<p> 2451 * 2452 * @return if the page is in drag mode 2453 */ 2454 public boolean isDragMode() { 2455 2456 return m_isDragMode; 2457 } 2458 2459 /** 2460 * Returns the flag to indicate if in drag and drop mode.<p> 2461 * 2462 * @return <code>true</code> if in drag and drop mode 2463 */ 2464 public boolean isEdited() { 2465 2466 return m_edited; 2467 } 2468 2469 /** 2470 * Checks if the flag that forces edit mode to be disabled is set. 2471 * 2472 * @return true if the flag that disables edit mode is set 2473 */ 2474 public boolean isForceDisableEditMode() { 2475 2476 return m_forceDisableEditMode; 2477 } 2478 2479 /** 2480 * Returns if the current element is a model group.<p> 2481 * 2482 * @return <code>true</code> if the current element is a model group 2483 */ 2484 public boolean isModelGroupElement() { 2485 2486 return (m_element != null) && !m_element.isInMemoryOnly() && isModelGroupPage() && m_element.isModelGroup(); 2487 } 2488 2489 /** 2490 * Returns if the current page is used to manage model groups.<p> 2491 * 2492 * @return <code>true</code> if the current page is used to manage model groups 2493 */ 2494 public boolean isModelGroupPage() { 2495 2496 CmsResource page = getPageResource(); 2497 return (page != null) && CmsContainerpageService.isEditingModelGroups(m_cms, page); 2498 2499 } 2500 2501 /** 2502 * Renders the elements of container in a container page wrapper as HTML (without a surrounding element). 2503 * 2504 * @param page the page wrapper 2505 * @param name the name or name prefix of the container 2506 * @return the rendered HTML 2507 */ 2508 public String renderContainer(CmsJspContainerPageWrapper page, String name) { 2509 2510 String result = page.renderContainer(this, name); 2511 return result; 2512 } 2513 2514 /** 2515 * Sets the container the currently rendered element is part of.<p> 2516 * 2517 * @param container the container the currently rendered element is part of 2518 */ 2519 public void setContainer(CmsContainerBean container) { 2520 2521 m_container = container; 2522 } 2523 2524 /** 2525 * Sets the detail only page.<p> 2526 * 2527 * @param detailOnlyPage the detail only page to set 2528 */ 2529 public void setDetailOnlyPage(CmsContainerPageBean detailOnlyPage) { 2530 2531 m_detailOnlyPage = detailOnlyPage; 2532 clearPageData(); 2533 } 2534 2535 /** 2536 * Sets if the page is in drag mode.<p> 2537 * 2538 * @param isDragMode if the page is in drag mode 2539 */ 2540 public void setDragMode(boolean isDragMode) { 2541 2542 m_isDragMode = isDragMode; 2543 } 2544 2545 /** 2546 * Sets the flag to indicate if in drag and drop mode.<p> 2547 * 2548 * @param edited <code>true</code> if in drag and drop mode 2549 */ 2550 public void setEdited(boolean edited) { 2551 2552 m_edited = edited; 2553 } 2554 2555 /** 2556 * In edit mode, creates a meta tag that tells the form-based content editor to use the stylesheet with the given path as a default. 2557 * 2558 * <p>Does nothing outside of edit mode. 2559 * 2560 * @param path the site path of a style sheet 2561 * @return the meta tag 2562 */ 2563 public String setEditorCssPath(String path) { 2564 2565 if (getIsEditMode()) { 2566 return "\n<meta name=\"" 2567 + CmsGwtConstants.META_EDITOR_STYLESHEET 2568 + "\" content=\"" 2569 + CmsEncoder.escapeXml(path) 2570 + "\">\n"; 2571 } else { 2572 return ""; 2573 } 2574 } 2575 2576 /** 2577 * Sets the currently rendered element.<p> 2578 * 2579 * @param element the currently rendered element to set 2580 */ 2581 public void setElement(CmsContainerElementBean element) { 2582 2583 m_element = element; 2584 } 2585 2586 /** 2587 * Enables / disables the flag that forces edit mode to be disabled. 2588 * 2589 * @param forceDisableEditMode the new value for the flag 2590 */ 2591 public void setForceDisableEditMode(boolean forceDisableEditMode) { 2592 2593 m_forceDisableEditMode = forceDisableEditMode; 2594 } 2595 2596 /** 2597 * Sets the currently displayed container page.<p> 2598 * 2599 * @param page the currently displayed container page to set 2600 */ 2601 public void setPage(CmsContainerPageBean page) { 2602 2603 m_page = page; 2604 clearPageData(); 2605 } 2606 2607 /** 2608 * Updates the internally stored OpenCms user context.<p> 2609 * 2610 * @param cms the new OpenCms user context 2611 */ 2612 public void updateCmsObject(CmsObject cms) { 2613 2614 try { 2615 m_cms = OpenCms.initCmsObject(cms); 2616 } catch (CmsException e) { 2617 LOG.error(e.getLocalizedMessage(), e); 2618 m_cms = cms; 2619 } 2620 try { 2621 m_config = OpenCms.getADEManager().lookupConfigurationWithCache(cms, cms.getRequestContext().getRootUri()); 2622 } catch (Exception e) { 2623 LOG.error(e.getLocalizedMessage(), e); 2624 } 2625 } 2626 2627 /** 2628 * Updates the standard context bean from the request.<p> 2629 * 2630 * @param cmsFlexRequest the request from which to update the data 2631 */ 2632 public void updateRequestData(CmsFlexRequest cmsFlexRequest) { 2633 2634 CmsResource detailRes = CmsDetailPageResourceHandler.getDetailResource(cmsFlexRequest); 2635 m_detailContentResource = detailRes; 2636 m_request = cmsFlexRequest; 2637 2638 } 2639 2640 /** 2641 * Accessor for the CmsObject. 2642 * 2643 * @return the CmsObject 2644 */ 2645 protected CmsObject getCmsObject() { 2646 2647 return m_cms; 2648 } 2649 2650 /** 2651 * Returns the formatter configuration to the given element.<p> 2652 * 2653 * @param element the element 2654 * 2655 * @return the formatter configuration 2656 */ 2657 protected I_CmsFormatterBean getElementFormatter(CmsContainerElementBean element) { 2658 2659 if (m_elementInstances == null) { 2660 initPageData(); 2661 } 2662 I_CmsFormatterBean formatter = null; 2663 CmsContainerBean container = m_parentContainers.get(element.getInstanceId()); 2664 if (container == null) { 2665 // use the current container 2666 container = getContainer(); 2667 } 2668 if (container != null) { 2669 String containerName = container.getName(); 2670 Map<String, String> settings = element.getSettings(); 2671 if (settings != null) { 2672 String formatterConfigId = settings.get(CmsFormatterConfig.getSettingsKeyForContainer(containerName)); 2673 I_CmsFormatterBean dynamicFmt = m_config.findFormatter(formatterConfigId); 2674 if (dynamicFmt != null) { 2675 formatter = dynamicFmt; 2676 } 2677 } 2678 if (formatter == null) { 2679 try { 2680 CmsResource resource = m_cms.readResource(m_cms.getRequestContext().getUri()); 2681 2682 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration( 2683 m_cms, 2684 resource.getRootPath()); 2685 CmsFormatterConfiguration formatters = config.getFormatters(m_cms, resource); 2686 int width = -2; 2687 try { 2688 width = Integer.parseInt(container.getWidth()); 2689 } catch (Exception e) { 2690 LOG.debug(e.getLocalizedMessage(), e); 2691 } 2692 formatter = formatters.getDefaultSchemaFormatter(container.getType(), width); 2693 } catch (CmsException e1) { 2694 if (LOG.isWarnEnabled()) { 2695 LOG.warn(e1.getLocalizedMessage(), e1); 2696 } 2697 } 2698 } 2699 } 2700 return formatter; 2701 } 2702 2703 /** 2704 * Returns the title according to the given locale. 2705 * @param locale the locale for which the title should be read. 2706 * @return the title according to the given locale 2707 */ 2708 protected String getLocaleSpecificTitle(Locale locale) { 2709 2710 String result = null; 2711 2712 try { 2713 2714 if (isDetailRequest()) { 2715 // this is a request to a detail page 2716 CmsResource res = getDetailContent(); 2717 CmsFile file = m_cms.readFile(res); 2718 CmsXmlContent content = CmsXmlContentFactory.unmarshal(m_cms, file); 2719 result = content.getHandler().getTitleMapping(m_cms, content, m_cms.getRequestContext().getLocale()); 2720 if (result == null) { 2721 // title not found, maybe no mapping OR not available in the current locale 2722 // read the title of the detail resource as fall back (may contain mapping from another locale) 2723 result = m_cms.readPropertyObject( 2724 res, 2725 CmsPropertyDefinition.PROPERTY_TITLE, 2726 false, 2727 locale).getValue(); 2728 } 2729 } 2730 if (result == null) { 2731 // read the title of the requested resource as fall back 2732 result = m_cms.readPropertyObject( 2733 m_cms.getRequestContext().getUri(), 2734 CmsPropertyDefinition.PROPERTY_TITLE, 2735 true, 2736 locale).getValue(); 2737 } 2738 } catch (CmsException e) { 2739 LOG.debug(e.getLocalizedMessage(), e); 2740 } 2741 if (CmsStringUtil.isEmptyOrWhitespaceOnly(result)) { 2742 result = ""; 2743 } 2744 2745 return result; 2746 } 2747 2748 /** 2749 * Returns the parent element if available.<p> 2750 * 2751 * @param element the element 2752 * 2753 * @return the parent element or null 2754 */ 2755 protected CmsContainerElementBean getParentElement(CmsContainerElementBean element) { 2756 2757 if (m_elementInstances == null) { 2758 initPageData(); 2759 } 2760 CmsContainerElementBean parent = null; 2761 CmsContainerBean cont = m_parentContainers.get(element.getInstanceId()); 2762 if ((cont != null) && cont.isNestedContainer()) { 2763 parent = m_elementInstances.get(cont.getParentInstanceId()); 2764 } 2765 return parent; 2766 } 2767 2768 /** 2769 * Accessor for the sitemap configuration. 2770 * 2771 * @return the sitemap configuration 2772 */ 2773 protected CmsADEConfigData getSitemapConfigInternal() { 2774 2775 return m_config; 2776 } 2777 2778 /** 2779 * Reads a dynamic function bean, given its name in the module configuration.<p> 2780 * 2781 * @param configuredName the name of the dynamic function in the module configuration 2782 * @return the dynamic function bean for the dynamic function configured under that name 2783 * 2784 * @throws CmsException if something goes wrong 2785 */ 2786 protected CmsDynamicFunctionBean readDynamicFunctionBean(String configuredName) throws CmsException { 2787 2788 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration( 2789 m_cms, 2790 m_cms.addSiteRoot(m_cms.getRequestContext().getUri())); 2791 CmsFunctionReference functionRef = config.getFunctionReference(configuredName); 2792 if (functionRef == null) { 2793 return null; 2794 } 2795 CmsDynamicFunctionParser parser = new CmsDynamicFunctionParser(); 2796 CmsResource functionResource = m_cms.readResource(functionRef.getStructureId()); 2797 CmsDynamicFunctionBean result = parser.parseFunctionBean(m_cms, functionResource); 2798 return result; 2799 } 2800 2801 /** 2802 * Adds the mappings of the given formatter configuration.<p> 2803 * 2804 * @param formatterBean the formatter bean 2805 * @param elementId the element content structure id 2806 * @param resolver The macro resolver used on key and default value of the mappings 2807 * @param isDetailContent in case of a detail content 2808 */ 2809 private void addMappingsForFormatter( 2810 I_CmsFormatterBean formatterBean, 2811 CmsUUID elementId, 2812 CmsMacroResolver resolver, 2813 boolean isDetailContent) { 2814 2815 if ((formatterBean != null) && (formatterBean.getMetaMappings() != null)) { 2816 for (CmsMetaMapping map : formatterBean.getMetaMappings()) { 2817 String key = map.getKey(); 2818 key = resolver.resolveMacros(key); 2819 // the detail content mapping overrides other mappings 2820 if (isDetailContent 2821 || !m_metaMappings.containsKey(key) 2822 || (m_metaMappings.get(key).m_order <= map.getOrder())) { 2823 MetaMapping mapping = new MetaMapping(); 2824 mapping.m_key = key; 2825 mapping.m_elementXPath = map.getElement(); 2826 mapping.m_defaultValue = resolver.resolveMacros(map.getDefaultValue()); 2827 mapping.m_order = map.getOrder(); 2828 mapping.m_contentId = elementId; 2829 m_metaMappings.put(key, mapping); 2830 } 2831 } 2832 } 2833 } 2834 2835 /** 2836 * Clears the page element data.<p> 2837 */ 2838 private void clearPageData() { 2839 2840 m_elementInstances = null; 2841 m_parentContainers = null; 2842 } 2843 2844 /** 2845 * Finds the first ancestor of a resource matching a given predicate. 2846 * 2847 * @param cms the CMS context 2848 * @param resource the resource 2849 * @param predicate the predicate to test 2850 * 2851 * @return the first ancestor matching the predicate (which may possibly be the given resource itself), or null if no matching ancestor is found 2852 * @throws CmsException 2853 */ 2854 private CmsResource findAncestor(CmsObject cms, CmsResource resource, Predicate<CmsResource> predicate) { 2855 2856 try { 2857 CmsObject rootCms = OpenCms.initCmsObject(cms); 2858 rootCms.getRequestContext().setSiteRoot(""); 2859 CmsResource ancestor = resource; 2860 while (ancestor != null) { 2861 if (predicate.test(ancestor)) { 2862 return ancestor; 2863 } 2864 String parentFolder = CmsResource.getParentFolder(ancestor.getRootPath()); 2865 if (parentFolder == null) { 2866 break; 2867 } 2868 try { 2869 ancestor = rootCms.readResource(parentFolder, CmsResourceFilter.IGNORE_EXPIRATION); 2870 } catch (CmsException e) { 2871 LOG.info(e.getLocalizedMessage(), e); 2872 break; 2873 } 2874 } 2875 } catch (CmsException e) { 2876 LOG.error(e.getLocalizedMessage(), e); 2877 } 2878 return null; 2879 } 2880 2881 /** 2882 * Returns the container page bean for the give resource.<p> 2883 * 2884 * @param pageResource the resource 2885 * 2886 * @return the container page bean 2887 * 2888 * @throws CmsException in case reading the page bean fails 2889 */ 2890 private CmsContainerPageBean getPage(CmsResource pageResource) throws CmsException { 2891 2892 CmsContainerPageBean result = null; 2893 if ((pageResource != null) && CmsResourceTypeXmlContainerPage.isContainerPage(pageResource)) { 2894 CmsXmlContainerPage xmlContainerPage = CmsXmlContainerPageFactory.unmarshal(m_cms, pageResource, m_request); 2895 result = xmlContainerPage.getContainerPage(m_cms); 2896 CmsModelGroupHelper modelHelper = new CmsModelGroupHelper( 2897 m_cms, 2898 OpenCms.getADEManager().lookupConfiguration(m_cms, pageResource.getRootPath()), 2899 CmsJspTagEditable.isEditableRequest(m_request) && (m_request instanceof HttpServletRequest) 2900 ? CmsADESessionCache.getCache((HttpServletRequest)m_request, m_cms) 2901 : null, 2902 CmsContainerpageService.isEditingModelGroups(m_cms, pageResource)); 2903 result = modelHelper.readModelGroups(xmlContainerPage.getContainerPage(m_cms)); 2904 } 2905 return result; 2906 } 2907 2908 /** 2909 * Convenience method for getting a request attribute without an explicit cast.<p> 2910 * 2911 * @param name the attribute name 2912 * @return the request attribute 2913 */ 2914 @SuppressWarnings("unchecked") 2915 private <A> A getRequestAttribute(String name) { 2916 2917 Object attribute = m_request.getAttribute(name); 2918 2919 return attribute != null ? (A)attribute : null; 2920 } 2921 2922 /** 2923 * Initializes the mapping configuration.<p> 2924 */ 2925 private void initMetaMappings() { 2926 2927 if (m_metaMappings == null) { 2928 m_metaMappings = new HashMap<String, MetaMapping>(); 2929 try { 2930 initPage(); 2931 CmsMacroResolver resolver = new CmsMacroResolver(); 2932 resolver.setKeepEmptyMacros(true); 2933 resolver.setCmsObject(m_cms); 2934 resolver.setMessages(OpenCms.getWorkplaceManager().getMessages(getLocale())); 2935 CmsResourceFilter filter = getIsEditMode() 2936 ? CmsResourceFilter.IGNORE_EXPIRATION 2937 : CmsResourceFilter.DEFAULT; 2938 for (CmsContainerBean container : m_page.getContainers().values()) { 2939 for (CmsContainerElementBean element : container.getElements()) { 2940 String settingsKey = CmsFormatterConfig.getSettingsKeyForContainer(container.getName()); 2941 String formatterConfigId = element.getSettings() != null 2942 ? element.getSettings().get(settingsKey) 2943 : null; 2944 I_CmsFormatterBean formatterBean = null; 2945 formatterBean = m_config.findFormatter(formatterConfigId); 2946 if ((formatterBean != null) 2947 && formatterBean.useMetaMappingsForNormalElements() 2948 && m_cms.existsResource(element.getId(), filter)) { 2949 addMappingsForFormatter(formatterBean, element.getId(), resolver, false); 2950 } 2951 2952 } 2953 } 2954 if (getDetailContentId() != null) { 2955 try { 2956 CmsResource detailContent = m_cms.readResource( 2957 getDetailContentId(), 2958 CmsResourceFilter.ignoreExpirationOffline(m_cms)); 2959 CmsFormatterConfiguration config = OpenCms.getADEManager().lookupConfiguration( 2960 m_cms, 2961 m_cms.getRequestContext().getRootUri()).getFormatters(m_cms, detailContent); 2962 for (I_CmsFormatterBean formatter : config.getDetailFormatters()) { 2963 addMappingsForFormatter(formatter, getDetailContentId(), resolver, true); 2964 } 2965 } catch (CmsException e) { 2966 LOG.error( 2967 Messages.get().getBundle().key( 2968 Messages.ERR_READING_REQUIRED_RESOURCE_1, 2969 getDetailContentId()), 2970 e); 2971 } 2972 } 2973 } catch (Exception e) { 2974 LOG.error(e.getLocalizedMessage(), e); 2975 } 2976 } 2977 } 2978 2979 /** 2980 * Initializes the page element data.<p> 2981 */ 2982 private void initPageData() { 2983 2984 m_elementInstances = new HashMap<String, CmsContainerElementBean>(); 2985 m_parentContainers = new HashMap<String, CmsContainerBean>(); 2986 if (m_page != null) { 2987 for (CmsContainerBean container : m_page.getContainers().values()) { 2988 for (CmsContainerElementBean element : container.getElements()) { 2989 m_elementInstances.put(element.getInstanceId(), element); 2990 m_parentContainers.put(element.getInstanceId(), container); 2991 try { 2992 if (element.isGroupContainer(m_cms) || element.isInheritedContainer(m_cms)) { 2993 List<CmsContainerElementBean> children; 2994 if (element.isGroupContainer(m_cms)) { 2995 children = CmsJspTagContainer.getGroupContainerElements( 2996 m_cms, 2997 element, 2998 m_request, 2999 container.getType()); 3000 } else { 3001 children = CmsJspTagContainer.getInheritedContainerElements(m_cms, element); 3002 } 3003 for (CmsContainerElementBean childElement : children) { 3004 m_elementInstances.put(childElement.getInstanceId(), childElement); 3005 m_parentContainers.put(childElement.getInstanceId(), container); 3006 } 3007 } 3008 } catch (CmsException e) { 3009 LOG.error(e.getLocalizedMessage(), e); 3010 } 3011 } 3012 } 3013 // also add detail only data 3014 if (m_detailOnlyPage != null) { 3015 for (CmsContainerBean container : m_detailOnlyPage.getContainers().values()) { 3016 for (CmsContainerElementBean element : container.getElements()) { 3017 m_elementInstances.put(element.getInstanceId(), element); 3018 m_parentContainers.put(element.getInstanceId(), container); 3019 } 3020 } 3021 } 3022 } 3023 } 3024 3025}