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.CmsADEManager; 032import org.opencms.ade.configuration.CmsElementView; 033import org.opencms.ade.configuration.CmsModelPageConfig; 034import org.opencms.ade.configuration.CmsResourceTypeConfig; 035import org.opencms.ade.containerpage.inherited.CmsInheritanceReference; 036import org.opencms.ade.containerpage.inherited.CmsInheritanceReferenceParser; 037import org.opencms.ade.containerpage.inherited.CmsInheritedContainerState; 038import org.opencms.ade.containerpage.shared.CmsCntPageData; 039import org.opencms.ade.containerpage.shared.CmsCntPageData.ElementDeleteMode; 040import org.opencms.ade.containerpage.shared.CmsCntPageData.ElementReuseMode; 041import org.opencms.ade.containerpage.shared.CmsContainer; 042import org.opencms.ade.containerpage.shared.CmsContainerElement; 043import org.opencms.ade.containerpage.shared.CmsContainerElement.ModelGroupState; 044import org.opencms.ade.containerpage.shared.CmsContainerElementData; 045import org.opencms.ade.containerpage.shared.CmsContainerPageGalleryData; 046import org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext; 047import org.opencms.ade.containerpage.shared.CmsCreateElementData; 048import org.opencms.ade.containerpage.shared.CmsDialogOptions; 049import org.opencms.ade.containerpage.shared.CmsDialogOptionsAndInfo; 050import org.opencms.ade.containerpage.shared.CmsElementSettingsConfig; 051import org.opencms.ade.containerpage.shared.CmsElementViewInfo; 052import org.opencms.ade.containerpage.shared.CmsFormatterConfig; 053import org.opencms.ade.containerpage.shared.CmsGroupContainer; 054import org.opencms.ade.containerpage.shared.CmsGroupContainerSaveResult; 055import org.opencms.ade.containerpage.shared.CmsInheritanceContainer; 056import org.opencms.ade.containerpage.shared.CmsInheritanceInfo; 057import org.opencms.ade.containerpage.shared.CmsLocaleLinkBean; 058import org.opencms.ade.containerpage.shared.CmsRemovedElementStatus; 059import org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService; 060import org.opencms.ade.detailpage.CmsDetailPageInfo; 061import org.opencms.ade.detailpage.CmsDetailPageResourceHandler; 062import org.opencms.ade.galleries.CmsGalleryService; 063import org.opencms.ade.galleries.shared.CmsGalleryDataBean; 064import org.opencms.ade.galleries.shared.CmsGallerySearchBean; 065import org.opencms.ade.galleries.shared.CmsResourceTypeBean; 066import org.opencms.ade.galleries.shared.CmsVfsEntryBean; 067import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryTabId; 068import org.opencms.ade.sitemap.CmsVfsSitemapService; 069import org.opencms.file.CmsFile; 070import org.opencms.file.CmsObject; 071import org.opencms.file.CmsProperty; 072import org.opencms.file.CmsPropertyDefinition; 073import org.opencms.file.CmsResource; 074import org.opencms.file.CmsResourceFilter; 075import org.opencms.file.CmsUser; 076import org.opencms.file.CmsVfsResourceNotFoundException; 077import org.opencms.file.types.CmsResourceTypeBinary; 078import org.opencms.file.types.CmsResourceTypeFunctionConfig; 079import org.opencms.file.types.CmsResourceTypeImage; 080import org.opencms.file.types.CmsResourceTypePlain; 081import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 082import org.opencms.file.types.CmsResourceTypeXmlContent; 083import org.opencms.file.types.I_CmsResourceType; 084import org.opencms.flex.CmsFlexController; 085import org.opencms.gwt.CmsDefaultResourceStatusProvider; 086import org.opencms.gwt.CmsGwtActionElement; 087import org.opencms.gwt.CmsGwtService; 088import org.opencms.gwt.CmsIconUtil; 089import org.opencms.gwt.CmsRpcException; 090import org.opencms.gwt.CmsVfsService; 091import org.opencms.gwt.shared.CmsGwtConstants; 092import org.opencms.gwt.shared.CmsListElementCreationDialogData; 093import org.opencms.gwt.shared.CmsListElementCreationOption; 094import org.opencms.gwt.shared.CmsListInfoBean; 095import org.opencms.gwt.shared.CmsModelResourceInfo; 096import org.opencms.gwt.shared.CmsTemplateContextInfo; 097import org.opencms.gwt.shared.I_CmsAutoBeanFactory; 098import org.opencms.gwt.shared.I_CmsListAddMetadata; 099import org.opencms.gwt.shared.I_CmsUnlockData; 100import org.opencms.i18n.CmsEncoder; 101import org.opencms.i18n.CmsLocaleGroup; 102import org.opencms.i18n.CmsLocaleManager; 103import org.opencms.i18n.CmsMessages; 104import org.opencms.jsp.CmsJspTagEdit; 105import org.opencms.jsp.util.CmsJspStandardContextBean.TemplateBean; 106import org.opencms.loader.CmsTemplateContextManager; 107import org.opencms.loader.I_CmsTemplateContextProvider; 108import org.opencms.lock.CmsLock; 109import org.opencms.lock.CmsLockType; 110import org.opencms.main.CmsException; 111import org.opencms.main.CmsIllegalArgumentException; 112import org.opencms.main.CmsLog; 113import org.opencms.main.OpenCms; 114import org.opencms.module.CmsModule; 115import org.opencms.relations.CmsRelation; 116import org.opencms.relations.CmsRelationFilter; 117import org.opencms.relations.CmsRelationType; 118import org.opencms.search.galleries.CmsGallerySearch; 119import org.opencms.search.galleries.CmsGallerySearchResult; 120import org.opencms.security.CmsPermissionSet; 121import org.opencms.security.CmsPermissionViolationException; 122import org.opencms.security.CmsRole; 123import org.opencms.site.CmsSite; 124import org.opencms.site.CmsSiteManagerImpl; 125import org.opencms.ui.apps.CmsQuickLaunchLocationCache; 126import org.opencms.util.CmsFileUtil; 127import org.opencms.util.CmsPair; 128import org.opencms.util.CmsRequestUtil; 129import org.opencms.util.CmsStringUtil; 130import org.opencms.util.CmsUUID; 131import org.opencms.workplace.CmsWorkplace; 132import org.opencms.workplace.CmsWorkplaceMessages; 133import org.opencms.workplace.CmsWorkplaceSettings; 134import org.opencms.workplace.editors.CmsWorkplaceEditorManager; 135import org.opencms.workplace.editors.directedit.I_CmsEditHandler; 136import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 137import org.opencms.workplace.explorer.CmsResourceUtil; 138import org.opencms.xml.CmsXmlException; 139import org.opencms.xml.containerpage.CmsADESessionCache; 140import org.opencms.xml.containerpage.CmsContainerBean; 141import org.opencms.xml.containerpage.CmsContainerElementBean; 142import org.opencms.xml.containerpage.CmsContainerPageBean; 143import org.opencms.xml.containerpage.CmsFormatterConfiguration; 144import org.opencms.xml.containerpage.CmsGroupContainerBean; 145import org.opencms.xml.containerpage.CmsMacroFormatterBean; 146import org.opencms.xml.containerpage.CmsXmlContainerPage; 147import org.opencms.xml.containerpage.CmsXmlContainerPageFactory; 148import org.opencms.xml.containerpage.CmsXmlGroupContainer; 149import org.opencms.xml.containerpage.CmsXmlGroupContainerFactory; 150import org.opencms.xml.containerpage.I_CmsFormatterBean; 151import org.opencms.xml.content.CmsXmlContent; 152import org.opencms.xml.content.CmsXmlContentFactory; 153import org.opencms.xml.content.CmsXmlContentProperty; 154import org.opencms.xml.content.CmsXmlContentPropertyHelper; 155 156import java.nio.charset.StandardCharsets; 157import java.security.MessageDigest; 158import java.security.NoSuchAlgorithmException; 159import java.util.ArrayList; 160import java.util.Arrays; 161import java.util.Collection; 162import java.util.Collections; 163import java.util.HashMap; 164import java.util.HashSet; 165import java.util.Iterator; 166import java.util.LinkedHashMap; 167import java.util.List; 168import java.util.Locale; 169import java.util.Map; 170import java.util.Map.Entry; 171import java.util.Set; 172 173import javax.servlet.http.HttpServletRequest; 174import javax.servlet.http.HttpServletResponse; 175 176import org.apache.commons.codec.binary.Hex; 177import org.apache.commons.logging.Log; 178 179import com.google.common.base.Optional; 180import com.google.common.collect.Lists; 181import com.google.common.collect.Maps; 182import com.google.common.collect.Sets; 183import com.google.web.bindery.autobean.shared.AutoBean; 184import com.google.web.bindery.autobean.shared.AutoBeanCodex; 185import com.google.web.bindery.autobean.vm.AutoBeanFactorySource; 186 187/** 188 * The RPC service used by the container-page editor.<p> 189 * 190 * @since 8.0.0 191 */ 192public class CmsContainerpageService extends CmsGwtService implements I_CmsContainerpageService { 193 194 /** 195 * Helper class used to determine both the available views and the active start view when loading a container page.<p> 196 */ 197 private class InitialElementViewProvider { 198 199 /** Start view id. */ 200 private CmsUUID m_defaultView; 201 202 /** Map of available views. */ 203 private Map<CmsUUID, CmsElementViewInfo> m_viewMap; 204 205 /** 206 * Empty default constructor.<p> 207 */ 208 public InitialElementViewProvider() { 209 210 // do nothing 211 } 212 213 /** 214 * Returns the default view info.<p> 215 * 216 * @return the default view info 217 */ 218 public CmsElementViewInfo getDefaultView() { 219 220 return getViewMap().get(getDefaultViewId()); 221 } 222 223 /** 224 * Gets the start view id.<p> 225 * 226 * @return the start view id 227 */ 228 public CmsUUID getDefaultViewId() { 229 230 return m_defaultView; 231 } 232 233 /** 234 * Gets the map of available views.<p> 235 * 236 * @return the map of available views 237 */ 238 public Map<CmsUUID, CmsElementViewInfo> getViewMap() { 239 240 return m_viewMap; 241 } 242 243 /** 244 * Initializes this object.<p> 245 * 246 * @param defaultValue the default view id from the session cache 247 * @param checkRes the resource used to check permissions 248 * @param templateContextInfo the template context information 249 */ 250 @SuppressWarnings("synthetic-access") 251 public void init(CmsUUID defaultValue, CmsResource checkRes, CmsTemplateContextInfo templateContextInfo) { 252 253 Map<CmsUUID, CmsElementViewInfo> result = new LinkedHashMap<CmsUUID, CmsElementViewInfo>(); 254 CmsObject cms = getCmsObject(); 255 String templateKey = templateContextInfo != null ? templateContextInfo.getCurrentContext() : null; 256 257 // collect the actually used element view ids 258 CmsADEConfigData config = getConfigData( 259 cms.getRequestContext().addSiteRoot(cms.getRequestContext().getUri())); 260 Set<CmsUUID> usedIds = new HashSet<CmsUUID>(); 261 for (CmsResourceTypeConfig typeConfig : config.getResourceTypes()) { 262 if (typeConfig.isAvailableInTemplate(templateKey)) { 263 usedIds.add(typeConfig.getElementView()); 264 } 265 } 266 267 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 268 Map<CmsUUID, CmsElementView> realViewMap = OpenCms.getADEManager().getElementViews(cms); 269 270 Set<CmsUUID> parentIds = Sets.newHashSet(); 271 for (CmsElementView view : realViewMap.values()) { 272 if (view.getParentViewId() != null) { 273 parentIds.add(view.getParentViewId()); 274 } 275 // add only element view that are used within the type configuration and the user has sufficient permissions for 276 if (usedIds.contains(view.getId()) && view.hasPermission(cms, checkRes) && !view.isOther()) { 277 result.put(view.getId(), new CmsElementViewInfo(view.getTitle(cms, wpLocale), view.getId())); 278 } 279 280 } 281 m_viewMap = result; 282 for (Map.Entry<CmsUUID, CmsElementViewInfo> viewEntry : m_viewMap.entrySet()) { 283 CmsElementView realView = realViewMap.get(viewEntry.getKey()); 284 CmsUUID parentViewId = realView.getParentViewId(); 285 if ((parentViewId != null) && !parentIds.contains(viewEntry.getKey())) { 286 CmsElementViewInfo parentBean = m_viewMap.get(parentViewId); 287 if (parentBean != null) { 288 viewEntry.getValue().setParent(parentBean); 289 } 290 } 291 } 292 if (m_viewMap.containsKey(defaultValue)) { 293 m_defaultView = defaultValue; 294 } else if (m_viewMap.containsKey(CmsElementView.DEFAULT_ELEMENT_VIEW.getId())) { 295 m_defaultView = CmsElementView.DEFAULT_ELEMENT_VIEW.getId(); 296 } else if (!m_viewMap.isEmpty()) { 297 m_defaultView = m_viewMap.values().iterator().next().getElementViewId(); 298 } else { 299 m_defaultView = defaultValue; 300 LOG.error( 301 "Initial view not available and no suitable replacement view found: user=" 302 + getCmsObject().getRequestContext().getCurrentUser().getName() 303 + " view=" 304 + defaultValue 305 + " path=" 306 + checkRes.getRootPath()); 307 } 308 309 } 310 } 311 312 /** Additional info key for storing the "edit small elements" setting on the user. */ 313 public static final String ADDINFO_EDIT_SMALL_ELEMENTS = "EDIT_SMALL_ELEMENTS"; 314 315 /** Session attribute name used to store the selected clipboard tab. */ 316 public static final String ATTR_CLIPBOARD_TAB = "clipboardtab"; 317 318 /** The model group pages path fragment. */ 319 public static final String MODEL_GROUP_PATH_FRAGMENT = "/.content/.modelgroups/"; 320 321 /** The source container page id settings key. */ 322 public static final String SOURCE_CONTAINERPAGE_ID_SETTING = "source_containerpage_id"; 323 324 /** Static reference to the log. */ 325 static final Log LOG = CmsLog.getLog(CmsContainerpageService.class); 326 327 /** Serial version UID. */ 328 private static final long serialVersionUID = -6188370638303594280L; 329 330 /** The configuration data of the current container page context. */ 331 private CmsADEConfigData m_configData; 332 333 /** The session cache. */ 334 private CmsADESessionCache m_sessionCache; 335 336 /** The workplace settings. */ 337 private CmsWorkplaceSettings m_workplaceSettings; 338 339 /** 340 * Generates the model resource data list.<p> 341 * 342 * @param cms the cms context 343 * @param resourceType the resource type name 344 * @param modelResources the model resource 345 * @param contentLocale the content locale 346 * 347 * @return the model resources data 348 * 349 * @throws CmsException if something goes wrong reading the resource information 350 */ 351 public static List<CmsModelResourceInfo> generateModelResourceList( 352 CmsObject cms, 353 String resourceType, 354 List<CmsResource> modelResources, 355 Locale contentLocale) 356 throws CmsException { 357 358 List<CmsModelResourceInfo> result = new ArrayList<CmsModelResourceInfo>(); 359 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 360 CmsModelResourceInfo defaultInfo = new CmsModelResourceInfo( 361 Messages.get().getBundle(wpLocale).key(Messages.GUI_TITLE_DEFAULT_RESOURCE_CONTENT_0), 362 Messages.get().getBundle(wpLocale).key(Messages.GUI_DESCRIPTION_DEFAULT_RESOURCE_CONTENT_0), 363 null); 364 defaultInfo.setResourceType(resourceType); 365 result.add(defaultInfo); 366 for (CmsResource model : modelResources) { 367 CmsGallerySearchResult searchInfo = CmsGallerySearch.searchById(cms, model.getStructureId(), contentLocale); 368 CmsModelResourceInfo modelInfo = new CmsModelResourceInfo( 369 searchInfo.getTitle(), 370 searchInfo.getDescription(), 371 null); 372 modelInfo.addAdditionalInfo( 373 Messages.get().getBundle(wpLocale).key(Messages.GUI_LABEL_PATH_0), 374 cms.getSitePath(model)); 375 modelInfo.setResourceType(resourceType); 376 modelInfo.setStructureId(model.getStructureId()); 377 result.add(modelInfo); 378 } 379 return result; 380 } 381 382 /** 383 * Returns serialized container data.<p> 384 * 385 * @param container the container 386 * 387 * @return the serialized data 388 * 389 * @throws Exception if serialization fails 390 */ 391 public static String getSerializedContainerInfo(CmsContainer container) throws Exception { 392 393 return CmsGwtActionElement.serialize(I_CmsContainerpageService.class.getMethod("getContainerInfo"), container); 394 } 395 396 /** 397 * Returns the serialized element data.<p> 398 * 399 * @param cms the cms context 400 * @param request the servlet request 401 * @param response the servlet response 402 * @param elementBean the element to serialize 403 * @param page the container page 404 * 405 * @return the serialized element data 406 * 407 * @throws Exception if something goes wrong 408 */ 409 public static String getSerializedElementInfo( 410 CmsObject cms, 411 HttpServletRequest request, 412 HttpServletResponse response, 413 CmsContainerElementBean elementBean, 414 CmsContainerPageBean page) 415 throws Exception { 416 417 CmsContainerElement result = new CmsContainerElement(); 418 CmsElementUtil util = new CmsElementUtil( 419 cms, 420 cms.getRequestContext().getUri(), 421 page, 422 null, 423 request, 424 response, 425 false, 426 cms.getRequestContext().getLocale()); 427 util.setElementInfo(elementBean, result); 428 return CmsGwtActionElement.serialize(I_CmsContainerpageService.class.getMethod("getElementInfo"), result); 429 } 430 431 /** 432 * Checks whether the current page is a model group page.<p> 433 * 434 * @param cms the CMS context 435 * @param containerPage the current page 436 * 437 * @return <code>true</code> if the current page is a model group page 438 */ 439 public static boolean isEditingModelGroups(CmsObject cms, CmsResource containerPage) { 440 441 return (OpenCms.getResourceManager().getResourceType(containerPage).getTypeName().equals( 442 CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME) 443 && OpenCms.getRoleManager().hasRole(cms, CmsRole.DEVELOPER)); 444 } 445 446 /** 447 * Fetches the container page data.<p> 448 * 449 * @param request the current request 450 * 451 * @return the container page data 452 * 453 * @throws CmsRpcException if something goes wrong 454 */ 455 public static CmsCntPageData prefetch(HttpServletRequest request) throws CmsRpcException { 456 457 CmsContainerpageService srv = new CmsContainerpageService(); 458 srv.setCms(CmsFlexController.getCmsObject(request)); 459 srv.setRequest(request); 460 CmsCntPageData result = null; 461 try { 462 result = srv.prefetch(); 463 } finally { 464 srv.clearThreadStorage(); 465 } 466 return result; 467 } 468 469 /** 470 * Unlocks a page or set of pages if they are locked by the current user. 471 * 472 * <p>This is not called via the normal GWT-RPC mechanism, but with the browser's sendBeacon function. 473 * 474 * @param cms the CMS context 475 * @param request the current request 476 * @param response the current response 477 * @throws Exception if something goes wrong 478 */ 479 public static void unlockPage(CmsObject cms, HttpServletRequest request, HttpServletResponse response) 480 throws Exception { 481 482 // don't bother doing anything unless we have a session and are offline 483 484 if (request.getSession(false) == null) { 485 LOG.debug("no session found"); 486 return; 487 } 488 if (cms.getRequestContext().getCurrentProject().isOnlineProject()) { 489 LOG.debug("can't unlock page in online project"); 490 return; 491 } 492 byte[] byteData = CmsFileUtil.readFully(request.getInputStream(), false); 493 494 String encoding = request.getCharacterEncoding(); 495 if (encoding == null) { 496 encoding = "UTF-8"; 497 } 498 String strData = new String(byteData, encoding); 499 LOG.debug("Unlock request received: " + strData); 500 501 AutoBean<I_CmsUnlockData> data = AutoBeanCodex.decode( 502 AutoBeanFactorySource.create(I_CmsAutoBeanFactory.class), 503 I_CmsUnlockData.class, 504 strData); 505 506 I_CmsUnlockData unlockData = data.as(); 507 List<CmsUUID> ids = new ArrayList<>(); 508 if (CmsUUID.isValidUUID(unlockData.getPageId())) { 509 ids.add(new CmsUUID(unlockData.getPageId())); 510 } 511 CmsUUID detailId = null; 512 if (CmsUUID.isValidUUID(unlockData.getDetailId())) { 513 detailId = new CmsUUID(unlockData.getDetailId()); 514 try { 515 CmsResource detailResource = cms.readResource(detailId, CmsResourceFilter.ALL); 516 Optional<CmsResource> detailOnlyPage = CmsDetailOnlyContainerUtil.getDetailOnlyPage( 517 cms, 518 detailResource, 519 unlockData.getLocale()); 520 if (detailOnlyPage.isPresent()) { 521 ids.add(detailOnlyPage.get().getStructureId()); 522 } 523 } catch (CmsVfsResourceNotFoundException e) { 524 LOG.info(e.getLocalizedMessage(), e); 525 } catch (Exception e) { 526 LOG.error(e.getLocalizedMessage(), e); 527 } 528 } 529 530 for (CmsUUID id : ids) { 531 try { 532 CmsResource page = cms.readResource(id, CmsResourceFilter.IGNORE_EXPIRATION); 533 CmsLock lock = cms.getLock(page); 534 if (!lock.isUnlocked() && lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) { 535 LOG.debug("Unlocking " + page.getRootPath()); 536 cms.unlockResource(page); 537 } else { 538 LOG.debug("Can't unlock " + page.getRootPath() + " because it's not locked for the current user."); 539 } 540 } catch (Exception e) { 541 LOG.error(e.getLocalizedMessage(), e); 542 } 543 } 544 } 545 546 /** 547 * Returns the server id part of the given client id.<p> 548 * 549 * @param id the id 550 * 551 * @return the server id 552 */ 553 private static String getServerIdString(String id) { 554 555 if (id.contains(CmsADEManager.CLIENT_ID_SEPERATOR)) { 556 id = id.substring(0, id.indexOf(CmsADEManager.CLIENT_ID_SEPERATOR)); 557 } 558 return id; 559 } 560 561 /** 562 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#addToFavoriteList(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, java.lang.String) 563 */ 564 public void addToFavoriteList(CmsContainerPageRpcContext context, String clientId) throws CmsRpcException { 565 566 try { 567 ensureSession(); 568 List<CmsContainerElementBean> list = OpenCms.getADEManager().getFavoriteList(getCmsObject()); 569 CmsResource containerPage = getCmsObject().readResource( 570 context.getPageStructureId(), 571 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 572 updateFavoriteRecentList(containerPage, clientId, list); 573 OpenCms.getADEManager().saveFavoriteList(getCmsObject(), list); 574 } catch (Throwable e) { 575 error(e); 576 } 577 } 578 579 /** 580 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#addToRecentList(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, java.lang.String) 581 */ 582 public void addToRecentList(CmsContainerPageRpcContext context, String clientId) throws CmsRpcException { 583 584 try { 585 ensureSession(); 586 List<CmsContainerElementBean> list = OpenCms.getADEManager().getRecentList(getCmsObject()); 587 CmsResource containerPage = getCmsObject().readResource( 588 context.getPageStructureId(), 589 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 590 updateFavoriteRecentList(containerPage, clientId, list); 591 OpenCms.getADEManager().saveRecentList(getCmsObject(), list); 592 } catch (Throwable e) { 593 error(e); 594 } 595 } 596 597 /** 598 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#checkContainerpageOrElementsChanged(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID, java.lang.String) 599 */ 600 public boolean checkContainerpageOrElementsChanged( 601 CmsUUID structureId, 602 CmsUUID detailContentId, 603 String contentLocale) 604 throws CmsRpcException { 605 606 try { 607 List<CmsUUID> additionalIds = new ArrayList<CmsUUID>(); 608 additionalIds.add(structureId); 609 boolean detailOnlyChanged = false; 610 if (detailContentId != null) { 611 additionalIds.add(detailContentId); 612 try { 613 614 CmsObject cms = getCmsObject(); 615 CmsResource detailContentRes = cms.readResource(detailContentId, CmsResourceFilter.ALL); 616 OpenCms.getLocaleManager(); 617 CmsResource page = cms.readResource(structureId, CmsResourceFilter.ignoreExpirationOffline(cms)); 618 Optional<CmsResource> detailOnlyRes = CmsDetailOnlyContainerUtil.getDetailOnlyResource( 619 cms, 620 contentLocale, 621 detailContentRes, 622 page); 623 if (detailOnlyRes.isPresent()) { 624 detailOnlyChanged = CmsDefaultResourceStatusProvider.getContainerpageRelationTargets( 625 getCmsObject(), 626 detailOnlyRes.get().getStructureId(), 627 Arrays.asList(detailOnlyRes.get().getStructureId()), 628 true).isChanged(); 629 } 630 } catch (CmsException e) { 631 LOG.error(e.getLocalizedMessage(), e); 632 } 633 } 634 return detailOnlyChanged 635 || CmsDefaultResourceStatusProvider.getContainerpageRelationTargets( 636 getCmsObject(), 637 structureId, 638 additionalIds, 639 true /*stop looking if we find a changed resource.*/).isChanged(); 640 } catch (Throwable e) { 641 error(e); 642 return false; // will never be reached 643 } 644 645 } 646 647 /** 648 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#checkCreateNewElement(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID, java.lang.String, java.lang.String, org.opencms.ade.containerpage.shared.CmsContainer, java.lang.String) 649 */ 650 public CmsCreateElementData checkCreateNewElement( 651 CmsUUID pageStructureId, 652 CmsUUID detailContentId, 653 String clientId, 654 String resourceType, 655 CmsContainer container, 656 String locale) 657 throws CmsRpcException { 658 659 CmsObject cms = getCmsObject(); 660 CmsCreateElementData result = new CmsCreateElementData(); 661 try { 662 CmsResource currentPage = cms.readResource(pageStructureId, CmsResourceFilter.ignoreExpirationOffline(cms)); 663 664 List<CmsResource> modelResources = CmsResourceTypeXmlContent.getModelFiles( 665 getCmsObject(), 666 CmsResource.getFolderPath(cms.getSitePath(currentPage)), 667 resourceType); 668 if (modelResources.isEmpty()) { 669 CmsContainerElementBean bean = getCachedElement(clientId, currentPage.getRootPath()); 670 I_CmsFormatterBean formatter = CmsElementUtil.getFormatterForContainer( 671 cms, 672 bean, 673 container, 674 getConfigData(currentPage.getRootPath()), 675 getSessionCache()); 676 CmsUUID modelResId = null; 677 if (formatter instanceof CmsMacroFormatterBean) { 678 modelResId = ((CmsMacroFormatterBean)formatter).getDefaultContentStructureId(); 679 } 680 result.setCreatedElement( 681 createNewElement(pageStructureId, detailContentId, clientId, resourceType, modelResId, locale)); 682 } else { 683 result.setModelResources( 684 generateModelResourceList( 685 getCmsObject(), 686 resourceType, 687 modelResources, 688 CmsLocaleManager.getLocale(locale))); 689 } 690 } catch (CmsException e) { 691 error(e); 692 } 693 return result; 694 } 695 696 /** 697 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#checkNewWidgetsAvailable(org.opencms.util.CmsUUID) 698 */ 699 public boolean checkNewWidgetsAvailable(CmsUUID structureId) throws CmsRpcException { 700 701 try { 702 CmsObject cms = getCmsObject(); 703 CmsResource resource = cms.readResource(structureId); 704 return CmsWorkplaceEditorManager.checkAcaciaEditorAvailable(cms, resource); 705 } catch (Throwable t) { 706 error(t); 707 } 708 return false; 709 } 710 711 /** 712 * Parses an element id.<p> 713 * 714 * @param id the element id 715 * 716 * @return the corresponding structure id 717 * 718 * @throws CmsIllegalArgumentException if the id has not the right format 719 */ 720 public CmsUUID convertToServerId(String id) throws CmsIllegalArgumentException { 721 722 if (id == null) { 723 throw new CmsIllegalArgumentException( 724 org.opencms.xml.containerpage.Messages.get().container( 725 org.opencms.xml.containerpage.Messages.ERR_INVALID_ID_1, 726 id)); 727 } 728 String serverId = getServerIdString(id); 729 try { 730 return new CmsUUID(serverId); 731 } catch (NumberFormatException e) { 732 throw new CmsIllegalArgumentException( 733 org.opencms.xml.containerpage.Messages.get().container( 734 org.opencms.xml.containerpage.Messages.ERR_INVALID_ID_1, 735 id), 736 e); 737 } 738 } 739 740 /** 741 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#copyElement(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID, java.lang.String) 742 */ 743 public CmsUUID copyElement(CmsUUID pageId, CmsUUID originalElementId, String locale) throws CmsRpcException { 744 745 try { 746 CmsObject cms = OpenCms.initCmsObject(getCmsObject()); 747 cms.getRequestContext().setLocale(CmsLocaleManager.getLocale(locale)); 748 CmsResource page = cms.readResource(pageId, CmsResourceFilter.IGNORE_EXPIRATION); 749 CmsResource element = cms.readResource(originalElementId, CmsResourceFilter.IGNORE_EXPIRATION); 750 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration(cms, page.getRootPath()); 751 String typeName = OpenCms.getResourceManager().getResourceType(element.getTypeId()).getTypeName(); 752 CmsResourceTypeConfig typeConfig = config.getResourceType(typeName); 753 if (typeConfig == null) { 754 LOG.error("copyElement: Type not configured in ADE configuration: " + typeName); 755 return originalElementId; 756 } else { 757 CmsResource newResource = typeConfig.createNewElement( 758 cms, 759 element, 760 CmsResource.getParentFolder(page.getRootPath())); 761 return newResource.getStructureId(); 762 } 763 } catch (Throwable e) { 764 error(e); 765 return null; // will never be reached 766 } 767 } 768 769 /** 770 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#createNewElement(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID, java.lang.String, java.lang.String, org.opencms.util.CmsUUID, java.lang.String) 771 */ 772 public CmsContainerElement createNewElement( 773 CmsUUID pageStructureId, 774 CmsUUID detailContentId, 775 String clientId, 776 String resourceType, 777 CmsUUID modelResourceStructureId, 778 String locale) 779 throws CmsRpcException { 780 781 CmsContainerElement element = null; 782 try { 783 ensureSession(); 784 CmsObject cms = getCmsObject(); 785 CmsResource pageResource = cms.readResource( 786 pageStructureId, 787 CmsResourceFilter.ignoreExpirationOffline(cms)); 788 CmsADEConfigData configData = getConfigData(pageResource.getRootPath()); 789 CmsResourceTypeConfig typeConfig = configData.getResourceType(resourceType); 790 CmsObject cloneCms = OpenCms.initCmsObject(cms); 791 cloneCms.getRequestContext().setLocale(CmsLocaleManager.getLocale(locale)); 792 793 CmsResource modelResource = null; 794 if (modelResourceStructureId != null) { 795 modelResource = cms.readResource(modelResourceStructureId); 796 } 797 String pageFolderForElementCreation = CmsResource.getParentFolder(pageResource.getRootPath()); 798 if (detailContentId != null) { 799 try { 800 CmsResource detailResource = cms.readResource(detailContentId, CmsResourceFilter.IGNORE_EXPIRATION); 801 pageFolderForElementCreation = CmsResource.getParentFolder( 802 CmsDetailOnlyContainerUtil.getDetailOnlyPageName( 803 cloneCms, 804 pageResource, 805 detailResource.getRootPath(), 806 locale)); 807 } catch (Exception e) { 808 // pageFolderForElementCreation remains the folder of the detail page in this case 809 LOG.info(e.getLocalizedMessage(), e); 810 } 811 } 812 CmsResource newResource = typeConfig.createNewElement( 813 cloneCms, 814 modelResource, 815 pageFolderForElementCreation); 816 CmsContainerElementBean bean = getCachedElement(clientId, pageResource.getRootPath()); 817 Map<String, String> settings = new HashMap<String, String>(); 818 819 settings = bean.getIndividualSettings(); 820 821 CmsContainerElementBean newBean = new CmsContainerElementBean( 822 newResource.getStructureId(), 823 null, 824 settings, 825 typeConfig.isCopyInModels()); 826 String newClientId = newBean.editorHash(); 827 getSessionCache().setCacheContainerElement(newClientId, newBean); 828 element = new CmsContainerElement(); 829 element.setNewEditorDisabled(!CmsWorkplaceEditorManager.checkAcaciaEditorAvailable(cms, newResource)); 830 element.setClientId(newClientId); 831 element.setSitePath(cms.getSitePath(newResource)); 832 element.setResourceType(resourceType); 833 element.setIconClasses( 834 CmsIconUtil.getIconClasses(CmsIconUtil.getDisplayType(cms, newResource), null, false)); 835 element.setCreateNew(newBean.isCreateNew()); 836 } catch (CmsException e) { 837 error(e); 838 } 839 return element; 840 } 841 842 /** 843 * Reads the cached element-bean for the given client-side-id from cache.<p> 844 * 845 * @param clientId the client-side-id 846 * @param pageRootPath the container page root path 847 * 848 * @return the cached container element bean 849 * 850 * @throws CmsException in case reading the element resource fails 851 */ 852 public CmsContainerElementBean getCachedElement(String clientId, String pageRootPath) throws CmsException { 853 854 String id = clientId; 855 CmsContainerElementBean element = null; 856 element = getSessionCache().getCacheContainerElement(id); 857 if (element != null) { 858 return element; 859 } 860 if (id.contains(CmsADEManager.CLIENT_ID_SEPERATOR)) { 861 throw new CmsException(Messages.get().container(Messages.ERR_MISSING_CACHED_ELEMENT_0)); 862 } 863 // this is necessary if the element has not been cached yet 864 CmsResource resource = getCmsObject().readResource(convertToServerId(id), CmsResourceFilter.IGNORE_EXPIRATION); 865 CmsADEConfigData configData = getConfigData(pageRootPath); 866 CmsResourceTypeConfig typeConfig = configData.getResourceType( 867 OpenCms.getResourceManager().getResourceType(resource).getTypeName()); 868 element = new CmsContainerElementBean( 869 convertToServerId(id), 870 null, 871 null, 872 (typeConfig != null) && typeConfig.isCopyInModels()); 873 getSessionCache().setCacheContainerElement(element.editorHash(), element); 874 return element; 875 } 876 877 /** 878 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getContainerInfo() 879 */ 880 public CmsContainer getContainerInfo() { 881 882 throw new UnsupportedOperationException("This method is used for serialization only."); 883 } 884 885 /** 886 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getDeleteOptions(java.lang.String, org.opencms.util.CmsUUID, java.lang.String) 887 */ 888 public CmsDialogOptionsAndInfo getDeleteOptions(String clientId, CmsUUID pageId, String requestParams) 889 throws CmsRpcException { 890 891 try { 892 CmsResource pageResource = getCmsObject().readResource( 893 pageId, 894 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 895 CmsContainerElementBean element = getCachedElement(clientId, pageResource.getRootPath()); 896 element.initResource(getCmsObject()); 897 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource()); 898 if (type instanceof CmsResourceTypeXmlContent) { 899 I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)type).getEditHandler(getCmsObject()); 900 Map<String, String[]> params = CmsRequestUtil.createParameterMap( 901 CmsEncoder.decode(requestParams), 902 true, 903 CmsEncoder.ENCODING_UTF_8); 904 CmsDialogOptions options = handler.getDeleteOptions(getCmsObject(), element, pageId, params); 905 if (options != null) { 906 return new CmsDialogOptionsAndInfo( 907 options, 908 CmsVfsService.getPageInfo(getCmsObject(), element.getResource())); 909 } 910 } 911 } catch (CmsException e) { 912 error(e); 913 } 914 return null; 915 } 916 917 /** 918 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getEditOptions(java.lang.String, org.opencms.util.CmsUUID, java.lang.String, boolean) 919 */ 920 public CmsDialogOptionsAndInfo getEditOptions( 921 String clientId, 922 CmsUUID pageId, 923 String requestParams, 924 boolean isListElement) 925 throws CmsRpcException { 926 927 try { 928 CmsResource pageResource = getCmsObject().readResource( 929 pageId, 930 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 931 CmsContainerElementBean element = getCachedElement(clientId, pageResource.getRootPath()); 932 element.initResource(getCmsObject()); 933 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource()); 934 if (type instanceof CmsResourceTypeXmlContent) { 935 I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)type).getEditHandler(getCmsObject()); 936 Map<String, String[]> params = CmsRequestUtil.createParameterMap( 937 CmsEncoder.decode(requestParams), 938 true, 939 CmsEncoder.ENCODING_UTF_8); 940 CmsDialogOptions options = handler.getEditOptions( 941 getCmsObject(), 942 element, 943 pageId, 944 params, 945 isListElement); 946 if (options != null) { 947 return new CmsDialogOptionsAndInfo( 948 options, 949 CmsVfsService.getPageInfo(getCmsObject(), element.getResource())); 950 } 951 } 952 } catch (CmsException e) { 953 error(e); 954 } 955 return null; 956 } 957 958 /** 959 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getElementInfo() 960 */ 961 public CmsContainerElement getElementInfo() { 962 963 throw new UnsupportedOperationException("This method is used for serialization only."); 964 } 965 966 /** 967 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getElementsData(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, org.opencms.util.CmsUUID, java.lang.String, java.util.Collection, java.util.Collection, boolean, java.lang.String, java.lang.String) 968 */ 969 public Map<String, CmsContainerElementData> getElementsData( 970 CmsContainerPageRpcContext context, 971 CmsUUID detailContentId, 972 String reqParams, 973 Collection<String> clientIds, 974 Collection<CmsContainer> containers, 975 boolean allwaysCopy, 976 String dndSource, 977 String locale) 978 throws CmsRpcException { 979 980 Map<String, CmsContainerElementData> result = null; 981 try { 982 ensureSession(); 983 CmsResource pageResource = getCmsObject().readResource( 984 context.getPageStructureId(), 985 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 986 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration( 987 getCmsObject(), 988 pageResource.getRootPath()); 989 initRequestFromRpcContext(context); 990 String containerpageUri = getCmsObject().getSitePath(pageResource); 991 result = getElements( 992 config, 993 pageResource, 994 clientIds, 995 containerpageUri, 996 detailContentId, 997 containers, 998 allwaysCopy, 999 dndSource, 1000 CmsStringUtil.isNotEmptyOrWhitespaceOnly(dndSource), 1001 CmsLocaleManager.getLocale(locale)); 1002 } catch (Throwable e) { 1003 error(e); 1004 } 1005 return result; 1006 } 1007 1008 /** 1009 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getElementSettingsConfig(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, java.lang.String, java.lang.String, java.util.Collection, java.lang.String) 1010 */ 1011 public CmsElementSettingsConfig getElementSettingsConfig( 1012 CmsContainerPageRpcContext context, 1013 String clientId, 1014 String containerId, 1015 Collection<CmsContainer> containers, 1016 String locale) 1017 throws CmsRpcException { 1018 1019 try { 1020 ensureSession(); 1021 CmsObject cms = getCmsObject(); 1022 CmsResource pageResource = cms.readResource( 1023 context.getPageStructureId(), 1024 CmsResourceFilter.ignoreExpirationOffline(cms)); 1025 initRequestFromRpcContext(context); 1026 String containerpageUri = cms.getSitePath(pageResource); 1027 1028 CmsContainerPageBean pageBean = generateContainerPageForContainers( 1029 containers, 1030 cms.getRequestContext().addSiteRoot(containerpageUri)); 1031 1032 CmsElementUtil elemUtil = new CmsElementUtil( 1033 cms, 1034 containerpageUri, 1035 pageBean, 1036 null, 1037 getRequest(), 1038 getResponse(), 1039 false, 1040 CmsLocaleManager.getLocale(locale)); 1041 CmsContainerElementBean element = getCachedElement( 1042 clientId, 1043 cms.getRequestContext().addSiteRoot(containerpageUri)); 1044 if (element.getInstanceId() == null) { 1045 element = element.clone(); 1046 getSessionCache().setCacheContainerElement(element.editorHash(), element); 1047 } 1048 element.initResource(cms); 1049 return elemUtil.getElementSettingsConfig(pageResource, element, containerId, containers); 1050 } catch (Throwable e) { 1051 error(e); 1052 } 1053 return null; 1054 } 1055 1056 /** 1057 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getElementsLockedForPublishing(java.util.Set) 1058 */ 1059 public Set<CmsUUID> getElementsLockedForPublishing(Set<CmsUUID> idsToCheck) throws CmsRpcException { 1060 1061 try { 1062 CmsObject cms = getCmsObject(); 1063 Set<CmsUUID> result = new HashSet<>(); 1064 for (CmsUUID id : idsToCheck) { 1065 try { 1066 CmsResource resource = cms.readResource(id, CmsResourceFilter.ALL); 1067 CmsLock lock = cms.getLock(resource); 1068 if (!lock.getSystemLock().isUnlocked() 1069 && lock.getUserId().equals(cms.getRequestContext().getCurrentUser().getId())) { 1070 result.add(resource.getStructureId()); 1071 } 1072 } catch (CmsVfsResourceNotFoundException e) { 1073 LOG.debug(e.getLocalizedMessage(), e); 1074 } 1075 } 1076 return result; 1077 } catch (Exception e) { 1078 error(e); 1079 return null; 1080 } 1081 } 1082 1083 /** 1084 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getElementWithSettings(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, org.opencms.util.CmsUUID, java.lang.String, java.lang.String, java.util.Map, java.util.Collection, java.lang.String) 1085 */ 1086 public CmsContainerElementData getElementWithSettings( 1087 CmsContainerPageRpcContext context, 1088 CmsUUID detailContentId, 1089 String uriParams, 1090 String clientId, 1091 Map<String, String> settings, 1092 Collection<CmsContainer> containers, 1093 String locale) 1094 throws CmsRpcException { 1095 1096 CmsContainerElementData element = null; 1097 try { 1098 ensureSession(); 1099 CmsObject cms = getCmsObject(); 1100 CmsResource pageResource = cms.readResource( 1101 context.getPageStructureId(), 1102 CmsResourceFilter.ignoreExpirationOffline(cms)); 1103 initRequestFromRpcContext(context); 1104 String containerpageUri = cms.getSitePath(pageResource); 1105 Locale contentLocale = CmsLocaleManager.getLocale(locale); 1106 CmsElementUtil elemUtil = new CmsElementUtil( 1107 cms, 1108 containerpageUri, 1109 generateContainerPageForContainers(containers, pageResource.getRootPath()), 1110 detailContentId, 1111 getRequest(), 1112 getResponse(), 1113 false, 1114 contentLocale); 1115 1116 CmsContainerElementBean elementBean = getCachedElement(clientId, pageResource.getRootPath()); 1117 elementBean.initResource(cms); 1118 storeFormatterSelection(elementBean, settings); 1119 // make sure to keep the element instance id 1120 if (!settings.containsKey(CmsContainerElement.ELEMENT_INSTANCE_ID) 1121 && elementBean.getIndividualSettings().containsKey(CmsContainerElement.ELEMENT_INSTANCE_ID)) { 1122 settings.put( 1123 CmsContainerElement.ELEMENT_INSTANCE_ID, 1124 elementBean.getIndividualSettings().get(CmsContainerElement.ELEMENT_INSTANCE_ID)); 1125 } 1126 1127 elementBean = CmsContainerElementBean.cloneWithSettings( 1128 elementBean, 1129 convertSettingValues(elementBean.getResource(), settings, contentLocale)); 1130 getSessionCache().setCacheContainerElement(elementBean.editorHash(), elementBean); 1131 element = elemUtil.getElementData(pageResource, elementBean, containers); 1132 } catch (Throwable e) { 1133 error(e); 1134 } 1135 return element; 1136 } 1137 1138 /** 1139 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getFavoriteList(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID, java.util.Collection, java.lang.String) 1140 */ 1141 public List<CmsContainerElementData> getFavoriteList( 1142 CmsUUID pageStructureId, 1143 CmsUUID detailContentId, 1144 Collection<CmsContainer> containers, 1145 String locale) 1146 throws CmsRpcException { 1147 1148 List<CmsContainerElementData> result = null; 1149 try { 1150 ensureSession(); 1151 CmsResource containerpage = getCmsObject().readResource( 1152 pageStructureId, 1153 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 1154 String containerpageUri = getCmsObject().getSitePath(containerpage); 1155 result = getListElementsData( 1156 OpenCms.getADEManager().getFavoriteList(getCmsObject()), 1157 containerpageUri, 1158 detailContentId, 1159 containers, 1160 CmsLocaleManager.getLocale(locale)); 1161 } catch (Throwable e) { 1162 error(e); 1163 } 1164 return result; 1165 } 1166 1167 /** 1168 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getGalleryDataForPage(java.util.List, org.opencms.util.CmsUUID, java.lang.String, org.opencms.util.CmsUUID, java.lang.String, org.opencms.gwt.shared.CmsTemplateContextInfo) 1169 */ 1170 public CmsContainerPageGalleryData getGalleryDataForPage( 1171 final List<CmsContainer> containers, 1172 CmsUUID elementView, 1173 String uri, 1174 CmsUUID detailContentId, 1175 String locale, 1176 CmsTemplateContextInfo templateContextInfo) 1177 throws CmsRpcException { 1178 1179 CmsGalleryDataBean data = null; 1180 try { 1181 CmsObject cms = getCmsObject(); 1182 String pageFolderRootPath = cms.getRequestContext().addSiteRoot(uri); 1183 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration(cms, pageFolderRootPath); 1184 Map<String, CmsResourceTypeConfig> typesByName = config.getTypesByName(); 1185 final String templateContextStr = (templateContextInfo != null) 1186 && (templateContextInfo.getCurrentContext() != null) ? templateContextInfo.getCurrentContext() : null; 1187 CmsAddDialogTypeHelper typeHelper = new CmsAddDialogTypeHelper(CmsResourceTypeConfig.AddMenuType.ade) { 1188 1189 @Override 1190 protected boolean exclude(CmsResourceTypeBean type) { 1191 1192 CmsResourceTypeConfig typeConfig = typesByName.get(type.getType()); 1193 if ((typeConfig != null) 1194 && (templateContextStr != null) 1195 && !typeConfig.isAvailableInTemplate(templateContextStr)) { 1196 return true; 1197 } 1198 return false; 1199 1200 } 1201 }; 1202 if (detailContentId != null) { 1203 try { 1204 CmsResource page = cms.readResource(uri, CmsResourceFilter.IGNORE_EXPIRATION); 1205 CmsResource detailContent = cms.readResource(detailContentId, CmsResourceFilter.IGNORE_EXPIRATION); 1206 pageFolderRootPath = CmsResource.getParentFolder( 1207 CmsDetailOnlyContainerUtil.getDetailOnlyPageName( 1208 cms, 1209 page, 1210 detailContent.getRootPath(), 1211 "" + locale)); 1212 } catch (Exception e) { 1213 LOG.error(e.getLocalizedMessage(), e); 1214 } 1215 } 1216 List<CmsResourceTypeBean> resTypeBeans = typeHelper.getResourceTypes( 1217 cms, 1218 cms.getRequestContext().addSiteRoot(uri), 1219 pageFolderRootPath, 1220 uri, 1221 OpenCms.getADEManager().getElementViews(cms).get(elementView), 1222 new I_CmsResourceTypeEnabledCheck() { 1223 1224 public boolean checkEnabled( 1225 CmsObject paramCms, 1226 CmsADEConfigData config2, 1227 I_CmsResourceType resType) { 1228 1229 boolean isModelGroup = CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME.equals( 1230 resType.getTypeName()); 1231 return isModelGroup || config2.hasFormatters(paramCms, resType, containers); 1232 } 1233 }); 1234 CmsGalleryService srv = new CmsGalleryService(); 1235 srv.setCms(cms); 1236 srv.setRequest(getRequest()); 1237 data = srv.getInitialSettingsForContainerPage(resTypeBeans, uri, locale); 1238 CmsContainerPageGalleryData result = new CmsContainerPageGalleryData(); 1239 1240 CmsADESessionCache cache = CmsADESessionCache.getCache(getRequest(), cms); 1241 CmsGallerySearchBean search = cache.getLastPageEditorGallerySearch(); 1242 String subsite = OpenCms.getADEManager().getSubSiteRoot(cms, cms.addSiteRoot(uri)); 1243 1244 // The template context now influences the gallery search results, so use checksum of the template context provider and context as part of the cache key 1245 String providerSuffix = "null"; 1246 if (templateContextInfo != null) { 1247 String providerKey = templateContextInfo.getContextProvider(); 1248 I_CmsTemplateContextProvider provider = OpenCms.getTemplateContextManager().getTemplateContextProvider( 1249 providerKey); 1250 if (provider != null) { 1251 try { 1252 MessageDigest md5 = MessageDigest.getInstance("md5"); 1253 md5.update(providerKey.getBytes(StandardCharsets.UTF_8)); 1254 if (templateContextInfo.getCurrentContext() != null) { 1255 md5.update((byte)0); // 0 byte as separator 1256 md5.update(templateContextInfo.getCurrentContext().getBytes(StandardCharsets.UTF_8)); 1257 providerSuffix = Hex.encodeHexString(md5.digest()); 1258 } 1259 } catch (NoSuchAlgorithmException e) { 1260 // MD5 must be in standard library 1261 } 1262 } 1263 } 1264 1265 String searchStoreKey = elementView + "|" + subsite + "|" + locale + "|" + providerSuffix; 1266 data.getContextParameters().put("searchStoreKey", searchStoreKey); 1267 if ((search != null) && !search.getServerSearchTypes().contains(CmsResourceTypeFunctionConfig.TYPE_NAME)) { 1268 if (searchStoreKey.equals( 1269 search.getOriginalGalleryData().getContextParameters().get("searchStoreKey"))) { 1270 if (hasCompatibleSearchData(search.getOriginalGalleryData(), data, search)) { 1271 1272 CmsVfsEntryBean preloadData = null; 1273 if (search.getFolders() != null) { 1274 preloadData = CmsGalleryService.generateVfsPreloadData( 1275 getCmsObject(), 1276 CmsGalleryService.getVfsTreeState(getRequest(), data.getTreeToken()), 1277 search.getFolders()); 1278 } 1279 1280 // only restore last result list if the search was performed in a 'similar' context 1281 search.setTabId(GalleryTabId.cms_tab_results.toString()); 1282 search.setPage(1); 1283 search.setLastPage(0); 1284 data.setStartTab(GalleryTabId.cms_tab_results); 1285 search = srv.getSearch(search); 1286 data.setVfsPreloadData(preloadData); 1287 data.setIncludeExpiredDefault(search.isIncludeExpired()); 1288 result.setGallerySearch(search); 1289 } 1290 } 1291 } 1292 result.setGalleryData(data); 1293 return result; 1294 1295 } catch (Exception e) { 1296 error(e); 1297 return null; 1298 } 1299 } 1300 1301 /** 1302 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getListElementCreationOptions(org.opencms.util.CmsUUID, java.lang.String) 1303 */ 1304 public CmsListElementCreationDialogData getListElementCreationOptions(CmsUUID structureId, String jsonListAddData) 1305 throws CmsRpcException { 1306 1307 CmsObject cms = getCmsObject(); 1308 Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 1309 CmsMessages msg = Messages.get().getBundle(locale); 1310 try { 1311 CmsUUID listId = structureId; 1312 1313 String jsonConfig = jsonListAddData; 1314 I_CmsAutoBeanFactory beanFactory = AutoBeanFactorySource.create(I_CmsAutoBeanFactory.class); 1315 AutoBean<I_CmsListAddMetadata> listAddData = AutoBeanCodex.decode( 1316 beanFactory, 1317 I_CmsListAddMetadata.class, 1318 jsonConfig); 1319 CmsListElementCreationDialogData result = new CmsListElementCreationDialogData(); 1320 result.setCaption(msg.key(Messages.GUI_LISTADD_CAPTION_0)); 1321 result.setPostCreateHandler(listAddData.as().getPostCreateHandler()); 1322 String uploadFolder = listAddData.as().getUploadFolder(); 1323 boolean isUpload = false; 1324 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(uploadFolder) && !"none".equals(uploadFolder)) { 1325 if (listAddData.as().getTypes().stream().anyMatch( 1326 type -> CmsResourceTypeBinary.getStaticTypeName().equals(type) 1327 || CmsResourceTypePlain.getStaticTypeName().equals(type) 1328 || CmsResourceTypeImage.getStaticTypeName().equals(type))) { 1329 1330 CmsResource uploadFolderResource = null; 1331 try { 1332 uploadFolderResource = cms.readResource(uploadFolder, CmsResourceFilter.IGNORE_EXPIRATION); 1333 if (cms.hasPermissions( 1334 uploadFolderResource, 1335 CmsPermissionSet.ACCESS_WRITE, 1336 false, 1337 CmsResourceFilter.IGNORE_EXPIRATION)) { 1338 isUpload = true; 1339 } 1340 } catch (CmsVfsResourceNotFoundException | CmsPermissionViolationException e) { 1341 LOG.debug(e.getLocalizedMessage(), e); 1342 } catch (Exception e) { 1343 LOG.error(e.getLocalizedMessage(), e); 1344 } 1345 } 1346 } 1347 if (isUpload) { 1348 result.setUploadFolder(uploadFolder); 1349 CmsListInfoBean listResourceInfo = CmsVfsService.getPageInfo( 1350 cms, 1351 cms.readResource(uploadFolder, CmsResourceFilter.IGNORE_EXPIRATION)); 1352 result.setListInfo(listResourceInfo); 1353 } else { 1354 CmsADEConfigData adeConfig = OpenCms.getADEManager().lookupConfiguration( 1355 cms, 1356 cms.getRequestContext().getRootUri()); 1357 CmsResource listResource = cms.readResource(listId, CmsResourceFilter.IGNORE_EXPIRATION); 1358 CmsListInfoBean listResourceInfo = CmsVfsService.getPageInfo(cms, listResource); 1359 result.setListInfo(listResourceInfo); 1360 List<String> createTypes = listAddData.as().getTypes(); 1361 Map<String, CmsResourceTypeConfig> typeMap = adeConfig.getTypesByName(); 1362 for (String type : createTypes) { 1363 try { 1364 CmsResourceTypeConfig currentType = typeMap.get(type); 1365 if (currentType != null) { 1366 if (adeConfig.getDirectEditPermissions(type).canCreate() 1367 && currentType.checkCreatable(cms, null)) { 1368 CmsListInfoBean typeInfo = new CmsListInfoBean(); 1369 CmsExplorerTypeSettings explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting( 1370 type); 1371 String title = CmsWorkplaceMessages.getResourceTypeName(locale, type); 1372 typeInfo.setTitle(title); 1373 String description = CmsWorkplaceMessages.getResourceTypeDescription(locale, type); 1374 typeInfo.setSubTitle(description); 1375 typeInfo.setResourceType(type); 1376 typeInfo.setBigIconClasses(CmsIconUtil.getIconClasses(explorerType, null, false)); 1377 String newLink = CmsJspTagEdit.getNewLink( 1378 cms, 1379 OpenCms.getResourceManager().getResourceType(type), 1380 cms.getRequestContext().getUri()); 1381 CmsListElementCreationOption option = new CmsListElementCreationOption( 1382 type, 1383 typeInfo, 1384 newLink); 1385 result.add(option); 1386 } 1387 } 1388 } catch (Exception e) { 1389 LOG.error(e.getLocalizedMessage(), e); 1390 } 1391 } 1392 if (result.getOptions().size() == 0) { 1393 result.setMessage(msg.key(Messages.GUI_LISTADD_NO_TYPES_0)); 1394 } 1395 } 1396 1397 return result; 1398 } catch (Exception e) { 1399 error(e); 1400 return null; 1401 } 1402 } 1403 1404 /** 1405 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getNewElementData(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, org.opencms.util.CmsUUID, java.lang.String, java.lang.String, java.util.Collection, java.lang.String) 1406 */ 1407 public CmsContainerElementData getNewElementData( 1408 CmsContainerPageRpcContext context, 1409 CmsUUID detailContentId, 1410 String reqParams, 1411 String resourceType, 1412 Collection<CmsContainer> containers, 1413 String localeName) 1414 throws CmsRpcException { 1415 1416 CmsContainerElementData result = null; 1417 try { 1418 ensureSession(); 1419 CmsResource pageResource = getCmsObject().readResource( 1420 context.getPageStructureId(), 1421 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 1422 initRequestFromRpcContext(context); 1423 String containerpageUri = getCmsObject().getSitePath(pageResource); 1424 Locale locale = CmsLocaleManager.getLocale(localeName); 1425 result = getNewElement( 1426 getServerIdString(resourceType), 1427 containerpageUri, 1428 detailContentId, 1429 containers, 1430 locale); 1431 } catch (Throwable e) { 1432 error(e); 1433 } 1434 return result; 1435 } 1436 1437 /** 1438 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getNewOptions(java.lang.String, org.opencms.util.CmsUUID, java.lang.String) 1439 */ 1440 public CmsDialogOptionsAndInfo getNewOptions(String clientId, CmsUUID pageStructureId, String requestParams) 1441 throws CmsRpcException { 1442 1443 try { 1444 CmsResource pageResource = getCmsObject().readResource( 1445 pageStructureId, 1446 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 1447 CmsContainerElementBean element = getCachedElement(clientId, pageResource.getRootPath()); 1448 element.initResource(getCmsObject()); 1449 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource()); 1450 if (type instanceof CmsResourceTypeXmlContent) { 1451 I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)type).getEditHandler(getCmsObject()); 1452 Map<String, String[]> params = CmsRequestUtil.createParameterMap( 1453 CmsEncoder.decode(requestParams), 1454 true, 1455 CmsEncoder.ENCODING_UTF_8); 1456 CmsDialogOptions options = handler.getNewOptions(getCmsObject(), element, pageStructureId, params); 1457 if (options != null) { 1458 return new CmsDialogOptionsAndInfo( 1459 options, 1460 CmsVfsService.getPageInfo(getCmsObject(), element.getResource())); 1461 } 1462 } 1463 } catch (CmsException e) { 1464 error(e); 1465 } 1466 return null; 1467 1468 } 1469 1470 /** 1471 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getRecentList(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID, java.util.Collection, java.lang.String) 1472 */ 1473 public List<CmsContainerElementData> getRecentList( 1474 CmsUUID pageStructureId, 1475 CmsUUID detailContentId, 1476 Collection<CmsContainer> containers, 1477 String locale) 1478 throws CmsRpcException { 1479 1480 List<CmsContainerElementData> result = null; 1481 try { 1482 ensureSession(); 1483 CmsResource containerpage = getCmsObject().readResource( 1484 pageStructureId, 1485 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 1486 String containerpageUri = getCmsObject().getSitePath(containerpage); 1487 result = getListElementsData( 1488 OpenCms.getADEManager().getRecentList(getCmsObject()), 1489 containerpageUri, 1490 detailContentId, 1491 containers, 1492 CmsLocaleManager.getLocale(locale)); 1493 } catch (Throwable e) { 1494 error(e); 1495 } 1496 return result; 1497 } 1498 1499 /** 1500 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#getRemovedElementStatus(java.lang.String, org.opencms.util.CmsUUID) 1501 */ 1502 public CmsRemovedElementStatus getRemovedElementStatus(String id, CmsUUID containerpageId) throws CmsRpcException { 1503 1504 if ((id == null) || !id.matches(CmsUUID.UUID_REGEX + ".*$")) { 1505 return new CmsRemovedElementStatus(null, null, false, null); 1506 } 1507 try { 1508 CmsUUID structureId = convertToServerId(id); 1509 return internalGetRemovedElementStatus(structureId, containerpageId); 1510 } catch (CmsException e) { 1511 error(e); 1512 return null; 1513 } 1514 } 1515 1516 /** 1517 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#handleDelete(java.lang.String, java.lang.String, org.opencms.util.CmsUUID, java.lang.String) 1518 */ 1519 public void handleDelete(String clientId, String deleteOption, CmsUUID pageId, String requestParams) 1520 throws CmsRpcException { 1521 1522 try { 1523 CmsResource pageResource = getCmsObject().readResource( 1524 pageId, 1525 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 1526 CmsContainerElementBean element = getCachedElement(clientId, pageResource.getRootPath()); 1527 element.initResource(getCmsObject()); 1528 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource()); 1529 if (type instanceof CmsResourceTypeXmlContent) { 1530 I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)type).getEditHandler(getCmsObject()); 1531 Map<String, String[]> params = CmsRequestUtil.createParameterMap( 1532 CmsEncoder.decode(requestParams), 1533 true, 1534 CmsEncoder.ENCODING_UTF_8); 1535 handler.handleDelete(getCmsObject(), element, deleteOption, pageId, params); 1536 } 1537 } catch (CmsException e) { 1538 error(e); 1539 } 1540 } 1541 1542 /** 1543 * Internal helper method to get the status of a removed element.<p> 1544 * 1545 * @param structureId the structure id of the removed element 1546 * @param containerpageId the id of the page to exclude from the relation check, or null if no page should be excluded 1547 * 1548 * @return the status of the removed element 1549 * 1550 * @throws CmsException in case reading the resource fails 1551 */ 1552 public CmsRemovedElementStatus internalGetRemovedElementStatus(CmsUUID structureId, CmsUUID containerpageId) 1553 throws CmsException { 1554 1555 CmsObject cms = getCmsObject(); 1556 CmsResource elementResource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION); 1557 boolean hasWritePermissions = cms.hasPermissions( 1558 elementResource, 1559 CmsPermissionSet.ACCESS_WRITE, 1560 false, 1561 CmsResourceFilter.ALL); 1562 boolean isSystemResource = elementResource.getRootPath().startsWith(CmsResource.VFS_FOLDER_SYSTEM + "/"); 1563 CmsRelationFilter relationFilter = CmsRelationFilter.relationsToStructureId(structureId); 1564 List<CmsRelation> relationsToElement = cms.readRelations(relationFilter); 1565 Iterator<CmsRelation> iter = relationsToElement.iterator(); 1566 1567 // ignore XML_STRONG (i.e. container element) relations from the container page, this must be checked on the client side. 1568 while (iter.hasNext()) { 1569 CmsRelation relation = iter.next(); 1570 if ((containerpageId != null) 1571 && containerpageId.equals(relation.getSourceId()) 1572 && relation.getType().equals(CmsRelationType.XML_STRONG)) { 1573 iter.remove(); 1574 } 1575 } 1576 ElementDeleteMode elementDeleteMode = null; 1577 CmsResource pageResource = cms.readResource(containerpageId, CmsResourceFilter.IGNORE_EXPIRATION); 1578 CmsADEConfigData adeConfig = OpenCms.getADEManager().lookupConfiguration(cms, pageResource.getRootPath()); 1579 CmsResourceTypeConfig typeConfig = adeConfig.getResourceType( 1580 OpenCms.getResourceManager().getResourceType(elementResource).getTypeName()); 1581 1582 if (typeConfig != null) { 1583 elementDeleteMode = typeConfig.getElementDeleteMode(); 1584 } 1585 1586 boolean hasNoRelations = relationsToElement.isEmpty(); 1587 boolean deletionCandidate = hasNoRelations && hasWritePermissions && !isSystemResource; 1588 CmsListInfoBean elementInfo = CmsVfsService.getPageInfo(cms, elementResource); 1589 return new CmsRemovedElementStatus(structureId, elementInfo, deletionCandidate, elementDeleteMode); 1590 } 1591 1592 /** 1593 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#loadClipboardTab() 1594 */ 1595 public int loadClipboardTab() { 1596 1597 Integer clipboardTab = (Integer)(getRequest().getSession().getAttribute(ATTR_CLIPBOARD_TAB)); 1598 if (clipboardTab == null) { 1599 clipboardTab = Integer.valueOf(0); 1600 } 1601 return clipboardTab.intValue(); 1602 } 1603 1604 /** 1605 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#prefetch() 1606 */ 1607 public CmsCntPageData prefetch() throws CmsRpcException { 1608 1609 CmsCntPageData data = null; 1610 CmsObject cms = getCmsObject(); 1611 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 1612 HttpServletRequest request = getRequest(); 1613 1614 try { 1615 Map<String, String> sessionStorageData = new HashMap<>(); 1616 CmsTemplateContextInfo info = OpenCms.getTemplateContextManager().getContextInfoBean(cms, request); 1617 CmsResource containerPage = getContainerpage(cms); 1618 Set<String> detailTypes = getDetailTypes(cms, containerPage); 1619 boolean isEditingModelGroup = isEditingModelGroups(cms, containerPage); 1620 boolean isModelPage = isModelPage(cms, containerPage); 1621 if (isModelPage) { 1622 // the model edit confirm dialog should only be shown once per session, disable it after first model editing 1623 getRequest().getSession().setAttribute( 1624 CmsVfsSitemapService.ATTR_SHOW_MODEL_EDIT_CONFIRM, 1625 Boolean.FALSE); 1626 } 1627 1628 TemplateBean templateBean = (TemplateBean)getRequest().getAttribute( 1629 CmsTemplateContextManager.ATTR_TEMPLATE_BEAN); 1630 CmsADESessionCache sessionCache = CmsADESessionCache.getCache(getRequest(), cms); 1631 sessionCache.setTemplateBean(containerPage.getRootPath(), templateBean); 1632 long lastModified = containerPage.getDateLastModified(); 1633 String editorUri = OpenCms.getWorkplaceManager().getEditorHandler().getEditorUri( 1634 cms, 1635 CmsResourceTypeXmlContent.getStaticTypeName(), 1636 "User agent", 1637 false); 1638 boolean useClassicEditor = (editorUri == null) || !editorUri.contains("acacia"); 1639 CmsResource detailResource = CmsDetailPageResourceHandler.getDetailResource(request); 1640 String noEditReason; 1641 String detailContainerPage = null; 1642 CmsQuickLaunchLocationCache locationCache = CmsQuickLaunchLocationCache.getLocationCache( 1643 request.getSession()); 1644 CmsUUID detailContainerPageId = null; 1645 if (detailResource != null) { 1646 locationCache.setPageEditorResource(cms.getRequestContext().getSiteRoot(), detailResource); 1647 CmsObject rootCms = OpenCms.initCmsObject(cms); 1648 rootCms.getRequestContext().setSiteRoot(""); 1649 String detailResourcePath = detailResource.getRootPath(); 1650 String locale = cms.getRequestContext().getLocale().toString(); 1651 detailContainerPage = CmsDetailOnlyContainerUtil.getDetailOnlyPageName( 1652 cms, 1653 containerPage, 1654 detailResourcePath, 1655 locale); 1656 1657 if (rootCms.existsResource(detailContainerPage, CmsResourceFilter.IGNORE_EXPIRATION)) { 1658 detailContainerPageId = rootCms.readResource( 1659 detailContainerPage, 1660 CmsResourceFilter.IGNORE_EXPIRATION).getStructureId(); 1661 noEditReason = getNoEditReason( 1662 rootCms, 1663 rootCms.readResource(detailContainerPage, CmsResourceFilter.IGNORE_EXPIRATION)); 1664 } else { 1665 String permissionFolder = CmsResource.getFolderPath(detailContainerPage); 1666 while (!rootCms.existsResource(permissionFolder, CmsResourceFilter.IGNORE_EXPIRATION)) { 1667 permissionFolder = CmsResource.getParentFolder(permissionFolder); 1668 } 1669 noEditReason = getNoEditReason( 1670 rootCms, 1671 rootCms.readResource(permissionFolder, CmsResourceFilter.IGNORE_EXPIRATION)); 1672 } 1673 } else { 1674 if (!isModelPage && !isEditingModelGroup) { 1675 locationCache.setPageEditorResource(cms.getRequestContext().getSiteRoot(), containerPage); 1676 sessionStorageData.put( 1677 CmsGwtConstants.LAST_CONTAINER_PAGE_ID, 1678 containerPage.getStructureId().toString()); 1679 } 1680 noEditReason = getNoEditReason(cms, containerPage); 1681 } 1682 1683 String sitemapPath = ""; 1684 boolean sitemapManager = OpenCms.getRoleManager().hasRole(cms, CmsRole.EDITOR); 1685 if (sitemapManager) { 1686 sitemapPath = CmsADEManager.PATH_SITEMAP_EDITOR_JSP; 1687 } 1688 CmsCntPageData.ElementReuseMode reuseMode = ElementReuseMode.reuse; 1689 String reuseModeString = getWorkplaceSettings().getUserSettings().getAdditionalPreference( 1690 "elementReuseMode", 1691 true); 1692 1693 try { 1694 reuseMode = ElementReuseMode.valueOf(reuseModeString); 1695 } catch (Exception e) { 1696 LOG.info("Invalid reuse mode : " + reuseModeString, e); 1697 } 1698 InitialElementViewProvider viewHelper = new InitialElementViewProvider(); 1699 viewHelper.init(getSessionCache().getElementView(), containerPage, info); 1700 CmsLocaleGroup group = cms.getLocaleGroupService().readLocaleGroup(containerPage); 1701 Locale mainLocale = null; 1702 1703 if (group.isRealGroup() && !cms.getRequestContext().getLocale().equals(group.getMainLocale())) { 1704 mainLocale = group.getMainLocale(); 1705 } 1706 CmsSiteManagerImpl siteManager = OpenCms.getSiteManager(); 1707 String ownRoot = siteManager.getSiteRoot(containerPage.getRootPath()); 1708 Map<String, CmsLocaleLinkBean> localeLinkBeans = null; 1709 if (group.isRealGroup()) { 1710 localeLinkBeans = Maps.newHashMap(); 1711 Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 1712 for (Map.Entry<Locale, CmsResource> entry : group.getResourcesByLocale().entrySet()) { 1713 String otherRoot = siteManager.getSiteRoot(entry.getValue().getRootPath()); 1714 if ((otherRoot != null) && otherRoot.equals(ownRoot)) { 1715 String theLink = OpenCms.getLinkManager().substituteLinkForUnknownTarget( 1716 cms, 1717 cms.getRequestContext().removeSiteRoot(entry.getValue().getRootPath())); 1718 localeLinkBeans.put(entry.getKey().getDisplayLanguage(locale), CmsLocaleLinkBean.link(theLink)); 1719 } else { 1720 localeLinkBeans.put( 1721 entry.getKey().getDisplayLanguage(locale), 1722 CmsLocaleLinkBean.error( 1723 Messages.get().getBundle(locale).key(Messages.GUI_SHOWLOCALE_WRONG_SITE_0))); 1724 } 1725 } 1726 } 1727 1728 String onlineLink = null; 1729 CmsSite site = OpenCms.getSiteManager().getSiteForSiteRoot(cms.getRequestContext().getSiteRoot()); 1730 if ((site != null) && !OpenCms.getSiteManager().getWorkplaceServer().equals(site.getUrl())) { 1731 if (detailResource != null) { 1732 onlineLink = OpenCms.getLinkManager().getOnlineLink( 1733 cms, 1734 cms.getSitePath(detailResource), 1735 cms.getSitePath(containerPage), 1736 false); 1737 } else { 1738 onlineLink = OpenCms.getLinkManager().getOnlineLink(cms, cms.getSitePath(containerPage)); 1739 } 1740 } 1741 1742 String modelGroupElementId = null; 1743 if (isEditingModelGroup) { 1744 CmsProperty modelElementProp = cms.readPropertyObject( 1745 containerPage, 1746 CmsPropertyDefinition.PROPERTY_TEMPLATE_ELEMENTS, 1747 false); 1748 if (!modelElementProp.isNullProperty() && CmsUUID.isValidUUID(modelElementProp.getValue())) { 1749 modelGroupElementId = modelElementProp.getValue(); 1750 } 1751 } 1752 String title = null; 1753 if (isModelPage || isEditingModelGroup) { 1754 title = Messages.get().getBundle(wpLocale).key(Messages.GUI_TITLE_MODEL_0); 1755 1756 } 1757 ElementDeleteMode deleteMode = OpenCms.getWorkplaceManager().getElementDeleteMode(); 1758 if (deleteMode == null) { 1759 deleteMode = ElementDeleteMode.askDelete; 1760 } 1761 CmsListInfoBean pageInfo = CmsVfsService.getPageInfo(cms, containerPage); 1762 data = new CmsCntPageData( 1763 onlineLink, 1764 noEditReason, 1765 CmsRequestUtil.encodeParams(request), 1766 sitemapPath, 1767 sitemapManager, 1768 detailResource != null ? detailResource.getStructureId() : null, 1769 detailContainerPage, 1770 detailContainerPageId, 1771 detailTypes, 1772 lastModified, 1773 getLockInfo(containerPage), 1774 pageInfo, 1775 cms.getRequestContext().getLocale().toString(), 1776 useClassicEditor, 1777 info, 1778 isEditSmallElements(request, cms), 1779 Lists.newArrayList(viewHelper.getViewMap().values()), 1780 viewHelper.getDefaultView(), 1781 reuseMode, 1782 deleteMode, 1783 isModelPage, 1784 isEditingModelGroup, 1785 modelGroupElementId, 1786 mainLocale != null ? mainLocale.toString() : null, 1787 localeLinkBeans, 1788 title, 1789 System.currentTimeMillis()); 1790 boolean allowSettingsInEditor = true; 1791 CmsModule baseModule = OpenCms.getModuleManager().getModule("org.opencms.base"); 1792 if (baseModule != null) { 1793 String param = baseModule.getParameter("allowSettingsInEditor"); 1794 allowSettingsInEditor = CmsStringUtil.isEmptyOrWhitespaceOnly(param) 1795 || Boolean.valueOf(param).booleanValue(); 1796 } 1797 data.setAllowSettingsInEditor(allowSettingsInEditor); 1798 data.setSessionStorageData(sessionStorageData); 1799 } catch (Throwable e) { 1800 error(e); 1801 } 1802 return data; 1803 } 1804 1805 /** 1806 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#prepareForEdit(java.lang.String, java.lang.String, org.opencms.util.CmsUUID, java.lang.String) 1807 */ 1808 public CmsUUID prepareForEdit(String clientId, String editOption, CmsUUID pageId, String requestParams) 1809 throws CmsRpcException { 1810 1811 try { 1812 CmsResource pageResource = getCmsObject().readResource( 1813 pageId, 1814 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 1815 CmsContainerElementBean element = getCachedElement(clientId, pageResource.getRootPath()); 1816 element.initResource(getCmsObject()); 1817 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource()); 1818 if (type instanceof CmsResourceTypeXmlContent) { 1819 I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)type).getEditHandler(getCmsObject()); 1820 Map<String, String[]> params = CmsRequestUtil.createParameterMap( 1821 CmsEncoder.decode(requestParams), 1822 true, 1823 CmsEncoder.ENCODING_UTF_8); 1824 return handler.prepareForEdit(getCmsObject(), element, editOption, pageId, params); 1825 } 1826 } catch (CmsException e) { 1827 error(e); 1828 } 1829 return null; 1830 } 1831 1832 /** 1833 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#replaceElement(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, org.opencms.util.CmsUUID, java.lang.String, java.lang.String, java.lang.String, java.util.Collection, java.lang.String) 1834 */ 1835 public CmsContainerElementData replaceElement( 1836 CmsContainerPageRpcContext context, 1837 CmsUUID detailContentId, 1838 String reqParams, 1839 String clientId, 1840 String replaceId, 1841 Collection<CmsContainer> containers, 1842 String locale) 1843 throws CmsRpcException { 1844 1845 CmsContainerElementData element = null; 1846 try { 1847 ensureSession(); 1848 CmsObject cms = getCmsObject(); 1849 CmsResource pageResource = cms.readResource( 1850 context.getPageStructureId(), 1851 CmsResourceFilter.ignoreExpirationOffline(cms)); 1852 initRequestFromRpcContext(context); 1853 String containerpageUri = cms.getSitePath(pageResource); 1854 Locale contentLocale = CmsLocaleManager.getLocale(locale); 1855 CmsElementUtil elemUtil = new CmsElementUtil( 1856 cms, 1857 containerpageUri, 1858 generateContainerPageForContainers(containers, pageResource.getRootPath()), 1859 detailContentId, 1860 getRequest(), 1861 getResponse(), 1862 false, 1863 contentLocale); 1864 1865 CmsContainerElementBean elementBean = getCachedElement(clientId, pageResource.getRootPath()); 1866 Map<String, String> settings = new HashMap<String, String>(elementBean.getIndividualSettings()); 1867 settings.remove(CmsContainerElement.ELEMENT_INSTANCE_ID); 1868 CmsContainerElementBean replaceBean = new CmsContainerElementBean( 1869 new CmsUUID(replaceId), 1870 elementBean.getFormatterId(), 1871 settings, 1872 elementBean.isCreateNew()); 1873 getSessionCache().setCacheContainerElement(replaceBean.editorHash(), replaceBean); 1874 element = elemUtil.getElementData(pageResource, replaceBean, containers); 1875 } catch (Throwable e) { 1876 error(e); 1877 } 1878 return element; 1879 } 1880 1881 /** 1882 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#saveClipboardTab(int) 1883 */ 1884 public void saveClipboardTab(int tabIndex) { 1885 1886 getRequest().getSession().setAttribute(ATTR_CLIPBOARD_TAB, Integer.valueOf(tabIndex)); 1887 } 1888 1889 /** 1890 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#saveContainerpage(org.opencms.util.CmsUUID, java.util.List) 1891 */ 1892 public long saveContainerpage(CmsUUID pageStructureId, List<CmsContainer> containers) throws CmsRpcException { 1893 1894 CmsObject cms = getCmsObject(); 1895 try { 1896 ensureSession(); 1897 CmsResource containerpage = cms.readResource( 1898 pageStructureId, 1899 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 1900 ensureLock(containerpage); 1901 String containerpageUri = cms.getSitePath(containerpage); 1902 saveContainers(cms, containerpage, containerpageUri, containers); 1903 } catch (Throwable e) { 1904 error(e); 1905 } 1906 return System.currentTimeMillis(); 1907 } 1908 1909 /** 1910 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#saveDetailContainers(org.opencms.util.CmsUUID, java.lang.String, java.util.List) 1911 */ 1912 public long saveDetailContainers(CmsUUID detailId, String detailContainerResource, List<CmsContainer> containers) 1913 throws CmsRpcException { 1914 1915 CmsObject cms = getCmsObject(); 1916 try { 1917 ensureSession(); 1918 CmsObject rootCms = OpenCms.initCmsObject(cms); 1919 rootCms.getRequestContext().setSiteRoot(""); 1920 CmsResource containerpage; 1921 containerpage = CmsDetailOnlyContainerUtil.readOrCreateDetailOnlyPage( 1922 rootCms, 1923 detailId, 1924 detailContainerResource); 1925 saveContainers(rootCms, containerpage, detailContainerResource, containers); 1926 } catch (Throwable e) { 1927 error(e); 1928 } 1929 return System.currentTimeMillis(); 1930 } 1931 1932 /** 1933 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#saveElementSettings(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, org.opencms.util.CmsUUID, java.lang.String, java.lang.String, java.util.Map, java.util.List, java.lang.String) 1934 */ 1935 public CmsContainerElementData saveElementSettings( 1936 CmsContainerPageRpcContext context, 1937 CmsUUID detailContentId, 1938 String reqParams, 1939 String clientId, 1940 Map<String, String> settings, 1941 List<CmsContainer> containers, 1942 String locale) 1943 throws CmsRpcException { 1944 1945 CmsContainerElementData element = null; 1946 try { 1947 ensureSession(); 1948 CmsObject cms = getCmsObject(); 1949 CmsResource pageResource = cms.readResource( 1950 context.getPageStructureId(), 1951 CmsResourceFilter.ignoreExpirationOffline(cms)); 1952 initRequestFromRpcContext(context); 1953 Locale contentLocale = CmsLocaleManager.getLocale(locale); 1954 CmsContainerElementBean elementBean = getCachedElement(clientId, pageResource.getRootPath()); 1955 elementBean.initResource(cms); 1956 storeFormatterSelection(elementBean, settings); 1957 // make sure to keep the element instance id 1958 if (!settings.containsKey(CmsContainerElement.ELEMENT_INSTANCE_ID) 1959 && elementBean.getIndividualSettings().containsKey(CmsContainerElement.ELEMENT_INSTANCE_ID)) { 1960 settings.put( 1961 CmsContainerElement.ELEMENT_INSTANCE_ID, 1962 elementBean.getIndividualSettings().get(CmsContainerElement.ELEMENT_INSTANCE_ID)); 1963 } 1964 if (elementBean.getIndividualSettings().containsKey(CmsContainerElement.SETTING_PAGE_ID)) { 1965 settings.put( 1966 CmsContainerElement.SETTING_PAGE_ID, 1967 elementBean.getIndividualSettings().get(CmsContainerElement.SETTING_PAGE_ID)); 1968 } 1969 if (!isEditingModelGroups(cms, pageResource)) { 1970 // in case of model group state set to 'noGroup', the group will be dissolved and former group id forgotten 1971 if (!(settings.containsKey(CmsContainerElement.MODEL_GROUP_STATE) 1972 && (ModelGroupState.noGroup == ModelGroupState.evaluate( 1973 settings.get(CmsContainerElement.MODEL_GROUP_STATE))))) { 1974 if (elementBean.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_ID)) { 1975 // make sure to keep the model group id 1976 settings.put( 1977 CmsContainerElement.MODEL_GROUP_ID, 1978 elementBean.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_ID)); 1979 } 1980 if (elementBean.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_STATE)) { 1981 settings.put( 1982 CmsContainerElement.MODEL_GROUP_STATE, 1983 elementBean.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_STATE)); 1984 } 1985 } 1986 } 1987 elementBean = CmsContainerElementBean.cloneWithSettings( 1988 elementBean, 1989 convertSettingValues(elementBean.getResource(), settings, contentLocale)); 1990 getSessionCache().setCacheContainerElement(elementBean.editorHash(), elementBean); 1991 1992 // update client id within container data 1993 for (CmsContainer container : containers) { 1994 for (CmsContainerElement child : container.getElements()) { 1995 if (child.getClientId().equals(clientId)) { 1996 child.setClientId(elementBean.editorHash()); 1997 } 1998 } 1999 } 2000 if (detailContentId == null) { 2001 saveContainers(cms, pageResource, cms.getSitePath(pageResource), containers); 2002 } else { 2003 List<CmsContainer> detailContainers = new ArrayList<CmsContainer>(); 2004 for (CmsContainer container : containers) { 2005 if (container.isDetailOnly()) { 2006 detailContainers.add(container); 2007 } 2008 } 2009 CmsObject rootCms = OpenCms.initCmsObject(cms); 2010 rootCms.getRequestContext().setSiteRoot(""); 2011 CmsResource detailResource = rootCms.readResource(detailContentId, CmsResourceFilter.IGNORE_EXPIRATION); 2012 String detailRootPath = detailResource.getRootPath(); 2013 CmsResource detailContainerPage = rootCms.readResource( 2014 CmsDetailOnlyContainerUtil.getDetailOnlyPageName(cms, pageResource, detailRootPath, locale)); 2015 2016 ensureLock(detailContainerPage); 2017 saveContainers(rootCms, detailContainerPage, detailContainerPage.getRootPath(), detailContainers); 2018 } 2019 String containerpageUri = cms.getSitePath(pageResource); 2020 CmsElementUtil elemUtil = new CmsElementUtil( 2021 cms, 2022 containerpageUri, 2023 generateContainerPageForContainers(containers, pageResource.getRootPath()), 2024 detailContentId, 2025 getRequest(), 2026 getResponse(), 2027 false, 2028 contentLocale); 2029 element = elemUtil.getElementData(pageResource, elementBean, containers); 2030 } catch (Throwable e) { 2031 error(e); 2032 } 2033 return element; 2034 } 2035 2036 /** 2037 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#saveFavoriteList(java.util.List, java.lang.String) 2038 */ 2039 public void saveFavoriteList(List<String> clientIds, String uri) throws CmsRpcException { 2040 2041 try { 2042 ensureSession(); 2043 OpenCms.getADEManager().saveFavoriteList( 2044 getCmsObject(), 2045 getCachedElements(clientIds, getCmsObject().getRequestContext().addSiteRoot(uri))); 2046 } catch (Throwable e) { 2047 error(e); 2048 } 2049 } 2050 2051 /** 2052 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#saveGroupContainer(org.opencms.ade.containerpage.shared.CmsContainerPageRpcContext, org.opencms.util.CmsUUID, java.lang.String, org.opencms.ade.containerpage.shared.CmsGroupContainer, java.util.Collection, java.lang.String) 2053 */ 2054 public CmsGroupContainerSaveResult saveGroupContainer( 2055 CmsContainerPageRpcContext context, 2056 2057 CmsUUID detailContentId, 2058 String reqParams, 2059 CmsGroupContainer groupContainer, 2060 Collection<CmsContainer> containers, 2061 String locale) 2062 throws CmsRpcException { 2063 2064 CmsObject cms = getCmsObject(); 2065 List<CmsRemovedElementStatus> removedElements = null; 2066 try { 2067 CmsPair<CmsContainerElement, List<CmsRemovedElementStatus>> saveResult = internalSaveGroupContainer( 2068 cms, 2069 context.getPageStructureId(), 2070 groupContainer); 2071 removedElements = saveResult.getSecond(); 2072 } catch (Throwable e) { 2073 error(e); 2074 } 2075 Collection<String> ids = new ArrayList<String>(); 2076 ids.add(groupContainer.getClientId()); 2077 // update offline indices 2078 OpenCms.getSearchManager().updateOfflineIndexes(); 2079 return new CmsGroupContainerSaveResult( 2080 getElementsData(context, detailContentId, reqParams, ids, containers, false, null, locale), 2081 removedElements); 2082 } 2083 2084 /** 2085 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#saveInheritanceContainer(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID, org.opencms.ade.containerpage.shared.CmsInheritanceContainer, java.util.Collection, java.lang.String) 2086 */ 2087 public Map<String, CmsContainerElementData> saveInheritanceContainer( 2088 CmsUUID pageStructureId, 2089 CmsUUID detailContentId, 2090 CmsInheritanceContainer inheritanceContainer, 2091 Collection<CmsContainer> containers, 2092 String locale) 2093 throws CmsRpcException { 2094 2095 try { 2096 CmsObject cms = getCmsObject(); 2097 CmsADEConfigData rpcConfig = OpenCms.getADEManager().lookupConfiguration( 2098 cms, 2099 cms.getRequestContext().getRootUri()); 2100 CmsResource containerPage = cms.readResource( 2101 pageStructureId, 2102 CmsResourceFilter.ignoreExpirationOffline(getCmsObject())); 2103 String sitePath = cms.getSitePath(containerPage); 2104 Locale requestedLocale = CmsLocaleManager.getLocale(locale); 2105 CmsResource referenceResource = null; 2106 if (inheritanceContainer.isNew()) { 2107 CmsADEConfigData config = getConfigData(containerPage.getRootPath()); 2108 CmsResourceTypeConfig typeConfig = config.getResourceType( 2109 CmsResourceTypeXmlContainerPage.INHERIT_CONTAINER_TYPE_NAME); 2110 referenceResource = typeConfig.createNewElement(cms, containerPage.getRootPath()); 2111 inheritanceContainer.setClientId(referenceResource.getStructureId().toString()); 2112 } 2113 if (referenceResource == null) { 2114 CmsUUID id = convertToServerId(inheritanceContainer.getClientId()); 2115 referenceResource = cms.readResource(id, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2116 } 2117 ensureLock(referenceResource); 2118 saveInheritanceGroup(referenceResource, inheritanceContainer); 2119 tryUnlock(referenceResource); 2120 List<CmsContainerElementBean> elements = new ArrayList<CmsContainerElementBean>(); 2121 for (CmsContainerElement clientElement : inheritanceContainer.getElements()) { 2122 CmsContainerElementBean elementBean = getCachedElement( 2123 clientElement.getClientId(), 2124 containerPage.getRootPath()); 2125 elementBean = CmsContainerElementBean.cloneWithSettings( 2126 elementBean, 2127 elementBean.getIndividualSettings()); 2128 CmsInheritanceInfo inheritanceInfo = clientElement.getInheritanceInfo(); 2129 // if a local elements misses the key it was newly added 2130 if (inheritanceInfo.isNew() && CmsStringUtil.isEmptyOrWhitespaceOnly(inheritanceInfo.getKey())) { 2131 // generating new key 2132 inheritanceInfo.setKey(CmsResource.getFolderPath(sitePath) + new CmsUUID().toString()); 2133 } 2134 elementBean.setInheritanceInfo(inheritanceInfo); 2135 elements.add(elementBean); 2136 } 2137 cms.getRequestContext().setLocale(requestedLocale); 2138 if (inheritanceContainer.getElementsChanged()) { 2139 OpenCms.getADEManager().saveInheritedContainer( 2140 cms, 2141 containerPage, 2142 inheritanceContainer.getName(), 2143 true, 2144 elements); 2145 } 2146 return getElements( 2147 rpcConfig, 2148 containerPage, 2149 new ArrayList<String>(Collections.singletonList(inheritanceContainer.getClientId())), 2150 sitePath, 2151 detailContentId, 2152 containers, 2153 false, 2154 null, 2155 false, 2156 requestedLocale); 2157 } catch (Exception e) { 2158 error(e); 2159 } 2160 return null; 2161 } 2162 2163 /** 2164 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#saveRecentList(java.util.List, java.lang.String) 2165 */ 2166 public void saveRecentList(List<String> clientIds, String uri) throws CmsRpcException { 2167 2168 try { 2169 ensureSession(); 2170 OpenCms.getADEManager().saveRecentList( 2171 getCmsObject(), 2172 getCachedElements(clientIds, getCmsObject().getRequestContext().addSiteRoot(uri))); 2173 } catch (Throwable e) { 2174 error(e); 2175 } 2176 } 2177 2178 /** 2179 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#setEditSmallElements(boolean) 2180 */ 2181 public void setEditSmallElements(boolean editSmallElements) throws CmsRpcException { 2182 2183 try { 2184 CmsObject cms = getCmsObject(); 2185 CmsUser user = cms.getRequestContext().getCurrentUser(); 2186 user.getAdditionalInfo().put(ADDINFO_EDIT_SMALL_ELEMENTS, "" + editSmallElements); 2187 cms.writeUser(user); 2188 } catch (Throwable t) { 2189 error(t); 2190 } 2191 } 2192 2193 /** 2194 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#setElementView(org.opencms.util.CmsUUID) 2195 */ 2196 public void setElementView(CmsUUID elementView) { 2197 2198 getSessionCache().setElementView(elementView); 2199 } 2200 2201 /** 2202 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#setLastPage(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID) 2203 */ 2204 public void setLastPage(CmsUUID pageId, CmsUUID detailId) throws CmsRpcException { 2205 2206 try { 2207 HttpServletRequest req = getRequest(); 2208 CmsObject cms = getCmsObject(); 2209 CmsADESessionCache cache = CmsADESessionCache.getCache(req, cms); 2210 cache.setLastPage(cms, pageId, detailId); 2211 } catch (Exception e) { 2212 error(e); 2213 } 2214 2215 } 2216 2217 /** 2218 * Sets the session cache.<p> 2219 * 2220 * @param cache the session cache 2221 */ 2222 public void setSessionCache(CmsADESessionCache cache) { 2223 2224 m_sessionCache = cache; 2225 } 2226 2227 /** 2228 * @see org.opencms.ade.containerpage.shared.rpc.I_CmsContainerpageService#updateServerElementFormatter(java.lang.String, java.lang.String, java.util.Map) 2229 */ 2230 public void updateServerElementFormatter(String clientId, String containerId, Map<String, String> clientSettings) 2231 throws CmsRpcException { 2232 2233 try { 2234 CmsContainerElementBean elementBean = getSessionCache().getCacheContainerElement(clientId); 2235 if (elementBean != null) { 2236 HashMap<String, String> newSettings = new HashMap<>(elementBean.getIndividualSettings()); 2237 String key = CmsFormatterConfig.getSettingsKeyForContainer(containerId); 2238 String formatterId = clientSettings.get(key); 2239 if (formatterId != null) { 2240 newSettings.put(key, formatterId); 2241 } 2242 elementBean = CmsContainerElementBean.cloneWithSettings(elementBean, newSettings); 2243 getSessionCache().setCacheContainerElement(elementBean.editorHash(), elementBean); 2244 } 2245 2246 } catch (Exception e) { 2247 error(e); 2248 } 2249 } 2250 2251 /** 2252 * Gets the settings which should be updated for an element in the DND case.<p> 2253 * 2254 * @param config the sitemap configuration 2255 * @param originalSettings the original settings 2256 * @param formatterConfig the formatter configuration for the element 2257 * @param containers the containers 2258 * @param dndContainer the id of the DND origin container 2259 * 2260 * @return the map of settings to update 2261 */ 2262 Map<String, String> getSettingsToChangeForDnd( 2263 CmsADEConfigData config, 2264 Map<String, String> originalSettings, 2265 CmsFormatterConfiguration formatterConfig, 2266 Collection<CmsContainer> containers, 2267 String dndContainer) { 2268 2269 Map<String, String> result = Maps.newHashMap(); 2270 if (dndContainer == null) { 2271 return result; 2272 } 2273 String key = CmsFormatterConfig.getSettingsKeyForContainer(dndContainer); 2274 String formatterId = originalSettings.get(key); 2275 if (formatterId == null) { 2276 return result; 2277 } 2278 for (CmsContainer container : containers) { 2279 if (container.getName().equals(dndContainer)) { 2280 continue; 2281 } 2282 2283 Map<String, I_CmsFormatterBean> formatterSelection = formatterConfig.getFormatterSelection( 2284 container.getType(), 2285 container.getWidth()); 2286 I_CmsFormatterBean currentBean = config.findFormatter(formatterId); 2287 if (currentBean != null) { 2288 if (CmsFormatterConfiguration.matchFormatter(currentBean, container.getType(), container.getWidth())) { 2289 String newKey = CmsFormatterConfig.getSettingsKeyForContainer(container.getName()); 2290 result.put(newKey, currentBean.getKeyOrId()); 2291 } 2292 } else if (formatterSelection.containsKey(formatterId)) { 2293 // for backwards compatibility with schema-configured formatters 2294 String newKey = CmsFormatterConfig.getSettingsKeyForContainer(container.getName()); 2295 result.put(newKey, formatterId); 2296 } 2297 } 2298 return result; 2299 } 2300 2301 /** 2302 * Creates a new container element bean from an existing one, but changes some of the individual settings in the copy.<p> 2303 * 2304 * @param element the original container element 2305 * @param settingsToOverride the map of settings to change 2306 * 2307 * @return the new container element bean with the changed settings 2308 */ 2309 CmsContainerElementBean overrideSettings(CmsContainerElementBean element, Map<String, String> settingsToOverride) { 2310 2311 Map<String, String> settings = Maps.newHashMap(element.getIndividualSettings()); 2312 settings.putAll(settingsToOverride); 2313 CmsContainerElementBean result = new CmsContainerElementBean( 2314 element.getId(), 2315 element.getFormatterId(), 2316 settings, 2317 element.isCreateNew()); 2318 return result; 2319 } 2320 2321 /** 2322 * Adds the formatter to the recently used formatter list.<p> 2323 * 2324 * @param elementBean the element bean 2325 * @param settings the changed settings 2326 */ 2327 void storeFormatterSelection(CmsContainerElementBean elementBean, Map<String, String> settings) { 2328 2329 Entry<String, String> previousFormatterEntry = null; 2330 for (Entry<String, String> entry : elementBean.getIndividualSettings().entrySet()) { 2331 if (entry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) { 2332 previousFormatterEntry = entry; 2333 break; 2334 } 2335 } 2336 Entry<String, String> formatterEntry = null; 2337 for (Entry<String, String> entry : settings.entrySet()) { 2338 if (entry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) { 2339 formatterEntry = entry; 2340 break; 2341 } 2342 } 2343 if ((formatterEntry != null) 2344 && ((previousFormatterEntry == null) 2345 || !formatterEntry.getKey().equals(previousFormatterEntry.getKey()) 2346 || !formatterEntry.getValue().equals(previousFormatterEntry.getValue()))) { 2347 String idString = formatterEntry.getValue(); 2348 if (idString != null) { 2349 // the formatter setting has changed 2350 I_CmsResourceType resType = OpenCms.getResourceManager().getResourceType(elementBean.getResource()); 2351 getSessionCache().addRecentFormatter(resType.getTypeName(), idString); 2352 } 2353 } 2354 2355 } 2356 2357 /** 2358 * Converts the given setting values according to the setting configuration of the given resource.<p> 2359 * 2360 * @param resource the resource 2361 * @param settings the settings to convert 2362 * @param locale the locale used for accessing the element settings 2363 * 2364 * @return the converted settings 2365 * @throws CmsException if something goes wrong 2366 */ 2367 private Map<String, String> convertSettingValues(CmsResource resource, Map<String, String> settings, Locale locale) 2368 throws CmsException { 2369 2370 CmsObject cms = getCmsObject(); 2371 Locale origLocale = cms.getRequestContext().getLocale(); 2372 try { 2373 cms.getRequestContext().setLocale(locale); 2374 Map<String, CmsXmlContentProperty> settingsConf = OpenCms.getADEManager().getElementSettings(cms, resource); 2375 Map<String, String> changedSettings = new HashMap<String, String>(); 2376 if (settings != null) { 2377 for (Map.Entry<String, String> entry : settings.entrySet()) { 2378 String settingName = entry.getKey(); 2379 String settingType = "string"; 2380 if (settingsConf.get(settingName) != null) { 2381 settingType = settingsConf.get(settingName).getType(); 2382 } 2383 changedSettings.put( 2384 settingName, 2385 CmsXmlContentPropertyHelper.getPropValueIds(getCmsObject(), settingType, entry.getValue())); 2386 } 2387 } 2388 return changedSettings; 2389 } finally { 2390 cms.getRequestContext().setLocale(origLocale); 2391 } 2392 } 2393 2394 /** 2395 * Generates the XML container page bean for the given containers.<p> 2396 * 2397 * @param containers the containers 2398 * @param containerpageRootPath the container page root path 2399 * 2400 * @return the container page bean 2401 * @throws CmsException in case generating the page data fails 2402 */ 2403 private CmsContainerPageBean generateContainerPageForContainers( 2404 Collection<CmsContainer> containers, 2405 String containerpageRootPath) 2406 throws CmsException { 2407 2408 List<CmsContainerBean> containerBeans = new ArrayList<CmsContainerBean>(); 2409 for (CmsContainer container : containers) { 2410 CmsContainerBean containerBean = getContainerBeanToSave(container, containerpageRootPath); 2411 containerBeans.add(containerBean); 2412 } 2413 CmsContainerPageBean page = new CmsContainerPageBean(containerBeans); 2414 return page; 2415 } 2416 2417 /** 2418 * Returns a list of container elements from a list with client id's.<p> 2419 * 2420 * @param clientIds list of client id's 2421 * @param pageRootPath the container page root path 2422 * 2423 * @return a list of element beans 2424 * @throws CmsException in case reading the element resource fails 2425 */ 2426 private List<CmsContainerElementBean> getCachedElements(List<String> clientIds, String pageRootPath) 2427 throws CmsException { 2428 2429 List<CmsContainerElementBean> result = new ArrayList<CmsContainerElementBean>(); 2430 for (String id : clientIds) { 2431 try { 2432 result.add(getCachedElement(id, pageRootPath)); 2433 } catch (CmsIllegalArgumentException e) { 2434 log(e.getLocalizedMessage(), e); 2435 } 2436 } 2437 return result; 2438 } 2439 2440 /** 2441 * Returns the configuration data of the current container page context.<p> 2442 * 2443 * @param pageRootPath the container page root path 2444 * 2445 * @return the configuration data of the current container page context 2446 */ 2447 private CmsADEConfigData getConfigData(String pageRootPath) { 2448 2449 if (m_configData == null) { 2450 m_configData = OpenCms.getADEManager().lookupConfiguration(getCmsObject(), pageRootPath); 2451 } 2452 return m_configData; 2453 } 2454 2455 /** 2456 * Helper method for converting a CmsContainer to a CmsContainerBean when saving a container page.<p> 2457 * 2458 * @param container the container for which the CmsContainerBean should be created 2459 * @param containerpageRootPath the container page root path 2460 * 2461 * @return a container bean 2462 * 2463 * @throws CmsException in case generating the container data fails 2464 */ 2465 private CmsContainerBean getContainerBeanToSave(CmsContainer container, String containerpageRootPath) 2466 throws CmsException { 2467 2468 CmsObject cms = getCmsObject(); 2469 List<CmsContainerElementBean> elements = new ArrayList<CmsContainerElementBean>(); 2470 for (CmsContainerElement elementData : container.getElements()) { 2471 if (!elementData.isNew()) { 2472 CmsContainerElementBean newElementBean = getContainerElementBeanToSave( 2473 cms, 2474 containerpageRootPath, 2475 container, 2476 elementData); 2477 if (newElementBean != null) { 2478 elements.add(newElementBean); 2479 } 2480 } 2481 } 2482 CmsContainerBean result = CmsElementUtil.clientToServerContainer(container, elements); 2483 return result; 2484 } 2485 2486 /** 2487 * Converts container page element data to a bean which can be saved in a container page.<p> 2488 * 2489 * @param cms the current CMS context 2490 * @param containerpageRootPath the container page root path 2491 * @param container the container containing the element 2492 * @param elementData the data for the single element 2493 * 2494 * @return the container element bean 2495 * 2496 * @throws CmsException if something goes wrong 2497 */ 2498 private CmsContainerElementBean getContainerElementBeanToSave( 2499 CmsObject cms, 2500 String containerpageRootPath, 2501 CmsContainer container, 2502 CmsContainerElement elementData) 2503 throws CmsException { 2504 2505 String elementClientId = elementData.getClientId(); 2506 boolean hasUuidPrefix = (elementClientId != null) && elementClientId.matches(CmsUUID.UUID_REGEX + ".*$"); 2507 boolean isCreateNew = elementData.isCreateNew(); 2508 if (elementData.isNew() && !hasUuidPrefix) { 2509 2510 // Due to the changed save system without the save button, we need to make sure that new elements 2511 // are only created once. This must happen when the user first edits a new element. But we still 2512 // want to save changes to non-new elements on the page, so we skip new elements while saving. 2513 return null; 2514 } 2515 CmsContainerElementBean element = getCachedElement(elementData.getClientId(), containerpageRootPath); 2516 2517 CmsResource resource; 2518 if (element.getResource() == null) { 2519 element.initResource(cms); 2520 resource = element.getResource(); 2521 } else { 2522 // make sure resource is readable, this is necessary for new content elements 2523 if (element.getId().isNullUUID()) { 2524 // in memory only element, can not be read nor saved 2525 return null; 2526 } 2527 resource = cms.readResource(element.getId(), CmsResourceFilter.IGNORE_EXPIRATION); 2528 } 2529 2530 // check if there is a valid formatter 2531 int containerWidth = container.getWidth(); 2532 CmsADEConfigData config = getConfigData(containerpageRootPath); 2533 CmsFormatterConfiguration formatters = config.getFormatters(cms, resource); 2534 String containerType = null; 2535 containerType = container.getType(); 2536 I_CmsFormatterBean formatter = null; 2537 String formatterConfigId = null; 2538 if ((element.getIndividualSettings() != null) 2539 && (element.getIndividualSettings().get( 2540 CmsFormatterConfig.getSettingsKeyForContainer(container.getName())) != null)) { 2541 formatterConfigId = element.getIndividualSettings().get( 2542 CmsFormatterConfig.getSettingsKeyForContainer(container.getName())); 2543 I_CmsFormatterBean dynamicFmt = config.findFormatter(formatterConfigId); 2544 if (dynamicFmt != null) { 2545 formatter = dynamicFmt; 2546 } else if (formatterConfigId.startsWith(CmsFormatterConfig.SCHEMA_FORMATTER_ID) 2547 && CmsUUID.isValidUUID(formatterConfigId.substring(CmsFormatterConfig.SCHEMA_FORMATTER_ID.length()))) { 2548 formatter = formatters.getFormatterSelection(containerType, containerWidth).get(formatterConfigId); 2549 } 2550 } 2551 if (formatter == null) { 2552 formatter = CmsElementUtil.getFormatterForContainer(cms, element, container, config, getSessionCache()); 2553 if (formatter != null) { 2554 formatterConfigId = formatter.isFromFormatterConfigFile() 2555 ? formatter.getId() 2556 : CmsFormatterConfig.SCHEMA_FORMATTER_ID + formatter.getJspStructureId().toString(); 2557 } 2558 } 2559 CmsContainerElementBean newElementBean = null; 2560 if (formatter != null) { 2561 Map<String, String> settings = new HashMap<String, String>(element.getIndividualSettings()); 2562 String formatterKey = CmsFormatterConfig.getSettingsKeyForContainer(container.getName()); 2563 settings.put(formatterKey, formatterConfigId); 2564 // remove not used formatter settings 2565 Iterator<Entry<String, String>> entries = settings.entrySet().iterator(); 2566 while (entries.hasNext()) { 2567 Entry<String, String> entry = entries.next(); 2568 if (entry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY) 2569 && !entry.getKey().equals(formatterKey)) { 2570 entries.remove(); 2571 } 2572 } 2573 2574 newElementBean = new CmsContainerElementBean( 2575 element.getId(), 2576 formatter.getJspStructureId(), 2577 settings, 2578 isCreateNew); 2579 } 2580 return newElementBean; 2581 } 2582 2583 /** 2584 * Returns the requested container-page resource.<p> 2585 * 2586 * @param cms the current cms object 2587 * 2588 * @return the container-page resource 2589 * 2590 * @throws CmsException if the resource could not be read for any reason 2591 */ 2592 private CmsResource getContainerpage(CmsObject cms) throws CmsException { 2593 2594 String currentUri = cms.getRequestContext().getUri(); 2595 CmsResource containerPage = cms.readResource(currentUri, CmsResourceFilter.ignoreExpirationOffline(cms)); 2596 if (!CmsResourceTypeXmlContainerPage.isContainerPage(containerPage)) { 2597 // container page is used as template 2598 String cntPagePath = cms.readPropertyObject( 2599 containerPage, 2600 CmsPropertyDefinition.PROPERTY_TEMPLATE_ELEMENTS, 2601 true).getValue(""); 2602 try { 2603 containerPage = cms.readResource(cntPagePath, CmsResourceFilter.ignoreExpirationOffline(cms)); 2604 } catch (CmsException e) { 2605 if (!LOG.isDebugEnabled()) { 2606 LOG.warn(e.getLocalizedMessage()); 2607 } 2608 LOG.debug(e.getLocalizedMessage(), e); 2609 } 2610 } 2611 return containerPage; 2612 } 2613 2614 /** 2615 * Gets the (potentially empty) set of types for which the container page is registered as a detail page. 2616 * 2617 * @param cms the CMS context 2618 * @param containerPage a container page resource 2619 * 2620 * @return the set of names of types for which the container page is a detail page 2621 */ 2622 private Set<String> getDetailTypes(CmsObject cms, CmsResource containerPage) { 2623 2624 List<CmsDetailPageInfo> infos = OpenCms.getADEManager().getAllDetailPages(cms); 2625 Set<CmsUUID> ids = new HashSet<>(); 2626 ids.add(containerPage.getStructureId()); 2627 Set<String> result = new HashSet<>(); 2628 if (containerPage.isFile()) { 2629 try { 2630 CmsResource folder = cms.readParentFolder(containerPage.getStructureId()); 2631 if (folder != null) { 2632 ids.add(folder.getStructureId()); 2633 } 2634 } catch (CmsException e) { 2635 LOG.error(e.getLocalizedMessage(), e); 2636 } 2637 } 2638 for (CmsDetailPageInfo info : infos) { 2639 if (ids.contains(info.getId())) { 2640 result.add(info.getType()); 2641 } 2642 } 2643 2644 return result; 2645 2646 } 2647 2648 /** 2649 * Returns the data of the given elements.<p> 2650 * 2651 * @param config the sitemap configuration 2652 * @param page the current container page 2653 * @param clientIds the list of IDs of the elements to retrieve the data for 2654 * @param uriParam the current URI 2655 * @param detailContentId the detail content structure id 2656 * @param containers the containers for which the element data should be fetched 2657 * @param allwaysCopy <code>true</code> in case reading data for a clipboard element used as a copy group 2658 * @param dndOriginContainer the container from which an element was dragged (null if this method is not called for DND) 2659 * @param isDragMode if the page is in drag mode 2660 * @param locale the locale to use 2661 * 2662 * @return the elements data 2663 * 2664 * @throws CmsException if something really bad happens 2665 */ 2666 private Map<String, CmsContainerElementData> getElements( 2667 CmsADEConfigData config, 2668 CmsResource page, 2669 Collection<String> clientIds, 2670 String uriParam, 2671 CmsUUID detailContentId, 2672 Collection<CmsContainer> containers, 2673 boolean allwaysCopy, 2674 String dndOriginContainer, 2675 boolean isDragMode, 2676 Locale locale) 2677 throws CmsException { 2678 2679 CmsObject cms = getCmsObject(); 2680 CmsContainerPageBean pageBean = generateContainerPageForContainers( 2681 containers, 2682 cms.getRequestContext().addSiteRoot(uriParam)); 2683 Map<String, CmsContainerElementBean> idMapping = new HashMap<String, CmsContainerElementBean>(); 2684 for (String elemId : clientIds) { 2685 if ((elemId == null)) { 2686 continue; 2687 } 2688 CmsContainerElementBean element = getCachedElement(elemId, cms.getRequestContext().addSiteRoot(uriParam)); 2689 if (element.getInstanceId() == null) { 2690 element = element.clone(); 2691 getSessionCache().setCacheContainerElement(element.editorHash(), element); 2692 } 2693 element.initResource(cms); 2694 idMapping.put(elemId, element); 2695 } 2696 List<String> foundGroups = new ArrayList<String>(); 2697 if (CmsContainerElement.MENU_CONTAINER_ID.equals(dndOriginContainer)) { 2698 // this indicates the element is added to the page and not being repositioned, check for model group data 2699 CmsModelGroupHelper modelHelper = new CmsModelGroupHelper( 2700 cms, 2701 getConfigData(uriParam), 2702 getSessionCache(), 2703 isEditingModelGroups(cms, page)); 2704 String createElementContext = CmsResource.getParentFolder(page.getRootPath()); 2705 if (detailContentId != null) { 2706 try { 2707 CmsResource detailContent = cms.readResource(detailContentId, CmsResourceFilter.IGNORE_EXPIRATION); 2708 createElementContext = CmsResource.getParentFolder( 2709 CmsDetailOnlyContainerUtil.getDetailOnlyPageName( 2710 cms, 2711 page, 2712 detailContent.getRootPath(), 2713 "" + locale)); 2714 } catch (Exception e) { 2715 LOG.error(e.getLocalizedMessage(), e); 2716 } 2717 } 2718 pageBean = modelHelper.prepareforModelGroupContent( 2719 idMapping, 2720 foundGroups, 2721 pageBean, 2722 allwaysCopy, 2723 locale, 2724 createElementContext); 2725 } 2726 2727 CmsElementUtil elemUtil = new CmsElementUtil( 2728 cms, 2729 uriParam, 2730 pageBean, 2731 detailContentId, 2732 getRequest(), 2733 getResponse(), 2734 isDragMode, 2735 locale); 2736 Map<String, CmsContainerElementData> result = new HashMap<String, CmsContainerElementData>(); 2737 Set<String> ids = new HashSet<String>(); 2738 for (Entry<String, CmsContainerElementBean> entry : idMapping.entrySet()) { 2739 CmsContainerElementBean element = entry.getValue(); 2740 String dndId = null; 2741 if (ids.contains(element.editorHash())) { 2742 continue; 2743 } 2744 if ((dndOriginContainer != null) && !CmsContainerElement.MENU_CONTAINER_ID.equals(dndOriginContainer)) { 2745 CmsFormatterConfiguration formatterConfig = elemUtil.getFormatterConfiguration(element.getResource()); 2746 Map<String, String> dndSettings = getSettingsToChangeForDnd( 2747 config, 2748 element.getIndividualSettings(), 2749 formatterConfig, 2750 containers, 2751 dndOriginContainer); 2752 if (!dndSettings.isEmpty()) { 2753 CmsContainerElementBean dndElementBean = overrideSettings(element, dndSettings); 2754 getSessionCache().setCacheContainerElement(dndElementBean.editorHash(), dndElementBean); 2755 dndId = dndElementBean.editorHash(); 2756 Map<String, CmsContainerElementData> dndResults = getElements( 2757 config, 2758 page, 2759 Arrays.asList(dndId), 2760 uriParam, 2761 detailContentId, 2762 containers, 2763 false, 2764 null, 2765 isDragMode, 2766 locale); 2767 result.putAll(dndResults); 2768 } 2769 } 2770 2771 CmsContainerElementData elementData = elemUtil.getElementData(page, element, containers); 2772 if (elementData == null) { 2773 continue; 2774 } 2775 // make sure the element with it's current settings is cached 2776 getSessionCache().setCacheContainerElement(element.editorHash(), element); 2777 elementData.setDndId(dndId); 2778 result.put(entry.getKey(), elementData); 2779 if (elementData.isGroupContainer() || elementData.isInheritContainer()) { 2780 // this is a group-container 2781 CmsResource elementRes = cms.readResource(element.getId()); 2782 List<CmsContainerElementBean> subElements = elementData.isGroupContainer() 2783 ? getGroupContainerElements(elementRes) 2784 : getInheritedElements(elementRes, locale, uriParam); 2785 // adding all sub-items to the elements data 2786 for (CmsContainerElementBean subElement : subElements) { 2787 getSessionCache().setCacheContainerElement(subElement.editorHash(), subElement); 2788 if (!ids.contains(subElement.editorHash())) { 2789 CmsContainerElementData subItemData = elemUtil.getElementData(page, subElement, containers); 2790 ids.add(subElement.editorHash()); 2791 result.put(subElement.editorHash(), subItemData); 2792 } 2793 } 2794 } 2795 ids.add(element.editorHash()); 2796 } 2797 for (CmsContainerElementData elementData : result.values()) { 2798 elementData.setGroup(foundGroups.contains(elementData.getClientId())); 2799 } 2800 return result; 2801 } 2802 2803 /** 2804 * Helper method for converting a CmsGroupContainer to a CmsGroupContainerBean when saving a group container.<p> 2805 * 2806 * @param groupContainer the group-container data 2807 * @param containerPage the container page 2808 * @param locale the locale to use 2809 * 2810 * @return the group-container bean 2811 */ 2812 private CmsGroupContainerBean getGroupContainerBean( 2813 CmsGroupContainer groupContainer, 2814 CmsResource containerPage, 2815 String locale) { 2816 2817 CmsObject cms = getCmsObject(); 2818 List<CmsContainerElementBean> elements = new ArrayList<CmsContainerElementBean>(); 2819 for (CmsContainerElement elementData : groupContainer.getElements()) { 2820 try { 2821 if (elementData.isNew()) { 2822 elementData = createNewElement( 2823 containerPage.getStructureId(), 2824 null, 2825 elementData.getClientId(), 2826 elementData.getResourceType(), 2827 null, 2828 locale); 2829 } 2830 CmsContainerElementBean element = getCachedElement( 2831 elementData.getClientId(), 2832 containerPage.getRootPath()); 2833 2834 // make sure resource is readable, 2835 if (cms.existsResource(element.getId(), CmsResourceFilter.IGNORE_EXPIRATION)) { 2836 elements.add(element); 2837 } 2838 2839 } catch (Exception e) { 2840 log(e.getLocalizedMessage(), e); 2841 } 2842 } 2843 return new CmsGroupContainerBean( 2844 groupContainer.getTitle(), 2845 groupContainer.getDescription(), 2846 elements, 2847 groupContainer.getTypes()); 2848 } 2849 2850 /** 2851 * Returns the sub-elements of this group container resource.<p> 2852 * 2853 * @param resource the group container resource 2854 * 2855 * @return the sub-elements 2856 * 2857 * @throws CmsException if something goes wrong reading the resource 2858 */ 2859 private List<CmsContainerElementBean> getGroupContainerElements(CmsResource resource) throws CmsException { 2860 2861 CmsXmlGroupContainer xmlGroupContainer = CmsXmlGroupContainerFactory.unmarshal( 2862 getCmsObject(), 2863 resource, 2864 getRequest()); 2865 CmsGroupContainerBean groupContainer = xmlGroupContainer.getGroupContainer(getCmsObject()); 2866 return groupContainer.getElements(); 2867 } 2868 2869 /** 2870 * Gets the structure ids of group container elements from an unmarshalled group container for a single locale.<p> 2871 * 2872 * @param groupContainer the group container 2873 * @param locale the locale for which we want the element ids 2874 * 2875 * @return the group container's element ids for the given locale 2876 */ 2877 private Set<CmsUUID> getGroupElementIds(CmsXmlGroupContainer groupContainer, Locale locale) { 2878 2879 Set<CmsUUID> idSet = new HashSet<CmsUUID>(); 2880 CmsGroupContainerBean groupContainerBean = groupContainer.getGroupContainer(getCmsObject()); 2881 if (groupContainerBean != null) { 2882 for (CmsContainerElementBean element : groupContainerBean.getElements()) { 2883 idSet.add(element.getId()); 2884 } 2885 } 2886 return idSet; 2887 2888 } 2889 2890 /** 2891 * Returns the sub-elements of this inherit container resource.<p> 2892 * 2893 * @param resource the inherit container resource 2894 * @param locale the requested locale 2895 * @param uriParam the current URI 2896 * 2897 * @return the sub-elements 2898 * 2899 * @throws CmsException if something goes wrong reading the resource 2900 */ 2901 private List<CmsContainerElementBean> getInheritedElements(CmsResource resource, Locale locale, String uriParam) 2902 throws CmsException { 2903 2904 CmsObject cms = getCmsObject(); 2905 cms.getRequestContext().setLocale(locale); 2906 CmsInheritanceReferenceParser parser = new CmsInheritanceReferenceParser(cms); 2907 parser.parse(resource); 2908 CmsInheritanceReference ref = parser.getReference(locale); 2909 if (ref == null) { 2910 // new inheritance reference, return an empty list 2911 return Collections.emptyList(); 2912 } 2913 String name = ref.getName(); 2914 CmsADEManager adeManager = OpenCms.getADEManager(); 2915 CmsInheritedContainerState result = adeManager.getInheritedContainerState(cms, cms.addSiteRoot(uriParam), name); 2916 return result.getElements(true); 2917 } 2918 2919 /** 2920 * Returns the data of the given elements.<p> 2921 * 2922 * @param listElements the list of element beans to retrieve the data for 2923 * @param containerpageUri the current URI 2924 * @param detailContentId the detail content structure id 2925 * @param containers the containers which exist on the container page 2926 * @param locale the locale to use 2927 * 2928 * @return the elements data 2929 * 2930 * @throws CmsException if something really bad happens 2931 */ 2932 private List<CmsContainerElementData> getListElementsData( 2933 List<CmsContainerElementBean> listElements, 2934 String containerpageUri, 2935 CmsUUID detailContentId, 2936 Collection<CmsContainer> containers, 2937 Locale locale) 2938 throws CmsException { 2939 2940 CmsObject cms = getCmsObject(); 2941 CmsElementUtil elemUtil = new CmsElementUtil( 2942 cms, 2943 containerpageUri, 2944 generateContainerPageForContainers(containers, cms.getRequestContext().addSiteRoot(containerpageUri)), 2945 detailContentId, 2946 getRequest(), 2947 getResponse(), 2948 true, 2949 locale); 2950 CmsADESessionCache cache = getSessionCache(); 2951 List<CmsContainerElementData> result = new ArrayList<CmsContainerElementData>(); 2952 for (CmsContainerElementBean element : listElements) { 2953 // checking if resource exists 2954 if (cms.existsResource(element.getId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireFile())) { 2955 try { 2956 CmsContainerElementBean clone = element.clone(); 2957 // Because ensureNewInstanceId() just generates a new UUID, 2958 // the key for the element cache will not collide with anything else, so 2959 // we do not need to set the SYSTEM::pageId setting for disambiguation here. 2960 clone.ensureNewInstanceId(); 2961 cache.setCacheContainerElement(clone.editorHash(), clone); 2962 CmsContainerElementData elementData = elemUtil.getElementData( 2963 elemUtil.getPage(), 2964 clone, 2965 containers); 2966 result.add(elementData); 2967 } catch (CmsVfsResourceNotFoundException e) { 2968 // model group id not found, or other resources 2969 LOG.info(e.getLocalizedMessage(), e); 2970 } 2971 } 2972 } 2973 return result; 2974 } 2975 2976 /** 2977 * Returns the lock information to the given resource.<p> 2978 * 2979 * @param resource the resource 2980 * 2981 * @return lock information, if the page is locked by another user 2982 * 2983 * @throws CmsException if something goes wrong reading the lock owner user 2984 */ 2985 private String getLockInfo(CmsResource resource) throws CmsException { 2986 2987 CmsObject cms = getCmsObject(); 2988 CmsResourceUtil resourceUtil = new CmsResourceUtil(cms, resource); 2989 CmsLock lock = resourceUtil.getLock(); 2990 String lockInfo = null; 2991 if (!lock.isLockableBy(cms.getRequestContext().getCurrentUser())) { 2992 if (lock.getType() == CmsLockType.PUBLISH) { 2993 lockInfo = Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key( 2994 Messages.GUI_LOCKED_FOR_PUBLISH_0); 2995 } else { 2996 CmsUser lockOwner = cms.readUser(lock.getUserId()); 2997 lockInfo = Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key( 2998 Messages.GUI_LOCKED_BY_1, 2999 lockOwner.getFullName()); 3000 } 3001 } 3002 return lockInfo; 3003 } 3004 3005 /** 3006 * Returns the element data for a new element not existing in the VFS yet.<p> 3007 * 3008 * @param resourceTypeName the resource type name 3009 * @param uriParam the request parameters 3010 * @param detailContentId the detail content structure id 3011 * @param containers the containers of the template 3012 * @param locale the current locale 3013 * 3014 * @return the element data 3015 * 3016 * @throws CmsException if something goes wrong 3017 */ 3018 private CmsContainerElementData getNewElement( 3019 String resourceTypeName, 3020 String uriParam, 3021 CmsUUID detailContentId, 3022 Collection<CmsContainer> containers, 3023 Locale locale) 3024 throws CmsException { 3025 3026 CmsObject cms = getCmsObject(); 3027 CmsElementUtil elemUtil = new CmsElementUtil( 3028 cms, 3029 uriParam, 3030 generateContainerPageForContainers(containers, cms.getRequestContext().addSiteRoot(uriParam)), 3031 detailContentId, 3032 getRequest(), 3033 getResponse(), 3034 true, 3035 locale); 3036 CmsADEConfigData configData = getConfigData(cms.getRequestContext().addSiteRoot(uriParam)); 3037 CmsResourceTypeConfig typeConfig = configData.getResourceType(resourceTypeName); 3038 CmsContainerElementBean elementBean = CmsContainerElementBean.createElementForResourceType( 3039 cms, 3040 OpenCms.getResourceManager().getResourceType(resourceTypeName), 3041 "/", 3042 Collections.<String, String> emptyMap(), 3043 typeConfig.isCopyInModels(), 3044 locale); 3045 CmsContainerElementData data = elemUtil.getElementData(elemUtil.getPage(), elementBean, containers); 3046 data.setClientId(elementBean.editorHash()); 3047 getSessionCache().setCacheContainerElement(resourceTypeName, elementBean); 3048 getSessionCache().setCacheContainerElement(elementBean.editorHash(), elementBean); 3049 return data; 3050 } 3051 3052 /** 3053 * Returns the no-edit reason for the given resource.<p> 3054 * 3055 * @param cms the current cms object 3056 * @param containerPage the resource 3057 * 3058 * @return the no-edit reason, empty if editing is allowed 3059 * 3060 * @throws CmsException is something goes wrong 3061 */ 3062 private String getNoEditReason(CmsObject cms, CmsResource containerPage) throws CmsException { 3063 3064 return new CmsResourceUtil(cms, containerPage).getNoEditReason( 3065 OpenCms.getWorkplaceManager().getWorkplaceLocale(cms), 3066 !cms.getRequestContext().getCurrentProject().isOnlineProject()); 3067 } 3068 3069 /** 3070 * Returns the session cache.<p> 3071 * 3072 * @return the session cache 3073 */ 3074 private CmsADESessionCache getSessionCache() { 3075 3076 if (m_sessionCache == null) { 3077 m_sessionCache = CmsADESessionCache.getCache(getRequest(), getCmsObject()); 3078 } 3079 return m_sessionCache; 3080 } 3081 3082 /** 3083 * Returns the workplace settings of the current user.<p> 3084 * 3085 * @return the workplace settings 3086 */ 3087 private CmsWorkplaceSettings getWorkplaceSettings() { 3088 3089 if (m_workplaceSettings == null) { 3090 m_workplaceSettings = CmsWorkplace.getWorkplaceSettings(getCmsObject(), getRequest()); 3091 } 3092 return m_workplaceSettings; 3093 } 3094 3095 /** 3096 * Checks if results for the stored gallery data can be restored for the new gallery data.<p> 3097 * 3098 * @param originalGalleryData the original gallery data 3099 * @param data the new gallery data 3100 * @param search the search bean 3101 * 3102 * @return true if the original and new gallery data are compatible, i.e. we can restore the search results 3103 */ 3104 private boolean hasCompatibleSearchData( 3105 CmsGalleryDataBean originalGalleryData, 3106 CmsGalleryDataBean data, 3107 CmsGallerySearchBean search) { 3108 3109 Set<String> originalUsableTypes = Sets.newHashSet(); 3110 Set<String> usableTypes = Sets.newHashSet(); 3111 for (CmsResourceTypeBean type : originalGalleryData.getTypes()) { 3112 if (!type.isDeactivated()) { 3113 originalUsableTypes.add(type.getType()); 3114 } 3115 } 3116 for (CmsResourceTypeBean type : data.getTypes()) { 3117 if (!type.isDeactivated()) { 3118 usableTypes.add(type.getType()); 3119 } 3120 } 3121 if (!usableTypes.containsAll(originalUsableTypes)) { 3122 return false; 3123 } 3124 return true; 3125 } 3126 3127 /** 3128 * Initializes request attributes using data from the RPC context.<p> 3129 * 3130 * @param context the RPC context 3131 */ 3132 private void initRequestFromRpcContext(CmsContainerPageRpcContext context) { 3133 3134 if (context.getTemplateContext() != null) { 3135 getRequest().setAttribute( 3136 CmsTemplateContextManager.ATTR_RPC_CONTEXT_OVERRIDE, 3137 context.getTemplateContext()); 3138 } 3139 } 3140 3141 /** 3142 * Internal method for saving a group container.<p> 3143 * 3144 * @param cms the cms context 3145 * @param pageStructureId the container page structure id 3146 * @param groupContainer the group container to save 3147 * 3148 * @return the container element representing the group container 3149 * 3150 * @throws CmsException if something goes wrong 3151 * @throws CmsXmlException if the XML processing goes wrong 3152 */ 3153 private CmsPair<CmsContainerElement, List<CmsRemovedElementStatus>> internalSaveGroupContainer( 3154 CmsObject cms, 3155 CmsUUID pageStructureId, 3156 CmsGroupContainer groupContainer) 3157 throws CmsException, CmsXmlException { 3158 3159 ensureSession(); 3160 CmsResource pageResource = getCmsObject().readResource(pageStructureId, CmsResourceFilter.IGNORE_EXPIRATION); 3161 CmsResource groupContainerResource = null; 3162 if (groupContainer.isNew()) { 3163 CmsADEConfigData config = getConfigData(pageResource.getRootPath()); 3164 CmsResourceTypeConfig typeConfig = config.getResourceType( 3165 CmsResourceTypeXmlContainerPage.GROUP_CONTAINER_TYPE_NAME); 3166 groupContainerResource = typeConfig.createNewElement(getCmsObject(), pageResource.getRootPath()); 3167 String resourceName = cms.getSitePath(groupContainerResource); 3168 groupContainer.setSitePath(resourceName); 3169 groupContainer.setClientId(groupContainerResource.getStructureId().toString()); 3170 } 3171 if (groupContainerResource == null) { 3172 CmsUUID id = convertToServerId(groupContainer.getClientId()); 3173 groupContainerResource = cms.readResource(id, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3174 } 3175 CmsGroupContainerBean groupContainerBean = getGroupContainerBean( 3176 groupContainer, 3177 pageResource, 3178 Locale.ENGLISH.toString()); 3179 3180 cms.lockResourceTemporary(groupContainerResource); 3181 CmsFile groupContainerFile = cms.readFile(groupContainerResource); 3182 Locale locale = Locale.ENGLISH; 3183 CmsXmlGroupContainer xmlGroupContainer = CmsXmlGroupContainerFactory.unmarshal(cms, groupContainerFile); 3184 Set<CmsUUID> oldElementIds = getGroupElementIds(xmlGroupContainer, locale); 3185 xmlGroupContainer.clearLocales(); 3186 xmlGroupContainer.save(cms, groupContainerBean, locale); 3187 cms.unlockResource(groupContainerResource); 3188 Set<CmsUUID> newElementIds = getGroupElementIds(xmlGroupContainer, locale); 3189 Set<CmsUUID> removedElementIds = Sets.difference(oldElementIds, newElementIds); 3190 List<CmsRemovedElementStatus> deletionCandidateStatuses = new ArrayList<CmsRemovedElementStatus>(); 3191 for (CmsUUID removedId : removedElementIds) { 3192 CmsRemovedElementStatus status = internalGetRemovedElementStatus(removedId, null); 3193 if (status.isDeletionCandidate()) { 3194 deletionCandidateStatuses.add(status); 3195 } 3196 } 3197 CmsContainerElement element = new CmsContainerElement(); 3198 element.setClientId(groupContainerFile.getStructureId().toString()); 3199 element.setSitePath(cms.getSitePath(groupContainerFile)); 3200 element.setResourceType(CmsResourceTypeXmlContainerPage.GROUP_CONTAINER_TYPE_NAME); 3201 return CmsPair.create(element, deletionCandidateStatuses); 3202 } 3203 3204 /** 3205 * Checks if small elements in a container page should be initially editable.<p> 3206 * 3207 * @param request the current request 3208 * @param cms the current CMS context 3209 * @return true if small elements should be initially editable 3210 */ 3211 private boolean isEditSmallElements(HttpServletRequest request, CmsObject cms) { 3212 3213 CmsUser user = cms.getRequestContext().getCurrentUser(); 3214 String editSmallElementsStr = (String)(user.getAdditionalInfo().get(ADDINFO_EDIT_SMALL_ELEMENTS)); 3215 if (editSmallElementsStr == null) { 3216 return true; 3217 } else { 3218 return Boolean.valueOf(editSmallElementsStr).booleanValue(); 3219 } 3220 } 3221 3222 /** 3223 * Checks if a page is a model page.<p> 3224 * 3225 * @param cms the CMS context to use 3226 * @param containerPage the page to check 3227 * 3228 * @return true if the resource is a model page 3229 */ 3230 private boolean isModelPage(CmsObject cms, CmsResource containerPage) { 3231 3232 CmsADEConfigData config = getConfigData(containerPage.getRootPath()); 3233 for (CmsModelPageConfig modelConfig : config.getModelPages()) { 3234 if (modelConfig.getResource().getStructureId().equals(containerPage.getStructureId())) { 3235 return true; 3236 } 3237 } 3238 return false; 3239 } 3240 3241 /** 3242 * Saves the given containers to the container page resource.<p> 3243 * 3244 * @param cms the cms context 3245 * @param containerpage the container page resource 3246 * @param containerpageUri the container page site path 3247 * @param containers the container to save 3248 * 3249 * @throws CmsException if something goes wrong writing the file 3250 */ 3251 private void saveContainers( 3252 CmsObject cms, 3253 CmsResource containerpage, 3254 String containerpageUri, 3255 List<CmsContainer> containers) 3256 throws CmsException { 3257 3258 CmsContainerPageBean page = generateContainerPageForContainers(containers, containerpage.getRootPath()); 3259 3260 CmsModelGroupHelper modelHelper = new CmsModelGroupHelper( 3261 getCmsObject(), 3262 getConfigData(containerpage.getRootPath()), 3263 getSessionCache(), 3264 isEditingModelGroups(cms, containerpage)); 3265 if (isEditingModelGroups(cms, containerpage)) { 3266 page = modelHelper.saveModelGroups(page, containerpage); 3267 } else { 3268 page = modelHelper.removeModelGroupContainers(page); 3269 } 3270 CmsXmlContainerPage xmlCnt = CmsXmlContainerPageFactory.unmarshal( 3271 cms, 3272 cms.readFile(containerpageUri, CmsResourceFilter.ignoreExpirationOffline(cms))); 3273 xmlCnt.save(cms, page); 3274 } 3275 3276 /** 3277 * Saves the inheritance group.<p> 3278 * 3279 * @param resource the inheritance group resource 3280 * @param inheritanceContainer the inherited group container data 3281 * 3282 * @throws CmsException if something goes wrong 3283 */ 3284 private void saveInheritanceGroup(CmsResource resource, CmsInheritanceContainer inheritanceContainer) 3285 throws CmsException { 3286 3287 CmsObject cms = getCmsObject(); 3288 CmsFile file = cms.readFile(resource); 3289 CmsXmlContent document = CmsXmlContentFactory.unmarshal(cms, file); 3290 3291 for (Locale docLocale : document.getLocales()) { 3292 document.removeLocale(docLocale); 3293 } 3294 Locale locale = Locale.ENGLISH; 3295 document.addLocale(cms, locale); 3296 document.getValue("Title", locale).setStringValue(cms, inheritanceContainer.getTitle()); 3297 document.getValue("Description", locale).setStringValue(cms, inheritanceContainer.getDescription()); 3298 document.getValue("ConfigName", locale).setStringValue(cms, inheritanceContainer.getName()); 3299 byte[] content = document.marshal(); 3300 file.setContents(content); 3301 cms.writeFile(file); 3302 } 3303 3304 /** 3305 * Update favorite or recent list with the given element.<p> 3306 * 3307 * @param containerPage the edited container page 3308 * @param clientId the elements client id 3309 * @param list the list to update 3310 * 3311 * @return the updated list 3312 * 3313 * @throws CmsException in case reading the element resource fails 3314 */ 3315 private List<CmsContainerElementBean> updateFavoriteRecentList( 3316 CmsResource containerPage, 3317 String clientId, 3318 List<CmsContainerElementBean> list) 3319 throws CmsException { 3320 3321 try { 3322 CmsContainerElementBean element = getCachedElement(clientId, containerPage.getRootPath()); 3323 Map<String, String> settings = new HashMap<String, String>(element.getIndividualSettings()); 3324 String formatterID = null; 3325 Iterator<Entry<String, String>> entries = settings.entrySet().iterator(); 3326 while (entries.hasNext()) { 3327 Entry<String, String> entry = entries.next(); 3328 if (entry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) { 3329 formatterID = entry.getValue(); 3330 entries.remove(); 3331 } 3332 } 3333 settings.put(CmsFormatterConfig.FORMATTER_SETTINGS_KEY, formatterID); 3334 settings.put(SOURCE_CONTAINERPAGE_ID_SETTING, containerPage.getStructureId().toString()); 3335 settings.remove(CmsContainerElement.SETTING_PAGE_ID); 3336 element = CmsContainerElementBean.cloneWithSettings(element, settings); 3337 Iterator<CmsContainerElementBean> listIt = list.iterator(); 3338 while (listIt.hasNext()) { 3339 CmsContainerElementBean listElem = listIt.next(); 3340 if (element.getInstanceId().equals(listElem.getInstanceId())) { 3341 listIt.remove(); 3342 } 3343 } 3344 list.add(0, element); 3345 return list; 3346 } catch (CmsVfsResourceNotFoundException e) { 3347 LOG.warn(e.getLocalizedMessage(), e); 3348 return list; 3349 } 3350 } 3351 3352}