001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://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.sitemap; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.configuration.CmsADEConfigData.AttributeMode; 032import org.opencms.ade.configuration.CmsADEConfigDataInternal.AttributeValue; 033import org.opencms.ade.configuration.CmsADEManager; 034import org.opencms.ade.configuration.CmsFunctionAvailability; 035import org.opencms.ade.configuration.CmsFunctionReference; 036import org.opencms.ade.configuration.CmsModelPageConfig; 037import org.opencms.ade.configuration.CmsResourceTypeConfig; 038import org.opencms.ade.configuration.formatters.CmsFormatterConfigurationCacheState; 039import org.opencms.ade.detailpage.CmsDetailPageConfigurationWriter; 040import org.opencms.ade.detailpage.CmsDetailPageInfo; 041import org.opencms.ade.sitemap.shared.CmsClientSitemapEntry; 042import org.opencms.ade.sitemap.shared.CmsClientSitemapEntry.EntryType; 043import org.opencms.ade.sitemap.shared.CmsDetailPageTable; 044import org.opencms.ade.sitemap.shared.CmsGalleryFolderEntry; 045import org.opencms.ade.sitemap.shared.CmsGalleryType; 046import org.opencms.ade.sitemap.shared.CmsLocaleComparePropertyData; 047import org.opencms.ade.sitemap.shared.CmsModelInfo; 048import org.opencms.ade.sitemap.shared.CmsModelPageEntry; 049import org.opencms.ade.sitemap.shared.CmsNewResourceInfo; 050import org.opencms.ade.sitemap.shared.CmsSitemapAttributeData; 051import org.opencms.ade.sitemap.shared.CmsSitemapCategoryData; 052import org.opencms.ade.sitemap.shared.CmsSitemapChange; 053import org.opencms.ade.sitemap.shared.CmsSitemapChange.ChangeType; 054import org.opencms.ade.sitemap.shared.CmsSitemapClipboardData; 055import org.opencms.ade.sitemap.shared.CmsSitemapData; 056import org.opencms.ade.sitemap.shared.CmsSitemapData.EditorMode; 057import org.opencms.ade.sitemap.shared.CmsSitemapInfo; 058import org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService; 059import org.opencms.configuration.CmsDefaultUserSettings; 060import org.opencms.db.CmsAlias; 061import org.opencms.db.CmsAliasManager; 062import org.opencms.db.CmsRewriteAlias; 063import org.opencms.file.CmsFile; 064import org.opencms.file.CmsObject; 065import org.opencms.file.CmsProject; 066import org.opencms.file.CmsProperty; 067import org.opencms.file.CmsPropertyDefinition; 068import org.opencms.file.CmsRequestContext; 069import org.opencms.file.CmsResource; 070import org.opencms.file.CmsResourceFilter; 071import org.opencms.file.CmsUser; 072import org.opencms.file.CmsVfsResourceAlreadyExistsException; 073import org.opencms.file.CmsVfsResourceNotFoundException; 074import org.opencms.file.history.CmsHistoryResourceHandler; 075import org.opencms.file.types.CmsResourceTypeFolder; 076import org.opencms.file.types.CmsResourceTypeFolderExtended; 077import org.opencms.file.types.CmsResourceTypeFolderSubSitemap; 078import org.opencms.file.types.CmsResourceTypeFunctionConfig; 079import org.opencms.file.types.CmsResourceTypeUnknownFolder; 080import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 081import org.opencms.file.types.I_CmsResourceType; 082import org.opencms.flex.CmsFlexController; 083import org.opencms.gwt.CmsCoreService; 084import org.opencms.gwt.CmsGwtService; 085import org.opencms.gwt.CmsIconUtil; 086import org.opencms.gwt.CmsPropertyEditorHelper; 087import org.opencms.gwt.CmsRpcException; 088import org.opencms.gwt.CmsTemplateFinder; 089import org.opencms.gwt.CmsVfsService; 090import org.opencms.gwt.shared.CmsCategoryTreeEntry; 091import org.opencms.gwt.shared.CmsClientLock; 092import org.opencms.gwt.shared.CmsCoreData; 093import org.opencms.gwt.shared.CmsCoreData.AdeContext; 094import org.opencms.gwt.shared.CmsGwtConstants; 095import org.opencms.gwt.shared.CmsListInfoBean; 096import org.opencms.gwt.shared.alias.CmsAliasEditValidationReply; 097import org.opencms.gwt.shared.alias.CmsAliasEditValidationRequest; 098import org.opencms.gwt.shared.alias.CmsAliasImportResult; 099import org.opencms.gwt.shared.alias.CmsAliasInitialFetchResult; 100import org.opencms.gwt.shared.alias.CmsAliasSaveValidationRequest; 101import org.opencms.gwt.shared.alias.CmsAliasTableRow; 102import org.opencms.gwt.shared.alias.CmsRewriteAliasTableRow; 103import org.opencms.gwt.shared.alias.CmsRewriteAliasValidationReply; 104import org.opencms.gwt.shared.alias.CmsRewriteAliasValidationRequest; 105import org.opencms.gwt.shared.property.CmsClientProperty; 106import org.opencms.gwt.shared.property.CmsPropertyModification; 107import org.opencms.i18n.CmsLocaleManager; 108import org.opencms.json.JSONArray; 109import org.opencms.jsp.CmsJspNavBuilder; 110import org.opencms.jsp.CmsJspNavBuilder.Visibility; 111import org.opencms.jsp.CmsJspNavElement; 112import org.opencms.jsp.CmsJspTagLink; 113import org.opencms.loader.CmsLoaderException; 114import org.opencms.lock.CmsLock; 115import org.opencms.lock.CmsLockUtil; 116import org.opencms.main.CmsException; 117import org.opencms.main.CmsLog; 118import org.opencms.main.OpenCms; 119import org.opencms.main.OpenCmsServlet; 120import org.opencms.relations.CmsCategory; 121import org.opencms.relations.CmsCategoryService; 122import org.opencms.search.galleries.CmsGallerySearch; 123import org.opencms.search.galleries.CmsGallerySearchResult; 124import org.opencms.security.CmsPermissionSet; 125import org.opencms.security.CmsRole; 126import org.opencms.security.CmsRoleViolationException; 127import org.opencms.security.CmsSecurityException; 128import org.opencms.site.CmsSite; 129import org.opencms.ui.apps.CmsQuickLaunchLocationCache; 130import org.opencms.util.CmsDateUtil; 131import org.opencms.util.CmsFileUtil; 132import org.opencms.util.CmsMacroResolver; 133import org.opencms.util.CmsPath; 134import org.opencms.util.CmsStringUtil; 135import org.opencms.util.CmsUUID; 136import org.opencms.workplace.CmsWorkplaceManager; 137import org.opencms.workplace.CmsWorkplaceMessages; 138import org.opencms.workplace.explorer.CmsExplorerTypeAccess; 139import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 140import org.opencms.workplace.galleries.A_CmsAjaxGallery; 141import org.opencms.xml.CmsXmlException; 142import org.opencms.xml.I_CmsXmlDocument; 143import org.opencms.xml.containerpage.CmsADESessionCache; 144import org.opencms.xml.containerpage.CmsContainerBean; 145import org.opencms.xml.containerpage.CmsContainerElementBean; 146import org.opencms.xml.containerpage.CmsContainerPageBean; 147import org.opencms.xml.containerpage.CmsXmlContainerPage; 148import org.opencms.xml.containerpage.CmsXmlContainerPageFactory; 149import org.opencms.xml.containerpage.CmsXmlDynamicFunctionHandler; 150import org.opencms.xml.containerpage.mutable.CmsContainerPageWrapper; 151import org.opencms.xml.containerpage.mutable.CmsMutableContainer; 152import org.opencms.xml.containerpage.mutable.CmsMutableContainerPage; 153import org.opencms.xml.content.CmsXmlContent; 154import org.opencms.xml.content.CmsXmlContentFactory; 155import org.opencms.xml.content.CmsXmlContentProperty; 156import org.opencms.xml.content.CmsXmlContentPropertyHelper; 157import org.opencms.xml.types.I_CmsXmlContentValue; 158 159import java.text.DateFormat; 160import java.util.ArrayList; 161import java.util.Arrays; 162import java.util.Collection; 163import java.util.Collections; 164import java.util.Comparator; 165import java.util.Date; 166import java.util.HashMap; 167import java.util.LinkedHashMap; 168import java.util.List; 169import java.util.ListIterator; 170import java.util.Locale; 171import java.util.Map; 172import java.util.regex.Pattern; 173import java.util.regex.PatternSyntaxException; 174 175import javax.servlet.http.HttpServletRequest; 176 177import org.apache.commons.logging.Log; 178 179import com.google.common.collect.ComparisonChain; 180import com.google.common.collect.Lists; 181import com.google.common.collect.Maps; 182import com.google.common.collect.Ordering; 183 184/** 185 * Handles all RPC services related to the vfs sitemap.<p> 186 * 187 * @since 8.0.0 188 * 189 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService 190 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapServiceAsync 191 */ 192public class CmsVfsSitemapService extends CmsGwtService implements I_CmsSitemapService { 193 194 /** Helper class for representing information about a lock. */ 195 protected class LockInfo { 196 197 /** The lock state. */ 198 private CmsLock m_lock; 199 200 /** True if the lock was just locked. */ 201 private boolean m_wasJustLocked; 202 203 /** 204 * Creates a new LockInfo object.<p> 205 * 206 * @param lock the lock state 207 * @param wasJustLocked true if the lock was just locked 208 */ 209 public LockInfo(CmsLock lock, boolean wasJustLocked) { 210 211 m_lock = lock; 212 m_wasJustLocked = wasJustLocked; 213 } 214 215 /** 216 * Returns the lock state.<p> 217 * 218 * @return the lock state 219 */ 220 public CmsLock getLock() { 221 222 return m_lock; 223 } 224 225 /** 226 * Returns true if the lock was just locked.<p> 227 * 228 * @return true if the lock was just locked 229 */ 230 public boolean wasJustLocked() { 231 232 return m_wasJustLocked; 233 } 234 } 235 236 /** The path of the JSP used to download aliases. */ 237 public static final String ALIAS_DOWNLOAD_PATH = "/system/workplace/commons/download-aliases.jsp"; 238 239 /** The path to the JSP used to upload aliases. */ 240 public static final String ALIAS_IMPORT_PATH = "/system/workplace/commons/import-aliases.jsp"; 241 242 /** The show model edit confirm dialog attribute name. */ 243 public static final String ATTR_SHOW_MODEL_EDIT_CONFIRM = "showModelEditConfirm"; 244 245 /** Properties to remove from the copied template when creating a new sitemap entry. */ 246 public static final List<String> FILTER_PROPERTIES = Arrays.asList( 247 new String[] { 248 CmsPropertyDefinition.PROPERTY_TITLE, 249 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 250 CmsPropertyDefinition.PROPERTY_DESCRIPTION_HTML, 251 CmsPropertyDefinition.PROPERTY_NAVTEXT, 252 CmsPropertyDefinition.PROPERTY_NAVINFO}); 253 254 /** The galleries folder name. */ 255 public static final String GALLERIES_FOLDER_NAME = ".galleries"; 256 257 /** The configuration key for the functionDetail attribute in the container.info property. */ 258 public static final String KEY_FUNCTION_DETAIL = "functionDetail"; 259 260 /** The additional user info key for deleted list. */ 261 private static final String ADDINFO_ADE_DELETED_LIST = "ADE_DELETED_LIST"; 262 263 /** The additional user info key for modified list. */ 264 private static final String ADDINFO_ADE_MODIFIED_LIST = "ADE_MODIFIED_LIST"; 265 266 /** The lock table to prevent multiple users from editing the alias table concurrently. */ 267 private static CmsAliasEditorLockTable aliasEditorLockTable = new CmsAliasEditorLockTable(); 268 269 /** The table containing the alias import results. */ 270 private static CmsAliasImportResponseTable aliasImportResponseTable = new CmsAliasImportResponseTable(); 271 272 /** The static log object for this class. */ 273 private static final Log LOG = CmsLog.getLog(CmsVfsSitemapService.class); 274 275 /** The redirect recource type name. */ 276 private static final String RECOURCE_TYPE_NAME_REDIRECT = "htmlredirect"; 277 278 /** The redirect target XPath. */ 279 private static final String REDIRECT_LINK_TARGET_XPATH = "Link"; 280 281 /** Serialization uid. */ 282 private static final long serialVersionUID = -7236544324371767330L; 283 284 /** The VFS path of the redirect copy page for navigation level entries. */ 285 private static final String SUB_LEVEL_REDIRECT_COPY_PAGE = "/system/modules/org.opencms.base/copyresources/sub-level-redirect.html"; 286 287 /** The navigation builder. */ 288 private CmsJspNavBuilder m_navBuilder; 289 290 /** 291 * Adds an alias import result.<p> 292 * 293 * @param results the list of alias import results to add 294 * 295 * @return the key to retrieve the alias import results 296 */ 297 public static String addAliasImportResult(List<CmsAliasImportResult> results) { 298 299 return aliasImportResponseTable.addImportResult(results); 300 } 301 302 /** 303 * Creates a client property bean from a server-side property.<p> 304 * 305 * @param prop the property from which to create the client property 306 * @param preserveOrigin if true, the origin will be copied into the new object 307 * 308 * @return the new client property 309 */ 310 public static CmsClientProperty createClientProperty(CmsProperty prop, boolean preserveOrigin) { 311 312 CmsClientProperty result = new CmsClientProperty( 313 prop.getName(), 314 prop.getStructureValue(), 315 prop.getResourceValue()); 316 if (preserveOrigin) { 317 result.setOrigin(prop.getOrigin()); 318 } 319 return result; 320 } 321 322 /** 323 * Fetches the sitemap data.<p> 324 * 325 * @param request the current request 326 * @param sitemapUri the site relative path 327 * 328 * @return the sitemap data 329 * 330 * @throws CmsRpcException if something goes wrong 331 */ 332 public static CmsSitemapData prefetch(HttpServletRequest request, String sitemapUri) throws CmsRpcException { 333 334 CmsVfsSitemapService service = new CmsVfsSitemapService(); 335 service.setCms(CmsFlexController.getCmsObject(request)); 336 service.setRequest(request); 337 CmsSitemapData result = null; 338 try { 339 result = service.prefetch(sitemapUri); 340 } finally { 341 service.clearThreadStorage(); 342 } 343 return result; 344 } 345 346 /** 347 * Converts a sequence of properties to a map of client-side property beans.<p> 348 * 349 * @param props the sequence of properties 350 * @param preserveOrigin if true, the origin of the properties should be copied to the client properties 351 * 352 * @return the map of client properties 353 * 354 */ 355 static Map<String, CmsClientProperty> createClientProperties(Iterable<CmsProperty> props, boolean preserveOrigin) { 356 357 Map<String, CmsClientProperty> result = new HashMap<String, CmsClientProperty>(); 358 for (CmsProperty prop : props) { 359 CmsClientProperty clientProp = createClientProperty(prop, preserveOrigin); 360 result.put(prop.getName(), clientProp); 361 } 362 return result; 363 } 364 365 /** 366 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#changeCategory(java.lang.String, org.opencms.util.CmsUUID, java.lang.String, java.lang.String) 367 */ 368 public void changeCategory(String entryPoint, CmsUUID id, String title, String name) throws CmsRpcException { 369 370 try { 371 name = OpenCms.getResourceManager().getFileTranslator().translateResource(name.trim().replace('/', '-')); 372 CmsObject cms = getCmsObject(); 373 CmsResource categoryResource = cms.readResource(id); 374 ensureLock(categoryResource); 375 String sitePath = cms.getSitePath(categoryResource); 376 String newPath = CmsStringUtil.joinPaths(CmsResource.getParentFolder(sitePath), name); 377 cms.writePropertyObject(sitePath, new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, title, null)); 378 if (!CmsStringUtil.joinPaths("/", newPath, "/").equals(CmsStringUtil.joinPaths("/", sitePath, "/"))) { 379 cms.moveResource(sitePath, newPath); 380 } 381 } catch (Exception e) { 382 error(e); 383 } 384 } 385 386 /** 387 * @see org.opencms.gwt.CmsGwtService#checkPermissions(org.opencms.file.CmsObject) 388 */ 389 @Override 390 public void checkPermissions(CmsObject cms) throws CmsRoleViolationException { 391 392 OpenCms.getRoleManager().checkRole(cms, CmsRole.EDITOR); 393 } 394 395 /** 396 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#createCategory(java.lang.String, org.opencms.util.CmsUUID, java.lang.String, java.lang.String) 397 */ 398 public void createCategory(String entryPoint, CmsUUID id, String title, String name) throws CmsRpcException { 399 400 try { 401 if ((name == null) || (name.length() == 0)) { 402 name = title; 403 } 404 name = OpenCms.getResourceManager().getFileTranslator().translateResource(name.trim().replace('/', '-')); 405 CmsObject cms = getCmsObject(); 406 CmsCategoryService catService = CmsCategoryService.getInstance(); 407 408 CmsCategory createdCategory = null; 409 if (id.isNullUUID()) { 410 String localRepositoryPath = CmsStringUtil.joinPaths( 411 entryPoint, 412 CmsCategoryService.getInstance().getRepositoryBaseFolderName(getCmsObject())); 413 414 // ensure category repository exists 415 if (!cms.existsResource(localRepositoryPath)) { 416 tryUnlock( 417 cms.createResource( 418 localRepositoryPath, 419 OpenCms.getResourceManager().getResourceType(CmsResourceTypeFolder.getStaticTypeName()))); 420 } 421 createdCategory = catService.createCategory(cms, null, name, title, "", localRepositoryPath); 422 } else { 423 CmsResource parentResource = cms.readResource(id); 424 CmsCategory parent = catService.getCategory(cms, parentResource); 425 createdCategory = catService.createCategory( 426 cms, 427 parent, 428 name, 429 title, 430 "", 431 cms.getRequestContext().removeSiteRoot(parentResource.getRootPath())); 432 } 433 tryUnlock(cms.readResource(createdCategory.getId())); 434 } catch (Exception e) { 435 error(e); 436 } 437 } 438 439 /** 440 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#createNewGalleryFolder(java.lang.String, java.lang.String, int) 441 */ 442 public CmsGalleryFolderEntry createNewGalleryFolder(String parentFolder, String title, int folderTypeId) 443 throws CmsRpcException { 444 445 CmsObject cms = getCmsObject(); 446 CmsGalleryFolderEntry folderEntry = null; 447 try { 448 if (!cms.existsResource(parentFolder, CmsResourceFilter.IGNORE_EXPIRATION)) { 449 CmsResource parent = cms.createResource( 450 parentFolder, 451 OpenCms.getResourceManager().getResourceType(CmsResourceTypeFolder.getStaticTypeName())); 452 tryUnlock(parent); 453 } 454 String folderName = OpenCms.getResourceManager().getFileTranslator().translateResource(title); 455 456 folderName = OpenCms.getResourceManager().getNameGenerator().getUniqueFileName( 457 cms, 458 parentFolder, 459 folderName); 460 String folderPath = CmsStringUtil.joinPaths(parentFolder, folderName); 461 462 @SuppressWarnings("deprecation") 463 CmsResource galleryFolder = cms.createResource( 464 folderPath, 465 folderTypeId, 466 null, 467 Collections.singletonList(new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, title, null))); 468 folderEntry = readGalleryFolderEntry( 469 galleryFolder, 470 OpenCms.getResourceManager().getResourceType(galleryFolder).getTypeName()); 471 tryUnlock(galleryFolder); 472 } catch (CmsException e) { 473 error(e); 474 } 475 return folderEntry; 476 } 477 478 /** 479 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#createNewModelPage(java.lang.String, java.lang.String, java.lang.String, org.opencms.util.CmsUUID, boolean) 480 */ 481 public CmsModelPageEntry createNewModelPage( 482 String entryPointUri, 483 String title, 484 String description, 485 CmsUUID copyId, 486 boolean isModelGroup) 487 throws CmsRpcException { 488 489 try { 490 CmsObject cms = getCmsObject(); 491 CmsResource rootResource = cms.readResource(entryPointUri); 492 CmsModelPageHelper helper = new CmsModelPageHelper(getCmsObject(), rootResource); 493 CmsResource page; 494 if (isModelGroup) { 495 page = helper.createModelGroupPage(title, description, copyId); 496 } else { 497 page = helper.createPageInModelFolder(title, description, copyId); 498 String configPath = CmsStringUtil.joinPaths(entryPointUri, ".content/.config"); 499 CmsResource configResource = cms.readResource(configPath); 500 helper.addModelPageToSitemapConfiguration(configResource, page, false); 501 } 502 CmsModelPageEntry result = helper.createModelPageEntry(page, false, false, getWorkplaceLocale()); 503 OpenCms.getADEManager().waitForCacheUpdate(false); 504 return result; 505 } catch (Throwable e) { 506 error(e); 507 return null; 508 } 509 } 510 511 /** 512 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#createSubSitemap(org.opencms.util.CmsUUID) 513 */ 514 public CmsSitemapChange createSubSitemap(CmsUUID entryId) throws CmsRpcException { 515 516 CmsObject cms = getCmsObject(); 517 try { 518 ensureSession(); 519 CmsResource subSitemapFolder = cms.readResource(entryId); 520 ensureLock(subSitemapFolder); 521 String sitePath = cms.getSitePath(subSitemapFolder); 522 createSitemapContentFolder(cms, subSitemapFolder); 523 subSitemapFolder.setType(getSubsitemapType()); 524 cms.writeResource(subSitemapFolder); 525 tryUnlock(subSitemapFolder); 526 CmsSitemapClipboardData clipboard = getClipboardData(); 527 CmsClientSitemapEntry entry = toClientEntry( 528 getNavBuilder().getNavigationForResource(sitePath, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED), 529 false); 530 clipboard.addModified(entry); 531 setClipboardData(clipboard); 532 CmsSitemapChange result = new CmsSitemapChange(entry.getId(), entry.getSitePath(), ChangeType.modify); 533 result.setUpdatedEntry(entry); 534 return result; 535 } catch (Exception e) { 536 error(e); 537 } 538 return null; 539 540 } 541 542 /** 543 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#disableModelPage(java.lang.String, org.opencms.util.CmsUUID, boolean) 544 */ 545 public void disableModelPage(String baseUri, CmsUUID modelPageId, boolean disabled) throws CmsRpcException { 546 547 try { 548 CmsObject cms = getCmsObject(); 549 CmsResource rootResource = cms.readResource(baseUri); 550 CmsModelPageHelper helper = new CmsModelPageHelper(getCmsObject(), rootResource); 551 String configPath = CmsStringUtil.joinPaths(baseUri, ".content/.config"); 552 CmsResource configResource = cms.readResource(configPath); 553 helper.disableModelPage(configResource, modelPageId, disabled); 554 OpenCms.getADEManager().waitForCacheUpdate(false); 555 } catch (Throwable e) { 556 error(e); 557 } 558 } 559 560 /** 561 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#editAttributeData(org.opencms.util.CmsUUID) 562 */ 563 public CmsSitemapAttributeData editAttributeData(CmsUUID rootId) throws CmsRpcException { 564 565 try { 566 CmsObject cms = getCmsObject(); 567 CmsResource root = cms.readResource(rootId); 568 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration(cms, root.getRootPath()); 569 String sitePath = cms.getSitePath(root); 570 String configPath = CmsStringUtil.joinPaths(sitePath, "/.content/.config"); 571 CmsResource configResource = cms.readResource(configPath); 572 cms.lockResourceTemporary(configResource); 573 CmsListInfoBean configInfo = CmsVfsService.getPageInfo(cms, configResource); 574 Map<String, CmsXmlContentProperty> definitions = config.getAttributeEditorConfiguration().getAttributeDefinitions(); 575 cms.getRequestContext().setAttribute( 576 CmsRequestContext.ATTRIBUTE_ADE_CONTEXT_PATH, 577 configResource.getRootPath()); 578 definitions = CmsXmlContentPropertyHelper.resolveMacrosInProperties( 579 definitions, 580 CmsMacroResolver.newWorkplaceLocaleResolver(cms)); 581 582 HashMap<String, String> values = new HashMap<>(); 583 Map<String, AttributeValue> attributes = config.getAttributes(AttributeMode.excludeInjectedForThisLevel); 584 for (String key : definitions.keySet()) { 585 AttributeValue val = attributes.get(key); 586 String strVal; 587 if (val == null) { 588 strVal = ""; 589 } else { 590 strVal = val.getValue(); 591 } 592 values.put(key, strVal); 593 } 594 String unlockUrl = CmsStringUtil.joinPaths( 595 OpenCms.getStaticExportManager().getVfsPrefix(), 596 OpenCmsServlet.HANDLE_BUILTIN_SERVICE, 597 CmsGwtConstants.UNLOCK_FILE_PREFIX, 598 configResource.getStructureId().toString()); 599 CmsSitemapAttributeData result = new CmsSitemapAttributeData(configInfo, definitions, values, unlockUrl); 600 return result; 601 } catch (Exception e) { 602 error(e); 603 return null; 604 } 605 } 606 607 /** 608 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#getAliasImportResult(java.lang.String) 609 */ 610 public List<CmsAliasImportResult> getAliasImportResult(String resultKey) { 611 612 return aliasImportResponseTable.getAndRemove(resultKey); 613 } 614 615 /** 616 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#getAliasTable() 617 */ 618 public CmsAliasInitialFetchResult getAliasTable() throws CmsRpcException { 619 620 try { 621 CmsObject cms = getCmsObject(); 622 CmsAliasManager aliasManager = OpenCms.getAliasManager(); 623 List<CmsAlias> aliases = aliasManager.getAliasesForSite(cms, cms.getRequestContext().getSiteRoot()); 624 List<CmsAliasTableRow> rows = new ArrayList<CmsAliasTableRow>(); 625 CmsAliasInitialFetchResult result = new CmsAliasInitialFetchResult(); 626 for (CmsAlias alias : aliases) { 627 CmsAliasTableRow row = createAliasTableEntry(cms, alias); 628 rows.add(row); 629 } 630 result.setRows(rows); 631 632 List<CmsRewriteAlias> rewriteAliases = aliasManager.getRewriteAliases( 633 cms, 634 cms.getRequestContext().getSiteRoot()); 635 636 List<CmsRewriteAliasTableRow> rewriteRows = new ArrayList<CmsRewriteAliasTableRow>(); 637 for (CmsRewriteAlias rewriteAlias : rewriteAliases) { 638 CmsRewriteAliasTableRow rewriteRow = new CmsRewriteAliasTableRow( 639 rewriteAlias.getId(), 640 rewriteAlias.getPatternString(), 641 rewriteAlias.getReplacementString(), 642 rewriteAlias.getMode()); 643 rewriteRows.add(rewriteRow); 644 } 645 result.setRewriteRows(rewriteRows); 646 CmsUser otherLockOwner = aliasEditorLockTable.update(cms, cms.getRequestContext().getSiteRoot()); 647 if (otherLockOwner != null) { 648 result.setAliasLockOwner(otherLockOwner.getName()); 649 } 650 result.setDownloadUrl(OpenCms.getLinkManager().substituteLinkForRootPath(cms, ALIAS_DOWNLOAD_PATH)); 651 return result; 652 } catch (Throwable e) { 653 error(e); 654 return null; 655 } 656 } 657 658 /** 659 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#getCategoryData(java.lang.String) 660 */ 661 public CmsSitemapCategoryData getCategoryData(String entryPoint) throws CmsRpcException { 662 663 CmsObject cms = getCmsObject(); 664 try { 665 CmsResource entryPointResource = cms.readResource(entryPoint); 666 String basePath = CmsStringUtil.joinPaths( 667 entryPointResource.getRootPath(), 668 CmsCategoryService.getInstance().getRepositoryBaseFolderName(getCmsObject())); 669 670 List<CmsCategoryTreeEntry> entries = CmsCoreService.getCategoriesForSitePathStatic( 671 cms, 672 entryPoint, 673 cms.getRequestContext().removeSiteRoot(basePath)); 674 CmsSitemapCategoryData categoryData = new CmsSitemapCategoryData(); 675 for (CmsCategoryTreeEntry entry : entries) { 676 categoryData.add(entry); 677 } 678 679 categoryData.setBasePath(basePath); 680 return categoryData; 681 } catch (Exception e) { 682 error(e); 683 return null; 684 } 685 } 686 687 /** 688 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#getChildren(java.lang.String, org.opencms.util.CmsUUID, int) 689 */ 690 public CmsClientSitemapEntry getChildren(String entryPointUri, CmsUUID entryId, int levels) throws CmsRpcException { 691 692 CmsClientSitemapEntry entry = null; 693 694 try { 695 CmsObject cms = getCmsObject(); 696 697 //ensure that root ends with a '/' if it's a folder 698 CmsResource rootRes = cms.readResource(entryId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 699 String root = cms.getSitePath(rootRes); 700 CmsJspNavElement navElement = getNavBuilder().getNavigationForResource( 701 root, 702 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 703 boolean isRoot = root.equals(entryPointUri); 704 entry = toClientEntry(navElement, isRoot); 705 if ((levels > 0) && (isRoot || (rootRes.isFolder()))) { 706 entry.setSubEntries(getChildren(root, levels, null), null); 707 } 708 } catch (Throwable e) { 709 error(e); 710 } 711 return entry; 712 } 713 714 /** 715 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#getGalleryData(java.lang.String) 716 */ 717 public Map<CmsGalleryType, List<CmsGalleryFolderEntry>> getGalleryData(String entryPointUri) { 718 719 List<String> subSitePaths = OpenCms.getADEManager().getSubSitePaths( 720 getCmsObject(), 721 getCmsObject().getRequestContext().addSiteRoot(entryPointUri)); 722 List<CmsGalleryType> galleryTypes = collectGalleryTypes(); 723 Map<CmsGalleryType, List<CmsGalleryFolderEntry>> result = new HashMap<CmsGalleryType, List<CmsGalleryFolderEntry>>(); 724 for (CmsGalleryType type : galleryTypes) { 725 List<CmsGalleryFolderEntry> galleries = null; 726 try { 727 galleries = getGalleriesForType(entryPointUri, type, subSitePaths); 728 } catch (CmsException e) { 729 log(e.getLocalizedMessage(), e); 730 } 731 result.put(type, galleries); 732 } 733 return result; 734 } 735 736 /** 737 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#getModelInfos(org.opencms.util.CmsUUID) 738 */ 739 public CmsModelInfo getModelInfos(CmsUUID rootId) throws CmsRpcException { 740 741 try { 742 CmsObject cms = getCmsObject(); 743 CmsResource rootResource = cms.readResource(rootId); 744 CmsModelPageHelper modelPageHelper = new CmsModelPageHelper(getCmsObject(), rootResource); 745 return modelPageHelper.getModelInfo(); 746 } catch (Throwable e) { 747 error(e); 748 return null; // will never be reached 749 } 750 751 } 752 753 /** 754 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#getNewElementInfo(java.lang.String) 755 */ 756 public List<CmsNewResourceInfo> getNewElementInfo(String entryPointUri) throws CmsRpcException { 757 758 try { 759 CmsObject cms = getCmsObject(); 760 String rootPath = cms.getRequestContext().addSiteRoot(entryPointUri); 761 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration(cms, rootPath); 762 List<CmsNewResourceInfo> result = getNewResourceInfos(cms, config, getWorkplaceLocale()); 763 return result; 764 } catch (Throwable e) { 765 error(e); 766 return null; 767 } 768 } 769 770 /** 771 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#getResourceLink(org.opencms.util.CmsUUID, java.lang.String) 772 */ 773 public String getResourceLink(CmsUUID baseId, String sitePath) throws CmsRpcException { 774 775 try { 776 CmsObject cms = OpenCms.initCmsObject(getCmsObject()); 777 CmsResource baseResource = cms.readResource(baseId, CmsResourceFilter.IGNORE_EXPIRATION); 778 String contextPath = cms.getSitePath(baseResource); 779 cms.getRequestContext().setUri(contextPath); 780 Locale locale = CmsJspTagLink.getBaseUriLocale(cms, contextPath); 781 if (locale != null) { 782 cms.getRequestContext().setLocale(locale); 783 } 784 String result = OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, sitePath); 785 return result; 786 } catch (Exception e) { 787 error(e); 788 } 789 return null; 790 } 791 792 /** 793 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#loadPropertyDataForLocaleCompareView(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID) 794 */ 795 public CmsLocaleComparePropertyData loadPropertyDataForLocaleCompareView(CmsUUID id, CmsUUID rootId) 796 throws CmsRpcException { 797 798 try { 799 CmsLocaleComparePropertyData result = new CmsLocaleComparePropertyData(); 800 CmsObject cms = getCmsObject(); 801 CmsResourceFilter filter = CmsResourceFilter.IGNORE_EXPIRATION; 802 CmsResource resource = cms.readResource(id, filter); 803 CmsResource defaultFile = cms.readDefaultFile(id.toString()); 804 result.setDefaultFileId(defaultFile != null ? defaultFile.getStructureId() : null); 805 result.setId(id); 806 result.setFolder(resource.isFolder()); 807 List<CmsProperty> props = cms.readPropertyObjects(resource, false); 808 List<CmsProperty> defaultFileProps = cms.readPropertyObjects(defaultFile, false); 809 Map<String, CmsClientProperty> clientProps = createClientProperties(props, true); 810 Map<String, CmsClientProperty> clientDefaultFileProps = createClientProperties(defaultFileProps, true); 811 812 result.setOwnProperties(clientProps); 813 result.setDefaultFileProperties(clientDefaultFileProps); 814 List<CmsResource> blockingLocked = cms.getBlockingLockedResources(resource); 815 816 CmsResource parent = cms.readParentFolder(resource.getStructureId()); 817 List<CmsResource> resourcesInSameFolder = cms.readResources(parent, CmsResourceFilter.ALL, false); 818 List<String> forbiddenUrlNames = Lists.newArrayList(); 819 for (CmsResource resourceInSameFolder : resourcesInSameFolder) { 820 String otherName = CmsResource.getName(resourceInSameFolder.getRootPath()); 821 forbiddenUrlNames.add(otherName); 822 } 823 result.setForbiddenUrlNames(forbiddenUrlNames); 824 result.setInheritedProperties(createClientProperties(cms.readPropertyObjects(parent, true), true)); 825 result.setPath(resource.getRootPath()); 826 String name = CmsFileUtil.removeTrailingSeparator(CmsResource.getName(resource.getRootPath())); 827 result.setName(name); 828 result.setHasEditableName(!CmsStringUtil.isEmptyOrWhitespaceOnly(name) && blockingLocked.isEmpty()); 829 return result; 830 } catch (Exception e) { 831 error(e); 832 return null; 833 } 834 } 835 836 /** 837 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#mergeSubSitemap(java.lang.String, org.opencms.util.CmsUUID) 838 */ 839 @SuppressWarnings("deprecation") 840 public CmsSitemapChange mergeSubSitemap(String entryPoint, CmsUUID subSitemapId) throws CmsRpcException { 841 842 CmsObject cms = getCmsObject(); 843 try { 844 ensureSession(); 845 CmsResource subSitemapFolder = cms.readResource(subSitemapId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 846 ensureLock(subSitemapFolder); 847 subSitemapFolder.setType( 848 OpenCms.getResourceManager().getResourceType(CmsResourceTypeFolder.RESOURCE_TYPE_NAME).getTypeId()); 849 cms.writeResource(subSitemapFolder); 850 String sitePath = cms.getSitePath(subSitemapFolder); 851 String sitemapConfigName = CmsStringUtil.joinPaths( 852 sitePath, 853 CmsADEManager.CONTENT_FOLDER_NAME, 854 CmsADEManager.CONFIG_FILE_NAME); 855 if (cms.existsResource(sitemapConfigName)) { 856 cms.deleteResource(sitemapConfigName, CmsResource.DELETE_PRESERVE_SIBLINGS); 857 } 858 tryUnlock(subSitemapFolder); 859 CmsSitemapClipboardData clipboard = getClipboardData(); 860 CmsClientSitemapEntry entry = toClientEntry( 861 getNavBuilder().getNavigationForResource( 862 cms.getSitePath(subSitemapFolder), 863 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED), 864 false); 865 clipboard.addModified(entry); 866 setClipboardData(clipboard); 867 entry = getChildren(entryPoint, subSitemapId, 1); 868 CmsSitemapChange result = new CmsSitemapChange(entry.getId(), entry.getSitePath(), ChangeType.modify); 869 result.setUpdatedEntry(entry); 870 return result; 871 } catch (Exception e) { 872 error(e); 873 } 874 return null; 875 } 876 877 /** 878 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#prefetch(java.lang.String) 879 */ 880 public CmsSitemapData prefetch(String sitemapUri) throws CmsRpcException { 881 882 CmsSitemapData result = null; 883 CmsObject cms = getCmsObject(); 884 885 try { 886 OpenCms.getRoleManager().checkRole(cms, CmsRole.EDITOR); 887 String openPath = getRequest().getParameter(CmsCoreData.PARAM_PATH); 888 if (!isValidOpenPath(cms, openPath)) { 889 // if no path is supplied, start from root 890 openPath = "/"; 891 } 892 CmsQuickLaunchLocationCache.getLocationCache(getRequest().getSession()).setSitemapEditorLocation( 893 cms.getRequestContext().getSiteRoot(), 894 openPath); 895 CmsADEConfigData configData = OpenCms.getADEManager().lookupConfiguration( 896 cms, 897 cms.getRequestContext().addSiteRoot(openPath)); 898 Map<String, CmsXmlContentProperty> propertyConfig = new LinkedHashMap<String, CmsXmlContentProperty>( 899 configData.getPropertyConfigurationAsMap()); 900 propertyConfig = CmsXmlContentPropertyHelper.resolveMacrosInProperties( 901 propertyConfig, 902 CmsMacroResolver.newWorkplaceLocaleResolver(getCmsObject())); 903 904 Map<String, CmsClientProperty> parentProperties = generateParentProperties(configData.getBasePath()); 905 String siteRoot = cms.getRequestContext().getSiteRoot(); 906 String exportRfsPrefix = OpenCms.getStaticExportManager().getDefaultRfsPrefix(); 907 CmsSite site = OpenCms.getSiteManager().getSiteForSiteRoot(siteRoot); 908 boolean isSecure = (site != null) && site.hasSecureServer(); 909 String parentSitemap = null; 910 911 if (configData.getBasePath() != null) { 912 CmsADEConfigData parentConfigData = OpenCms.getADEManager().lookupConfiguration( 913 cms, 914 CmsResource.getParentFolder(configData.getBasePath())); 915 parentSitemap = parentConfigData.getBasePath(); 916 if (parentSitemap != null) { 917 parentSitemap = cms.getRequestContext().removeSiteRoot(parentSitemap); 918 } 919 } 920 String noEdit = ""; 921 CmsNewResourceInfo defaultNewInfo = null; 922 List<CmsNewResourceInfo> newResourceInfos = null; 923 CmsDetailPageTable detailPages = null; 924 List<CmsNewResourceInfo> resourceTypeInfos = null; 925 boolean canEditDetailPages = false; 926 boolean isOnlineProject = CmsProject.isOnlineProject(cms.getRequestContext().getCurrentProject().getUuid()); 927 String defaultGalleryFolder = GALLERIES_FOLDER_NAME; 928 try { 929 CmsObject rootCms = OpenCms.initCmsObject(cms); 930 rootCms.getRequestContext().setSiteRoot(""); 931 CmsResource baseDir = rootCms.readResource( 932 configData.getBasePath(), 933 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 934 CmsProperty galleryFolderProp = cms.readPropertyObject( 935 baseDir, 936 CmsPropertyDefinition.PROPERTY_GALLERIES_FOLDER, 937 true); 938 if (!galleryFolderProp.isNullProperty() 939 && CmsStringUtil.isNotEmptyOrWhitespaceOnly(galleryFolderProp.getValue())) { 940 defaultGalleryFolder = galleryFolderProp.getValue(); 941 } 942 CmsPropertyEditorHelper.updateWysiwygConfig(propertyConfig, cms, baseDir); 943 } catch (CmsException e) { 944 LOG.warn(e.getLocalizedMessage(), e); 945 } 946 947 detailPages = new CmsDetailPageTable(configData.getAllDetailPages()); 948 if (!isOnlineProject) { 949 newResourceInfos = getNewResourceInfos(cms, configData, getWorkplaceLocale()); 950 CmsResource modelResource = null; 951 if (configData.getDefaultModelPage() != null) { 952 if (cms.existsResource(configData.getDefaultModelPage().getResource().getStructureId())) { 953 modelResource = configData.getDefaultModelPage().getResource(); 954 } else { 955 try { 956 modelResource = cms.readResource( 957 cms.getSitePath(configData.getDefaultModelPage().getResource()), 958 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 959 } catch (CmsException e) { 960 LOG.warn(e.getLocalizedMessage(), e); 961 } 962 } 963 } 964 if ((modelResource == null) && !newResourceInfos.isEmpty()) { 965 try { 966 modelResource = cms.readResource(newResourceInfos.get(0).getCopyResourceId()); 967 } catch (CmsException e) { 968 LOG.warn(e.getLocalizedMessage(), e); 969 } 970 } 971 CmsFormatterConfigurationCacheState formatterState = OpenCms.getADEManager().getCachedFormatters( 972 cms.getRequestContext().getCurrentProject().isOnlineProject()); 973 if (modelResource != null) { 974 resourceTypeInfos = getResourceTypeInfos( 975 getCmsObject(), 976 configData.getResourceTypes(), 977 configData.getFunctionReferences(), 978 configData.getDynamicFunctionAvailability(formatterState), 979 modelResource, 980 getWorkplaceLocale()); 981 try { 982 defaultNewInfo = createNewResourceInfo(cms, modelResource, getWorkplaceLocale()); 983 } catch (CmsException e) { 984 LOG.warn(e.getLocalizedMessage(), e); 985 } 986 } 987 canEditDetailPages = !(configData.isModuleConfiguration()); 988 } 989 if (isOnlineProject) { 990 noEdit = Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_SITEMAP_NO_EDIT_ONLINE_0); 991 } 992 List<String> allPropNames = getPropertyNames(cms); 993 String returnCode = getRequest().getParameter(CmsCoreData.PARAM_RETURNCODE); 994 if (!isValidReturnCode(returnCode)) { 995 returnCode = null; 996 } 997 cms.getRequestContext().getSiteRoot(); 998 String aliasImportUrl = OpenCms.getLinkManager().substituteLinkForRootPath(cms, ALIAS_IMPORT_PATH); 999 boolean canEditAliases = OpenCms.getAliasManager().hasPermissionsForMassEdit(cms, siteRoot); 1000 List<CmsListInfoBean> subsitemapFolderTypeInfos = collectSitemapTypeInfos(cms, configData); 1001 1002 // evaluate the editor mode 1003 EditorMode editorMode = CmsADESessionCache.getCache(getRequest(), getCmsObject()).getSitemapEditorMode(); 1004 if ((editorMode == null) || (editorMode == EditorMode.compareLocales)) { 1005 editorMode = EditorMode.navigation; 1006 } 1007 1008 String basePath = configData.getBasePath(); 1009 1010 if (!cms.existsResource( 1011 cms.getRequestContext().removeSiteRoot(basePath), 1012 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 1013 basePath = cms.getRequestContext().getSiteRoot(); 1014 } 1015 Boolean showModelEditConfirm = (Boolean)getRequest().getSession().getAttribute( 1016 ATTR_SHOW_MODEL_EDIT_CONFIRM); 1017 if (showModelEditConfirm == null) { 1018 showModelEditConfirm = Boolean.TRUE; 1019 } 1020 boolean showLocaleComparison = !(getCmsObject().getRequestContext().getCurrentProject().isOnlineProject()) 1021 && (site != null) 1022 && (site.getMainTranslationLocale(null) != null); 1023 1024 result = new CmsSitemapData( 1025 (new CmsTemplateFinder(cms)).getTemplates(), 1026 propertyConfig, 1027 getClipboardData(), 1028 CmsCoreService.getContextMenuEntries( 1029 cms, 1030 configData.getResource().getStructureId(), 1031 AdeContext.sitemapeditor, 1032 new HashMap<>()), 1033 parentProperties, 1034 allPropNames, 1035 exportRfsPrefix, 1036 isSecure, 1037 noEdit, 1038 isDisplayToolbar(getRequest()), 1039 defaultNewInfo, 1040 newResourceInfos, 1041 createResourceTypeInfo(OpenCms.getResourceManager().getResourceType(RECOURCE_TYPE_NAME_REDIRECT), null), 1042 createNavigationLevelTypeInfo(), 1043 getSitemapInfo(basePath), 1044 parentSitemap, 1045 getRootEntry(basePath, CmsResource.getFolderPath(openPath)), 1046 openPath, 1047 30, 1048 detailPages, 1049 resourceTypeInfos, 1050 returnCode, 1051 canEditDetailPages, 1052 aliasImportUrl, 1053 canEditAliases, 1054 OpenCms.getWorkplaceManager().getDefaultUserSettings().getSubsitemapCreationMode() == CmsDefaultUserSettings.SubsitemapCreationMode.createfolder, 1055 OpenCms.getRoleManager().hasRole(cms, CmsRole.GALLERY_EDITOR), 1056 OpenCms.getRoleManager().hasRole(cms, CmsRole.CATEGORY_EDITOR), 1057 subsitemapFolderTypeInfos, 1058 editorMode, 1059 defaultGalleryFolder, 1060 showModelEditConfirm.booleanValue()); 1061 1062 CmsUUID rootId = cms.readResource("/", CmsResourceFilter.ALL).getStructureId(); 1063 result.setSiteRootId(rootId); 1064 result.setLocaleComparisonEnabled(showLocaleComparison); 1065 boolean allowCreateNestedGalleries = Boolean.parseBoolean( 1066 "" + OpenCms.getRuntimeProperty("ade.sitemap.allowCreateNestedGalleries")); 1067 result.setAllowCreateNestedGalleries(allowCreateNestedGalleries); 1068 } catch (Throwable e) { 1069 error(e); 1070 } 1071 return result; 1072 } 1073 1074 /** 1075 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#prepareReloadSitemap(org.opencms.util.CmsUUID, org.opencms.ade.sitemap.shared.CmsSitemapData.EditorMode) 1076 */ 1077 public String prepareReloadSitemap(CmsUUID rootId, EditorMode mode) throws CmsRpcException { 1078 1079 try { 1080 CmsObject cms = getCmsObject(); 1081 CmsResource res = cms.readResource(CmsADEManager.PATH_SITEMAP_EDITOR_JSP); 1082 1083 CmsResource target = cms.readResource(rootId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1084 String targetRootPath = OpenCms.getADEManager().getSubSiteRoot(cms, target.getRootPath()); 1085 CmsSite targetSite = OpenCms.getSiteManager().getSiteForRootPath(targetRootPath); 1086 CmsADESessionCache.getCache(getRequest(), getCmsObject()).setSitemapEditorMode(mode); 1087 if (targetSite != null) { 1088 cms.getRequestContext().setSiteRoot(targetSite.getSiteRoot()); 1089 String path = cms.getRequestContext().removeSiteRoot(targetRootPath); 1090 String link = OpenCms.getLinkManager().substituteLink(cms, res); 1091 link = link + "?path=" + path; 1092 return link; 1093 } 1094 return null; 1095 } catch (Exception e) { 1096 error(e); 1097 return null; 1098 } 1099 } 1100 1101 /** 1102 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#removeModelPage(java.lang.String, org.opencms.util.CmsUUID) 1103 */ 1104 public void removeModelPage(String entryPointUri, CmsUUID id) throws CmsRpcException { 1105 1106 try { 1107 CmsObject cms = getCmsObject(); 1108 CmsResource rootResource = cms.readResource(entryPointUri); 1109 CmsModelPageHelper helper = new CmsModelPageHelper(getCmsObject(), rootResource); 1110 String configPath = CmsStringUtil.joinPaths(entryPointUri, ".content/.config"); 1111 CmsResource configResource = cms.readResource(configPath); 1112 helper.removeModelPage(configResource, id); 1113 OpenCms.getADEManager().waitForCacheUpdate(false); 1114 } catch (Throwable e) { 1115 error(e); 1116 1117 } 1118 1119 } 1120 1121 /** 1122 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#save(java.lang.String, org.opencms.ade.sitemap.shared.CmsSitemapChange) 1123 */ 1124 public CmsSitemapChange save(String entryPoint, CmsSitemapChange change) throws CmsRpcException { 1125 1126 CmsSitemapChange result = null; 1127 try { 1128 result = saveInternal(entryPoint, change); 1129 } catch (Exception e) { 1130 error(e); 1131 } 1132 return result; 1133 } 1134 1135 /** 1136 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#saveAliases(org.opencms.gwt.shared.alias.CmsAliasSaveValidationRequest) 1137 */ 1138 public CmsAliasEditValidationReply saveAliases(CmsAliasSaveValidationRequest saveRequest) throws CmsRpcException { 1139 1140 CmsObject cms = getCmsObject(); 1141 CmsAliasBulkEditHelper helper = new CmsAliasBulkEditHelper(cms); 1142 try { 1143 return helper.saveAliases(saveRequest); 1144 } catch (Exception e) { 1145 error(e); 1146 return null; 1147 } 1148 } 1149 1150 /** 1151 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#savePropertiesForLocaleCompareMode(org.opencms.util.CmsUUID, java.lang.String, java.util.List, boolean) 1152 */ 1153 public void savePropertiesForLocaleCompareMode( 1154 CmsUUID id, 1155 String newUrlName, 1156 List<CmsPropertyModification> propertyChanges, 1157 boolean editedName) 1158 throws CmsRpcException { 1159 1160 try { 1161 CmsObject cms = getCmsObject(); 1162 CmsResource ownRes = cms.readResource(id, CmsResourceFilter.IGNORE_EXPIRATION); 1163 CmsResource defaultFileRes = cms.readDefaultFile("" + id); 1164 boolean shallow = !editedName; 1165 try (AutoCloseable c = CmsLockUtil.withLockedResources(cms, shallow, ownRes, defaultFileRes)) { 1166 updateProperties(cms, ownRes, defaultFileRes, propertyChanges); 1167 if (editedName) { 1168 String parent = CmsResource.getParentFolder(ownRes.getRootPath()); 1169 newUrlName = CmsFileUtil.removeTrailingSeparator(newUrlName); 1170 String newPath = CmsStringUtil.joinPaths(parent, newUrlName); 1171 CmsObject rootCms = OpenCms.initCmsObject(cms); 1172 rootCms.getRequestContext().setSiteRoot(""); 1173 if (!CmsPath.equal(ownRes.getRootPath(), newPath)) { 1174 rootCms.moveResource(ownRes.getRootPath(), newPath); 1175 } 1176 } 1177 } 1178 } catch (Exception e) { 1179 error(e); 1180 } 1181 } 1182 1183 /** 1184 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#saveSitemapAttributes(org.opencms.util.CmsUUID, java.util.Map) 1185 */ 1186 public void saveSitemapAttributes(CmsUUID rootId, Map<String, String> attributes) throws CmsRpcException { 1187 1188 CmsResource configResource = null; 1189 try { 1190 CmsObject cms = getCmsObject(); 1191 CmsResource root = cms.readResource(rootId); 1192 String sitePath = cms.getSitePath(root); 1193 String configPath = CmsStringUtil.joinPaths(sitePath, "/.content/.config"); 1194 configResource = cms.readResource(configPath); 1195 CmsXmlContent configContent = CmsXmlContentFactory.unmarshal(cms, cms.readFile(configResource)); 1196 CmsSitemapAttributeUpdater updater = new CmsSitemapAttributeUpdater(cms, configContent); 1197 if (updater.saveAttributesFromEditorDialog(attributes)) { 1198 byte[] newContentBytes = configContent.marshal(); 1199 CmsFile file = configContent.getFile(); 1200 file.setContents(newContentBytes); 1201 cms.writeFile(file); 1202 OpenCms.getADEManager().waitForCacheUpdate(false); 1203 } 1204 } catch (Exception e) { 1205 error(e); 1206 } finally { 1207 try { 1208 if (configResource != null) { 1209 getCmsObject().unlockResource(configResource); 1210 } 1211 } catch (Exception e) { 1212 LOG.debug(e.getLocalizedMessage(), e); 1213 } 1214 } 1215 1216 } 1217 1218 /** 1219 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#setDefaultModel(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID) 1220 */ 1221 public CmsModelInfo setDefaultModel(CmsUUID rootId, CmsUUID modelId) throws CmsRpcException { 1222 1223 CmsModelInfo result = null; 1224 try { 1225 CmsObject cms = getCmsObject(); 1226 CmsResource rootResource = cms.readResource(rootId); 1227 CmsModelPageHelper modelPageHelper = new CmsModelPageHelper(getCmsObject(), rootResource); 1228 CmsResource configFile = OpenCms.getADEManager().lookupConfiguration( 1229 cms, 1230 rootResource.getRootPath()).getResource(); 1231 ensureLock(configFile); 1232 result = modelPageHelper.setDefaultModelPage(configFile, modelId); 1233 tryUnlock(configFile); 1234 } catch (Throwable e) { 1235 error(e); 1236 } 1237 return result; 1238 } 1239 1240 /** 1241 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#setEditorMode(org.opencms.ade.sitemap.shared.CmsSitemapData.EditorMode) 1242 */ 1243 public void setEditorMode(EditorMode editorMode) { 1244 1245 CmsADESessionCache.getCache(getRequest(), getCmsObject()).setSitemapEditorMode(editorMode); 1246 } 1247 1248 /** 1249 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#updateAliasEditorStatus(boolean) 1250 */ 1251 public void updateAliasEditorStatus(boolean editing) { 1252 1253 CmsObject cms = getCmsObject(); 1254 if (editing) { 1255 aliasEditorLockTable.update(cms, cms.getRequestContext().getSiteRoot()); 1256 } else { 1257 aliasEditorLockTable.clear(cms, cms.getRequestContext().getSiteRoot()); 1258 } 1259 } 1260 1261 /** 1262 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#validateAliases(org.opencms.gwt.shared.alias.CmsAliasEditValidationRequest) 1263 */ 1264 public CmsAliasEditValidationReply validateAliases(CmsAliasEditValidationRequest validationRequest) { 1265 1266 CmsObject cms = getCmsObject(); 1267 CmsAliasBulkEditHelper helper = new CmsAliasBulkEditHelper(cms); 1268 return helper.validateAliases(validationRequest); 1269 } 1270 1271 /** 1272 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#validateRewriteAliases(org.opencms.gwt.shared.alias.CmsRewriteAliasValidationRequest) 1273 */ 1274 public CmsRewriteAliasValidationReply validateRewriteAliases(CmsRewriteAliasValidationRequest validationRequest) { 1275 1276 CmsRewriteAliasValidationReply result = new CmsRewriteAliasValidationReply(); 1277 for (CmsRewriteAliasTableRow editedRow : validationRequest.getEditedRewriteAliases()) { 1278 try { 1279 String patternString = editedRow.getPatternString(); 1280 Pattern.compile(patternString); 1281 } catch (PatternSyntaxException e) { 1282 result.addError(editedRow.getId(), "Syntax error in regular expression: " + e.getMessage()); 1283 } 1284 } 1285 return result; 1286 } 1287 1288 /** 1289 * Locks the given resource with a temporary, if not already locked by the current user. 1290 * Will throw an exception if the resource could not be locked for the current user.<p> 1291 * 1292 * @param resource the resource to lock 1293 * 1294 * @return the assigned lock 1295 * 1296 * @throws CmsException if the resource could not be locked 1297 */ 1298 protected LockInfo ensureLockAndGetInfo(CmsResource resource) throws CmsException { 1299 1300 CmsObject cms = getCmsObject(); 1301 boolean justLocked = false; 1302 List<CmsResource> blockingResources = cms.getBlockingLockedResources(resource); 1303 if ((blockingResources != null) && !blockingResources.isEmpty()) { 1304 throw new CmsException( 1305 org.opencms.gwt.Messages.get().container( 1306 org.opencms.gwt.Messages.ERR_RESOURCE_HAS_BLOCKING_LOCKED_CHILDREN_1, 1307 cms.getSitePath(resource))); 1308 } 1309 CmsUser user = cms.getRequestContext().getCurrentUser(); 1310 CmsLock lock = cms.getLock(resource); 1311 if (!lock.isOwnedBy(user)) { 1312 cms.lockResourceTemporary(resource); 1313 lock = cms.getLock(resource); 1314 justLocked = true; 1315 } else if (!lock.isOwnedInProjectBy(user, cms.getRequestContext().getCurrentProject())) { 1316 cms.changeLock(resource); 1317 lock = cms.getLock(resource); 1318 justLocked = true; 1319 } 1320 return new LockInfo(lock, justLocked); 1321 } 1322 1323 /** 1324 * Internal method for saving a sitemap.<p> 1325 * 1326 * @param entryPoint the URI of the sitemap to save 1327 * @param change the change to save 1328 * 1329 * @return list of changed sitemap entries 1330 * 1331 * @throws CmsException if something goes wrong 1332 */ 1333 protected CmsSitemapChange saveInternal(String entryPoint, CmsSitemapChange change) throws CmsException { 1334 1335 ensureSession(); 1336 switch (change.getChangeType()) { 1337 case clipboardOnly: 1338 // do nothing 1339 break; 1340 case remove: 1341 change = removeEntryFromNavigation(change); 1342 break; 1343 case undelete: 1344 change = undelete(change); 1345 break; 1346 default: 1347 change = applyChange(entryPoint, change); 1348 } 1349 setClipboardData(change.getClipBoardData()); 1350 return change; 1351 } 1352 1353 /** 1354 * Gets the properties of a resource as a map of client properties.<p> 1355 * 1356 * @param cms the CMS context to use 1357 * @param res the resource whose properties to read 1358 * @param search true if the inherited properties should be read 1359 * 1360 * @return the client properties as a map 1361 * 1362 * @throws CmsException if something goes wrong 1363 */ 1364 Map<String, CmsClientProperty> getClientProperties(CmsObject cms, CmsResource res, boolean search) 1365 throws CmsException { 1366 1367 List<CmsProperty> props = cms.readPropertyObjects(res, search); 1368 Map<String, CmsClientProperty> result = createClientProperties(props, false); 1369 return result; 1370 } 1371 1372 /** 1373 * Adds a function detail element to a container page.<p> 1374 * 1375 * @param cms the current CMS context 1376 * @param page the container page which should be changed 1377 * @param containerName the name of the container which should be used for function detail elements 1378 * @param elementId the structure id of the element to add 1379 * @param formatterId the structure id of the formatter for the element 1380 * 1381 * @throws CmsException if something goes wrong 1382 */ 1383 private void addFunctionDetailElement( 1384 CmsObject cms, 1385 CmsXmlContainerPage page, 1386 String containerName, 1387 CmsUUID elementId, 1388 CmsUUID formatterId) 1389 throws CmsException { 1390 1391 CmsContainerPageBean bean = page.getContainerPage(cms); 1392 List<CmsContainerBean> containerBeans = new ArrayList<CmsContainerBean>(); 1393 Collection<CmsContainerBean> originalContainers = bean.getContainers().values(); 1394 if ((containerName == null) && !originalContainers.isEmpty()) { 1395 CmsContainerBean firstContainer = originalContainers.iterator().next(); 1396 containerName = firstContainer.getName(); 1397 } 1398 boolean foundContainer = false; 1399 for (CmsContainerBean cntBean : originalContainers) { 1400 boolean isDetailTarget = cntBean.getName().equals(containerName); 1401 if (isDetailTarget && !foundContainer) { 1402 foundContainer = true; 1403 List<CmsContainerElementBean> newElems = new ArrayList<CmsContainerElementBean>(); 1404 newElems.addAll(cntBean.getElements()); 1405 CmsContainerElementBean newElement = new CmsContainerElementBean( 1406 elementId, 1407 formatterId, 1408 new HashMap<String, String>(), 1409 false); 1410 newElems.add(0, newElement); 1411 CmsContainerBean newCntBean = cntBean.copyWithNewElements(newElems); 1412 containerBeans.add(newCntBean); 1413 } else { 1414 containerBeans.add(cntBean); 1415 } 1416 } 1417 if (!foundContainer) { 1418 throw new CmsException( 1419 Messages.get().container(Messages.ERR_NO_FUNCTION_DETAIL_CONTAINER_1, page.getFile().getRootPath())); 1420 } 1421 CmsContainerPageBean bean2 = new CmsContainerPageBean(new ArrayList<CmsContainerBean>(containerBeans)); 1422 page.writeContainerPage(cms, bean2); 1423 1424 } 1425 1426 /** 1427 * Applys the given change to the VFS.<p> 1428 * 1429 * @param entryPoint the sitemap entry-point 1430 * @param change the change 1431 * 1432 * @return the updated entry 1433 * 1434 * @throws CmsException if something goes wrong 1435 */ 1436 private CmsSitemapChange applyChange(String entryPoint, CmsSitemapChange change) throws CmsException { 1437 1438 CmsObject cms = getCmsObject(); 1439 CmsResource configFile = null; 1440 // lock the config file first, to avoid half done changes 1441 if (change.hasDetailPageInfos()) { 1442 CmsADEConfigData configData = OpenCms.getADEManager().lookupConfiguration( 1443 cms, 1444 cms.getRequestContext().addSiteRoot(entryPoint)); 1445 if (!configData.isModuleConfiguration() && (configData.getResource() != null)) { 1446 configFile = configData.getResource(); 1447 } 1448 if (configFile != null) { 1449 ensureLock(configFile); 1450 } 1451 } 1452 if (change.isNew()) { 1453 CmsClientSitemapEntry newEntry = createNewEntry(entryPoint, change); 1454 change.setUpdatedEntry(newEntry); 1455 change.setEntryId(newEntry.getId()); 1456 } else if (change.getChangeType() == ChangeType.delete) { 1457 delete(change); 1458 } else if (change.getEntryId() != null) { 1459 modifyEntry(change); 1460 } 1461 if (change.hasDetailPageInfos() && (configFile != null)) { 1462 saveDetailPages(change.getDetailPageInfos(), configFile, change.getEntryId(), change.getUpdatedEntry()); 1463 tryUnlock(configFile); 1464 } 1465 1466 return change; 1467 } 1468 1469 /** 1470 * Changes the navigation for a moved entry and its neighbors.<p> 1471 * 1472 * @param change the sitemap change 1473 * @param entryFolder the moved entry 1474 * 1475 * @throws CmsException if something goes wrong 1476 */ 1477 private void applyNavigationChanges(CmsSitemapChange change, CmsResource entryFolder) throws CmsException { 1478 1479 CmsObject cms = getCmsObject(); 1480 String parentPath = null; 1481 if (change.hasNewParent()) { 1482 CmsResource parent = cms.readResource(change.getParentId()); 1483 parentPath = cms.getSitePath(parent); 1484 } else { 1485 parentPath = CmsResource.getParentFolder(cms.getSitePath(entryFolder)); 1486 } 1487 List<CmsJspNavElement> navElements = getNavBuilder().getNavigationForFolder( 1488 parentPath, 1489 Visibility.all, 1490 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1491 CmsSitemapNavPosCalculator npc = new CmsSitemapNavPosCalculator(navElements, entryFolder, change.getPosition()); 1492 List<CmsJspNavElement> navs = npc.getNavigationChanges(); 1493 List<CmsResource> needToUnlock = new ArrayList<CmsResource>(); 1494 1495 try { 1496 for (CmsJspNavElement nav : navs) { 1497 LockInfo lockInfo = ensureLockAndGetInfo(nav.getResource()); 1498 if (!nav.getResource().equals(entryFolder) && lockInfo.wasJustLocked()) { 1499 needToUnlock.add(nav.getResource()); 1500 } 1501 } 1502 for (CmsJspNavElement nav : navs) { 1503 CmsProperty property = new CmsProperty( 1504 CmsPropertyDefinition.PROPERTY_NAVPOS, 1505 "" + nav.getNavPosition(), 1506 null); 1507 cms.writePropertyObject(cms.getSitePath(nav.getResource()), property); 1508 } 1509 } finally { 1510 for (CmsResource lockedRes : needToUnlock) { 1511 try { 1512 cms.unlockResource(lockedRes); 1513 } catch (CmsException e) { 1514 // we catch this because we still want to unlock the other resources 1515 LOG.error(e.getLocalizedMessage(), e); 1516 } 1517 } 1518 } 1519 } 1520 1521 /** 1522 * Builds the list info bean for a resource type which can be used as a sub-sitemap folder.<p> 1523 * 1524 * @param sitemapType the sitemap folder type 1525 * 1526 * @return the list info bean for the given type 1527 */ 1528 private CmsListInfoBean buildSitemapTypeInfo(I_CmsResourceType sitemapType) { 1529 1530 CmsListInfoBean result = new CmsListInfoBean(); 1531 CmsWorkplaceManager wm = OpenCms.getWorkplaceManager(); 1532 String typeName = sitemapType.getTypeName(); 1533 Locale wpLocale = wm.getWorkplaceLocale(getCmsObject()); 1534 String title = typeName; 1535 String description = ""; 1536 try { 1537 title = CmsWorkplaceMessages.getResourceTypeName(wpLocale, typeName); 1538 } catch (Throwable e) { 1539 LOG.warn(e.getLocalizedMessage(), e); 1540 } 1541 try { 1542 description = CmsWorkplaceMessages.getResourceTypeDescription(wpLocale, typeName); 1543 } catch (Throwable e) { 1544 LOG.warn(e.getLocalizedMessage(), e); 1545 } 1546 result.setResourceType(typeName); 1547 result.setTitle(title); 1548 result.setSubTitle(description); 1549 return result; 1550 } 1551 1552 /** 1553 * Returns all available gallery folder resource types.<p> 1554 * 1555 * @return the gallery folder resource types 1556 */ 1557 @SuppressWarnings("deprecation") 1558 private List<CmsGalleryType> collectGalleryTypes() { 1559 1560 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject()); 1561 Map<String, List<String>> galleryContentTypes = new HashMap<String, List<String>>(); 1562 List<CmsGalleryType> result = new ArrayList<CmsGalleryType>(); 1563 for (I_CmsResourceType resourceType : OpenCms.getResourceManager().getResourceTypes()) { 1564 if (resourceType instanceof CmsResourceTypeFolderExtended) { 1565 // found a configured extended folder resource type 1566 CmsResourceTypeFolderExtended galleryType = (CmsResourceTypeFolderExtended)resourceType; 1567 String folderClassName = galleryType.getFolderClassName(); 1568 if (CmsStringUtil.isNotEmpty(folderClassName)) { 1569 // only process this as a gallery if the folder name is not empty 1570 try { 1571 // check, if the folder class is a subclass of A_CmsGallery 1572 if (A_CmsAjaxGallery.class.isAssignableFrom(Class.forName(folderClassName))) { 1573 CmsGalleryType gallery = new CmsGalleryType(); 1574 gallery.setTypeId(resourceType.getTypeId()); 1575 gallery.setResourceType(resourceType.getTypeName()); 1576 gallery.setTitle( 1577 CmsWorkplaceMessages.getResourceTypeName(wpLocale, resourceType.getTypeName())); 1578 gallery.setSubTitle( 1579 CmsWorkplaceMessages.getResourceTypeDescription(wpLocale, resourceType.getTypeName())); 1580 gallery.setBigIconClasses( 1581 CmsIconUtil.getIconClasses(resourceType.getTypeName(), null, false)); 1582 result.add(gallery); 1583 } 1584 } catch (Exception e) { 1585 this.log(e.getLocalizedMessage(), e); 1586 } 1587 } 1588 } else { 1589 List<I_CmsResourceType> galleryTypes = resourceType.getGalleryTypes(); 1590 if ((galleryTypes != null) && !galleryTypes.isEmpty()) { 1591 for (I_CmsResourceType galleryType : galleryTypes) { 1592 List<String> typeList = galleryContentTypes.get(galleryType.getTypeName()); 1593 if (typeList == null) { 1594 typeList = new ArrayList<String>(); 1595 galleryContentTypes.put(galleryType.getTypeName(), typeList); 1596 } 1597 typeList.add(resourceType.getTypeName()); 1598 } 1599 } 1600 } 1601 } 1602 for (CmsGalleryType galleryType : result) { 1603 galleryType.setContentTypeNames(galleryContentTypes.get(galleryType.getResourceType())); 1604 } 1605 return result; 1606 } 1607 1608 /** 1609 * Gets the information for the available sitemap folder types.<p> 1610 * 1611 * @param cms the current CMS context 1612 * @param configData the configuration data for the current subsitemap 1613 * @return the list info beans corresponding to available sitemap folder types 1614 */ 1615 private List<CmsListInfoBean> collectSitemapTypeInfos(CmsObject cms, CmsADEConfigData configData) { 1616 1617 List<CmsListInfoBean> subsitemapFolderTypeInfos = new ArrayList<CmsListInfoBean>(); 1618 List<Integer> sitemapTypeIds = CmsResourceTypeFolderSubSitemap.getSubSitemapResourceTypeIds(); 1619 String checkPath = configData.getBasePath(); 1620 if (checkPath != null) { 1621 checkPath = cms.getRequestContext().removeSiteRoot(checkPath); 1622 } else { 1623 checkPath = "/"; 1624 } 1625 CmsResource checkResource = null; 1626 try { 1627 checkResource = cms.readResource(checkPath); 1628 } catch (CmsException e) { 1629 LOG.warn(e.getLocalizedMessage(), e); 1630 } 1631 1632 for (Integer typeId : sitemapTypeIds) { 1633 try { 1634 I_CmsResourceType sitemapType = OpenCms.getResourceManager().getResourceType(typeId.intValue()); 1635 String typeName = sitemapType.getTypeName(); 1636 CmsExplorerTypeSettings explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName); 1637 1638 // if explorer type and check resource available, perform a permission check 1639 if ((explorerType != null) && (checkResource != null)) { 1640 try { 1641 CmsExplorerTypeAccess access = explorerType.getAccess(); 1642 if (!access.getPermissions(cms, checkResource).requiresControlPermission()) { 1643 continue; 1644 } 1645 } catch (Exception e) { 1646 LOG.error(e.getLocalizedMessage(), e); 1647 } 1648 } 1649 CmsListInfoBean infoBean = buildSitemapTypeInfo(sitemapType); 1650 subsitemapFolderTypeInfos.add(infoBean); 1651 1652 } catch (CmsLoaderException e) { 1653 LOG.warn("Could not read sitemap folder type " + typeId + ": " + e.getLocalizedMessage(), e); 1654 } 1655 } 1656 return subsitemapFolderTypeInfos; 1657 } 1658 1659 /** 1660 * Creates a client alias bean from a server-side alias.<p> 1661 * 1662 * @param cms the current CMS context 1663 * @param alias the alias to convert 1664 * 1665 * @return the alias table row 1666 * 1667 * @throws CmsException if something goes wrong 1668 */ 1669 private CmsAliasTableRow createAliasTableEntry(CmsObject cms, CmsAlias alias) throws CmsException { 1670 1671 CmsResource resource = cms.readResource(alias.getStructureId(), CmsResourceFilter.ALL); 1672 CmsAliasTableRow result = new CmsAliasTableRow(); 1673 result.setStructureId(alias.getStructureId()); 1674 result.setOriginalStructureId(alias.getStructureId()); 1675 result.setAliasPath(alias.getAliasPath()); 1676 result.setResourcePath(cms.getSitePath(resource)); 1677 result.setKey((new CmsUUID()).toString()); 1678 result.setMode(alias.getMode()); 1679 result.setChanged(false); 1680 return result; 1681 } 1682 1683 /** 1684 * Creates a navigation level type info.<p> 1685 * 1686 * @return the navigation level type info bean 1687 * 1688 * @throws CmsException if reading the sub level redirect copy page fails 1689 */ 1690 private CmsNewResourceInfo createNavigationLevelTypeInfo() throws CmsException { 1691 1692 String name = CmsResourceTypeFolder.getStaticTypeName(); 1693 Locale locale = getWorkplaceLocale(); 1694 String subtitle = Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_NAVIGATION_LEVEL_SUBTITLE_0); 1695 if (CmsStringUtil.isEmptyOrWhitespaceOnly(subtitle)) { 1696 subtitle = CmsWorkplaceMessages.getResourceTypeName(locale, name); 1697 } 1698 CmsNewResourceInfo result = new CmsNewResourceInfo( 1699 CmsResourceTypeFolder.getStaticTypeId(), 1700 name, 1701 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_NAVIGATION_LEVEL_TITLE_0), 1702 subtitle, 1703 getCmsObject().readResource(SUB_LEVEL_REDIRECT_COPY_PAGE).getStructureId(), 1704 false, 1705 subtitle); 1706 result.setBigIconClasses(CmsIconUtil.ICON_NAV_LEVEL_BIG); 1707 result.setCreateParameter(CmsJspNavBuilder.NAVIGATION_LEVEL_FOLDER); 1708 return result; 1709 } 1710 1711 /** 1712 * Creates new content elements if required by the model page.<p> 1713 * 1714 * @param cms the cms context 1715 * @param page the page 1716 * @param sitePath the resource site path 1717 * 1718 * @throws CmsException when unable to create the content elements 1719 */ 1720 private boolean createNewContainerElements(CmsObject cms, CmsMutableContainerPage page, String sitePath) 1721 throws CmsException { 1722 1723 boolean needsChanges = false; 1724 CmsADEConfigData configData = OpenCms.getADEManager().lookupConfiguration(cms, cms.addSiteRoot(sitePath)); 1725 Locale contentLocale = OpenCms.getLocaleManager().getDefaultLocale(cms, CmsResource.getFolderPath(sitePath)); 1726 CmsObject cloneCms = OpenCms.initCmsObject(cms); 1727 cloneCms.getRequestContext().setLocale(contentLocale); 1728 for (CmsMutableContainer container : page.containers()) { 1729 ListIterator<CmsContainerElementBean> iter = container.elements().listIterator(); 1730 while (iter.hasNext()) { 1731 CmsContainerElementBean elem = iter.next(); 1732 if (elem.isCreateNew() && !elem.isGroupContainer(cms) && !elem.isInheritedContainer(cms)) { 1733 String typeName = OpenCms.getResourceManager().getResourceType(elem.getResource()).getTypeName(); 1734 CmsResourceTypeConfig typeConfig = configData.getResourceType(typeName); 1735 if (typeConfig == null) { 1736 throw new IllegalArgumentException( 1737 "Can not copy template model element '" 1738 + elem.getResource().getRootPath() 1739 + "' because the resource type '" 1740 + typeName 1741 + "' is not available in this sitemap."); 1742 } 1743 1744 CmsResource newResource = typeConfig.createNewElement( 1745 cloneCms, 1746 elem.getResource(), 1747 CmsResource.getParentFolder(cms.getRequestContext().addSiteRoot(sitePath))); 1748 CmsContainerElementBean newBean = new CmsContainerElementBean( 1749 newResource.getStructureId(), 1750 elem.getFormatterId(), 1751 elem.getIndividualSettings(), 1752 false); 1753 iter.set(newBean); 1754 needsChanges = true; 1755 } 1756 } 1757 } 1758 return needsChanges; 1759 } 1760 1761 /** 1762 * Creates new content elements if required by the model page.<p> 1763 * 1764 * @param cms the cms context 1765 * @param page the page 1766 * @param sitePath the resource site path 1767 * 1768 * @throws CmsException when unable to create the content elements 1769 */ 1770 private void createNewContainerElements(CmsObject cms, CmsXmlContainerPage page, String sitePath) 1771 throws CmsException { 1772 1773 CmsADEConfigData configData = OpenCms.getADEManager().lookupConfiguration(cms, cms.addSiteRoot(sitePath)); 1774 Locale contentLocale = OpenCms.getLocaleManager().getDefaultLocale(cms, CmsResource.getFolderPath(sitePath)); 1775 CmsObject cloneCms = OpenCms.initCmsObject(cms); 1776 cloneCms.getRequestContext().setLocale(contentLocale); 1777 CmsContainerPageBean pageBean = page.getContainerPage(cms); 1778 boolean needsChanges = false; 1779 List<CmsContainerBean> updatedContainers = new ArrayList<CmsContainerBean>(); 1780 for (CmsContainerBean container : pageBean.getContainers().values()) { 1781 List<CmsContainerElementBean> updatedElements = new ArrayList<CmsContainerElementBean>(); 1782 for (CmsContainerElementBean element : container.getElements()) { 1783 if (element.isCreateNew() && !element.isGroupContainer(cms) && !element.isInheritedContainer(cms)) { 1784 needsChanges = true; 1785 String typeName = OpenCms.getResourceManager().getResourceType(element.getResource()).getTypeName(); 1786 CmsResourceTypeConfig typeConfig = configData.getResourceType(typeName); 1787 if (typeConfig == null) { 1788 throw new IllegalArgumentException( 1789 "Can not copy template model element '" 1790 + element.getResource().getRootPath() 1791 + "' because the resource type '" 1792 + typeName 1793 + "' is not available in this sitemap."); 1794 } 1795 1796 CmsResource newResource = typeConfig.createNewElement( 1797 cloneCms, 1798 element.getResource(), 1799 CmsResource.getParentFolder(cms.getRequestContext().addSiteRoot(sitePath))); 1800 CmsContainerElementBean newBean = new CmsContainerElementBean( 1801 newResource.getStructureId(), 1802 element.getFormatterId(), 1803 element.getIndividualSettings(), 1804 false); 1805 updatedElements.add(newBean); 1806 } else { 1807 updatedElements.add(element); 1808 } 1809 } 1810 1811 CmsContainerBean updatedContainer = container.copyWithNewElements(updatedElements); 1812 updatedContainers.add(updatedContainer); 1813 } 1814 if (needsChanges) { 1815 CmsContainerPageBean updatedPage = new CmsContainerPageBean(updatedContainers); 1816 page.writeContainerPage(cms, updatedPage); 1817 } 1818 } 1819 1820 /** 1821 * Creates a new page in navigation.<p> 1822 * 1823 * @param entryPoint the site-map entry-point 1824 * @param change the new change 1825 * 1826 * @return the updated entry 1827 * 1828 * @throws CmsException if something goes wrong 1829 */ 1830 @SuppressWarnings("deprecation") 1831 private CmsClientSitemapEntry createNewEntry(String entryPoint, CmsSitemapChange change) throws CmsException { 1832 1833 CmsObject cms = getCmsObject(); 1834 CmsClientSitemapEntry newEntry = null; 1835 if (change.getParentId() != null) { 1836 CmsResource parentFolder = cms.readResource( 1837 change.getParentId(), 1838 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1839 String entryPath = ""; 1840 CmsResource entryFolder = null; 1841 CmsResource newRes = null; 1842 byte[] content = null; 1843 List<CmsProperty> properties = Collections.emptyList(); 1844 CmsResource copyPage = null; 1845 if (change.getNewCopyResourceId() != null) { 1846 copyPage = cms.readResource(change.getNewCopyResourceId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1847 content = cms.readFile(copyPage).getContents(); 1848 properties = cms.readPropertyObjects(copyPage, false); 1849 } 1850 List<CmsProperty> filteredProperties = new ArrayList<CmsProperty>(); 1851 for (CmsProperty property : properties) { 1852 boolean filter = false; 1853 if (FILTER_PROPERTIES.contains(property.getName())) { 1854 filter = true; 1855 1856 } else { 1857 // filter localized versions also 1858 for (String filterProp : FILTER_PROPERTIES) { 1859 if (property.getName().startsWith(filterProp + "_")) { 1860 filter = true; 1861 break; 1862 } 1863 } 1864 } 1865 if (!filter) { 1866 filteredProperties.add(property); 1867 } 1868 } 1869 properties = filteredProperties; 1870 if (isRedirectType(change.getNewResourceTypeId())) { 1871 entryPath = CmsStringUtil.joinPaths(cms.getSitePath(parentFolder), change.getName()); 1872 newRes = cms.createResource( 1873 entryPath, 1874 change.getNewResourceTypeId(), 1875 null, 1876 Collections.singletonList( 1877 new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, change.getName(), null))); 1878 cms.writePropertyObjects(newRes, generateInheritProperties(change, newRes)); 1879 applyNavigationChanges(change, newRes); 1880 } else { 1881 String entryFolderPath = CmsStringUtil.joinPaths(cms.getSitePath(parentFolder), change.getName() + "/"); 1882 boolean idWasNull = change.getEntryId() == null; 1883 // we don't really need to create a folder object here anymore. 1884 if (idWasNull) { 1885 // need this for calculateNavPosition, even though the id will get overwritten 1886 change.setEntryId(new CmsUUID()); 1887 } 1888 1889 boolean isFunctionDetail = false; 1890 boolean isNavigationLevel = false; 1891 if (change.getCreateParameter() != null) { 1892 if (CmsUUID.isValidUUID(change.getCreateParameter())) { 1893 isFunctionDetail = true; 1894 } else if (CmsJspNavBuilder.NAVIGATION_LEVEL_FOLDER.equals(change.getCreateParameter())) { 1895 isNavigationLevel = true; 1896 } 1897 } 1898 String folderType = CmsResourceTypeFolder.getStaticTypeName(); 1899 String createSitemapFolderType = change.getCreateSitemapFolderType(); 1900 if (createSitemapFolderType != null) { 1901 folderType = createSitemapFolderType; 1902 } 1903 1904 int folderTypeId = OpenCms.getResourceManager().getResourceType(folderType).getTypeId(); 1905 entryFolder = new CmsResource( 1906 change.getEntryId(), 1907 new CmsUUID(), 1908 entryFolderPath, 1909 folderTypeId, 1910 true, 1911 0, 1912 cms.getRequestContext().getCurrentProject().getUuid(), 1913 CmsResource.STATE_NEW, 1914 System.currentTimeMillis(), 1915 cms.getRequestContext().getCurrentUser().getId(), 1916 System.currentTimeMillis(), 1917 cms.getRequestContext().getCurrentUser().getId(), 1918 CmsResource.DATE_RELEASED_DEFAULT, 1919 CmsResource.DATE_EXPIRED_DEFAULT, 1920 1, 1921 0, 1922 System.currentTimeMillis(), 1923 0); 1924 List<CmsProperty> folderProperties = generateInheritProperties(change, entryFolder); 1925 if (isNavigationLevel) { 1926 folderProperties.add( 1927 new CmsProperty( 1928 CmsPropertyDefinition.PROPERTY_DEFAULT_FILE, 1929 CmsJspNavBuilder.NAVIGATION_LEVEL_FOLDER, 1930 null)); 1931 } 1932 entryFolder = cms.createResource(entryFolderPath, folderTypeId, null, folderProperties); 1933 if (createSitemapFolderType != null) { 1934 createSitemapContentFolder(cms, entryFolder); 1935 } 1936 if (idWasNull) { 1937 change.setEntryId(entryFolder.getStructureId()); 1938 } 1939 applyNavigationChanges(change, entryFolder); 1940 entryPath = CmsStringUtil.joinPaths(entryFolderPath, "index.html"); 1941 boolean isContainerPage = change.getNewResourceTypeId() == CmsResourceTypeXmlContainerPage.getContainerPageTypeIdSafely(); 1942 if (isContainerPage && (copyPage != null)) { 1943 1944 // do *NOT* get this from the cache, because we perform some destructive operation on the XML content 1945 CmsXmlContainerPage page = CmsXmlContainerPageFactory.unmarshal( 1946 cms, 1947 cms.readFile(copyPage), 1948 true, 1949 true); 1950 CmsContainerPageWrapper wrapper = new CmsContainerPageWrapper(cms, page); 1951 if (isFunctionDetail) { 1952 String functionDetailContainer = getFunctionDetailContainerName(parentFolder); 1953 if (functionDetailContainer != null) { 1954 CmsUUID functionStructureId = new CmsUUID(change.getCreateParameter()); 1955 CmsResource functionRes = cms.readResource( 1956 functionStructureId, 1957 CmsResourceFilter.IGNORE_EXPIRATION); 1958 CmsResource functionFormatter; 1959 if (OpenCms.getResourceManager().matchResourceType( 1960 CmsResourceTypeFunctionConfig.TYPE_NAME, 1961 functionRes.getTypeId())) { 1962 functionFormatter = cms.readResource(CmsResourceTypeFunctionConfig.FORMATTER_PATH); 1963 } else { 1964 functionFormatter = cms.readResource( 1965 CmsResourceTypeFunctionConfig.FORMATTER_PATH, 1966 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1967 } 1968 if (!wrapper.addElementToContainer( 1969 functionDetailContainer, 1970 new CmsContainerElementBean( 1971 functionStructureId, 1972 functionFormatter.getStructureId(), 1973 new HashMap<>(), 1974 false))) { 1975 1976 throw new CmsException( 1977 Messages.get().container( 1978 Messages.ERR_NO_FUNCTION_DETAIL_CONTAINER_1, 1979 page.getFile().getRootPath())); 1980 } 1981 } else { 1982 LOG.debug("function detail container is null for " + parentFolder.getRootPath()); 1983 } 1984 } 1985 createNewContainerElements(cms, wrapper.page(), entryPath); 1986 content = wrapper.marshal(); 1987 } 1988 newRes = cms.createResource( 1989 entryPath, 1990 copyPage != null ? copyPage.getTypeId() : change.getNewResourceTypeId(), 1991 content, 1992 properties); 1993 cms.writePropertyObjects(newRes, generateOwnProperties(change)); 1994 } 1995 1996 if (entryFolder != null) { 1997 tryUnlock(entryFolder); 1998 String sitePath = cms.getSitePath(entryFolder); 1999 newEntry = toClientEntry( 2000 getNavBuilder().getNavigationForResource(sitePath, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED), 2001 false); 2002 newEntry.setSubEntries(getChildren(sitePath, 1, null), null); 2003 newEntry.setChildrenLoadedInitially(true); 2004 } 2005 if (newRes != null) { 2006 tryUnlock(newRes); 2007 } 2008 if (newEntry == null) { 2009 newEntry = toClientEntry( 2010 getNavBuilder().getNavigationForResource( 2011 cms.getSitePath(newRes), 2012 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED), 2013 false); 2014 } 2015 // mark position as not set 2016 newEntry.setPosition(-1); 2017 newEntry.setNew(true); 2018 change.getClipBoardData().getModifications().remove(null); 2019 change.getClipBoardData().getModifications().put(newEntry.getId(), newEntry); 2020 } 2021 return newEntry; 2022 } 2023 2024 /** 2025 * Creates a new resource info to a given model page resource.<p> 2026 * 2027 * @param cms the current CMS context 2028 * @param modelResource the model page resource 2029 * @param locale the locale used for retrieving descriptions/titles 2030 * 2031 * @return the new resource info 2032 * 2033 * @throws CmsException if something goes wrong 2034 */ 2035 private CmsNewResourceInfo createNewResourceInfo(CmsObject cms, CmsResource modelResource, Locale locale) 2036 throws CmsException { 2037 2038 // if model page got overwritten by another resource, reread from site path 2039 if (!cms.existsResource(modelResource.getStructureId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 2040 modelResource = cms.readResource(cms.getSitePath(modelResource), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2041 } 2042 int typeId = modelResource.getTypeId(); 2043 String name = OpenCms.getResourceManager().getResourceType(typeId).getTypeName(); 2044 String title = cms.readPropertyObject( 2045 modelResource, 2046 CmsPropertyDefinition.PROPERTY_TITLE, 2047 false, 2048 locale).getValue(); 2049 String description = cms.readPropertyObject( 2050 modelResource, 2051 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 2052 false, 2053 locale).getValue(); 2054 2055 boolean editable = false; 2056 try { 2057 CmsResource freshModelResource = cms.readResource( 2058 modelResource.getStructureId(), 2059 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2060 editable = cms.hasPermissions( 2061 freshModelResource, 2062 CmsPermissionSet.ACCESS_WRITE, 2063 false, 2064 CmsResourceFilter.DEFAULT); 2065 } catch (CmsException e) { 2066 LOG.warn(e.getLocalizedMessage(), e); 2067 } 2068 CmsNewResourceInfo info = new CmsNewResourceInfo( 2069 typeId, 2070 name, 2071 title, 2072 description, 2073 modelResource.getStructureId(), 2074 editable, 2075 description); 2076 info.setBigIconClasses(CmsIconUtil.getIconClasses(name, null, false)); 2077 Float navpos = null; 2078 try { 2079 CmsProperty navposProp = cms.readPropertyObject(modelResource, CmsPropertyDefinition.PROPERTY_NAVPOS, true); 2080 String navposStr = navposProp.getValue(); 2081 if (navposStr != null) { 2082 try { 2083 navpos = Float.valueOf(navposStr); 2084 } catch (NumberFormatException e) { 2085 // noop 2086 } 2087 } 2088 } catch (CmsException e) { 2089 LOG.warn(e.getLocalizedMessage(), e); 2090 } 2091 2092 info.setNavPos(navpos); 2093 info.setDate( 2094 CmsDateUtil.getDate(new Date(modelResource.getDateLastModified()), DateFormat.LONG, getWorkplaceLocale())); 2095 info.setVfsPath(modelResource.getRootPath()); 2096 return info; 2097 } 2098 2099 /** 2100 * Creates a resource type info bean for a given resource type.<p> 2101 * 2102 * @param resType the resource type 2103 * @param copyResource the structure id of the copy resource 2104 * 2105 * @return the resource type info bean 2106 */ 2107 @SuppressWarnings("deprecation") 2108 private CmsNewResourceInfo createResourceTypeInfo(I_CmsResourceType resType, CmsResource copyResource) { 2109 2110 String name = resType.getTypeName(); 2111 Locale locale = getWorkplaceLocale(); 2112 String subtitle = CmsWorkplaceMessages.getResourceTypeDescription(locale, name); 2113 if (CmsStringUtil.isEmptyOrWhitespaceOnly(subtitle)) { 2114 subtitle = CmsWorkplaceMessages.getResourceTypeName(locale, name); 2115 } 2116 if (copyResource != null) { 2117 CmsNewResourceInfo info = new CmsNewResourceInfo( 2118 copyResource.getTypeId(), 2119 name, 2120 CmsWorkplaceMessages.getResourceTypeName(locale, name), 2121 CmsWorkplaceMessages.getResourceTypeDescription(locale, name), 2122 copyResource.getStructureId(), 2123 false, 2124 subtitle); 2125 info.setBigIconClasses(CmsIconUtil.getIconClasses(name, null, false)); 2126 return info; 2127 } else { 2128 CmsNewResourceInfo info = new CmsNewResourceInfo( 2129 resType.getTypeId(), 2130 name, 2131 CmsWorkplaceMessages.getResourceTypeName(locale, name), 2132 CmsWorkplaceMessages.getResourceTypeDescription(locale, name), 2133 null, 2134 false, 2135 subtitle); 2136 info.setBigIconClasses(CmsIconUtil.getIconClasses(name, null, false)); 2137 return info; 2138 } 2139 } 2140 2141 /** 2142 * Helper method for creating the .content folder of a sub-sitemap.<p> 2143 * 2144 * @param cms the current CMS context 2145 * @param subSitemapFolder the sub-sitemap folder in which the .content folder should be created 2146 * 2147 * @throws CmsException if something goes wrong 2148 */ 2149 @SuppressWarnings("deprecation") 2150 private void createSitemapContentFolder(CmsObject cms, CmsResource subSitemapFolder) throws CmsException { 2151 2152 String sitePath = cms.getSitePath(subSitemapFolder); 2153 String folderName = CmsStringUtil.joinPaths(sitePath, CmsADEManager.CONTENT_FOLDER_NAME + "/"); 2154 String sitemapConfigName = CmsStringUtil.joinPaths(folderName, CmsADEManager.CONFIG_FILE_NAME); 2155 if (!cms.existsResource(folderName)) { 2156 cms.createResource( 2157 folderName, 2158 OpenCms.getResourceManager().getResourceType(CmsADEManager.CONFIG_FOLDER_TYPE)); 2159 } 2160 I_CmsResourceType configType = OpenCms.getResourceManager().getResourceType(CmsADEManager.CONFIG_TYPE); 2161 if (cms.existsResource(sitemapConfigName)) { 2162 CmsResource configFile = cms.readResource(sitemapConfigName); 2163 if (configFile.getTypeId() != configType.getTypeId()) { 2164 throw new CmsException( 2165 Messages.get().container( 2166 Messages.ERR_CREATING_SUB_SITEMAP_WRONG_CONFIG_FILE_TYPE_2, 2167 sitemapConfigName, 2168 CmsADEManager.CONFIG_TYPE)); 2169 } 2170 } else { 2171 cms.createResource( 2172 sitemapConfigName, 2173 OpenCms.getResourceManager().getResourceType(CmsADEManager.CONFIG_TYPE)); 2174 } 2175 2176 } 2177 2178 /** 2179 * Deletes a resource according to the change data.<p> 2180 * 2181 * @param change the change data 2182 * 2183 * @return CmsClientSitemapEntry always null 2184 * 2185 * 2186 * @throws CmsException if something goes wrong 2187 */ 2188 private CmsClientSitemapEntry delete(CmsSitemapChange change) throws CmsException { 2189 2190 CmsObject cms = getCmsObject(); 2191 CmsResource resource = cms.readResource(change.getEntryId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2192 ensureLock(resource); 2193 cms.deleteResource(cms.getSitePath(resource), CmsResource.DELETE_PRESERVE_SIBLINGS); 2194 tryUnlock(resource); 2195 return null; 2196 } 2197 2198 /** 2199 * Generates a client side lock info object representing the current lock state of the given resource.<p> 2200 * 2201 * @param resource the resource 2202 * 2203 * @return the client lock 2204 * 2205 * @throws CmsException if something goes wrong 2206 */ 2207 private CmsClientLock generateClientLock(CmsResource resource) throws CmsException { 2208 2209 CmsObject cms = getCmsObject(); 2210 CmsLock lock = cms.getLock(resource); 2211 CmsClientLock clientLock = new CmsClientLock(); 2212 clientLock.setLockType(CmsClientLock.LockType.valueOf(lock.getType().getMode())); 2213 CmsUUID ownerId = lock.getUserId(); 2214 if (!lock.isUnlocked() && (ownerId != null)) { 2215 clientLock.setLockOwner(cms.readUser(ownerId).getDisplayName(cms, cms.getRequestContext().getLocale())); 2216 clientLock.setOwnedByUser(cms.getRequestContext().getCurrentUser().getId().equals(ownerId)); 2217 } 2218 return clientLock; 2219 } 2220 2221 /** 2222 * Generates a list of property object to save to the sitemap entry folder to apply the given change.<p> 2223 * 2224 * @param change the change 2225 * @param entryFolder the entry folder 2226 * 2227 * @return the property objects 2228 */ 2229 private List<CmsProperty> generateInheritProperties(CmsSitemapChange change, CmsResource entryFolder) { 2230 2231 List<CmsProperty> result = new ArrayList<CmsProperty>(); 2232 Map<String, CmsClientProperty> clientProps = change.getOwnInternalProperties(); 2233 boolean hasTitle = false; 2234 if (clientProps != null) { 2235 for (CmsClientProperty clientProp : clientProps.values()) { 2236 if (CmsPropertyDefinition.PROPERTY_TITLE.equals(clientProp.getName())) { 2237 hasTitle = true; 2238 } 2239 CmsProperty prop = new CmsProperty( 2240 clientProp.getName(), 2241 clientProp.getStructureValue(), 2242 clientProp.getResourceValue()); 2243 result.add(prop); 2244 } 2245 } 2246 if (!hasTitle) { 2247 result.add(new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, change.getName(), null)); 2248 } 2249 return result; 2250 } 2251 2252 /** 2253 * Generates a list of property object to save to the sitemap entry resource to apply the given change.<p> 2254 * 2255 * @param change the change 2256 * 2257 * @return the property objects 2258 */ 2259 private List<CmsProperty> generateOwnProperties(CmsSitemapChange change) { 2260 2261 List<CmsProperty> result = new ArrayList<CmsProperty>(); 2262 2263 Map<String, CmsClientProperty> clientProps = change.getDefaultFileProperties(); 2264 boolean hasTitle = false; 2265 if (clientProps != null) { 2266 for (CmsClientProperty clientProp : clientProps.values()) { 2267 if (CmsPropertyDefinition.PROPERTY_TITLE.equals(clientProp.getName())) { 2268 hasTitle = true; 2269 } 2270 CmsProperty prop = new CmsProperty( 2271 clientProp.getName(), 2272 clientProp.getStructureValue(), 2273 clientProp.getResourceValue()); 2274 result.add(prop); 2275 } 2276 } 2277 if (!hasTitle) { 2278 result.add(new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, change.getName(), null)); 2279 } 2280 return result; 2281 } 2282 2283 /** 2284 * Generates a list of property values inherited to the site-map root entry.<p> 2285 * 2286 * @param rootPath the root entry name 2287 * 2288 * @return the list of property values inherited to the site-map root entry 2289 * 2290 * @throws CmsException if something goes wrong reading the properties 2291 */ 2292 private Map<String, CmsClientProperty> generateParentProperties(String rootPath) throws CmsException { 2293 2294 CmsObject cms = getCmsObject(); 2295 if (rootPath == null) { 2296 rootPath = cms.getRequestContext().addSiteRoot("/"); 2297 } 2298 CmsObject rootCms = OpenCms.initCmsObject(cms); 2299 rootCms.getRequestContext().setSiteRoot(""); 2300 String parentRootPath = CmsResource.getParentFolder(rootPath); 2301 2302 Map<String, CmsClientProperty> result = new HashMap<String, CmsClientProperty>(); 2303 if (parentRootPath != null) { 2304 List<CmsProperty> props = rootCms.readPropertyObjects(parentRootPath, true); 2305 for (CmsProperty prop : props) { 2306 CmsClientProperty clientProp = createClientProperty(prop, true); 2307 result.put(clientProp.getName(), clientProp); 2308 } 2309 } 2310 return result; 2311 } 2312 2313 /** 2314 * Returns the sitemap children for the given path with all descendants up to the given level or to the given target path, ie. 2315 * <dl><dt>levels=1 <dd>only children<dt>levels=2<dd>children and great children</dl> 2316 * and so on.<p> 2317 * 2318 * @param root the site relative root 2319 * @param levels the levels to recurse 2320 * @param targetPath the target path 2321 * 2322 * @return the sitemap children 2323 */ 2324 private List<CmsClientSitemapEntry> getChildren(String root, int levels, String targetPath) { 2325 2326 List<CmsClientSitemapEntry> children = new ArrayList<CmsClientSitemapEntry>(); 2327 int i = 0; 2328 for (CmsJspNavElement navElement : getNavBuilder().getNavigationForFolder( 2329 root, 2330 Visibility.all, 2331 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 2332 try { 2333 CmsClientSitemapEntry child = toClientEntry(navElement, false); 2334 if (child != null) { 2335 child.setPosition(i); 2336 children.add(child); 2337 int nextLevels = levels; 2338 if ((nextLevels == 2) && (targetPath != null) && targetPath.startsWith(child.getSitePath())) { 2339 nextLevels = 3; 2340 } 2341 if (child.isFolderType() && ((nextLevels > 1) || (nextLevels == -1)) && !isSubSitemap(navElement)) { 2342 2343 child.setSubEntries(getChildren(child.getSitePath(), nextLevels - 1, targetPath), null); 2344 child.setChildrenLoadedInitially(true); 2345 } 2346 i++; 2347 } 2348 } catch (CmsException e) { 2349 LOG.error("Could not read sitemap entry.", e); 2350 } 2351 } 2352 return children; 2353 } 2354 2355 /** 2356 * Returns the clipboard data from the current user.<p> 2357 * 2358 * @return the clipboard data 2359 */ 2360 private CmsSitemapClipboardData getClipboardData() { 2361 2362 CmsSitemapClipboardData result = new CmsSitemapClipboardData(); 2363 result.setModifications(getModifiedList()); 2364 result.setDeletions(getDeletedList()); 2365 return result; 2366 } 2367 2368 /** 2369 * Returns the deleted list from the current user.<p> 2370 * 2371 * @return the deleted list 2372 */ 2373 private LinkedHashMap<CmsUUID, CmsClientSitemapEntry> getDeletedList() { 2374 2375 CmsObject cms = getCmsObject(); 2376 CmsUser user = cms.getRequestContext().getCurrentUser(); 2377 Object obj = user.getAdditionalInfo(ADDINFO_ADE_DELETED_LIST); 2378 LinkedHashMap<CmsUUID, CmsClientSitemapEntry> result = new LinkedHashMap<CmsUUID, CmsClientSitemapEntry>(); 2379 if (obj instanceof String) { 2380 try { 2381 JSONArray array = new JSONArray((String)obj); 2382 for (int i = 0; i < array.length(); i++) { 2383 try { 2384 CmsUUID delId = new CmsUUID(array.getString(i)); 2385 CmsResource res = cms.readResource(delId, CmsResourceFilter.ALL); 2386 if (res.getState().isDeleted()) { 2387 // make sure resource is still deleted 2388 CmsClientSitemapEntry delEntry = new CmsClientSitemapEntry(); 2389 delEntry.setSitePath(cms.getSitePath(res)); 2390 delEntry.setOwnProperties(getClientProperties(cms, res, false)); 2391 delEntry.setName(res.getName()); 2392 delEntry.setVfsPath(cms.getSitePath(res)); 2393 delEntry.setResourceTypeName( 2394 OpenCms.getResourceManager().getResourceType(res).getTypeName()); 2395 delEntry.setEntryType( 2396 res.isFolder() 2397 ? EntryType.folder 2398 : isRedirectType(res.getTypeId()) ? EntryType.redirect : EntryType.leaf); 2399 delEntry.setNavModeIcon( 2400 CmsIconUtil.getIconClasses( 2401 delEntry.getResourceTypeName(), 2402 delEntry.getVfsPath(), 2403 false)); 2404 delEntry.setId(delId); 2405 result.put(delId, delEntry); 2406 } 2407 } catch (Throwable e) { 2408 // should never happen, catches wrong or no longer existing values 2409 LOG.warn(e.getLocalizedMessage()); 2410 } 2411 } 2412 } catch (Throwable e) { 2413 // should never happen, catches json parsing 2414 LOG.warn(e.getLocalizedMessage()); 2415 } 2416 } 2417 return result; 2418 } 2419 2420 /** 2421 * Gets the container name for function detail elements depending on the parent folder.<p> 2422 * 2423 * @param parent the parent folder 2424 * @return the name of the function detail container 2425 */ 2426 private String getFunctionDetailContainerName(CmsResource parent) { 2427 2428 CmsObject cms = getCmsObject(); 2429 String notFound = null; 2430 String containerInfo = OpenCms.getTemplateContextManager().readPropertyFromTemplate( 2431 cms, 2432 parent, 2433 CmsPropertyDefinition.PROPERTY_CONTAINER_INFO, 2434 notFound); 2435 if (containerInfo == notFound) { 2436 return null; 2437 } 2438 Map<String, String> attrs = CmsStringUtil.splitAsMap(containerInfo, "|", "="); //$NON-NLS-2$ 2439 String functionDetailContainerName = attrs.get(KEY_FUNCTION_DETAIL); 2440 return functionDetailContainerName; 2441 } 2442 2443 /** 2444 * Returns the galleries of the given sub site for the requested gallery type.<p> 2445 * 2446 * @param entryPointUri the sub site entry point 2447 * @param galleryType the gallery type 2448 * @param subSitePaths the sub site paths 2449 * 2450 * @return the gallery folder entries 2451 * 2452 * @throws CmsException if reading the resources fails 2453 */ 2454 private List<CmsGalleryFolderEntry> getGalleriesForType( 2455 String entryPointUri, 2456 CmsGalleryType galleryType, 2457 List<String> subSitePaths) 2458 throws CmsException { 2459 2460 List<CmsGalleryFolderEntry> galleries = new ArrayList<CmsGalleryFolderEntry>(); 2461 @SuppressWarnings("deprecation") 2462 List<CmsResource> galleryFolders = getCmsObject().readResources( 2463 entryPointUri, 2464 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryType.getTypeId())); 2465 for (CmsResource folder : galleryFolders) { 2466 try { 2467 if (!isInSubsite(subSitePaths, folder.getRootPath())) { 2468 galleries.add(readGalleryFolderEntry(folder, galleryType.getResourceType())); 2469 } 2470 } catch (CmsException ex) { 2471 log(ex.getLocalizedMessage(), ex); 2472 } 2473 } 2474 // create a tree structure 2475 Collections.sort(galleries, new Comparator<CmsGalleryFolderEntry>() { 2476 2477 public int compare(CmsGalleryFolderEntry o1, CmsGalleryFolderEntry o2) { 2478 2479 return o1.getSitePath().compareTo(o2.getSitePath()); 2480 } 2481 }); 2482 List<CmsGalleryFolderEntry> galleryTree = new ArrayList<CmsGalleryFolderEntry>(); 2483 for (int i = 0; i < galleries.size(); i++) { 2484 boolean isSubGallery = false; 2485 if (i > 0) { 2486 for (int j = i - 1; j >= 0; j--) { 2487 if (galleries.get(i).getSitePath().startsWith(galleries.get(j).getSitePath())) { 2488 galleries.get(j).addSubGallery(galleries.get(i)); 2489 isSubGallery = true; 2490 break; 2491 } 2492 } 2493 } 2494 if (!isSubGallery) { 2495 galleryTree.add(galleries.get(i)); 2496 } 2497 } 2498 return galleryTree; 2499 } 2500 2501 /** 2502 * Returns the modified list from the current user.<p> 2503 * 2504 * @return the modified list 2505 */ 2506 private LinkedHashMap<CmsUUID, CmsClientSitemapEntry> getModifiedList() { 2507 2508 CmsObject cms = getCmsObject(); 2509 CmsUser user = cms.getRequestContext().getCurrentUser(); 2510 Object obj = user.getAdditionalInfo(ADDINFO_ADE_MODIFIED_LIST); 2511 LinkedHashMap<CmsUUID, CmsClientSitemapEntry> result = new LinkedHashMap<CmsUUID, CmsClientSitemapEntry>(); 2512 if (obj instanceof String) { 2513 try { 2514 JSONArray array = new JSONArray((String)obj); 2515 for (int i = 0; i < array.length(); i++) { 2516 try { 2517 CmsUUID modId = new CmsUUID(array.getString(i)); 2518 CmsResource res = cms.readResource(modId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2519 String sitePath = cms.getSitePath(res); 2520 CmsJspNavElement navEntry = getNavBuilder().getNavigationForResource( 2521 sitePath, 2522 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2523 if (navEntry.isInNavigation()) { 2524 CmsClientSitemapEntry modEntry = toClientEntry(navEntry, false); 2525 result.put(modId, modEntry); 2526 } 2527 } catch (Throwable e) { 2528 // should never happen, catches wrong or no longer existing values 2529 LOG.warn(e.getLocalizedMessage()); 2530 } 2531 } 2532 } catch (Throwable e) { 2533 // should never happen, catches json parsing 2534 LOG.warn(e.getLocalizedMessage()); 2535 } 2536 } 2537 return result; 2538 } 2539 2540 /** 2541 * Returns a navigation builder reference.<p> 2542 * 2543 * @return the navigation builder 2544 */ 2545 private CmsJspNavBuilder getNavBuilder() { 2546 2547 if (m_navBuilder == null) { 2548 m_navBuilder = new CmsJspNavBuilder(getCmsObject()); 2549 } 2550 return m_navBuilder; 2551 } 2552 2553 /** 2554 * Returns the new resource infos.<p> 2555 * 2556 * @param cms the current CMS context 2557 * @param configData the configuration data from which the new resource infos should be read 2558 * @param locale locale used for retrieving descriptions/titles 2559 * 2560 * @return the new resource infos 2561 */ 2562 private List<CmsNewResourceInfo> getNewResourceInfos(CmsObject cms, CmsADEConfigData configData, Locale locale) { 2563 2564 List<CmsNewResourceInfo> result = new ArrayList<CmsNewResourceInfo>(); 2565 for (CmsModelPageConfig modelConfig : configData.getModelPages()) { 2566 try { 2567 CmsNewResourceInfo info = createNewResourceInfo(cms, modelConfig.getResource(), locale); 2568 info.setDefault(modelConfig.isDefault()); 2569 result.add(info); 2570 } catch (CmsException e) { 2571 LOG.debug(e.getLocalizedMessage(), e); 2572 } 2573 } 2574 Collections.sort(result, new Comparator<CmsNewResourceInfo>() { 2575 2576 public int compare(CmsNewResourceInfo a, CmsNewResourceInfo b) { 2577 2578 return ComparisonChain.start().compareTrueFirst(a.isDefault(), b.isDefault()).compare( 2579 a.getNavPos(), 2580 b.getNavPos(), 2581 Ordering.natural().nullsLast()).result(); 2582 } 2583 }); 2584 return result; 2585 } 2586 2587 /** 2588 * Gets the names of all available properties.<p> 2589 * 2590 * @param cms the CMS context 2591 * 2592 * @return the list of all property names 2593 * 2594 * @throws CmsException if something goes wrong 2595 */ 2596 private List<String> getPropertyNames(CmsObject cms) throws CmsException { 2597 2598 List<CmsPropertyDefinition> propDefs = cms.readAllPropertyDefinitions(); 2599 List<String> result = new ArrayList<String>(); 2600 for (CmsPropertyDefinition propDef : propDefs) { 2601 result.add(propDef.getName()); 2602 } 2603 return result; 2604 } 2605 2606 /** 2607 * Gets the resource type info beans for types for which new detail pages can be created.<p> 2608 * 2609 * @param cms the current CMS context 2610 * @param resourceTypeConfigs the resource type configurations 2611 * @param functionReferences the function references 2612 * @param dynamicFunctionRestriction 2613 * @param modelResource the model resource 2614 * @param locale the locale used for retrieving descriptions/titles 2615 * 2616 * @return the resource type info beans for types for which new detail pages can be created 2617 */ 2618 private List<CmsNewResourceInfo> getResourceTypeInfos( 2619 CmsObject cms, 2620 List<CmsResourceTypeConfig> resourceTypeConfigs, 2621 List<CmsFunctionReference> functionReferences, 2622 CmsFunctionAvailability dynamicFunctionAvailability, 2623 CmsResource modelResource, 2624 Locale locale) { 2625 2626 List<CmsNewResourceInfo> result = new ArrayList<CmsNewResourceInfo>(); 2627 CmsNewResourceInfo defaultPageInfo; 2628 if (modelResource != null) { 2629 defaultPageInfo = new CmsNewResourceInfo( 2630 modelResource.getTypeId(), 2631 CmsADEManager.DEFAULT_DETAILPAGE_TYPE, 2632 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_TITLE_0), 2633 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_DESCRIPTION_0), 2634 modelResource.getStructureId(), 2635 false, 2636 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_DESCRIPTION_0)); 2637 2638 } else { 2639 defaultPageInfo = new CmsNewResourceInfo( 2640 CmsResourceTypeXmlContainerPage.getContainerPageTypeIdSafely(), 2641 CmsADEManager.DEFAULT_DETAILPAGE_TYPE, 2642 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_TITLE_0), 2643 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_DESCRIPTION_0), 2644 null, 2645 false, 2646 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_DESCRIPTION_0)); 2647 } 2648 2649 defaultPageInfo.setBigIconClasses( 2650 CmsIconUtil.getIconClasses(CmsResourceTypeXmlContainerPage.getStaticTypeName(), null, false)); 2651 result.add(defaultPageInfo); 2652 for (CmsResourceTypeConfig typeConfig : resourceTypeConfigs) { 2653 if (typeConfig.isDetailPagesDisabled()) { 2654 continue; 2655 } 2656 String typeName = typeConfig.getTypeName(); 2657 try { 2658 I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(typeName); 2659 result.add(createResourceTypeInfo(resourceType, modelResource)); 2660 } catch (CmsLoaderException e) { 2661 LOG.error(e.getLocalizedMessage(), e); 2662 } 2663 } 2664 for (CmsFunctionReference functionRef : functionReferences) { 2665 if (dynamicFunctionAvailability.isDefined()) { 2666 if (!dynamicFunctionAvailability.checkAvailable(functionRef.getStructureId())) { 2667 continue; 2668 } 2669 } 2670 try { 2671 CmsResource functionRes = cms.readResource(functionRef.getStructureId()); 2672 String description = cms.readPropertyObject( 2673 functionRes, 2674 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 2675 false).getValue(); 2676 String subtitle = description; 2677 try { 2678 CmsGallerySearchResult searchResult = CmsGallerySearch.searchById( 2679 cms, 2680 functionRef.getStructureId(), 2681 getWorkplaceLocale()); 2682 subtitle = searchResult.getDescription(); 2683 } catch (CmsException e) { 2684 LOG.warn(e.getLocalizedMessage(), e); 2685 } 2686 2687 CmsNewResourceInfo info = new CmsNewResourceInfo( 2688 modelResource.getTypeId(), 2689 CmsDetailPageInfo.FUNCTION_PREFIX + functionRef.getName(), 2690 functionRef.getName(), 2691 description, 2692 modelResource.getStructureId(), 2693 false, 2694 subtitle); 2695 info.setCreateParameter(functionRef.getStructureId().toString()); 2696 info.setIsFunction(true); 2697 info.setBigIconClasses( 2698 CmsIconUtil.getIconClasses(CmsXmlDynamicFunctionHandler.TYPE_FUNCTION, null, false)); 2699 result.add(info); 2700 } catch (CmsVfsResourceNotFoundException e) { 2701 LOG.warn(e.getLocalizedMessage(), e); 2702 } catch (CmsException e) { 2703 LOG.error(e.getLocalizedMessage(), e); 2704 } 2705 } 2706 return result; 2707 } 2708 2709 /** 2710 * Reeds the site root entry.<p> 2711 * 2712 * @param rootPath the root path of the sitemap root 2713 * @param targetPath the target path to open 2714 * 2715 * @return the site root entry 2716 * 2717 * @throws CmsSecurityException in case of insufficient permissions 2718 * @throws CmsException if something goes wrong 2719 */ 2720 private CmsClientSitemapEntry getRootEntry(String rootPath, String targetPath) 2721 throws CmsSecurityException, CmsException { 2722 2723 String sitePath = "/"; 2724 if ((rootPath != null)) { 2725 sitePath = getCmsObject().getRequestContext().removeSiteRoot(rootPath); 2726 } 2727 CmsJspNavElement navElement = getNavBuilder().getNavigationForResource( 2728 sitePath, 2729 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2730 CmsClientSitemapEntry result = toClientEntry(navElement, true); 2731 if (result != null) { 2732 result.setPosition(0); 2733 result.setChildrenLoadedInitially(true); 2734 result.setSubEntries(getChildren(sitePath, 2, targetPath), null); 2735 } 2736 return result; 2737 } 2738 2739 /** 2740 * Returns the sitemap info for the given base path.<p> 2741 * 2742 * @param basePath the base path 2743 * 2744 * @return the sitemap info 2745 * 2746 * @throws CmsException if something goes wrong reading the resources 2747 */ 2748 private CmsSitemapInfo getSitemapInfo(String basePath) throws CmsException { 2749 2750 CmsObject cms = getCmsObject(); 2751 CmsResource baseFolder = null; 2752 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(basePath)) { 2753 baseFolder = cms.readResource( 2754 cms.getRequestContext().removeSiteRoot(basePath), 2755 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2756 } else { 2757 // in case of an empty base path, use base folder of the current site 2758 basePath = "/"; 2759 baseFolder = cms.readResource("/"); 2760 } 2761 CmsResource defaultFile = cms.readDefaultFile(baseFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2762 String title = cms.readPropertyObject(baseFolder, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(); 2763 if (CmsStringUtil.isEmptyOrWhitespaceOnly(title) && (defaultFile != null)) { 2764 title = cms.readPropertyObject(defaultFile, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(); 2765 } 2766 String description = cms.readPropertyObject( 2767 baseFolder, 2768 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 2769 false).getValue(); 2770 if (CmsStringUtil.isEmptyOrWhitespaceOnly(description) && (defaultFile != null)) { 2771 description = cms.readPropertyObject( 2772 defaultFile, 2773 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 2774 false).getValue(); 2775 } 2776 return new CmsSitemapInfo( 2777 cms.getRequestContext().getCurrentProject().getName(), 2778 description, 2779 OpenCms.getLocaleManager().getDefaultLocale(cms, baseFolder).toString(), 2780 OpenCms.getSiteManager().getCurrentSite(cms).getUrl() 2781 + OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, basePath), 2782 title); 2783 } 2784 2785 /** 2786 * Gets the default type id for subsitemap folders.<p> 2787 * 2788 * @return the default type id for subsitemap folders 2789 * 2790 * @throws CmsRpcException in case of an error 2791 */ 2792 @SuppressWarnings("deprecation") 2793 private int getSubsitemapType() throws CmsRpcException { 2794 2795 try { 2796 return OpenCms.getResourceManager().getResourceType( 2797 CmsResourceTypeFolderSubSitemap.TYPE_SUBSITEMAP).getTypeId(); 2798 } catch (CmsLoaderException e) { 2799 error(e); 2800 } 2801 return CmsResourceTypeUnknownFolder.getStaticTypeId(); 2802 } 2803 2804 /** 2805 * Returns the workplace locale for the current user.<p> 2806 * 2807 * @return the workplace locale 2808 */ 2809 private Locale getWorkplaceLocale() { 2810 2811 Locale result = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject()); 2812 if (result == null) { 2813 result = CmsLocaleManager.getDefaultLocale(); 2814 } 2815 if (result == null) { 2816 result = Locale.getDefault(); 2817 } 2818 return result; 2819 } 2820 2821 /** 2822 * Checks whether the sitemap change has default file changes.<p> 2823 * 2824 * @param change a sitemap change 2825 * @return true if the change would change the default file 2826 */ 2827 private boolean hasDefaultFileChanges(CmsSitemapChange change) { 2828 2829 return (change.getDefaultFileId() != null) && !change.isNew(); 2830 } 2831 2832 /** 2833 * Checks whether the sitemap change has changes for the sitemap entry resource.<p> 2834 * 2835 * @param change the sitemap change 2836 * @return true if the change would change the original sitemap entry resource 2837 */ 2838 private boolean hasOwnChanges(CmsSitemapChange change) { 2839 2840 return !change.isNew(); 2841 } 2842 2843 /** 2844 * Checks whether a resource is a default file of a folder.<p> 2845 * 2846 * @param resource the resource to check 2847 * 2848 * @return true if the resource is the default file of a folder 2849 * 2850 * @throws CmsException if something goes wrong 2851 */ 2852 private boolean isDefaultFile(CmsResource resource) throws CmsException { 2853 2854 CmsObject cms = getCmsObject(); 2855 if (resource.isFolder()) { 2856 return false; 2857 } 2858 2859 CmsResource parent = cms.readResource( 2860 CmsResource.getParentFolder(cms.getSitePath(resource)), 2861 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2862 CmsResource defaultFile = cms.readDefaultFile(parent, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2863 return resource.equals(defaultFile); 2864 } 2865 2866 /** 2867 * Checks if the toolbar should be displayed.<p> 2868 * 2869 * @param request the current request to get the default locale from 2870 * 2871 * @return <code>true</code> if the toolbar should be displayed 2872 */ 2873 private boolean isDisplayToolbar(HttpServletRequest request) { 2874 2875 // display the toolbar by default 2876 boolean displayToolbar = true; 2877 if (CmsHistoryResourceHandler.isHistoryRequest(request)) { 2878 // we do not want to display the toolbar in case of an historical request 2879 displayToolbar = false; 2880 } 2881 return displayToolbar; 2882 } 2883 2884 /** 2885 * Returns if the given path is located below one of the given sub site paths.<p> 2886 * 2887 * @param subSitePaths the sub site root paths 2888 * @param path the root path to check 2889 * 2890 * @return <code>true</code> if the given path is located below one of the given sub site paths 2891 */ 2892 private boolean isInSubsite(List<String> subSitePaths, String path) { 2893 2894 boolean result = false; 2895 for (String subSite : subSitePaths) { 2896 if (path.startsWith(subSite)) { 2897 result = true; 2898 break; 2899 } 2900 } 2901 return result; 2902 } 2903 2904 /** 2905 * Returns if the given type id matches the xml-redirect resource type.<p> 2906 * 2907 * @param typeId the resource type id 2908 * 2909 * @return <code>true</code> if the given type id matches the xml-redirect resource type 2910 */ 2911 @SuppressWarnings("deprecation") 2912 private boolean isRedirectType(int typeId) { 2913 2914 try { 2915 return typeId == OpenCms.getResourceManager().getResourceType(RECOURCE_TYPE_NAME_REDIRECT).getTypeId(); 2916 } catch (Exception e) { 2917 return false; 2918 } 2919 } 2920 2921 /** 2922 * Returns if the given nav-element resembles a sub-sitemap entry-point.<p> 2923 * 2924 * @param navElement the nav-element 2925 * 2926 * @return <code>true</code> if the given nav-element resembles a sub-sitemap entry-point.<p> 2927 */ 2928 private boolean isSubSitemap(CmsJspNavElement navElement) { 2929 2930 return CmsResourceTypeFolderSubSitemap.isSubSitemap(navElement.getResource()); 2931 } 2932 2933 /** 2934 * Checks if the given open path is valid.<p> 2935 * 2936 * @param cms the cms context 2937 * @param openPath the open path 2938 * 2939 * @return <code>true</code> if the given open path is valid 2940 */ 2941 private boolean isValidOpenPath(CmsObject cms, String openPath) { 2942 2943 if (CmsStringUtil.isEmptyOrWhitespaceOnly(openPath)) { 2944 return false; 2945 } 2946 if (!cms.existsResource(openPath)) { 2947 // in case of a detail-page check the parent folder 2948 String parent = CmsResource.getParentFolder(openPath); 2949 if (CmsStringUtil.isEmptyOrWhitespaceOnly(parent) || !cms.existsResource(parent)) { 2950 return false; 2951 } 2952 } 2953 return true; 2954 } 2955 2956 /** 2957 * Returns if the given return code is valid.<p> 2958 * 2959 * @param returnCode the return code to check 2960 * 2961 * @return <code>true</code> if the return code is valid 2962 */ 2963 private boolean isValidReturnCode(String returnCode) { 2964 2965 if (CmsStringUtil.isEmptyOrWhitespaceOnly(returnCode)) { 2966 return false; 2967 } 2968 int pos = returnCode.indexOf(":"); 2969 if (pos > 0) { 2970 return CmsUUID.isValidUUID(returnCode.substring(0, pos)) 2971 && CmsUUID.isValidUUID(returnCode.substring(pos + 1)); 2972 } else { 2973 return CmsUUID.isValidUUID(returnCode); 2974 } 2975 } 2976 2977 /** 2978 * Applys the given changes to the entry.<p> 2979 * 2980 * @param change the change to apply 2981 * 2982 * @throws CmsException if something goes wrong 2983 */ 2984 private void modifyEntry(CmsSitemapChange change) throws CmsException { 2985 2986 CmsObject cms = getCmsObject(); 2987 CmsResource entryPage = null; 2988 CmsResource entryFolder = null; 2989 2990 CmsResource ownRes = null; 2991 CmsResource defaultFileRes = null; 2992 try { 2993 // lock all resources necessary first to avoid doing changes only half way through 2994 2995 if (hasOwnChanges(change)) { 2996 ownRes = cms.readResource(change.getEntryId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2997 boolean shallow = !change.hasChangedName() && !change.hasChangedPosition() && !change.hasNewParent(); 2998 2999 ensureLock(ownRes, shallow); 3000 } 3001 3002 if (hasDefaultFileChanges(change)) { 3003 defaultFileRes = cms.readResource(change.getDefaultFileId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3004 ensureLock(defaultFileRes, false); 3005 } 3006 3007 if ((ownRes != null) && ownRes.isFolder()) { 3008 entryFolder = ownRes; 3009 } 3010 3011 if ((ownRes != null) && ownRes.isFile()) { 3012 entryPage = ownRes; 3013 } 3014 3015 if (defaultFileRes != null) { 3016 entryPage = defaultFileRes; 3017 } 3018 3019 if (change.isLeafType()) { 3020 entryFolder = entryPage; 3021 } 3022 3023 String moveSrc = null; 3024 String moveDest = null; 3025 3026 if (entryFolder != null) { 3027 if (change.hasNewParent() || change.hasChangedName()) { 3028 String destinationPath; 3029 if (change.hasNewParent()) { 3030 CmsResource futureParent = cms.readResource( 3031 change.getParentId(), 3032 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3033 destinationPath = CmsStringUtil.joinPaths(cms.getSitePath(futureParent), change.getName()); 3034 } else { 3035 destinationPath = CmsStringUtil.joinPaths( 3036 CmsResource.getParentFolder(cms.getSitePath(entryFolder)), 3037 change.getName()); 3038 } 3039 if (change.isLeafType() && destinationPath.endsWith("/")) { 3040 destinationPath = destinationPath.substring(0, destinationPath.length() - 1); 3041 } 3042 // only if the site-path has really changed 3043 if (!CmsFileUtil.removeTrailingSeparator(cms.getSitePath(entryFolder)).equals( 3044 CmsFileUtil.removeTrailingSeparator(destinationPath))) { 3045 moveSrc = cms.getSitePath(entryFolder); 3046 moveDest = CmsFileUtil.removeTrailingSeparator(destinationPath); 3047 } 3048 } 3049 } 3050 if ((moveDest != null) && cms.existsResource(moveDest, CmsResourceFilter.IGNORE_EXPIRATION)) { 3051 throw new CmsVfsResourceAlreadyExistsException( 3052 org.opencms.db.generic.Messages.get().container( 3053 org.opencms.db.generic.Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1, 3054 moveDest)); 3055 } 3056 3057 updateProperties(cms, ownRes, defaultFileRes, change.getPropertyChanges()); 3058 if (change.hasChangedPosition()) { 3059 updateNavPos(ownRes, change); 3060 } 3061 3062 if (moveDest != null) { 3063 cms.moveResource(moveSrc, moveDest); 3064 } 3065 entryFolder = cms.readResource(entryFolder.getStructureId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3066 3067 } finally { 3068 if (entryPage != null) { 3069 tryUnlock(entryPage); 3070 } 3071 if (entryFolder != null) { 3072 tryUnlock(entryFolder); 3073 } 3074 } 3075 } 3076 3077 /** 3078 * Reads the gallery folder properties.<p> 3079 * 3080 * @param folder the folder resource 3081 * @param typeName the resource type name 3082 * 3083 * @return the folder entry data 3084 * 3085 * @throws CmsException if the folder properties can not be read 3086 */ 3087 private CmsGalleryFolderEntry readGalleryFolderEntry(CmsResource folder, String typeName) throws CmsException { 3088 3089 CmsObject cms = getCmsObject(); 3090 CmsGalleryFolderEntry folderEntry = new CmsGalleryFolderEntry(); 3091 folderEntry.setResourceType(typeName); 3092 folderEntry.setSitePath(cms.getSitePath(folder)); 3093 folderEntry.setStructureId(folder.getStructureId()); 3094 folderEntry.setOwnProperties(getClientProperties(cms, folder, false)); 3095 folderEntry.setIconClasses(CmsIconUtil.getIconClasses(typeName, null, false)); 3096 return folderEntry; 3097 } 3098 3099 /** 3100 * Helper method for removing all locales except one from a container page.<p> 3101 * 3102 * @param page the container page to proces 3103 * @param localeToKeep the locale which should be kept 3104 * 3105 * @throws CmsXmlException if something goes wrong 3106 */ 3107 private void removeAllLocalesExcept(CmsXmlContainerPage page, Locale localeToKeep) throws CmsXmlException { 3108 3109 List<Locale> locales = page.getLocales(); 3110 for (Locale locale : locales) { 3111 if (!locale.equals(localeToKeep)) { 3112 page.removeLocale(locale); 3113 } 3114 } 3115 } 3116 3117 /** 3118 * Applys the given remove change.<p> 3119 * 3120 * @param change the change to apply 3121 * 3122 * @return the changed client sitemap entry or <code>null</code> 3123 * 3124 * @throws CmsException if something goes wrong 3125 */ 3126 private CmsSitemapChange removeEntryFromNavigation(CmsSitemapChange change) throws CmsException { 3127 3128 CmsObject cms = getCmsObject(); 3129 CmsResource entryFolder = cms.readResource(change.getEntryId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3130 ensureLock(entryFolder); 3131 List<CmsProperty> properties = new ArrayList<CmsProperty>(); 3132 properties.add( 3133 new CmsProperty( 3134 CmsPropertyDefinition.PROPERTY_NAVTEXT, 3135 CmsProperty.DELETE_VALUE, 3136 CmsProperty.DELETE_VALUE)); 3137 properties.add( 3138 new CmsProperty(CmsPropertyDefinition.PROPERTY_NAVPOS, CmsProperty.DELETE_VALUE, CmsProperty.DELETE_VALUE)); 3139 cms.writePropertyObjects(cms.getSitePath(entryFolder), properties); 3140 tryUnlock(entryFolder); 3141 return change; 3142 } 3143 3144 /** 3145 * Saves the detail page information of a sitemap to the sitemap's configuration file.<p> 3146 * 3147 * @param detailPages saves the detailpage configuration 3148 * @param resource the configuration file resource 3149 * @param newId the structure id to use for new detail page entries 3150 * @param updateEntry the new detail page entry 3151 * 3152 * @throws CmsException if something goes wrong 3153 */ 3154 private void saveDetailPages( 3155 List<CmsDetailPageInfo> detailPages, 3156 CmsResource resource, 3157 CmsUUID newId, 3158 CmsClientSitemapEntry updateEntry) 3159 throws CmsException { 3160 3161 CmsObject cms = getCmsObject(); 3162 if (updateEntry != null) { 3163 for (CmsDetailPageInfo info : detailPages) { 3164 if (info.getId() == null) { 3165 updateEntry.setDetailpageTypeName(info.getType()); 3166 break; 3167 } 3168 } 3169 } 3170 CmsDetailPageConfigurationWriter writer = new CmsDetailPageConfigurationWriter(cms, resource); 3171 writer.updateAndSave(detailPages, newId); 3172 } 3173 3174 /** 3175 * Saves the given clipboard data to the session.<p> 3176 * 3177 * @param clipboardData the clipboard data to save 3178 * 3179 * @throws CmsException if something goes wrong writing the user 3180 */ 3181 private void setClipboardData(CmsSitemapClipboardData clipboardData) throws CmsException { 3182 3183 CmsObject cms = getCmsObject(); 3184 CmsUser user = cms.getRequestContext().getCurrentUser(); 3185 if (clipboardData != null) { 3186 JSONArray modified = new JSONArray(); 3187 if (clipboardData.getModifications() != null) { 3188 for (CmsUUID id : clipboardData.getModifications().keySet()) { 3189 if (id != null) { 3190 modified.put(id.toString()); 3191 } 3192 } 3193 } 3194 user.setAdditionalInfo(ADDINFO_ADE_MODIFIED_LIST, modified.toString()); 3195 JSONArray deleted = new JSONArray(); 3196 if (clipboardData.getDeletions() != null) { 3197 for (CmsUUID id : clipboardData.getDeletions().keySet()) { 3198 if (id != null) { 3199 deleted.put(id.toString()); 3200 } 3201 } 3202 } 3203 user.setAdditionalInfo(ADDINFO_ADE_DELETED_LIST, deleted.toString()); 3204 cms.writeUser(user); 3205 } 3206 } 3207 3208 /** 3209 * Determines if the title property of the default file should be changed.<p> 3210 * 3211 * @param properties the current default file properties 3212 * @param folderNavtext the 'NavText' property of the folder 3213 * 3214 * @return <code>true</code> if the title property should be changed 3215 */ 3216 private boolean shouldChangeDefaultFileTitle(Map<String, CmsProperty> properties, CmsProperty folderNavtext) { 3217 3218 return (properties == null) 3219 || (properties.get(CmsPropertyDefinition.PROPERTY_TITLE) == null) 3220 || (properties.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue() == null) 3221 || ((folderNavtext != null) 3222 && properties.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue().equals(folderNavtext.getValue())); 3223 } 3224 3225 /** 3226 * Determines if the title property should be changed in case of a 'NavText' change.<p> 3227 * 3228 * @param properties the current resource properties 3229 * 3230 * @return <code>true</code> if the title property should be changed in case of a 'NavText' change 3231 */ 3232 private boolean shouldChangeTitle(Map<String, CmsProperty> properties) { 3233 3234 return (properties == null) 3235 || (properties.get(CmsPropertyDefinition.PROPERTY_TITLE) == null) 3236 || (properties.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue() == null) 3237 || ((properties.get(CmsPropertyDefinition.PROPERTY_NAVTEXT) != null) 3238 && properties.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue().equals( 3239 properties.get(CmsPropertyDefinition.PROPERTY_NAVTEXT).getValue())); 3240 } 3241 3242 /** 3243 * Synchronizes the title from the NavText for a specific resource after properties have been edited, if NavText isn't empty and the title isn't already set to a different non-empty value. 3244 * 3245 * @param resource the resource 3246 * @param oldNavText the NavText before editing the properties 3247 * @param newNavText the NavText after editing the properties (may be the same as oldNavText) 3248 * @throws CmsException if something goes wrong 3249 */ 3250 private void synchTitleFromNavText(CmsResource resource, String oldNavText, String newNavText) throws CmsException { 3251 3252 CmsObject cms = getCmsObject(); 3253 3254 if (CmsStringUtil.isEmpty(newNavText)) { 3255 return; 3256 } 3257 CmsProperty titleProp = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, false); 3258 String title = titleProp.getValue(); 3259 if (title == null) { 3260 title = ""; 3261 } 3262 // We don't check if oldNavText is different from newNavText, because we also want the synchronization to happen 3263 // when we don't actually change the NavText, but e.g. when we change the title to an empty string. 3264 if (CmsStringUtil.isEmpty(title) || title.equals(oldNavText)) { 3265 if (!newNavText.equals(title)) { 3266 cms.writePropertyObjects( 3267 resource, 3268 Arrays.asList(new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, newNavText, null))); 3269 } 3270 } 3271 } 3272 3273 /** 3274 * Converts a jsp navigation element into a client sitemap entry.<p> 3275 * 3276 * @param navElement the jsp navigation element 3277 * @param isRoot true if the entry is a root entry 3278 * 3279 * @return the client sitemap entry 3280 * 3281 * @throws CmsException if something goes wrong 3282 */ 3283 private CmsClientSitemapEntry toClientEntry(CmsJspNavElement navElement, boolean isRoot) throws CmsException { 3284 3285 CmsResource entryPage = null; 3286 CmsObject cms = getCmsObject(); 3287 CmsClientSitemapEntry clientEntry = new CmsClientSitemapEntry(); 3288 CmsResource entryFolder = null; 3289 3290 CmsResource ownResource = navElement.getResource(); 3291 clientEntry.setResourceState(ownResource.getState()); 3292 CmsResource defaultFileResource = null; 3293 if (ownResource.isFolder() && !navElement.isNavigationLevel()) { 3294 defaultFileResource = cms.readDefaultFile(ownResource, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3295 } 3296 3297 Map<String, CmsClientProperty> ownProps = getClientProperties(cms, ownResource, false); 3298 3299 Map<String, CmsClientProperty> defaultFileProps = null; 3300 if (defaultFileResource != null) { 3301 defaultFileProps = getClientProperties(cms, defaultFileResource, false); 3302 clientEntry.setDefaultFileId(defaultFileResource.getStructureId()); 3303 clientEntry.setDefaultFileType( 3304 OpenCms.getResourceManager().getResourceType(defaultFileResource.getTypeId()).getTypeName()); 3305 clientEntry.setDefaultFileReleased(defaultFileResource.isReleasedAndNotExpired(System.currentTimeMillis())); 3306 } else { 3307 defaultFileProps = new HashMap<String, CmsClientProperty>(); 3308 } 3309 boolean isDefault = isDefaultFile(ownResource); 3310 clientEntry.setId(ownResource.getStructureId()); 3311 clientEntry.setResourceTypeId(ownResource.getTypeId()); 3312 clientEntry.setFolderDefaultPage(isDefault); 3313 if (navElement.getResource().isFolder()) { 3314 entryFolder = navElement.getResource(); 3315 entryPage = defaultFileResource; 3316 clientEntry.setName(entryFolder.getName()); 3317 if (entryPage == null) { 3318 entryPage = entryFolder; 3319 } 3320 if (!isRoot && isSubSitemap(navElement)) { 3321 clientEntry.setEntryType(EntryType.subSitemap); 3322 clientEntry.setDefaultFileType(null); 3323 } else if (navElement.isNavigationLevel()) { 3324 clientEntry.setEntryType(EntryType.navigationLevel); 3325 } 3326 CmsLock folderLock = cms.getLock(entryFolder); 3327 clientEntry.setHasForeignFolderLock( 3328 !folderLock.isUnlocked() && !folderLock.isOwnedBy(cms.getRequestContext().getCurrentUser())); 3329 if (!cms.getRequestContext().getCurrentProject().isOnlineProject()) { 3330 List<CmsResource> blockingChildren = cms.getBlockingLockedResources(entryFolder); 3331 clientEntry.setBlockingLockedChildren((blockingChildren != null) && !blockingChildren.isEmpty()); 3332 } 3333 } else { 3334 entryPage = navElement.getResource(); 3335 clientEntry.setName(entryPage.getName()); 3336 if (isRedirectType(entryPage.getTypeId())) { 3337 clientEntry.setEntryType(EntryType.redirect); 3338 CmsFile file = getCmsObject().readFile(entryPage); 3339 I_CmsXmlDocument content = CmsXmlContentFactory.unmarshal(getCmsObject(), file); 3340 I_CmsXmlContentValue linkValue = content.getValue( 3341 REDIRECT_LINK_TARGET_XPATH, 3342 getCmsObject().getRequestContext().getLocale()); 3343 String link = linkValue != null 3344 ? linkValue.getStringValue(getCmsObject()) 3345 : Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_REDIRECT_SUB_LEVEL_0); 3346 clientEntry.setRedirectTarget(link); 3347 } else { 3348 clientEntry.setEntryType(EntryType.leaf); 3349 } 3350 } 3351 if (entryPage.isFile()) { 3352 List<CmsAlias> aliases = OpenCms.getAliasManager().getAliasesForStructureId( 3353 getCmsObject(), 3354 entryPage.getStructureId()); 3355 if (!aliases.isEmpty()) { 3356 List<String> aliasList = new ArrayList<String>(); 3357 for (CmsAlias alias : aliases) { 3358 String aliasPath = alias.getAliasPath(); 3359 aliasList.add(aliasPath); 3360 } 3361 clientEntry.setAliases(aliasList); 3362 } 3363 } 3364 long dateExpired = navElement.getResource().getDateExpired(); 3365 if (dateExpired != CmsResource.DATE_EXPIRED_DEFAULT) { 3366 clientEntry.setDateExpired( 3367 CmsDateUtil.getDate(new Date(dateExpired), DateFormat.SHORT, getWorkplaceLocale())); 3368 } 3369 long dateReleased = navElement.getResource().getDateReleased(); 3370 if (dateReleased != CmsResource.DATE_RELEASED_DEFAULT) { 3371 clientEntry.setDateReleased( 3372 CmsDateUtil.getDate(new Date(dateReleased), DateFormat.SHORT, getWorkplaceLocale())); 3373 } 3374 clientEntry.setResleasedAndNotExpired( 3375 navElement.getResource().isReleasedAndNotExpired(System.currentTimeMillis())); 3376 String path = cms.getSitePath(entryPage); 3377 clientEntry.setVfsPath(path); 3378 clientEntry.setOwnProperties(ownProps); 3379 clientEntry.setDefaultFileProperties(defaultFileProps); 3380 clientEntry.setSitePath(entryFolder != null ? cms.getSitePath(entryFolder) : path); 3381 clientEntry.setLock(generateClientLock(entryPage)); 3382 clientEntry.setInNavigation(isRoot || navElement.isInNavigation()); 3383 String type = OpenCms.getResourceManager().getResourceType(ownResource).getTypeName(); 3384 clientEntry.setResourceTypeName(type); 3385 clientEntry.setVfsModeIcon(CmsIconUtil.getIconClasses(type, ownResource.getName(), false)); 3386 3387 if (!clientEntry.isSubSitemapType()) { 3388 if (clientEntry.isNavigationLevelType()) { 3389 clientEntry.setNavModeIcon(CmsIconUtil.ICON_NAV_LEVEL_BIG); 3390 } else if (defaultFileResource != null) { 3391 clientEntry.setNavModeIcon( 3392 CmsIconUtil.getIconClasses(clientEntry.getDefaultFileType(), defaultFileResource.getName(), false)); 3393 } 3394 } 3395 clientEntry.setPermissionInfo(OpenCms.getADEManager().getPermissionInfo(cms, ownResource, null)); 3396 return clientEntry; 3397 } 3398 3399 /** 3400 * Un-deletes a resource according to the change data.<p> 3401 * 3402 * @param change the change data 3403 * 3404 * @return the changed entry or <code>null</code> 3405 * 3406 * @throws CmsException if something goes wrong 3407 */ 3408 private CmsSitemapChange undelete(CmsSitemapChange change) throws CmsException { 3409 3410 CmsObject cms = getCmsObject(); 3411 CmsResource deleted = cms.readResource(change.getEntryId(), CmsResourceFilter.ALL); 3412 if (deleted.getState().isDeleted()) { 3413 ensureLock(deleted); 3414 cms.undeleteResource(getCmsObject().getSitePath(deleted), true); 3415 tryUnlock(deleted); 3416 } 3417 String parentPath = CmsResource.getParentFolder(cms.getSitePath(deleted)); 3418 CmsJspNavElement navElement = getNavBuilder().getNavigationForResource( 3419 parentPath, 3420 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3421 CmsClientSitemapEntry entry = toClientEntry(navElement, navElement.isInNavigation()); 3422 entry.setSubEntries(getChildren(parentPath, 2, null), null); 3423 change.setUpdatedEntry(entry); 3424 change.setParentId(cms.readParentFolder(deleted.getStructureId()).getStructureId()); 3425 return change; 3426 } 3427 3428 /** 3429 * Updates the navigation position for a resource.<p> 3430 * 3431 * @param res the resource for which to update the navigation position 3432 * @param change the sitemap change 3433 * 3434 * @throws CmsException if something goes wrong 3435 */ 3436 private void updateNavPos(CmsResource res, CmsSitemapChange change) throws CmsException { 3437 3438 if (change.hasChangedPosition()) { 3439 applyNavigationChanges(change, res); 3440 } 3441 } 3442 3443 /** 3444 * Updates properties for a resource and possibly its detail page.<p> 3445 * 3446 * @param cms the CMS context 3447 * @param ownRes the resource 3448 * @param defaultFileRes the default file resource (possibly null) 3449 * @param propertyModifications the property modifications 3450 * 3451 * @throws CmsException if something goes wrong 3452 */ 3453 private void updateProperties( 3454 CmsObject cms, 3455 CmsResource ownRes, 3456 CmsResource defaultFileRes, 3457 List<CmsPropertyModification> propertyModifications) 3458 throws CmsException { 3459 3460 Map<String, CmsProperty> ownProps = getPropertiesByName(cms.readPropertyObjects(ownRes, false)); 3461 String oldNavText = null; 3462 if (ownProps.containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT)) { 3463 oldNavText = ownProps.get(CmsPropertyDefinition.PROPERTY_NAVTEXT).getValue(); 3464 } 3465 if (oldNavText == null) { 3466 oldNavText = ""; 3467 } 3468 Map<String, CmsProperty> defaultFileProps = Maps.newHashMap(); 3469 if (defaultFileRes != null) { 3470 defaultFileProps = getPropertiesByName(cms.readPropertyObjects(defaultFileRes, false)); 3471 } 3472 String newNavText = oldNavText; 3473 List<CmsProperty> ownPropertyChanges = new ArrayList<CmsProperty>(); 3474 List<CmsProperty> defaultFilePropertyChanges = new ArrayList<CmsProperty>(); 3475 for (CmsPropertyModification propMod : propertyModifications) { 3476 CmsProperty propToModify = null; 3477 Map<String, CmsProperty> propMap = null; 3478 List<CmsProperty> changeList = null; 3479 3480 if (ownRes.getStructureId().equals(propMod.getId())) { 3481 if (CmsPropertyDefinition.PROPERTY_NAVTEXT.equals(propMod.getName())) { 3482 newNavText = propMod.getValue(); 3483 } 3484 propMap = ownProps; 3485 changeList = ownPropertyChanges; 3486 } else { 3487 propMap = defaultFileProps; 3488 changeList = defaultFilePropertyChanges; 3489 } 3490 propToModify = propMap.get(propMod.getName()); 3491 if (propToModify == null) { 3492 propToModify = new CmsProperty(propMod.getName(), null, null); 3493 } 3494 String newValue = propMod.getValue(); 3495 if (newValue == null) { 3496 newValue = ""; 3497 } 3498 if (propMod.isStructureValue()) { 3499 propToModify.setStructureValue(newValue); 3500 } else { 3501 propToModify.setResourceValue(newValue); 3502 } 3503 changeList.add(propToModify); 3504 } 3505 3506 if (!ownPropertyChanges.isEmpty()) { 3507 cms.writePropertyObjects(ownRes, ownPropertyChanges); 3508 } 3509 if (!defaultFilePropertyChanges.isEmpty() && (defaultFileRes != null)) { 3510 cms.writePropertyObjects(defaultFileRes, defaultFilePropertyChanges); 3511 } 3512 synchTitleFromNavText(ownRes, oldNavText, newNavText); 3513 if (defaultFileRes != null) { 3514 synchTitleFromNavText(defaultFileRes, oldNavText, newNavText); 3515 } 3516 } 3517 3518}