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