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.ade.containerpage; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.configuration.CmsElementView; 032import org.opencms.ade.configuration.CmsResourceTypeConfig; 033import org.opencms.ade.containerpage.inherited.CmsContainerConfigurationCache; 034import org.opencms.ade.containerpage.inherited.CmsInheritanceReference; 035import org.opencms.ade.containerpage.inherited.CmsInheritanceReferenceParser; 036import org.opencms.ade.containerpage.inherited.CmsInheritedContainerState; 037import org.opencms.ade.containerpage.shared.CmsContainer; 038import org.opencms.ade.containerpage.shared.CmsContainerElement; 039import org.opencms.ade.containerpage.shared.CmsContainerElement.ModelGroupState; 040import org.opencms.ade.containerpage.shared.CmsContainerElementData; 041import org.opencms.ade.containerpage.shared.CmsElementLockInfo; 042import org.opencms.ade.containerpage.shared.CmsElementSettingsConfig; 043import org.opencms.ade.containerpage.shared.CmsFormatterConfig; 044import org.opencms.ade.containerpage.shared.CmsFormatterConfigCollection; 045import org.opencms.ade.containerpage.shared.CmsInheritanceInfo; 046import org.opencms.ade.detailpage.CmsDetailPageResourceHandler; 047import org.opencms.configuration.CmsConfigurationException; 048import org.opencms.db.CmsResourceState; 049import org.opencms.file.CmsFile; 050import org.opencms.file.CmsObject; 051import org.opencms.file.CmsRequestContext; 052import org.opencms.file.CmsResource; 053import org.opencms.file.CmsResourceFilter; 054import org.opencms.file.CmsUser; 055import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 056import org.opencms.file.types.CmsResourceTypeXmlContent; 057import org.opencms.file.types.I_CmsResourceType; 058import org.opencms.gwt.CmsDefaultResourceStatusProvider; 059import org.opencms.gwt.CmsIconUtil; 060import org.opencms.gwt.CmsVfsService; 061import org.opencms.gwt.shared.CmsAdditionalInfoBean; 062import org.opencms.gwt.shared.CmsListInfoBean; 063import org.opencms.gwt.shared.CmsPermissionInfo; 064import org.opencms.i18n.CmsMessageContainer; 065import org.opencms.i18n.CmsMessages; 066import org.opencms.jsp.util.CmsJspStandardContextBean; 067import org.opencms.jsp.util.CmsJspStandardContextBean.TemplateBean; 068import org.opencms.loader.CmsTemplateContextManager; 069import org.opencms.lock.CmsLock; 070import org.opencms.main.CmsException; 071import org.opencms.main.CmsLog; 072import org.opencms.main.OpenCms; 073import org.opencms.relations.CmsRelation; 074import org.opencms.relations.CmsRelationFilter; 075import org.opencms.relations.CmsRelationType; 076import org.opencms.search.galleries.CmsGallerySearch; 077import org.opencms.search.galleries.CmsGallerySearchResult; 078import org.opencms.util.CmsDateUtil; 079import org.opencms.util.CmsStringUtil; 080import org.opencms.util.CmsUUID; 081import org.opencms.workplace.CmsWorkplaceMessages; 082import org.opencms.workplace.editors.CmsWorkplaceEditorManager; 083import org.opencms.workplace.editors.directedit.CmsAdvancedDirectEditProvider; 084import org.opencms.workplace.editors.directedit.CmsDirectEditMode; 085import org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider; 086import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 087import org.opencms.workplace.explorer.CmsResourceUtil; 088import org.opencms.xml.containerpage.CmsADESessionCache; 089import org.opencms.xml.containerpage.CmsContainerBean; 090import org.opencms.xml.containerpage.CmsContainerElementBean; 091import org.opencms.xml.containerpage.CmsContainerPageBean; 092import org.opencms.xml.containerpage.CmsFormatterConfiguration; 093import org.opencms.xml.containerpage.CmsGroupContainerBean; 094import org.opencms.xml.containerpage.CmsXmlContainerPage; 095import org.opencms.xml.containerpage.CmsXmlContainerPageFactory; 096import org.opencms.xml.containerpage.CmsXmlGroupContainer; 097import org.opencms.xml.containerpage.CmsXmlGroupContainerFactory; 098import org.opencms.xml.containerpage.I_CmsFormatterBean; 099import org.opencms.xml.content.CmsXmlContent; 100import org.opencms.xml.content.CmsXmlContentFactory; 101import org.opencms.xml.content.CmsXmlContentProperty; 102import org.opencms.xml.content.CmsXmlContentPropertyHelper; 103 104import java.io.IOException; 105import java.text.DateFormat; 106import java.util.ArrayList; 107import java.util.Collection; 108import java.util.Collections; 109import java.util.Date; 110import java.util.HashMap; 111import java.util.HashSet; 112import java.util.LinkedHashMap; 113import java.util.LinkedHashSet; 114import java.util.List; 115import java.util.Locale; 116import java.util.Map; 117import java.util.Map.Entry; 118import java.util.Set; 119import java.util.function.Function; 120 121import javax.servlet.ServletException; 122import javax.servlet.http.HttpServletRequest; 123import javax.servlet.http.HttpServletResponse; 124 125import org.apache.commons.logging.Log; 126 127import org.jsoup.Jsoup; 128import org.jsoup.nodes.Document; 129import org.jsoup.select.Elements; 130 131import com.google.common.base.Supplier; 132import com.google.common.base.Suppliers; 133import com.google.common.collect.Sets; 134 135/** 136 * Utility class to generate the element data objects used within the container-page editor.<p> 137 * 138 * @since 8.0.0 139 */ 140public class CmsElementUtil { 141 142 /** The maximum number of nested container levels. */ 143 public static final int MAX_NESTING_LEVEL = 7; 144 145 /** Static reference to the log. */ 146 private static final Log LOG = CmsLog.getLog(org.opencms.ade.containerpage.CmsElementUtil.class); 147 148 /** The ADE configuration data for the current page URI. */ 149 private CmsADEConfigData m_adeConfig; 150 151 /** The cms context. */ 152 private CmsObject m_cms; 153 154 /** The current page uri. */ 155 private String m_currentPageUri; 156 157 /** The content locale. */ 158 private Locale m_locale; 159 160 /** The current container page. */ 161 private CmsResource m_page; 162 163 /** The request parameters to use while rendering the elements. */ 164 @SuppressWarnings("unused") 165 private Map<String, Object> m_parameterMap; 166 167 /** The http request. */ 168 private HttpServletRequest m_req; 169 170 /** The http response. */ 171 private HttpServletResponse m_res; 172 173 /** The standard context bean. */ 174 private CmsJspStandardContextBean m_standardContext; 175 176 /** 177 * Creates a new instance.<p> 178 * Use this constructor to set the current container page state.<p> 179 * 180 * @param cms the cms context 181 * @param currentPageUri the current page uri 182 * @param containerPage the container page bean with the current container state 183 * @param detailContentId the detail content structure id 184 * @param req the http request 185 * @param res the http response 186 * @param isDragMode if the page is in drag mode 187 * @param locale the content locale 188 * 189 * @throws CmsException if something goes wrong 190 */ 191 public CmsElementUtil( 192 CmsObject cms, 193 String currentPageUri, 194 CmsContainerPageBean containerPage, 195 CmsUUID detailContentId, 196 HttpServletRequest req, 197 HttpServletResponse res, 198 boolean isDragMode, 199 Locale locale) 200 throws CmsException { 201 202 m_cms = OpenCms.initCmsObject(cms); 203 String contextPath = (String)cms.getRequestContext().getAttribute(CmsRequestContext.ATTRIBUTE_ADE_CONTEXT_PATH); 204 if (contextPath != null) { 205 m_cms.getRequestContext().setAttribute(CmsRequestContext.ATTRIBUTE_ADE_CONTEXT_PATH, contextPath); 206 } 207 m_req = req; 208 m_res = res; 209 m_currentPageUri = currentPageUri; 210 m_locale = locale; 211 // initializing request for standard context bean 212 req.setAttribute(CmsJspStandardContextBean.ATTRIBUTE_CMS_OBJECT, m_cms); 213 if (detailContentId != null) { 214 CmsResource detailRes = m_cms.readResource( 215 detailContentId, 216 CmsResourceFilter.ignoreExpirationOffline(m_cms)); 217 req.setAttribute(CmsDetailPageResourceHandler.ATTR_DETAIL_CONTENT_RESOURCE, detailRes); 218 } 219 m_standardContext = CmsJspStandardContextBean.getInstance(req); 220 m_page = m_cms.readResource(currentPageUri, CmsResourceFilter.ignoreExpirationOffline(cms)); 221 m_standardContext.setPage(containerPage); 222 m_standardContext.setDragMode(isDragMode); 223 } 224 225 /** 226 * Creates a new instance.<p> 227 * 228 * @param cms the cms context 229 * @param currentPageUri the current page uri 230 * @param detailContentId the detail content structure id 231 * @param req the http request 232 * @param res the http response 233 * @param locale the content locale 234 * 235 * @throws CmsException if something goes wrong 236 */ 237 public CmsElementUtil( 238 CmsObject cms, 239 String currentPageUri, 240 CmsUUID detailContentId, 241 HttpServletRequest req, 242 HttpServletResponse res, 243 Locale locale) 244 throws CmsException { 245 246 m_cms = OpenCms.initCmsObject(cms); 247 m_req = req; 248 m_res = res; 249 m_currentPageUri = currentPageUri; 250 m_locale = locale; 251 // initializing request for standard context bean 252 req.setAttribute(CmsJspStandardContextBean.ATTRIBUTE_CMS_OBJECT, m_cms); 253 if (detailContentId != null) { 254 CmsResource detailRes = m_cms.readResource(detailContentId, CmsResourceFilter.ignoreExpirationOffline(cms)); 255 req.setAttribute(CmsDetailPageResourceHandler.ATTR_DETAIL_CONTENT_RESOURCE, detailRes); 256 } 257 m_standardContext = CmsJspStandardContextBean.getInstance(req); 258 m_page = m_cms.readResource(currentPageUri); 259 CmsXmlContainerPage xmlContainerPage = CmsXmlContainerPageFactory.unmarshal(cms, m_page, req); 260 CmsContainerPageBean containerPage = xmlContainerPage.getContainerPage(cms); 261 m_standardContext.setPage(containerPage); 262 } 263 264 /** 265 * Creates a new instance.<p> 266 * 267 * @param cms the cms context 268 * @param currentPageUri the current page uri 269 * @param detailContentId the detail content structure id 270 * @param requestParameters the request parameters to use while rendering the elements 271 * @param req the http request 272 * @param res the http response 273 * @param locale the content locale 274 * 275 * @throws CmsException if something goes wrong 276 */ 277 public CmsElementUtil( 278 CmsObject cms, 279 String currentPageUri, 280 CmsUUID detailContentId, 281 String requestParameters, 282 HttpServletRequest req, 283 HttpServletResponse res, 284 Locale locale) 285 throws CmsException { 286 287 this(cms, currentPageUri, detailContentId, req, res, locale); 288 m_parameterMap = parseRequestParameters(requestParameters); 289 } 290 291 /** 292 * Checks if a group element is allowed in a container with a given type.<p> 293 * 294 * @param containerType the container type spec (comma separated) 295 * @param groupContainer the group 296 * 297 * @return true if the group is allowed in the container 298 */ 299 public static boolean checkGroupAllowed(String containerType, CmsGroupContainerBean groupContainer) { 300 301 return !Sets.intersection(CmsContainer.splitType(containerType), groupContainer.getTypes()).isEmpty(); 302 } 303 304 /** 305 * Converts a client container bean to a server container bean. 306 * 307 * @param container the client container 308 * @param elements the elements of the container 309 * @return the server container bean 310 */ 311 public static CmsContainerBean clientToServerContainer( 312 CmsContainer container, 313 List<CmsContainerElementBean> elements) { 314 315 return new CmsContainerBean( 316 container.getName(), 317 container.getType(), 318 container.getParentInstanceId(), 319 container.isRootContainer(), 320 container.getMaxElements(), 321 elements); 322 323 } 324 325 /** 326 * Helper method to create a string template source for a given formatter and content. 327 * 328 * @param formatter the formatter 329 * @param contentSupplier the content supplier 330 * 331 * @return the string template provider 332 */ 333 public static Function<String, String> createStringTemplateSource( 334 I_CmsFormatterBean formatter, 335 Supplier<CmsXmlContent> contentSupplier) { 336 337 return key -> { 338 String result = null; 339 if (formatter != null) { 340 result = formatter.getAttributes().get(key); 341 } 342 if (result == null) { 343 CmsXmlContent content = contentSupplier.get(); 344 if (content != null) { 345 result = content.getHandler().getParameter(key); 346 } 347 } 348 return result; 349 }; 350 } 351 352 /** 353 * Returns the formatter bean for the given element and container.<p> 354 * 355 * @param cms the cms context 356 * @param element the element to render 357 * @param container the container 358 * @param config the configuration data 359 * @param cache the session cache 360 * 361 * @return the formatter bean 362 */ 363 public static I_CmsFormatterBean getFormatterForContainer( 364 CmsObject cms, 365 CmsContainerElementBean element, 366 CmsContainer container, 367 CmsADEConfigData config, 368 CmsADESessionCache cache) { 369 370 I_CmsFormatterBean formatter = null; 371 CmsFormatterConfiguration formatterSet = config.getFormatters(cms, element.getResource()); 372 Map<String, I_CmsFormatterBean> formatters = formatterSet.getFormatterSelectionByKeyOrId( 373 container.getType(), 374 container.getWidth()); 375 String formatterId = element.getIndividualSettings().get( 376 CmsFormatterConfig.getSettingsKeyForContainer(container.getName())); 377 if (formatterId != null) { 378 I_CmsFormatterBean dynamicFmt = config.findFormatter(formatterId); 379 if (dynamicFmt != null) { 380 formatter = dynamicFmt; 381 } else { 382 formatter = formatters.get(formatterId); 383 } 384 } 385 if (formatter == null) { 386 formatterId = element.getIndividualSettings().get(CmsFormatterConfig.FORMATTER_SETTINGS_KEY); 387 if (formatterId != null) { 388 formatter = lookupFormatter(config, formatterId, formatters); 389 } 390 } 391 if (formatter == null) { 392 // check for formatter config id stored for other containers matching the current container 393 for (Entry<String, String> settingsEntry : element.getIndividualSettings().entrySet()) { 394 if (settingsEntry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) { 395 formatter = lookupFormatter(config, settingsEntry.getValue(), formatters); 396 if (formatter != null) { 397 break; 398 } 399 } 400 } 401 } 402 if ((formatter == null) && (element.getFormatterId() != null)) { 403 for (I_CmsFormatterBean currentFormatter : formatters.values()) { 404 if ((currentFormatter.getJspStructureId() != null) 405 && currentFormatter.getJspStructureId().equals(element.getFormatterId())) { 406 formatter = currentFormatter; 407 break; 408 } 409 } 410 } 411 if (formatter == null) { 412 formatter = getStartFormatter(cms, container, config, element, cache); 413 } 414 return formatter; 415 } 416 417 /** 418 * Gets the ids for the current page and potentially detail-only containers. 419 * @param cms the CMS context 420 * @param pageId the id for the current page 421 * @param detailContent the current detail content 422 * @return the set of ids for the current page and detail-only containers 423 */ 424 public static Set<CmsUUID> getPageAndDetailOnlyIds(CmsObject cms, CmsUUID pageId, CmsResource detailContent) { 425 426 Set<CmsUUID> result = new HashSet<>(); 427 result.add(pageId); 428 if (detailContent != null) { 429 for (CmsResource detailOnlyRes : CmsDetailOnlyContainerUtil.getDetailOnlyResources(cms, detailContent)) { 430 result.add(detailOnlyRes.getStructureId()); 431 } 432 } 433 return result; 434 } 435 436 /** 437 * Checks if the given setting name is a system setting. 438 * 439 * @param name the setting name 440 * @return true if the name corresponds to a system setting 441 */ 442 public static final boolean isSystemSetting(String name) { 443 444 if (CmsXmlContainerPage.LEGACY_SYSTEM_SETTING_NAMES.contains(name) 445 || CmsContainerElement.ELEMENT_INSTANCE_ID.equals(name) 446 || name.startsWith(CmsXmlContainerPage.SYSTEM_SETTING_PREFIX) 447 || name.startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) { 448 return true; 449 } 450 return false; 451 } 452 453 /** 454 * Returns the start formatter for a newly dropped element.<p> 455 * This will be either the least recently used matching formatter or the default formatter.<p> 456 * 457 * @param cms the cms context 458 * @param cnt the container 459 * @param configData the configuration data 460 * @param element the container element 461 * @param cache the session cache 462 * 463 * @return the formatter bean 464 */ 465 private static I_CmsFormatterBean getStartFormatter( 466 CmsObject cms, 467 CmsContainer cnt, 468 CmsADEConfigData configData, 469 CmsContainerElementBean element, 470 CmsADESessionCache cache) { 471 472 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource()); 473 I_CmsFormatterBean formatter = cache.getRecentFormatter(type.getTypeName(), cnt, configData); 474 if (formatter == null) { 475 formatter = configData.getFormatters(cms, element.getResource()).getDefaultFormatter( 476 cnt.getType(), 477 cnt.getWidth()); 478 } 479 return formatter; 480 } 481 482 /** 483 * Helper method for looking up the correct formatter for an element. 484 * 485 * @param config the sitemap config 486 * @param keyOrId the key or id of the formatter stored with the container element 487 * @param active map of active formatters by key or id 488 * 489 * @return the formatter with the given key or id 490 */ 491 private static I_CmsFormatterBean lookupFormatter( 492 CmsADEConfigData config, 493 String keyOrId, 494 Map<String, I_CmsFormatterBean> active) { 495 496 I_CmsFormatterBean dynamicFmt = config.findFormatter(keyOrId); 497 if (dynamicFmt != null) { 498 for (String key : new String[] {dynamicFmt.getKey(), dynamicFmt.getId(), keyOrId}) { 499 if ((key != null) && (active.get(key) != null)) { 500 return active.get(key); 501 } 502 } 503 return null; 504 } else { 505 // schema formatters 506 return active.get(keyOrId); 507 } 508 } 509 510 /** 511 * Returns the HTML content for the given resource and container.<p> 512 * 513 * @param elementFile the element resource file 514 * @param elementId the element id 515 * @param container the container 516 * 517 * @return the HTML content 518 */ 519 public String getContentByContainer(CmsFile elementFile, String elementId, CmsContainer container) { 520 521 CmsContainerElementBean element = CmsADESessionCache.getCache(m_req, m_cms).getCacheContainerElement(elementId); 522 element = element.clone(); 523 element.setTemporaryFile(elementFile); 524 CmsFormatterConfiguration configs = getFormatterConfiguration(element.getResource()); 525 return getContentByContainer(element, container, configs); 526 } 527 528 /** 529 * Returns the data for an element.<p> 530 * 531 * @param page the current container page 532 * @param element the resource 533 * @param containers the containers on the current container page 534 * 535 * @return the data for an element 536 * 537 * @throws CmsException if something goes wrong 538 */ 539 public CmsContainerElementData getElementData( 540 CmsResource page, 541 CmsContainerElementBean element, 542 Collection<CmsContainer> containers) 543 throws CmsException { 544 545 Locale requestLocale = m_cms.getRequestContext().getLocale(); 546 m_cms.getRequestContext().setLocale(m_locale); 547 element.initResource(m_cms); 548 if (element.getResource().isFolder()) { 549 return null; 550 } 551 boolean typeDisabled = false; 552 boolean createDisabled = false; 553 if (page != null) { 554 555 CmsADEConfigData config = OpenCms.getADEManager().lookupConfigurationWithCache(m_cms, page.getRootPath()); 556 String typeName = OpenCms.getResourceManager().getResourceType(element.getResource()).getTypeName(); 557 if (!config.getAddableTypeNames().contains(typeName)) { 558 typeDisabled = true; 559 } 560 CmsResourceTypeConfig typeConfig = config.getTypesByName().get(typeName); 561 if ((typeConfig == null) || typeConfig.isCreateDisabled()) { 562 createDisabled = true; 563 } 564 } 565 566 CmsContainerElementData elementData = getBaseElementData(page, element); 567 elementData.setAddDisabled(typeDisabled); 568 elementData.setCopyDisabled(createDisabled); 569 CmsFormatterConfiguration formatterConfiguraton = getFormatterConfiguration(element.getResource()); 570 Map<String, String> contents = new HashMap<String, String>(); 571 if (element.isGroupContainer(m_cms)) { 572 Map<String, CmsContainer> containersByName = new HashMap<String, CmsContainer>(); 573 for (CmsContainer container : containers) { 574 containersByName.put(container.getName(), container); 575 } 576 CmsXmlGroupContainer xmlGroupContainer = CmsXmlGroupContainerFactory.unmarshal( 577 m_cms, 578 element.getResource(), 579 m_req); 580 CmsGroupContainerBean groupContainer = xmlGroupContainer.getGroupContainer(m_cms); 581 // make sure to use the content title and not the property title 582 elementData.setTitle(groupContainer.getTitle()); 583 elementData.setTypes(groupContainer.getTypes()); 584 elementData.setDescription(groupContainer.getDescription()); 585 if (groupContainer.getTypes().isEmpty()) { 586 if (groupContainer.getElements().isEmpty()) { 587 String emptySub = "<div>NEW AND EMPTY</div>"; 588 for (CmsContainer cont : containersByName.values()) { 589 if (formatterConfiguraton.hasFormatter(cont.getType(), cont.getWidth())) { 590 contents.put(cont.getName(), emptySub); 591 } 592 } 593 } else { 594 // TODO: throw appropriate exception 595 return null; 596 } 597 } else { 598 599 // add formatter and content entries for the supported types 600 for (CmsContainer cnt : containersByName.values()) { 601 602 String type = cnt.getType(); 603 if (checkGroupAllowed(type, groupContainer)) { 604 contents.put(cnt.getName(), "<div>should not be used</div>"); 605 } 606 } 607 } 608 // add subitems 609 List<String> subItems = new ArrayList<String>(); 610 611 for (CmsContainerElementBean subElement : groupContainer.getElements()) { 612 // collect ids 613 subItems.add(subElement.editorHash()); 614 } 615 elementData.setSubItems(subItems); 616 } else if (element.isInheritedContainer(m_cms)) { 617 CmsInheritanceReferenceParser parser = new CmsInheritanceReferenceParser(m_cms); 618 parser.parse(element.getResource()); 619 CmsInheritanceReference ref = parser.getReference(m_locale); 620 String name = null; 621 // check for new inheritance reference 622 if (ref != null) { 623 name = ref.getName(); 624 elementData.setDescription(ref.getDescription()); 625 elementData.setTitle(ref.getTitle()); 626 } 627 for (CmsContainer container : containers) { 628 if (formatterConfiguraton.hasFormatter(container.getType(), container.getWidth())) { 629 contents.put(container.getName(), "<div>should not be used</div>"); 630 } 631 } 632 633 List<CmsInheritanceInfo> inheritanceInfos = new ArrayList<CmsInheritanceInfo>(); 634 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(name)) { 635 CmsInheritedContainerState result = OpenCms.getADEManager().getInheritedContainerState( 636 m_cms, 637 m_cms.addSiteRoot(m_currentPageUri), 638 name); 639 for (CmsContainerElementBean subElement : result.getElements(true)) { 640 CmsInheritanceInfo inheritanceInfo = subElement.getInheritanceInfo(); 641 inheritanceInfo.setClientId(subElement.editorHash()); 642 inheritanceInfos.add(inheritanceInfo); 643 } 644 } else { 645 // setting a new id for name, will be persisted once the inheritance reference is edited and saved. 646 // use the structure id so it will always be the same for the resource 647 name = element.getResource().getStructureId().toString(); 648 } 649 elementData.setInheritanceInfos(inheritanceInfos); 650 elementData.setInheritanceName(name); 651 } else { 652 for (CmsContainer cnt : containers) { 653 boolean missesFormatterSetting = !elementData.getSettings().containsKey( 654 CmsFormatterConfig.getSettingsKeyForContainer(cnt.getName())); 655 if (missesFormatterSetting) { 656 if (element.getFormatterId() == null) { 657 I_CmsFormatterBean formatter = getStartFormatter( 658 m_cms, 659 cnt, 660 m_adeConfig, 661 element, 662 CmsADESessionCache.getCache(m_req, m_cms)); 663 if (formatter != null) { 664 elementData.getSettings().put( 665 CmsFormatterConfig.getSettingsKeyForContainer(cnt.getName()), 666 formatter.getId()); 667 element.addFormatterSetting(cnt.getName(), formatter.getKeyOrId()); 668 } 669 } else { 670 Map<String, I_CmsFormatterBean> formatterSelection = formatterConfiguraton.getFormatterSelection( 671 cnt.getType(), 672 cnt.getWidth()); 673 for (Entry<String, I_CmsFormatterBean> formatterEntry : formatterSelection.entrySet()) { 674 I_CmsFormatterBean formatter = formatterEntry.getValue(); 675 if (element.getFormatterId().equals(formatter.getJspStructureId())) { 676 elementData.getSettings().put( 677 CmsFormatterConfig.getSettingsKeyForContainer(cnt.getName()), 678 formatter.getKeyOrId()); 679 break; 680 } 681 } 682 } 683 } 684 } 685 // get the formatter configuration 686 Map<String, String> contentsByName = getContentsByContainerName(element, containers); 687 contents = contentsByName; 688 } 689 CmsListInfoBean listInfo = CmsVfsService.getPageInfo(m_cms, element.getResource()); 690 elementData.setListInfo(listInfo); 691 elementData.setContents(contents); 692 m_cms.getRequestContext().setLocale(requestLocale); 693 return elementData; 694 } 695 696 /** 697 * Returns the formatter and settings config data for an element.<p> 698 * 699 * @param page the current container page 700 * @param element the resource 701 * @param containerId the parent container id 702 * @param containers the containers on the current container page 703 * 704 * @return the data for an element 705 * 706 * @throws CmsException if something goes wrong 707 */ 708 public CmsElementSettingsConfig getElementSettingsConfig( 709 CmsResource page, 710 CmsContainerElementBean element, 711 String containerId, 712 Collection<CmsContainer> containers) 713 throws CmsException { 714 715 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms); 716 CmsADEConfigData adeConfig = OpenCms.getADEManager().lookupConfigurationWithCache(m_cms, page.getRootPath()); 717 boolean isCopyGroup = CmsResourceTypeXmlContainerPage.isModelCopyGroup(m_cms, page); 718 Locale requestLocale = m_cms.getRequestContext().getLocale(); 719 m_cms.getRequestContext().setLocale(m_locale); 720 element.initResource(m_cms); 721 if (element.getResource().isFolder()) { 722 return null; 723 } 724 String schema = null; 725 try { 726 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource()); 727 schema = type.getConfiguration().getString("schema", null); 728 } catch (Exception e) { 729 LOG.error(e.getLocalizedMessage(), e); 730 } 731 CmsContainerElementData elementData = getBaseElementData(page, element); 732 733 Map<String, String> settingUpdates = new HashMap<>(); 734 for (Map.Entry<String, String> entry : elementData.getSettings().entrySet()) { 735 int underscorePos = entry.getKey().indexOf("_"); 736 if ((underscorePos >= 0) && !isSystemSetting(entry.getKey())) { 737 String prefix = entry.getKey().substring(0, underscorePos); 738 I_CmsFormatterBean dynamicFmt = adeConfig.findFormatter(prefix, true); 739 740 if (CmsUUID.isValidUUID(prefix)) { 741 // If we already have a formatter referenced by name, we don't need to do anything 742 if ((dynamicFmt != null) && (dynamicFmt.getKey() != null)) { 743 // Replace setting prefix with formatter key 744 String newSettingName = dynamicFmt.getKey() + entry.getKey().substring(underscorePos); 745 settingUpdates.put(newSettingName, entry.getValue()); 746 settingUpdates.put(entry.getKey(), null); 747 } 748 } 749 } 750 751 if (entry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) { 752 String value = entry.getValue(); 753 if (CmsUUID.isValidUUID(value)) { 754 I_CmsFormatterBean dynamicFmt = adeConfig.findFormatter(value); 755 if ((dynamicFmt != null) && (dynamicFmt.getKey() != null)) { 756 settingUpdates.put(entry.getKey(), dynamicFmt.getKey()); 757 } 758 } 759 } 760 } 761 for (String key : settingUpdates.keySet()) { 762 String value = settingUpdates.get(key); 763 if (value == null) { 764 elementData.getSettings().remove(key); 765 } else { 766 elementData.getSettings().put(key, value); 767 } 768 } 769 Supplier<CmsXmlContent> contentSupplier = Suppliers.memoize(() -> { 770 try { 771 return CmsXmlContentFactory.unmarshal(m_cms, m_cms.readFile(element.getResource())); 772 } catch (CmsException e) { 773 LOG.error(e.getLocalizedMessage(), e); 774 return null; 775 } 776 }); 777 I_CmsFormatterBean foundFormatter = null; 778 779 if (!element.isGroupContainer(m_cms) && !element.isInheritedContainer(m_cms)) { 780 CmsFormatterConfiguration formatterConfiguraton = getFormatterConfiguration(element.getResource()); 781 Map<String, CmsFormatterConfigCollection> formatters = new HashMap<String, CmsFormatterConfigCollection>(); 782 for (CmsContainer cnt : containers) { 783 if (cnt.getName().equals(containerId)) { 784 CmsFormatterConfigCollection containerFormatters = new CmsFormatterConfigCollection(); 785 String foundFormatterKey = null; 786 for (String containerName : new String[] {cnt.getName(), ""}) { 787 foundFormatterKey = elementData.getSettings().get( 788 CmsFormatterConfig.getSettingsKeyForContainer(containerName)); 789 if (foundFormatterKey != null) { 790 break; 791 } 792 } 793 boolean missesFormatterSetting = (foundFormatterKey == null); 794 if (!missesFormatterSetting) { 795 foundFormatter = adeConfig.findFormatter(foundFormatterKey); 796 } 797 Map<String, I_CmsFormatterBean> formatterSelection = formatterConfiguraton.getFormatterSelection( 798 cnt.getType(), 799 cnt.getWidth()); 800 for (Entry<String, I_CmsFormatterBean> formatterEntry : formatterSelection.entrySet()) { 801 I_CmsFormatterBean formatter = formatterEntry.getValue(); 802 String id = formatterEntry.getValue().getId(); 803 if (missesFormatterSetting 804 && ((element.getFormatterId() == null) 805 || element.getFormatterId().equals(formatter.getJspStructureId()))) { 806 elementData.getSettings().put( 807 CmsFormatterConfig.getSettingsKeyForContainer(cnt.getName()), 808 id); 809 missesFormatterSetting = false; 810 } 811 String label = formatter.getNiceName(OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms)); 812 if (formatterEntry.getKey().startsWith(CmsFormatterConfig.SCHEMA_FORMATTER_ID)) { 813 label = Messages.get().getBundle().key(Messages.GUI_SCHEMA_FORMATTER_LABEL_0) 814 + " [" 815 + CmsResource.getName(formatter.getJspRootPath()) 816 + "]"; 817 } 818 if (CmsStringUtil.isEmptyOrWhitespaceOnly(label)) { 819 label = id; 820 } 821 CmsFormatterConfig config = new CmsFormatterConfig(id); 822 Set<String> cssResources = new LinkedHashSet<String>(); 823 for (String cssSitePath : formatter.getCssHeadIncludes()) { 824 cssResources.add(OpenCms.getLinkManager().getOnlineLink(m_cms, cssSitePath)); 825 } 826 config.setCssResources(cssResources); 827 config.setInlineCss(formatter.getInlineCss()); 828 config.setKey(formatter.getKey()); 829 config.setLabel(label); 830 config.setDescription( 831 formatter.getDescription(OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms))); 832 Map<String, CmsXmlContentProperty> settingsConfig = OpenCms.getADEManager().getFormatterSettings( 833 m_cms, 834 adeConfig, 835 formatter, 836 element.getResource(), 837 m_locale, 838 m_req); 839 Function<String, String> templateSource = createStringTemplateSource( 840 formatter, 841 contentSupplier); 842 settingsConfig = CmsXmlContentPropertyHelper.resolveMacrosForPropertyInfo( 843 m_cms, 844 page, 845 element.getResource(), 846 contentSupplier, 847 templateSource, 848 settingsConfig); 849 config.setSettingConfig(settingsConfig); 850 List<I_CmsFormatterBean> nestedFormatters = OpenCms.getADEManager().getNestedFormatters( 851 m_cms, 852 adeConfig, 853 element.getResource(), 854 m_locale, 855 m_req); 856 if ((nestedFormatters != null) && !nestedFormatters.isEmpty()) { 857 Map<String, String> settingPrefixes = new LinkedHashMap<String, String>(); 858 for (I_CmsFormatterBean nested : nestedFormatters) { 859 String sectionLabel = nested.getNiceName( 860 OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms)); 861 settingPrefixes.put(nested.getId(), sectionLabel); 862 if (nested.getKey() != null) { 863 settingPrefixes.put(nested.getKey() + "_", sectionLabel); 864 } 865 } 866 config.setNestedFormatterPrefixes(settingPrefixes); 867 } 868 869 config.setJspRootPath(formatter.getJspRootPath()); 870 containerFormatters.add(config); 871 } 872 formatters.put(cnt.getName(), containerFormatters); 873 } 874 } 875 elementData.setFormatters(formatters); 876 } 877 878 m_cms.getRequestContext().setLocale(requestLocale); 879 ArrayList<CmsAdditionalInfoBean> infos = new ArrayList<>(); 880 881 CmsResource resource = element.getResource(); 882 String resTypeName = OpenCms.getResourceManager().getResourceType(resource).getTypeName(); 883 CmsExplorerTypeSettings cmsExplorerTypeSettings = OpenCms.getWorkplaceManager().getExplorerTypeSetting( 884 resTypeName); 885 if (null == cmsExplorerTypeSettings) { 886 CmsMessageContainer errMsg = org.opencms.gwt.Messages.get().container( 887 org.opencms.gwt.Messages.ERR_EXPLORER_TYPE_SETTINGS_FOR_RESOURCE_TYPE_NOT_FOUND_3, 888 resource.getRootPath(), 889 resTypeName, 890 Integer.valueOf(resource.getTypeId())); 891 throw new CmsConfigurationException(errMsg); 892 } 893 String key = cmsExplorerTypeSettings.getKey(); 894 Locale currentLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms); 895 CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(currentLocale); 896 String resTypeNiceName = messages.key(key); 897 infos.add( 898 new CmsAdditionalInfoBean( 899 messages.key(org.opencms.workplace.commons.Messages.GUI_LABEL_TYPE_0), 900 resTypeNiceName, 901 null)); 902 903 try { 904 CmsRelationFilter filter = CmsRelationFilter.relationsFromStructureId( 905 element.getResource().getStructureId()).filterType(CmsRelationType.XSD); 906 for (CmsRelation relation : m_cms.readRelations(filter)) { 907 CmsResource target = relation.getTarget(m_cms, CmsResourceFilter.IGNORE_EXPIRATION); 908 String label = Messages.get().getBundle(wpLocale).key(Messages.GUI_ADDINFO_SCHEMA_0); 909 infos.add(new CmsAdditionalInfoBean(label, target.getRootPath(), null)); 910 break; 911 } 912 } catch (CmsException e) { 913 LOG.error(e.getLocalizedMessage(), e); 914 } 915 if (foundFormatter != null) { 916 Map<String, String> formatterInfo = CmsDefaultResourceStatusProvider.getFormatterInfo( 917 m_cms, 918 foundFormatter); 919 for (Map.Entry<String, String> entry : formatterInfo.entrySet()) { 920 infos.add(new CmsAdditionalInfoBean(entry.getKey(), entry.getValue(), null)); 921 } 922 } 923 924 CmsResourceState state = element.getResource().getState(); 925 return new CmsElementSettingsConfig(elementData, state, infos, schema, isCopyGroup); 926 } 927 928 /** 929 * Gets the container page.<p> 930 * 931 * @return the container page resource 932 */ 933 public CmsResource getPage() { 934 935 return m_page; 936 } 937 938 /** 939 * Sets the data to the given container element.<p> 940 * 941 * @param elementBean the element bean 942 * @param result the container element to set the data to 943 * 944 * @return the container element 945 * 946 * @throws CmsException if something goes wrong 947 */ 948 public CmsContainerElement setElementInfo(CmsContainerElementBean elementBean, CmsContainerElement result) 949 throws CmsException { 950 951 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms); 952 // reinitializing resource to avoid caching issues 953 elementBean.initResource(m_cms); 954 CmsResource resource = elementBean.getResource(); 955 boolean isModelGroup = elementBean.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_ID); 956 if (isModelGroup) { 957 CmsUUID groupId = new CmsUUID(elementBean.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_ID)); 958 resource = m_cms.readResource(groupId, CmsResourceFilter.IGNORE_EXPIRATION); 959 } 960 961 boolean newEditorDisabled = !CmsWorkplaceEditorManager.checkAcaciaEditorAvailable( 962 m_cms, 963 elementBean.getResource()); 964 result.setNewEditorDisabled(newEditorDisabled); 965 I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(resource); 966 String typeName = resourceType.getTypeName(); 967 result.setHasEditHandler( 968 (resourceType instanceof CmsResourceTypeXmlContent) 969 && (((CmsResourceTypeXmlContent)resourceType).getEditHandler(m_cms) != null)); 970 result.setResourceType(typeName); 971 result.setIconClasses( 972 CmsIconUtil.getIconClasses( 973 CmsIconUtil.getDisplayType(m_cms, resource), 974 elementBean.getResource().getName(), 975 false)); 976 CmsPermissionInfo permissionInfo; 977 String title; 978 String subTitle; 979 if (!elementBean.isInMemoryOnly()) { 980 CmsElementLockInfo lockInfo = getLockInfo(m_cms, resource); 981 result.setLockInfo(lockInfo); 982 permissionInfo = OpenCms.getADEManager().getPermissionInfo(m_cms, resource, m_page.getRootPath()); 983 if (CmsResourceTypeXmlContent.isXmlContent(resource)) { 984 if (CmsStringUtil.isEmptyOrWhitespaceOnly(permissionInfo.getNoEditReason()) 985 && elementBean.isInheritedContainer(m_cms)) { 986 String requestUri = m_cms.getRequestContext().getUri(); 987 String folderPath = CmsResource.getFolderPath(requestUri); 988 String configPath = CmsStringUtil.joinPaths( 989 folderPath, 990 CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME); 991 if (m_cms.existsResource(configPath)) { 992 permissionInfo.setNoEditReason( 993 new CmsResourceUtil(m_cms, m_cms.readResource(configPath)).getNoEditReason(wpLocale, true)); 994 } else { 995 if (!m_cms.getLock(folderPath).isLockableBy(m_cms.getRequestContext().getCurrentUser())) { 996 permissionInfo.setNoEditReason( 997 org.opencms.workplace.explorer.Messages.get().getBundle(wpLocale).key( 998 org.opencms.workplace.explorer.Messages.GUI_NO_EDIT_REASON_LOCK_1, 999 new CmsResourceUtil(m_cms, m_cms.readResource(folderPath)).getLockedByName())); 1000 } 1001 } 1002 } 1003 } else { 1004 permissionInfo.setNoEditReason( 1005 Messages.get().getBundle(wpLocale).key(Messages.GUI_ELEMENT_RESOURCE_CAN_NOT_BE_EDITED_0)); 1006 } 1007 CmsGallerySearchResult searchResult = CmsGallerySearch.searchById( 1008 m_cms, 1009 resource.getStructureId(), 1010 m_locale); 1011 title = searchResult.getTitle(); 1012 if (CmsStringUtil.isEmptyOrWhitespaceOnly(title)) { 1013 resource.getName(); 1014 } 1015 subTitle = searchResult.getUserLastModified(); 1016 Date lastModDate = searchResult.getDateLastModified(); 1017 if (lastModDate != null) { 1018 subTitle += " / " + CmsDateUtil.getDateTime(lastModDate, DateFormat.MEDIUM, wpLocale); 1019 } 1020 } else { 1021 permissionInfo = new CmsPermissionInfo(true, true, ""); 1022 title = CmsWorkplaceMessages.getResourceTypeName(wpLocale, typeName); 1023 subTitle = CmsWorkplaceMessages.getResourceTypeDescription(wpLocale, typeName); 1024 } 1025 result.setTitle(title); 1026 result.setSubTitle(subTitle); 1027 result.setClientId(elementBean.editorHash()); 1028 result.setSitePath(m_cms.getSitePath(resource)); 1029 1030 result.setCreateNew(elementBean.isCreateNew()); 1031 CmsResourceTypeConfig typeConfig = getConfigData().getResourceType(typeName); 1032 if (!elementBean.isInMemoryOnly() && (typeConfig != null)) { 1033 result.setCopyInModels(typeConfig.isCopyInModels()); 1034 if (typeConfig.isCheckReuse()) { 1035 final Set<CmsUUID> pageAndAttachments = getPageAndDetailOnlyIds(); 1036 boolean reused = OpenCms.getADEManager().isElementReused( 1037 resource, 1038 res -> pageAndAttachments.contains(res.getStructureId())); 1039 result.setReused(reused); 1040 } 1041 } 1042 1043 Map<CmsUUID, CmsElementView> viewMap = OpenCms.getADEManager().getElementViews(m_cms); 1044 1045 boolean isModelGroupEditing = CmsModelGroupHelper.isModelGroupResource(m_page); 1046 if (!isModelGroup 1047 && isModelGroupEditing 1048 && elementBean.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_STATE) 1049 && (ModelGroupState.isModelGroup == ModelGroupState.evaluate( 1050 elementBean.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_STATE)))) { 1051 isModelGroup = true; 1052 } 1053 if (!isModelGroupEditing && isModelGroup) { 1054 CmsResourceTypeConfig modelGroupConfig = getConfigData().getResourceType( 1055 CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME); 1056 if (modelGroupConfig != null) { 1057 CmsUUID elementView = modelGroupConfig.getElementView(); 1058 CmsElementView viewObject = viewMap.get(elementView); 1059 if ((viewObject != null) && (viewObject.getParentViewId() != null)) { 1060 elementView = viewObject.getParentViewId(); 1061 } 1062 result.setElementView(elementView); 1063 } 1064 } else if (typeConfig != null) { 1065 CmsUUID elementView = typeConfig.getElementView(); 1066 CmsElementView viewObject = viewMap.get(elementView); 1067 if ((viewObject != null) && (viewObject.getParentViewId() != null)) { 1068 elementView = viewObject.getParentViewId(); 1069 } 1070 result.setElementView(elementView); 1071 } 1072 if (CmsStringUtil.isEmptyOrWhitespaceOnly(permissionInfo.getNoEditReason()) 1073 && ((typeConfig == null) || typeConfig.isEditDisabled())) { 1074 String message = Messages.get().getBundle(wpLocale).key( 1075 Messages.GUI_CONTAINERPAGE_EDIT_DISABLED_BY_SITEMAP_CONFIG_0); 1076 permissionInfo.setNoEditReason(message); 1077 } 1078 result.setHasSettings(hasSettings(m_cms, elementBean.getResource())); 1079 result.setPermissionInfo(permissionInfo); 1080 result.setReleasedAndNotExpired(elementBean.isReleasedAndNotExpired()); 1081 if (elementBean.isModelGroup()) { 1082 String modelId = elementBean.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_ID); 1083 result.setModelGroupId(modelId != null ? new CmsUUID(modelId) : CmsUUID.getNullUUID()); 1084 } 1085 result.setWasModelGroup( 1086 elementBean.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_STATE) 1087 && (ModelGroupState.evaluate( 1088 elementBean.getIndividualSettings().get( 1089 CmsContainerElement.MODEL_GROUP_STATE)) == ModelGroupState.wasModelGroup)); 1090 return result; 1091 } 1092 1093 /** 1094 * Returns the formatter configuration for the given element resource.<p> 1095 * 1096 * @param resource the element resource 1097 * 1098 * @return the formatter configuration 1099 */ 1100 CmsFormatterConfiguration getFormatterConfiguration(CmsResource resource) { 1101 1102 return getConfigData().getFormatters(m_cms, resource); 1103 } 1104 1105 /** 1106 * Returns the base element data for the given element bean, without content or formatter info.<p> 1107 * 1108 * @param page the current container page 1109 * @param element the resource 1110 * 1111 * @return base element data 1112 * 1113 * @throws CmsException in case reading the data fails 1114 */ 1115 private CmsContainerElementData getBaseElementData(CmsResource page, CmsContainerElementBean element) 1116 throws CmsException { 1117 1118 CmsResourceUtil resUtil = new CmsResourceUtil(m_cms, element.getResource()); 1119 CmsContainerElementData elementData = new CmsContainerElementData(); 1120 setElementInfo(element, elementData); 1121 elementData.setLoadTime(System.currentTimeMillis()); 1122 elementData.setLastModifiedDate(element.getResource().getDateLastModified()); 1123 String userName = null; 1124 try { 1125 CmsUser user = m_cms.readUser(element.getResource().getUserLastModified()); 1126 userName = user.getName(); 1127 } catch (CmsException e) { 1128 userName = "" + element.getResource().getUserLastModified(); 1129 LOG.debug(e.getLocalizedMessage(), e); 1130 } 1131 elementData.setLastModifiedByUser(userName); 1132 elementData.setNavText(resUtil.getNavText()); 1133 Map<String, CmsXmlContentProperty> settingConfig = CmsXmlContentPropertyHelper.getPropertyInfo( 1134 m_cms, 1135 page, 1136 element.getResource()); 1137 elementData.setSettings( 1138 CmsXmlContentPropertyHelper.convertPropertiesToClientFormat( 1139 m_cms, 1140 element.getIndividualSettings(), 1141 settingConfig)); 1142 return elementData; 1143 } 1144 1145 /** 1146 * Returns the ADE configuration data for the current URI.<p> 1147 * 1148 * @return the ADE configuration data 1149 */ 1150 private CmsADEConfigData getConfigData() { 1151 1152 if (m_adeConfig == null) { 1153 m_adeConfig = OpenCms.getADEManager().lookupConfigurationWithCache( 1154 m_cms, 1155 m_cms.addSiteRoot(m_currentPageUri)); 1156 } 1157 return m_adeConfig; 1158 } 1159 1160 /** 1161 * Returns the HTML content of the given element and container.<p> 1162 * 1163 * @param element the element 1164 * @param container the container 1165 * @param configs the formatter configurations 1166 * 1167 * @return the HTML content 1168 */ 1169 private String getContentByContainer( 1170 CmsContainerElementBean element, 1171 CmsContainer container, 1172 CmsFormatterConfiguration configs) { 1173 1174 String content = null; 1175 1176 I_CmsFormatterBean formatter = getFormatterForContainer( 1177 m_cms, 1178 element, 1179 container, 1180 m_adeConfig, 1181 CmsADESessionCache.getCache(m_req, m_cms)); 1182 if (formatter != null) { 1183 element = element.clone(); // clone element because presets for different containers may be different 1184 element.initSettings(m_cms, m_adeConfig, formatter, m_locale, m_req, container.getSettingPresets()); 1185 try { 1186 content = getElementContent(element, m_cms.readResource(formatter.getJspStructureId()), container); 1187 // } 1188 } catch (Exception e) { 1189 LOG.error(e.getLocalizedMessage(), e); 1190 } 1191 if (content != null) { 1192 content = removeScriptTags(content); 1193 } 1194 } 1195 return content; 1196 } 1197 1198 /** 1199 * Returns the rendered element content for all the given containers. 1200 * 1201 * @param element the element to render 1202 * @param containers the containers the element appears in 1203 * 1204 * @return a map from container names to rendered page contents 1205 */ 1206 private Map<String, String> getContentsByContainerName( 1207 CmsContainerElementBean element, 1208 Collection<CmsContainer> containers) { 1209 1210 CmsFormatterConfiguration configs = getFormatterConfiguration(element.getResource()); 1211 Map<String, String> result = new HashMap<String, String>(); 1212 for (CmsContainer container : containers) { 1213 String content = getContentByContainer(element, container, configs); 1214 if (content != null) { 1215 content = removeScriptTags(content); 1216 } 1217 result.put(container.getName(), content); 1218 } 1219 return result; 1220 } 1221 1222 /** 1223 * Returns the content of an element when rendered with the given formatter.<p> 1224 * 1225 * @param element the element bean 1226 * @param formatter the formatter uri 1227 * @param container the container for which the element content should be retrieved 1228 * 1229 * @return generated html code 1230 * 1231 * @throws CmsException if an cms related error occurs 1232 * @throws ServletException if a jsp related error occurs 1233 * 1234 * @throws IOException if a jsp related error occurs 1235 */ 1236 private String getElementContent(CmsContainerElementBean element, CmsResource formatter, CmsContainer container) 1237 throws CmsException, ServletException, IOException { 1238 1239 element.initResource(m_cms); 1240 TemplateBean templateBean = CmsADESessionCache.getCache(m_req, m_cms).getTemplateBean( 1241 m_cms.addSiteRoot(m_currentPageUri), 1242 true); 1243 String oldUri = m_cms.getRequestContext().getUri(); 1244 try { 1245 m_cms.getRequestContext().setUri(m_currentPageUri); 1246 CmsContainerBean containerBean = null; 1247 if ((m_standardContext.getPage() != null) 1248 && m_standardContext.getPage().getContainers().containsKey(container.getName())) { 1249 containerBean = m_standardContext.getPage().getContainers().get(container.getName()); 1250 } else { 1251 containerBean = CmsElementUtil.clientToServerContainer( 1252 container, 1253 Collections.<CmsContainerElementBean> emptyList()); 1254 } 1255 if (containerBean.getWidth() == null) { 1256 containerBean.setWidth(String.valueOf(container.getWidth())); 1257 } 1258 containerBean.setDetailOnly(container.isDetailOnly()); 1259 m_standardContext.setContainer(containerBean); 1260 m_standardContext.setElement(element); 1261 m_standardContext.setEdited(true); 1262 // to enable 'old' direct edit features for content-collector-elements, 1263 // set the direct-edit-provider-attribute in the request 1264 I_CmsDirectEditProvider eb = new CmsAdvancedDirectEditProvider(); 1265 eb.init(m_cms, CmsDirectEditMode.TRUE, element.getSitePath()); 1266 m_req.setAttribute(I_CmsDirectEditProvider.ATTRIBUTE_DIRECT_EDIT_PROVIDER, eb); 1267 m_req.setAttribute(CmsTemplateContextManager.ATTR_TEMPLATE_BEAN, templateBean); 1268 String encoding = m_res.getCharacterEncoding(); 1269 return (new String( 1270 OpenCms.getResourceManager().getLoader(formatter).dump(m_cms, formatter, null, m_locale, m_req, m_res), 1271 encoding)).trim(); 1272 } finally { 1273 m_cms.getRequestContext().setUri(oldUri); 1274 } 1275 } 1276 1277 /** 1278 * Gets the lock information. 1279 * 1280 * @param cms the current CMS context 1281 * @param resource the resource for which to get lock information 1282 * @return the lock information 1283 */ 1284 private CmsElementLockInfo getLockInfo(CmsObject cms, CmsResource resource) { 1285 1286 try { 1287 CmsLock lock = cms.getLock(resource); 1288 CmsUUID owner = lock.getUserId(); 1289 boolean isPublish = lock.isPublish(); 1290 return new CmsElementLockInfo(owner, isPublish); 1291 } catch (Exception e) { 1292 LOG.error(e.getLocalizedMessage(), e); 1293 return new CmsElementLockInfo(null, false); 1294 } 1295 } 1296 1297 /** 1298 * Gets the ids for the current page and potentially detail-only containers. 1299 * 1300 * @return the set of ids for the current page and detail-only containers 1301 */ 1302 private Set<CmsUUID> getPageAndDetailOnlyIds() { 1303 1304 Set<CmsUUID> result = new HashSet<>(); 1305 result.add(m_page.getStructureId()); 1306 CmsResource detailContent = (CmsResource)m_req.getAttribute( 1307 CmsDetailPageResourceHandler.ATTR_DETAIL_CONTENT_RESOURCE); 1308 if (detailContent != null) { 1309 for (CmsResource detailOnlyRes : CmsDetailOnlyContainerUtil.getDetailOnlyResources(m_cms, detailContent)) { 1310 result.add(detailOnlyRes.getStructureId()); 1311 } 1312 } 1313 return result; 1314 } 1315 1316 /** 1317 * Helper method for checking whether there are properties defined for a given content element.<p> 1318 * 1319 * @param cms the CmsObject to use for VFS operations 1320 * @param resource the resource for which it should be checked whether it has properties 1321 * 1322 * @return true if the resource has properties defined 1323 * 1324 * @throws CmsException if something goes wrong 1325 */ 1326 private boolean hasSettings(CmsObject cms, CmsResource resource) throws CmsException { 1327 1328 if (!CmsResourceTypeXmlContent.isXmlContent(resource)) { 1329 return false; 1330 } 1331 1332 CmsADEConfigData config = getConfigData(); 1333 CmsFormatterConfiguration formatters = config.getFormatters(m_cms, resource); 1334 boolean result = (formatters.getAllFormatters().size() > 1) 1335 || !CmsXmlContentPropertyHelper.getPropertyInfo(m_cms, null, resource).isEmpty(); 1336 if (!result && (formatters.getAllFormatters().size() == 1)) { 1337 result = (formatters.getAllFormatters().get(0).getSettings(config).size() > 0); 1338 } 1339 return result; 1340 } 1341 1342 /** 1343 * Parses the given request parameters string into a parameter map.<p> 1344 * 1345 * @param requestParameters the request parameters to parse 1346 * 1347 * @return the parameter map 1348 */ 1349 private Map<String, Object> parseRequestParameters(String requestParameters) { 1350 1351 Map<String, Object> parameterMap; 1352 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(requestParameters)) { 1353 parameterMap = new HashMap<String, Object>(); 1354 String[] params = requestParameters.split("&"); 1355 for (int i = 0; i < params.length; i++) { 1356 int position = params[i].indexOf("="); 1357 if (position >= 0) { 1358 String key = params[i].substring(0, position); 1359 String value = params[i].substring(position + 1); 1360 if (value.contains(",")) { 1361 parameterMap.put(key, value.split(",")); 1362 } else { 1363 parameterMap.put(key, value); 1364 } 1365 } 1366 } 1367 } else { 1368 parameterMap = Collections.<String, Object> emptyMap(); 1369 } 1370 return parameterMap; 1371 } 1372 1373 /** 1374 * Removes all script tags from given input.<p> 1375 * 1376 * @param input the input to remove script tags from 1377 * 1378 * @return the cleaned input 1379 */ 1380 private String removeScriptTags(String input) { 1381 1382 Document doc = Jsoup.parseBodyFragment(input); 1383 Elements scriptTags = doc.select("script"); 1384 String output = input; 1385 if (scriptTags.size() > 0) { 1386 scriptTags.remove(); 1387 output = doc.body().html(); 1388 } 1389 return output; 1390 } 1391}