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 boolean canManageDetailPages = true; 947 String detailPageRole = OpenCms.getWorkplaceManager().getSitemapEditorDetailPageManagementRole(); 948 949 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(detailPageRole)) { 950 CmsRole role = null; 951 try { 952 if (detailPageRole.indexOf("/") == -1) { 953 role = CmsRole.valueOfRoleName(detailPageRole).forOrgUnit(null); 954 } else { 955 role = CmsRole.valueOfRoleName(detailPageRole); 956 } 957 if (role != null) { 958 canManageDetailPages = OpenCms.getRoleManager().hasRoleForResource( 959 cms, 960 role, 961 cms.getRequestContext().removeSiteRoot(configData.getBasePath())); 962 } else { 963 LOG.error("Configured role '" + detailPageRole + "' not found"); 964 } 965 } catch (Exception e) { 966 LOG.error(e.getLocalizedMessage(), e); 967 } 968 } 969 970 detailPages = new CmsDetailPageTable(configData.getAllDetailPages()); 971 if (!isOnlineProject) { 972 newResourceInfos = getNewResourceInfos(cms, configData, getWorkplaceLocale()); 973 CmsResource modelResource = null; 974 if (configData.getDefaultModelPage() != null) { 975 if (cms.existsResource(configData.getDefaultModelPage().getResource().getStructureId())) { 976 modelResource = configData.getDefaultModelPage().getResource(); 977 } else { 978 try { 979 modelResource = cms.readResource( 980 cms.getSitePath(configData.getDefaultModelPage().getResource()), 981 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 982 } catch (CmsException e) { 983 LOG.warn(e.getLocalizedMessage(), e); 984 } 985 } 986 } 987 if ((modelResource == null) && !newResourceInfos.isEmpty()) { 988 try { 989 modelResource = cms.readResource(newResourceInfos.get(0).getCopyResourceId()); 990 } catch (CmsException e) { 991 LOG.warn(e.getLocalizedMessage(), e); 992 } 993 } 994 CmsFormatterConfigurationCacheState formatterState = OpenCms.getADEManager().getCachedFormatters( 995 cms.getRequestContext().getCurrentProject().isOnlineProject()); 996 if (modelResource != null) { 997 resourceTypeInfos = getResourceTypeInfos( 998 getCmsObject(), 999 configData.getResourceTypes(), 1000 configData.getFunctionReferences(), 1001 configData.getDynamicFunctionAvailability(formatterState), 1002 modelResource, 1003 getWorkplaceLocale()); 1004 try { 1005 defaultNewInfo = createNewResourceInfo(cms, modelResource, getWorkplaceLocale()); 1006 } catch (CmsException e) { 1007 LOG.warn(e.getLocalizedMessage(), e); 1008 } 1009 } 1010 canEditDetailPages = !(configData.isModuleConfiguration()); 1011 } 1012 if (isOnlineProject) { 1013 noEdit = Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_SITEMAP_NO_EDIT_ONLINE_0); 1014 } 1015 List<String> allPropNames = getPropertyNames(cms); 1016 String returnCode = getRequest().getParameter(CmsCoreData.PARAM_RETURNCODE); 1017 if (!isValidReturnCode(returnCode)) { 1018 returnCode = null; 1019 } 1020 cms.getRequestContext().getSiteRoot(); 1021 String aliasImportUrl = OpenCms.getLinkManager().substituteLinkForRootPath(cms, ALIAS_IMPORT_PATH); 1022 boolean canEditAliases = OpenCms.getAliasManager().hasPermissionsForMassEdit(cms, siteRoot); 1023 List<CmsListInfoBean> subsitemapFolderTypeInfos = collectSitemapTypeInfos(cms, configData); 1024 1025 // evaluate the editor mode 1026 EditorMode editorMode = CmsADESessionCache.getCache(getRequest(), getCmsObject()).getSitemapEditorMode(); 1027 if ((editorMode == null) || (editorMode == EditorMode.compareLocales)) { 1028 editorMode = EditorMode.navigation; 1029 } 1030 1031 String basePath = configData.getBasePath(); 1032 1033 if (!cms.existsResource( 1034 cms.getRequestContext().removeSiteRoot(basePath), 1035 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 1036 basePath = cms.getRequestContext().getSiteRoot(); 1037 } 1038 Boolean showModelEditConfirm = (Boolean)getRequest().getSession().getAttribute( 1039 ATTR_SHOW_MODEL_EDIT_CONFIRM); 1040 if (showModelEditConfirm == null) { 1041 showModelEditConfirm = Boolean.TRUE; 1042 } 1043 boolean showLocaleComparison = !(getCmsObject().getRequestContext().getCurrentProject().isOnlineProject()) 1044 && (site != null) 1045 && (site.getMainTranslationLocale(null) != null); 1046 1047 result = new CmsSitemapData( 1048 (new CmsTemplateFinder(cms)).getTemplates(), 1049 propertyConfig, 1050 getClipboardData(), 1051 CmsCoreService.getContextMenuEntries( 1052 cms, 1053 configData.getResource().getStructureId(), 1054 AdeContext.sitemapeditor, 1055 new HashMap<>()), 1056 parentProperties, 1057 allPropNames, 1058 exportRfsPrefix, 1059 isSecure, 1060 noEdit, 1061 isDisplayToolbar(getRequest()), 1062 defaultNewInfo, 1063 newResourceInfos, 1064 createResourceTypeInfo(OpenCms.getResourceManager().getResourceType(RECOURCE_TYPE_NAME_REDIRECT), null), 1065 createNavigationLevelTypeInfo(), 1066 getSitemapInfo(basePath), 1067 parentSitemap, 1068 getRootEntry(basePath, CmsResource.getFolderPath(openPath)), 1069 openPath, 1070 30, 1071 detailPages, 1072 resourceTypeInfos, 1073 returnCode, 1074 canEditDetailPages && canManageDetailPages, 1075 aliasImportUrl, 1076 canEditAliases, 1077 OpenCms.getWorkplaceManager().getDefaultUserSettings().getSubsitemapCreationMode() == CmsDefaultUserSettings.SubsitemapCreationMode.createfolder, 1078 OpenCms.getRoleManager().hasRole(cms, CmsRole.GALLERY_EDITOR), 1079 OpenCms.getRoleManager().hasRole(cms, CmsRole.CATEGORY_EDITOR), 1080 subsitemapFolderTypeInfos, 1081 editorMode, 1082 defaultGalleryFolder, 1083 showModelEditConfirm.booleanValue()); 1084 1085 CmsUUID rootId = cms.readResource("/", CmsResourceFilter.ALL).getStructureId(); 1086 result.setSiteRootId(rootId); 1087 result.setLocaleComparisonEnabled(showLocaleComparison); 1088 result.setCanManageDetailPages(canManageDetailPages); 1089 1090 boolean allowCreateNestedGalleries = Boolean.parseBoolean( 1091 "" + OpenCms.getRuntimeProperty("ade.sitemap.allowCreateNestedGalleries")); 1092 result.setAllowCreateNestedGalleries(allowCreateNestedGalleries); 1093 1094 } catch (Throwable e) { 1095 error(e); 1096 } 1097 return result; 1098 } 1099 1100 /** 1101 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#prepareReloadSitemap(org.opencms.util.CmsUUID, org.opencms.ade.sitemap.shared.CmsSitemapData.EditorMode) 1102 */ 1103 public String prepareReloadSitemap(CmsUUID rootId, EditorMode mode) throws CmsRpcException { 1104 1105 try { 1106 CmsObject cms = getCmsObject(); 1107 CmsResource res = cms.readResource(CmsADEManager.PATH_SITEMAP_EDITOR_JSP); 1108 1109 CmsResource target = cms.readResource(rootId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1110 String targetRootPath = OpenCms.getADEManager().getSubSiteRoot(cms, target.getRootPath()); 1111 CmsSite targetSite = OpenCms.getSiteManager().getSiteForRootPath(targetRootPath); 1112 CmsADESessionCache.getCache(getRequest(), getCmsObject()).setSitemapEditorMode(mode); 1113 if (targetSite != null) { 1114 cms.getRequestContext().setSiteRoot(targetSite.getSiteRoot()); 1115 String path = cms.getRequestContext().removeSiteRoot(targetRootPath); 1116 String link = OpenCms.getLinkManager().substituteLink(cms, res); 1117 link = link + "?path=" + path; 1118 return link; 1119 } 1120 return null; 1121 } catch (Exception e) { 1122 error(e); 1123 return null; 1124 } 1125 } 1126 1127 /** 1128 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#removeModelPage(java.lang.String, org.opencms.util.CmsUUID) 1129 */ 1130 public void removeModelPage(String entryPointUri, CmsUUID id) throws CmsRpcException { 1131 1132 try { 1133 CmsObject cms = getCmsObject(); 1134 CmsResource rootResource = cms.readResource(entryPointUri); 1135 CmsModelPageHelper helper = new CmsModelPageHelper(getCmsObject(), rootResource); 1136 String configPath = CmsStringUtil.joinPaths(entryPointUri, ".content/.config"); 1137 CmsResource configResource = cms.readResource(configPath); 1138 helper.removeModelPage(configResource, id); 1139 OpenCms.getADEManager().waitForCacheUpdate(false); 1140 } catch (Throwable e) { 1141 error(e); 1142 1143 } 1144 1145 } 1146 1147 /** 1148 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#save(java.lang.String, org.opencms.ade.sitemap.shared.CmsSitemapChange) 1149 */ 1150 public CmsSitemapChange save(String entryPoint, CmsSitemapChange change) throws CmsRpcException { 1151 1152 CmsSitemapChange result = null; 1153 try { 1154 result = saveInternal(entryPoint, change); 1155 } catch (Exception e) { 1156 error(e); 1157 } 1158 return result; 1159 } 1160 1161 /** 1162 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#saveAliases(org.opencms.gwt.shared.alias.CmsAliasSaveValidationRequest) 1163 */ 1164 public CmsAliasEditValidationReply saveAliases(CmsAliasSaveValidationRequest saveRequest) throws CmsRpcException { 1165 1166 CmsObject cms = getCmsObject(); 1167 CmsAliasBulkEditHelper helper = new CmsAliasBulkEditHelper(cms); 1168 try { 1169 return helper.saveAliases(saveRequest); 1170 } catch (Exception e) { 1171 error(e); 1172 return null; 1173 } 1174 } 1175 1176 /** 1177 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#savePropertiesForLocaleCompareMode(org.opencms.util.CmsUUID, java.lang.String, java.util.List, boolean) 1178 */ 1179 public void savePropertiesForLocaleCompareMode( 1180 CmsUUID id, 1181 String newUrlName, 1182 List<CmsPropertyModification> propertyChanges, 1183 boolean editedName) 1184 throws CmsRpcException { 1185 1186 try { 1187 CmsObject cms = getCmsObject(); 1188 CmsResource ownRes = cms.readResource(id, CmsResourceFilter.IGNORE_EXPIRATION); 1189 CmsResource defaultFileRes = cms.readDefaultFile("" + id); 1190 boolean shallow = !editedName; 1191 try (AutoCloseable c = CmsLockUtil.withLockedResources(cms, shallow, ownRes, defaultFileRes)) { 1192 updateProperties(cms, ownRes, defaultFileRes, propertyChanges); 1193 if (editedName) { 1194 String parent = CmsResource.getParentFolder(ownRes.getRootPath()); 1195 newUrlName = CmsFileUtil.removeTrailingSeparator(newUrlName); 1196 String newPath = CmsStringUtil.joinPaths(parent, newUrlName); 1197 CmsObject rootCms = OpenCms.initCmsObject(cms); 1198 rootCms.getRequestContext().setSiteRoot(""); 1199 if (!CmsPath.equal(ownRes.getRootPath(), newPath)) { 1200 rootCms.moveResource(ownRes.getRootPath(), newPath); 1201 } 1202 } 1203 } 1204 } catch (Exception e) { 1205 error(e); 1206 } 1207 } 1208 1209 /** 1210 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#saveSitemapAttributes(org.opencms.util.CmsUUID, java.util.Map) 1211 */ 1212 public void saveSitemapAttributes(CmsUUID rootId, Map<String, String> attributes) throws CmsRpcException { 1213 1214 CmsResource configResource = null; 1215 try { 1216 CmsObject cms = getCmsObject(); 1217 CmsResource root = cms.readResource(rootId); 1218 String sitePath = cms.getSitePath(root); 1219 String configPath = CmsStringUtil.joinPaths(sitePath, "/.content/.config"); 1220 configResource = cms.readResource(configPath); 1221 CmsXmlContent configContent = CmsXmlContentFactory.unmarshal(cms, cms.readFile(configResource)); 1222 CmsSitemapAttributeUpdater updater = new CmsSitemapAttributeUpdater(cms, configContent); 1223 if (updater.saveAttributesFromEditorDialog(attributes)) { 1224 byte[] newContentBytes = configContent.marshal(); 1225 CmsFile file = configContent.getFile(); 1226 file.setContents(newContentBytes); 1227 cms.writeFile(file); 1228 OpenCms.getADEManager().waitForCacheUpdate(false); 1229 } 1230 } catch (Exception e) { 1231 error(e); 1232 } finally { 1233 try { 1234 if (configResource != null) { 1235 getCmsObject().unlockResource(configResource); 1236 } 1237 } catch (Exception e) { 1238 LOG.debug(e.getLocalizedMessage(), e); 1239 } 1240 } 1241 1242 } 1243 1244 /** 1245 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#setDefaultModel(org.opencms.util.CmsUUID, org.opencms.util.CmsUUID) 1246 */ 1247 public CmsModelInfo setDefaultModel(CmsUUID rootId, CmsUUID modelId) throws CmsRpcException { 1248 1249 CmsModelInfo result = null; 1250 try { 1251 CmsObject cms = getCmsObject(); 1252 CmsResource rootResource = cms.readResource(rootId); 1253 CmsModelPageHelper modelPageHelper = new CmsModelPageHelper(getCmsObject(), rootResource); 1254 CmsResource configFile = OpenCms.getADEManager().lookupConfiguration( 1255 cms, 1256 rootResource.getRootPath()).getResource(); 1257 ensureLock(configFile); 1258 result = modelPageHelper.setDefaultModelPage(configFile, modelId); 1259 tryUnlock(configFile); 1260 } catch (Throwable e) { 1261 error(e); 1262 } 1263 return result; 1264 } 1265 1266 /** 1267 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#setEditorMode(org.opencms.ade.sitemap.shared.CmsSitemapData.EditorMode) 1268 */ 1269 public void setEditorMode(EditorMode editorMode) { 1270 1271 CmsADESessionCache.getCache(getRequest(), getCmsObject()).setSitemapEditorMode(editorMode); 1272 } 1273 1274 /** 1275 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#updateAliasEditorStatus(boolean) 1276 */ 1277 public void updateAliasEditorStatus(boolean editing) { 1278 1279 CmsObject cms = getCmsObject(); 1280 if (editing) { 1281 aliasEditorLockTable.update(cms, cms.getRequestContext().getSiteRoot()); 1282 } else { 1283 aliasEditorLockTable.clear(cms, cms.getRequestContext().getSiteRoot()); 1284 } 1285 } 1286 1287 /** 1288 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#validateAliases(org.opencms.gwt.shared.alias.CmsAliasEditValidationRequest) 1289 */ 1290 public CmsAliasEditValidationReply validateAliases(CmsAliasEditValidationRequest validationRequest) { 1291 1292 CmsObject cms = getCmsObject(); 1293 CmsAliasBulkEditHelper helper = new CmsAliasBulkEditHelper(cms); 1294 return helper.validateAliases(validationRequest); 1295 } 1296 1297 /** 1298 * @see org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapService#validateRewriteAliases(org.opencms.gwt.shared.alias.CmsRewriteAliasValidationRequest) 1299 */ 1300 public CmsRewriteAliasValidationReply validateRewriteAliases(CmsRewriteAliasValidationRequest validationRequest) { 1301 1302 CmsRewriteAliasValidationReply result = new CmsRewriteAliasValidationReply(); 1303 for (CmsRewriteAliasTableRow editedRow : validationRequest.getEditedRewriteAliases()) { 1304 try { 1305 String patternString = editedRow.getPatternString(); 1306 Pattern.compile(patternString); 1307 } catch (PatternSyntaxException e) { 1308 result.addError(editedRow.getId(), "Syntax error in regular expression: " + e.getMessage()); 1309 } 1310 } 1311 return result; 1312 } 1313 1314 /** 1315 * Locks the given resource with a temporary, if not already locked by the current user. 1316 * Will throw an exception if the resource could not be locked for the current user.<p> 1317 * 1318 * @param resource the resource to lock 1319 * 1320 * @return the assigned lock 1321 * 1322 * @throws CmsException if the resource could not be locked 1323 */ 1324 protected LockInfo ensureLockAndGetInfo(CmsResource resource) throws CmsException { 1325 1326 CmsObject cms = getCmsObject(); 1327 boolean justLocked = false; 1328 List<CmsResource> blockingResources = cms.getBlockingLockedResources(resource); 1329 if ((blockingResources != null) && !blockingResources.isEmpty()) { 1330 throw new CmsException( 1331 org.opencms.gwt.Messages.get().container( 1332 org.opencms.gwt.Messages.ERR_RESOURCE_HAS_BLOCKING_LOCKED_CHILDREN_1, 1333 cms.getSitePath(resource))); 1334 } 1335 CmsUser user = cms.getRequestContext().getCurrentUser(); 1336 CmsLock lock = cms.getLock(resource); 1337 if (!lock.isOwnedBy(user)) { 1338 cms.lockResourceTemporary(resource); 1339 lock = cms.getLock(resource); 1340 justLocked = true; 1341 } else if (!lock.isOwnedInProjectBy(user, cms.getRequestContext().getCurrentProject())) { 1342 cms.changeLock(resource); 1343 lock = cms.getLock(resource); 1344 justLocked = true; 1345 } 1346 return new LockInfo(lock, justLocked); 1347 } 1348 1349 /** 1350 * Internal method for saving a sitemap.<p> 1351 * 1352 * @param entryPoint the URI of the sitemap to save 1353 * @param change the change to save 1354 * 1355 * @return list of changed sitemap entries 1356 * 1357 * @throws CmsException if something goes wrong 1358 */ 1359 protected CmsSitemapChange saveInternal(String entryPoint, CmsSitemapChange change) throws CmsException { 1360 1361 ensureSession(); 1362 switch (change.getChangeType()) { 1363 case clipboardOnly: 1364 // do nothing 1365 break; 1366 case remove: 1367 change = removeEntryFromNavigation(change); 1368 break; 1369 case undelete: 1370 change = undelete(change); 1371 break; 1372 default: 1373 change = applyChange(entryPoint, change); 1374 } 1375 setClipboardData(change.getClipBoardData()); 1376 return change; 1377 } 1378 1379 /** 1380 * Gets the properties of a resource as a map of client properties.<p> 1381 * 1382 * @param cms the CMS context to use 1383 * @param res the resource whose properties to read 1384 * @param search true if the inherited properties should be read 1385 * 1386 * @return the client properties as a map 1387 * 1388 * @throws CmsException if something goes wrong 1389 */ 1390 Map<String, CmsClientProperty> getClientProperties(CmsObject cms, CmsResource res, boolean search) 1391 throws CmsException { 1392 1393 List<CmsProperty> props = cms.readPropertyObjects(res, search); 1394 Map<String, CmsClientProperty> result = createClientProperties(props, false); 1395 return result; 1396 } 1397 1398 /** 1399 * Adds a function detail element to a container page.<p> 1400 * 1401 * @param cms the current CMS context 1402 * @param page the container page which should be changed 1403 * @param containerName the name of the container which should be used for function detail elements 1404 * @param elementId the structure id of the element to add 1405 * @param formatterId the structure id of the formatter for the element 1406 * 1407 * @throws CmsException if something goes wrong 1408 */ 1409 private void addFunctionDetailElement( 1410 CmsObject cms, 1411 CmsXmlContainerPage page, 1412 String containerName, 1413 CmsUUID elementId, 1414 CmsUUID formatterId) 1415 throws CmsException { 1416 1417 CmsContainerPageBean bean = page.getContainerPage(cms); 1418 List<CmsContainerBean> containerBeans = new ArrayList<CmsContainerBean>(); 1419 Collection<CmsContainerBean> originalContainers = bean.getContainers().values(); 1420 if ((containerName == null) && !originalContainers.isEmpty()) { 1421 CmsContainerBean firstContainer = originalContainers.iterator().next(); 1422 containerName = firstContainer.getName(); 1423 } 1424 boolean foundContainer = false; 1425 for (CmsContainerBean cntBean : originalContainers) { 1426 boolean isDetailTarget = cntBean.getName().equals(containerName); 1427 if (isDetailTarget && !foundContainer) { 1428 foundContainer = true; 1429 List<CmsContainerElementBean> newElems = new ArrayList<CmsContainerElementBean>(); 1430 newElems.addAll(cntBean.getElements()); 1431 CmsContainerElementBean newElement = new CmsContainerElementBean( 1432 elementId, 1433 formatterId, 1434 new HashMap<String, String>(), 1435 false); 1436 newElems.add(0, newElement); 1437 CmsContainerBean newCntBean = cntBean.copyWithNewElements(newElems); 1438 containerBeans.add(newCntBean); 1439 } else { 1440 containerBeans.add(cntBean); 1441 } 1442 } 1443 if (!foundContainer) { 1444 throw new CmsException( 1445 Messages.get().container(Messages.ERR_NO_FUNCTION_DETAIL_CONTAINER_1, page.getFile().getRootPath())); 1446 } 1447 CmsContainerPageBean bean2 = new CmsContainerPageBean(new ArrayList<CmsContainerBean>(containerBeans)); 1448 page.writeContainerPage(cms, bean2); 1449 1450 } 1451 1452 /** 1453 * Applys the given change to the VFS.<p> 1454 * 1455 * @param entryPoint the sitemap entry-point 1456 * @param change the change 1457 * 1458 * @return the updated entry 1459 * 1460 * @throws CmsException if something goes wrong 1461 */ 1462 private CmsSitemapChange applyChange(String entryPoint, CmsSitemapChange change) throws CmsException { 1463 1464 CmsObject cms = getCmsObject(); 1465 CmsResource configFile = null; 1466 // lock the config file first, to avoid half done changes 1467 if (change.hasDetailPageInfos()) { 1468 CmsADEConfigData configData = OpenCms.getADEManager().lookupConfiguration( 1469 cms, 1470 cms.getRequestContext().addSiteRoot(entryPoint)); 1471 if (!configData.isModuleConfiguration() && (configData.getResource() != null)) { 1472 configFile = configData.getResource(); 1473 } 1474 if (configFile != null) { 1475 ensureLock(configFile); 1476 } 1477 } 1478 if (change.isNew()) { 1479 CmsClientSitemapEntry newEntry = createNewEntry(entryPoint, change); 1480 change.setUpdatedEntry(newEntry); 1481 change.setEntryId(newEntry.getId()); 1482 } else if (change.getChangeType() == ChangeType.delete) { 1483 delete(change); 1484 } else if (change.getEntryId() != null) { 1485 modifyEntry(change); 1486 } 1487 if (change.hasDetailPageInfos() && (configFile != null)) { 1488 saveDetailPages(change.getDetailPageInfos(), configFile, change.getEntryId(), change.getUpdatedEntry()); 1489 tryUnlock(configFile); 1490 } 1491 1492 return change; 1493 } 1494 1495 /** 1496 * Changes the navigation for a moved entry and its neighbors.<p> 1497 * 1498 * @param change the sitemap change 1499 * @param entryFolder the moved entry 1500 * 1501 * @throws CmsException if something goes wrong 1502 */ 1503 private void applyNavigationChanges(CmsSitemapChange change, CmsResource entryFolder) throws CmsException { 1504 1505 CmsObject cms = getCmsObject(); 1506 String parentPath = null; 1507 if (change.hasNewParent()) { 1508 CmsResource parent = cms.readResource(change.getParentId()); 1509 parentPath = cms.getSitePath(parent); 1510 } else { 1511 parentPath = CmsResource.getParentFolder(cms.getSitePath(entryFolder)); 1512 } 1513 List<CmsJspNavElement> navElements = getNavBuilder().getNavigationForFolder( 1514 parentPath, 1515 Visibility.all, 1516 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1517 CmsSitemapNavPosCalculator npc = new CmsSitemapNavPosCalculator(navElements, entryFolder, change.getPosition()); 1518 List<CmsJspNavElement> navs = npc.getNavigationChanges(); 1519 List<CmsResource> needToUnlock = new ArrayList<CmsResource>(); 1520 1521 try { 1522 for (CmsJspNavElement nav : navs) { 1523 LockInfo lockInfo = ensureLockAndGetInfo(nav.getResource()); 1524 if (!nav.getResource().equals(entryFolder) && lockInfo.wasJustLocked()) { 1525 needToUnlock.add(nav.getResource()); 1526 } 1527 } 1528 for (CmsJspNavElement nav : navs) { 1529 CmsProperty property = new CmsProperty( 1530 CmsPropertyDefinition.PROPERTY_NAVPOS, 1531 "" + nav.getNavPosition(), 1532 null); 1533 cms.writePropertyObject(cms.getSitePath(nav.getResource()), property); 1534 } 1535 } finally { 1536 for (CmsResource lockedRes : needToUnlock) { 1537 try { 1538 cms.unlockResource(lockedRes); 1539 } catch (CmsException e) { 1540 // we catch this because we still want to unlock the other resources 1541 LOG.error(e.getLocalizedMessage(), e); 1542 } 1543 } 1544 } 1545 } 1546 1547 /** 1548 * Builds the list info bean for a resource type which can be used as a sub-sitemap folder.<p> 1549 * 1550 * @param sitemapType the sitemap folder type 1551 * 1552 * @return the list info bean for the given type 1553 */ 1554 private CmsListInfoBean buildSitemapTypeInfo(I_CmsResourceType sitemapType) { 1555 1556 CmsListInfoBean result = new CmsListInfoBean(); 1557 CmsWorkplaceManager wm = OpenCms.getWorkplaceManager(); 1558 String typeName = sitemapType.getTypeName(); 1559 Locale wpLocale = wm.getWorkplaceLocale(getCmsObject()); 1560 String title = typeName; 1561 String description = ""; 1562 try { 1563 title = CmsWorkplaceMessages.getResourceTypeName(wpLocale, typeName); 1564 } catch (Throwable e) { 1565 LOG.warn(e.getLocalizedMessage(), e); 1566 } 1567 try { 1568 description = CmsWorkplaceMessages.getResourceTypeDescription(wpLocale, typeName); 1569 } catch (Throwable e) { 1570 LOG.warn(e.getLocalizedMessage(), e); 1571 } 1572 result.setResourceType(typeName); 1573 result.setTitle(title); 1574 result.setSubTitle(description); 1575 return result; 1576 } 1577 1578 /** 1579 * Returns all available gallery folder resource types.<p> 1580 * 1581 * @return the gallery folder resource types 1582 */ 1583 @SuppressWarnings("deprecation") 1584 private List<CmsGalleryType> collectGalleryTypes() { 1585 1586 Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject()); 1587 Map<String, List<String>> galleryContentTypes = new HashMap<String, List<String>>(); 1588 List<CmsGalleryType> result = new ArrayList<CmsGalleryType>(); 1589 for (I_CmsResourceType resourceType : OpenCms.getResourceManager().getResourceTypes()) { 1590 if (resourceType instanceof CmsResourceTypeFolderExtended) { 1591 // found a configured extended folder resource type 1592 CmsResourceTypeFolderExtended galleryType = (CmsResourceTypeFolderExtended)resourceType; 1593 String folderClassName = galleryType.getFolderClassName(); 1594 if (CmsStringUtil.isNotEmpty(folderClassName)) { 1595 // only process this as a gallery if the folder name is not empty 1596 try { 1597 // check, if the folder class is a subclass of A_CmsGallery 1598 if (A_CmsAjaxGallery.class.isAssignableFrom(Class.forName(folderClassName))) { 1599 CmsGalleryType gallery = new CmsGalleryType(); 1600 gallery.setTypeId(resourceType.getTypeId()); 1601 gallery.setResourceType(resourceType.getTypeName()); 1602 gallery.setTitle( 1603 CmsWorkplaceMessages.getResourceTypeName(wpLocale, resourceType.getTypeName())); 1604 gallery.setSubTitle( 1605 CmsWorkplaceMessages.getResourceTypeDescription(wpLocale, resourceType.getTypeName())); 1606 gallery.setBigIconClasses( 1607 CmsIconUtil.getIconClasses(resourceType.getTypeName(), null, false)); 1608 result.add(gallery); 1609 } 1610 } catch (Exception e) { 1611 this.log(e.getLocalizedMessage(), e); 1612 } 1613 } 1614 } else { 1615 List<I_CmsResourceType> galleryTypes = resourceType.getGalleryTypes(); 1616 if ((galleryTypes != null) && !galleryTypes.isEmpty()) { 1617 for (I_CmsResourceType galleryType : galleryTypes) { 1618 List<String> typeList = galleryContentTypes.get(galleryType.getTypeName()); 1619 if (typeList == null) { 1620 typeList = new ArrayList<String>(); 1621 galleryContentTypes.put(galleryType.getTypeName(), typeList); 1622 } 1623 typeList.add(resourceType.getTypeName()); 1624 } 1625 } 1626 } 1627 } 1628 for (CmsGalleryType galleryType : result) { 1629 galleryType.setContentTypeNames(galleryContentTypes.get(galleryType.getResourceType())); 1630 } 1631 return result; 1632 } 1633 1634 /** 1635 * Gets the information for the available sitemap folder types.<p> 1636 * 1637 * @param cms the current CMS context 1638 * @param configData the configuration data for the current subsitemap 1639 * @return the list info beans corresponding to available sitemap folder types 1640 */ 1641 private List<CmsListInfoBean> collectSitemapTypeInfos(CmsObject cms, CmsADEConfigData configData) { 1642 1643 List<CmsListInfoBean> subsitemapFolderTypeInfos = new ArrayList<CmsListInfoBean>(); 1644 List<Integer> sitemapTypeIds = CmsResourceTypeFolderSubSitemap.getSubSitemapResourceTypeIds(); 1645 String checkPath = configData.getBasePath(); 1646 if (checkPath != null) { 1647 checkPath = cms.getRequestContext().removeSiteRoot(checkPath); 1648 } else { 1649 checkPath = "/"; 1650 } 1651 CmsResource checkResource = null; 1652 try { 1653 checkResource = cms.readResource(checkPath); 1654 } catch (CmsException e) { 1655 LOG.warn(e.getLocalizedMessage(), e); 1656 } 1657 1658 for (Integer typeId : sitemapTypeIds) { 1659 try { 1660 I_CmsResourceType sitemapType = OpenCms.getResourceManager().getResourceType(typeId.intValue()); 1661 String typeName = sitemapType.getTypeName(); 1662 CmsExplorerTypeSettings explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName); 1663 1664 // if explorer type and check resource available, perform a permission check 1665 if ((explorerType != null) && (checkResource != null)) { 1666 try { 1667 CmsExplorerTypeAccess access = explorerType.getAccess(); 1668 if (!access.getPermissions(cms, checkResource).requiresControlPermission()) { 1669 continue; 1670 } 1671 } catch (Exception e) { 1672 LOG.error(e.getLocalizedMessage(), e); 1673 } 1674 } 1675 CmsListInfoBean infoBean = buildSitemapTypeInfo(sitemapType); 1676 subsitemapFolderTypeInfos.add(infoBean); 1677 1678 } catch (CmsLoaderException e) { 1679 LOG.warn("Could not read sitemap folder type " + typeId + ": " + e.getLocalizedMessage(), e); 1680 } 1681 } 1682 return subsitemapFolderTypeInfos; 1683 } 1684 1685 /** 1686 * Creates a client alias bean from a server-side alias.<p> 1687 * 1688 * @param cms the current CMS context 1689 * @param alias the alias to convert 1690 * 1691 * @return the alias table row 1692 * 1693 * @throws CmsException if something goes wrong 1694 */ 1695 private CmsAliasTableRow createAliasTableEntry(CmsObject cms, CmsAlias alias) throws CmsException { 1696 1697 CmsResource resource = cms.readResource(alias.getStructureId(), CmsResourceFilter.ALL); 1698 CmsAliasTableRow result = new CmsAliasTableRow(); 1699 result.setStructureId(alias.getStructureId()); 1700 result.setOriginalStructureId(alias.getStructureId()); 1701 result.setAliasPath(alias.getAliasPath()); 1702 result.setResourcePath(cms.getSitePath(resource)); 1703 result.setKey((new CmsUUID()).toString()); 1704 result.setMode(alias.getMode()); 1705 result.setChanged(false); 1706 return result; 1707 } 1708 1709 /** 1710 * Creates a navigation level type info.<p> 1711 * 1712 * @return the navigation level type info bean 1713 * 1714 * @throws CmsException if reading the sub level redirect copy page fails 1715 */ 1716 private CmsNewResourceInfo createNavigationLevelTypeInfo() throws CmsException { 1717 1718 String name = CmsResourceTypeFolder.getStaticTypeName(); 1719 Locale locale = getWorkplaceLocale(); 1720 String subtitle = Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_NAVIGATION_LEVEL_SUBTITLE_0); 1721 if (CmsStringUtil.isEmptyOrWhitespaceOnly(subtitle)) { 1722 subtitle = CmsWorkplaceMessages.getResourceTypeName(locale, name); 1723 } 1724 CmsNewResourceInfo result = new CmsNewResourceInfo( 1725 CmsResourceTypeFolder.getStaticTypeId(), 1726 name, 1727 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_NAVIGATION_LEVEL_TITLE_0), 1728 subtitle, 1729 getCmsObject().readResource(SUB_LEVEL_REDIRECT_COPY_PAGE).getStructureId(), 1730 false, 1731 subtitle); 1732 result.setBigIconClasses(CmsIconUtil.ICON_NAV_LEVEL_BIG); 1733 result.setCreateParameter(CmsJspNavBuilder.NAVIGATION_LEVEL_FOLDER); 1734 return result; 1735 } 1736 1737 /** 1738 * Creates new content elements if required by the model page.<p> 1739 * 1740 * @param cms the cms context 1741 * @param page the page 1742 * @param sitePath the resource site path 1743 * 1744 * @throws CmsException when unable to create the content elements 1745 */ 1746 private boolean createNewContainerElements(CmsObject cms, CmsMutableContainerPage page, String sitePath) 1747 throws CmsException { 1748 1749 boolean needsChanges = false; 1750 CmsADEConfigData configData = OpenCms.getADEManager().lookupConfiguration(cms, cms.addSiteRoot(sitePath)); 1751 Locale contentLocale = OpenCms.getLocaleManager().getDefaultLocale(cms, CmsResource.getFolderPath(sitePath)); 1752 CmsObject cloneCms = OpenCms.initCmsObject(cms); 1753 cloneCms.getRequestContext().setLocale(contentLocale); 1754 for (CmsMutableContainer container : page.containers()) { 1755 ListIterator<CmsContainerElementBean> iter = container.elements().listIterator(); 1756 while (iter.hasNext()) { 1757 CmsContainerElementBean elem = iter.next(); 1758 if (elem.isCreateNew() && !elem.isGroupContainer(cms) && !elem.isInheritedContainer(cms)) { 1759 String typeName = OpenCms.getResourceManager().getResourceType(elem.getResource()).getTypeName(); 1760 CmsResourceTypeConfig typeConfig = configData.getResourceType(typeName); 1761 if (typeConfig == null) { 1762 throw new IllegalArgumentException( 1763 "Can not copy template model element '" 1764 + elem.getResource().getRootPath() 1765 + "' because the resource type '" 1766 + typeName 1767 + "' is not available in this sitemap."); 1768 } 1769 1770 CmsResource newResource = typeConfig.createNewElement( 1771 cloneCms, 1772 elem.getResource(), 1773 CmsResource.getParentFolder(cms.getRequestContext().addSiteRoot(sitePath))); 1774 CmsContainerElementBean newBean = new CmsContainerElementBean( 1775 newResource.getStructureId(), 1776 elem.getFormatterId(), 1777 elem.getIndividualSettings(), 1778 false); 1779 iter.set(newBean); 1780 needsChanges = true; 1781 } 1782 } 1783 } 1784 return needsChanges; 1785 } 1786 1787 /** 1788 * Creates new content elements if required by the model page.<p> 1789 * 1790 * @param cms the cms context 1791 * @param page the page 1792 * @param sitePath the resource site path 1793 * 1794 * @throws CmsException when unable to create the content elements 1795 */ 1796 private void createNewContainerElements(CmsObject cms, CmsXmlContainerPage page, String sitePath) 1797 throws CmsException { 1798 1799 CmsADEConfigData configData = OpenCms.getADEManager().lookupConfiguration(cms, cms.addSiteRoot(sitePath)); 1800 Locale contentLocale = OpenCms.getLocaleManager().getDefaultLocale(cms, CmsResource.getFolderPath(sitePath)); 1801 CmsObject cloneCms = OpenCms.initCmsObject(cms); 1802 cloneCms.getRequestContext().setLocale(contentLocale); 1803 CmsContainerPageBean pageBean = page.getContainerPage(cms); 1804 boolean needsChanges = false; 1805 List<CmsContainerBean> updatedContainers = new ArrayList<CmsContainerBean>(); 1806 for (CmsContainerBean container : pageBean.getContainers().values()) { 1807 List<CmsContainerElementBean> updatedElements = new ArrayList<CmsContainerElementBean>(); 1808 for (CmsContainerElementBean element : container.getElements()) { 1809 if (element.isCreateNew() && !element.isGroupContainer(cms) && !element.isInheritedContainer(cms)) { 1810 needsChanges = true; 1811 String typeName = OpenCms.getResourceManager().getResourceType(element.getResource()).getTypeName(); 1812 CmsResourceTypeConfig typeConfig = configData.getResourceType(typeName); 1813 if (typeConfig == null) { 1814 throw new IllegalArgumentException( 1815 "Can not copy template model element '" 1816 + element.getResource().getRootPath() 1817 + "' because the resource type '" 1818 + typeName 1819 + "' is not available in this sitemap."); 1820 } 1821 1822 CmsResource newResource = typeConfig.createNewElement( 1823 cloneCms, 1824 element.getResource(), 1825 CmsResource.getParentFolder(cms.getRequestContext().addSiteRoot(sitePath))); 1826 CmsContainerElementBean newBean = new CmsContainerElementBean( 1827 newResource.getStructureId(), 1828 element.getFormatterId(), 1829 element.getIndividualSettings(), 1830 false); 1831 updatedElements.add(newBean); 1832 } else { 1833 updatedElements.add(element); 1834 } 1835 } 1836 1837 CmsContainerBean updatedContainer = container.copyWithNewElements(updatedElements); 1838 updatedContainers.add(updatedContainer); 1839 } 1840 if (needsChanges) { 1841 CmsContainerPageBean updatedPage = new CmsContainerPageBean(updatedContainers); 1842 page.writeContainerPage(cms, updatedPage); 1843 } 1844 } 1845 1846 /** 1847 * Creates a new page in navigation.<p> 1848 * 1849 * @param entryPoint the site-map entry-point 1850 * @param change the new change 1851 * 1852 * @return the updated entry 1853 * 1854 * @throws CmsException if something goes wrong 1855 */ 1856 @SuppressWarnings("deprecation") 1857 private CmsClientSitemapEntry createNewEntry(String entryPoint, CmsSitemapChange change) throws CmsException { 1858 1859 CmsObject cms = getCmsObject(); 1860 CmsClientSitemapEntry newEntry = null; 1861 if (change.getParentId() != null) { 1862 CmsResource parentFolder = cms.readResource( 1863 change.getParentId(), 1864 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1865 String entryPath = ""; 1866 CmsResource entryFolder = null; 1867 CmsResource newRes = null; 1868 byte[] content = null; 1869 List<CmsProperty> properties = Collections.emptyList(); 1870 CmsResource copyPage = null; 1871 if (change.getNewCopyResourceId() != null) { 1872 copyPage = cms.readResource(change.getNewCopyResourceId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1873 content = cms.readFile(copyPage).getContents(); 1874 properties = cms.readPropertyObjects(copyPage, false); 1875 } 1876 List<CmsProperty> filteredProperties = new ArrayList<CmsProperty>(); 1877 for (CmsProperty property : properties) { 1878 boolean filter = false; 1879 if (FILTER_PROPERTIES.contains(property.getName())) { 1880 filter = true; 1881 1882 } else { 1883 // filter localized versions also 1884 for (String filterProp : FILTER_PROPERTIES) { 1885 if (property.getName().startsWith(filterProp + "_")) { 1886 filter = true; 1887 break; 1888 } 1889 } 1890 } 1891 if (!filter) { 1892 filteredProperties.add(property); 1893 } 1894 } 1895 properties = filteredProperties; 1896 if (isRedirectType(change.getNewResourceTypeId())) { 1897 entryPath = CmsStringUtil.joinPaths(cms.getSitePath(parentFolder), change.getName()); 1898 newRes = cms.createResource( 1899 entryPath, 1900 change.getNewResourceTypeId(), 1901 null, 1902 Collections.singletonList( 1903 new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, change.getName(), null))); 1904 cms.writePropertyObjects(newRes, generateInheritProperties(change, newRes)); 1905 applyNavigationChanges(change, newRes); 1906 } else { 1907 String entryFolderPath = CmsStringUtil.joinPaths(cms.getSitePath(parentFolder), change.getName() + "/"); 1908 boolean idWasNull = change.getEntryId() == null; 1909 // we don't really need to create a folder object here anymore. 1910 if (idWasNull) { 1911 // need this for calculateNavPosition, even though the id will get overwritten 1912 change.setEntryId(new CmsUUID()); 1913 } 1914 1915 boolean isFunctionDetail = false; 1916 boolean isNavigationLevel = false; 1917 if (change.getCreateParameter() != null) { 1918 if (CmsUUID.isValidUUID(change.getCreateParameter())) { 1919 isFunctionDetail = true; 1920 } else if (CmsJspNavBuilder.NAVIGATION_LEVEL_FOLDER.equals(change.getCreateParameter())) { 1921 isNavigationLevel = true; 1922 } 1923 } 1924 String folderType = CmsResourceTypeFolder.getStaticTypeName(); 1925 String createSitemapFolderType = change.getCreateSitemapFolderType(); 1926 if (createSitemapFolderType != null) { 1927 folderType = createSitemapFolderType; 1928 } 1929 1930 int folderTypeId = OpenCms.getResourceManager().getResourceType(folderType).getTypeId(); 1931 entryFolder = new CmsResource( 1932 change.getEntryId(), 1933 new CmsUUID(), 1934 entryFolderPath, 1935 folderTypeId, 1936 true, 1937 0, 1938 cms.getRequestContext().getCurrentProject().getUuid(), 1939 CmsResource.STATE_NEW, 1940 System.currentTimeMillis(), 1941 cms.getRequestContext().getCurrentUser().getId(), 1942 System.currentTimeMillis(), 1943 cms.getRequestContext().getCurrentUser().getId(), 1944 CmsResource.DATE_RELEASED_DEFAULT, 1945 CmsResource.DATE_EXPIRED_DEFAULT, 1946 1, 1947 0, 1948 System.currentTimeMillis(), 1949 0); 1950 List<CmsProperty> folderProperties = generateInheritProperties(change, entryFolder); 1951 if (isNavigationLevel) { 1952 folderProperties.add( 1953 new CmsProperty( 1954 CmsPropertyDefinition.PROPERTY_DEFAULT_FILE, 1955 CmsJspNavBuilder.NAVIGATION_LEVEL_FOLDER, 1956 null)); 1957 } 1958 entryFolder = cms.createResource(entryFolderPath, folderTypeId, null, folderProperties); 1959 if (createSitemapFolderType != null) { 1960 createSitemapContentFolder(cms, entryFolder); 1961 } 1962 if (idWasNull) { 1963 change.setEntryId(entryFolder.getStructureId()); 1964 } 1965 applyNavigationChanges(change, entryFolder); 1966 entryPath = CmsStringUtil.joinPaths(entryFolderPath, "index.html"); 1967 boolean isContainerPage = change.getNewResourceTypeId() == CmsResourceTypeXmlContainerPage.getContainerPageTypeIdSafely(); 1968 if (isContainerPage && (copyPage != null)) { 1969 1970 // do *NOT* get this from the cache, because we perform some destructive operation on the XML content 1971 CmsXmlContainerPage page = CmsXmlContainerPageFactory.unmarshal( 1972 cms, 1973 cms.readFile(copyPage), 1974 true, 1975 true); 1976 CmsContainerPageWrapper wrapper = new CmsContainerPageWrapper(cms, page); 1977 if (isFunctionDetail) { 1978 String functionDetailContainer = getFunctionDetailContainerName(parentFolder); 1979 if (functionDetailContainer != null) { 1980 CmsUUID functionStructureId = new CmsUUID(change.getCreateParameter()); 1981 CmsResource functionRes = cms.readResource( 1982 functionStructureId, 1983 CmsResourceFilter.IGNORE_EXPIRATION); 1984 CmsResource functionFormatter; 1985 if (OpenCms.getResourceManager().matchResourceType( 1986 CmsResourceTypeFunctionConfig.TYPE_NAME, 1987 functionRes.getTypeId())) { 1988 functionFormatter = cms.readResource(CmsResourceTypeFunctionConfig.FORMATTER_PATH); 1989 } else { 1990 functionFormatter = cms.readResource( 1991 CmsResourceTypeFunctionConfig.FORMATTER_PATH, 1992 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1993 } 1994 if (!wrapper.addElementToContainer( 1995 functionDetailContainer, 1996 new CmsContainerElementBean( 1997 functionStructureId, 1998 functionFormatter.getStructureId(), 1999 new HashMap<>(), 2000 false))) { 2001 2002 throw new CmsException( 2003 Messages.get().container( 2004 Messages.ERR_NO_FUNCTION_DETAIL_CONTAINER_1, 2005 page.getFile().getRootPath())); 2006 } 2007 } else { 2008 LOG.debug("function detail container is null for " + parentFolder.getRootPath()); 2009 } 2010 } 2011 createNewContainerElements(cms, wrapper.page(), entryPath); 2012 content = wrapper.marshal(); 2013 } 2014 newRes = cms.createResource( 2015 entryPath, 2016 copyPage != null ? copyPage.getTypeId() : change.getNewResourceTypeId(), 2017 content, 2018 properties); 2019 cms.writePropertyObjects(newRes, generateOwnProperties(change)); 2020 } 2021 2022 if (entryFolder != null) { 2023 tryUnlock(entryFolder); 2024 String sitePath = cms.getSitePath(entryFolder); 2025 newEntry = toClientEntry( 2026 getNavBuilder().getNavigationForResource(sitePath, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED), 2027 false); 2028 newEntry.setSubEntries(getChildren(sitePath, 1, null), null); 2029 newEntry.setChildrenLoadedInitially(true); 2030 } 2031 if (newRes != null) { 2032 tryUnlock(newRes); 2033 } 2034 if (newEntry == null) { 2035 newEntry = toClientEntry( 2036 getNavBuilder().getNavigationForResource( 2037 cms.getSitePath(newRes), 2038 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED), 2039 false); 2040 } 2041 // mark position as not set 2042 newEntry.setPosition(-1); 2043 newEntry.setNew(true); 2044 change.getClipBoardData().getModifications().remove(null); 2045 change.getClipBoardData().getModifications().put(newEntry.getId(), newEntry); 2046 } 2047 return newEntry; 2048 } 2049 2050 /** 2051 * Creates a new resource info to a given model page resource.<p> 2052 * 2053 * @param cms the current CMS context 2054 * @param modelResource the model page resource 2055 * @param locale the locale used for retrieving descriptions/titles 2056 * 2057 * @return the new resource info 2058 * 2059 * @throws CmsException if something goes wrong 2060 */ 2061 private CmsNewResourceInfo createNewResourceInfo(CmsObject cms, CmsResource modelResource, Locale locale) 2062 throws CmsException { 2063 2064 // if model page got overwritten by another resource, reread from site path 2065 if (!cms.existsResource(modelResource.getStructureId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 2066 modelResource = cms.readResource(cms.getSitePath(modelResource), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2067 } 2068 int typeId = modelResource.getTypeId(); 2069 String name = OpenCms.getResourceManager().getResourceType(typeId).getTypeName(); 2070 String title = cms.readPropertyObject( 2071 modelResource, 2072 CmsPropertyDefinition.PROPERTY_TITLE, 2073 false, 2074 locale).getValue(); 2075 String description = cms.readPropertyObject( 2076 modelResource, 2077 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 2078 false, 2079 locale).getValue(); 2080 2081 boolean editable = false; 2082 try { 2083 CmsResource freshModelResource = cms.readResource( 2084 modelResource.getStructureId(), 2085 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2086 editable = cms.hasPermissions( 2087 freshModelResource, 2088 CmsPermissionSet.ACCESS_WRITE, 2089 false, 2090 CmsResourceFilter.DEFAULT); 2091 } catch (CmsException e) { 2092 LOG.warn(e.getLocalizedMessage(), e); 2093 } 2094 CmsNewResourceInfo info = new CmsNewResourceInfo( 2095 typeId, 2096 name, 2097 title, 2098 description, 2099 modelResource.getStructureId(), 2100 editable, 2101 description); 2102 info.setBigIconClasses(CmsIconUtil.getIconClasses(name, null, false)); 2103 Float navpos = null; 2104 try { 2105 CmsProperty navposProp = cms.readPropertyObject(modelResource, CmsPropertyDefinition.PROPERTY_NAVPOS, true); 2106 String navposStr = navposProp.getValue(); 2107 if (navposStr != null) { 2108 try { 2109 navpos = Float.valueOf(navposStr); 2110 } catch (NumberFormatException e) { 2111 // noop 2112 } 2113 } 2114 } catch (CmsException e) { 2115 LOG.warn(e.getLocalizedMessage(), e); 2116 } 2117 2118 info.setNavPos(navpos); 2119 info.setDate( 2120 CmsDateUtil.getDate(new Date(modelResource.getDateLastModified()), DateFormat.LONG, getWorkplaceLocale())); 2121 info.setVfsPath(modelResource.getRootPath()); 2122 return info; 2123 } 2124 2125 /** 2126 * Creates a resource type info bean for a given resource type.<p> 2127 * 2128 * @param resType the resource type 2129 * @param copyResource the structure id of the copy resource 2130 * 2131 * @return the resource type info bean 2132 */ 2133 @SuppressWarnings("deprecation") 2134 private CmsNewResourceInfo createResourceTypeInfo(I_CmsResourceType resType, CmsResource copyResource) { 2135 2136 String name = resType.getTypeName(); 2137 Locale locale = getWorkplaceLocale(); 2138 String subtitle = CmsWorkplaceMessages.getResourceTypeDescription(locale, name); 2139 if (CmsStringUtil.isEmptyOrWhitespaceOnly(subtitle)) { 2140 subtitle = CmsWorkplaceMessages.getResourceTypeName(locale, name); 2141 } 2142 if (copyResource != null) { 2143 CmsNewResourceInfo info = new CmsNewResourceInfo( 2144 copyResource.getTypeId(), 2145 name, 2146 CmsWorkplaceMessages.getResourceTypeName(locale, name), 2147 CmsWorkplaceMessages.getResourceTypeDescription(locale, name), 2148 copyResource.getStructureId(), 2149 false, 2150 subtitle); 2151 info.setBigIconClasses(CmsIconUtil.getIconClasses(name, null, false)); 2152 return info; 2153 } else { 2154 CmsNewResourceInfo info = new CmsNewResourceInfo( 2155 resType.getTypeId(), 2156 name, 2157 CmsWorkplaceMessages.getResourceTypeName(locale, name), 2158 CmsWorkplaceMessages.getResourceTypeDescription(locale, name), 2159 null, 2160 false, 2161 subtitle); 2162 info.setBigIconClasses(CmsIconUtil.getIconClasses(name, null, false)); 2163 return info; 2164 } 2165 } 2166 2167 /** 2168 * Helper method for creating the .content folder of a sub-sitemap.<p> 2169 * 2170 * @param cms the current CMS context 2171 * @param subSitemapFolder the sub-sitemap folder in which the .content folder should be created 2172 * 2173 * @throws CmsException if something goes wrong 2174 */ 2175 @SuppressWarnings("deprecation") 2176 private void createSitemapContentFolder(CmsObject cms, CmsResource subSitemapFolder) throws CmsException { 2177 2178 String sitePath = cms.getSitePath(subSitemapFolder); 2179 String folderName = CmsStringUtil.joinPaths(sitePath, CmsADEManager.CONTENT_FOLDER_NAME + "/"); 2180 String sitemapConfigName = CmsStringUtil.joinPaths(folderName, CmsADEManager.CONFIG_FILE_NAME); 2181 if (!cms.existsResource(folderName)) { 2182 cms.createResource( 2183 folderName, 2184 OpenCms.getResourceManager().getResourceType(CmsADEManager.CONFIG_FOLDER_TYPE)); 2185 } 2186 I_CmsResourceType configType = OpenCms.getResourceManager().getResourceType(CmsADEManager.CONFIG_TYPE); 2187 if (cms.existsResource(sitemapConfigName)) { 2188 CmsResource configFile = cms.readResource(sitemapConfigName); 2189 if (configFile.getTypeId() != configType.getTypeId()) { 2190 throw new CmsException( 2191 Messages.get().container( 2192 Messages.ERR_CREATING_SUB_SITEMAP_WRONG_CONFIG_FILE_TYPE_2, 2193 sitemapConfigName, 2194 CmsADEManager.CONFIG_TYPE)); 2195 } 2196 } else { 2197 cms.createResource( 2198 sitemapConfigName, 2199 OpenCms.getResourceManager().getResourceType(CmsADEManager.CONFIG_TYPE)); 2200 } 2201 2202 } 2203 2204 /** 2205 * Deletes a resource according to the change data.<p> 2206 * 2207 * @param change the change data 2208 * 2209 * @return CmsClientSitemapEntry always null 2210 * 2211 * 2212 * @throws CmsException if something goes wrong 2213 */ 2214 private CmsClientSitemapEntry delete(CmsSitemapChange change) throws CmsException { 2215 2216 CmsObject cms = getCmsObject(); 2217 CmsResource resource = cms.readResource(change.getEntryId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2218 ensureLock(resource); 2219 cms.deleteResource(cms.getSitePath(resource), CmsResource.DELETE_PRESERVE_SIBLINGS); 2220 tryUnlock(resource); 2221 return null; 2222 } 2223 2224 /** 2225 * Generates a client side lock info object representing the current lock state of the given resource.<p> 2226 * 2227 * @param resource the resource 2228 * 2229 * @return the client lock 2230 * 2231 * @throws CmsException if something goes wrong 2232 */ 2233 private CmsClientLock generateClientLock(CmsResource resource) throws CmsException { 2234 2235 CmsObject cms = getCmsObject(); 2236 CmsLock lock = cms.getLock(resource); 2237 CmsClientLock clientLock = new CmsClientLock(); 2238 clientLock.setLockType(CmsClientLock.LockType.valueOf(lock.getType().getMode())); 2239 CmsUUID ownerId = lock.getUserId(); 2240 if (!lock.isUnlocked() && (ownerId != null)) { 2241 clientLock.setLockOwner(cms.readUser(ownerId).getDisplayName(cms, cms.getRequestContext().getLocale())); 2242 clientLock.setOwnedByUser(cms.getRequestContext().getCurrentUser().getId().equals(ownerId)); 2243 } 2244 return clientLock; 2245 } 2246 2247 /** 2248 * Generates a list of property object to save to the sitemap entry folder to apply the given change.<p> 2249 * 2250 * @param change the change 2251 * @param entryFolder the entry folder 2252 * 2253 * @return the property objects 2254 */ 2255 private List<CmsProperty> generateInheritProperties(CmsSitemapChange change, CmsResource entryFolder) { 2256 2257 List<CmsProperty> result = new ArrayList<CmsProperty>(); 2258 Map<String, CmsClientProperty> clientProps = change.getOwnInternalProperties(); 2259 boolean hasTitle = false; 2260 if (clientProps != null) { 2261 for (CmsClientProperty clientProp : clientProps.values()) { 2262 if (CmsPropertyDefinition.PROPERTY_TITLE.equals(clientProp.getName())) { 2263 hasTitle = true; 2264 } 2265 CmsProperty prop = new CmsProperty( 2266 clientProp.getName(), 2267 clientProp.getStructureValue(), 2268 clientProp.getResourceValue()); 2269 result.add(prop); 2270 } 2271 } 2272 if (!hasTitle) { 2273 result.add(new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, change.getName(), null)); 2274 } 2275 return result; 2276 } 2277 2278 /** 2279 * Generates a list of property object to save to the sitemap entry resource to apply the given change.<p> 2280 * 2281 * @param change the change 2282 * 2283 * @return the property objects 2284 */ 2285 private List<CmsProperty> generateOwnProperties(CmsSitemapChange change) { 2286 2287 List<CmsProperty> result = new ArrayList<CmsProperty>(); 2288 2289 Map<String, CmsClientProperty> clientProps = change.getDefaultFileProperties(); 2290 boolean hasTitle = false; 2291 if (clientProps != null) { 2292 for (CmsClientProperty clientProp : clientProps.values()) { 2293 if (CmsPropertyDefinition.PROPERTY_TITLE.equals(clientProp.getName())) { 2294 hasTitle = true; 2295 } 2296 CmsProperty prop = new CmsProperty( 2297 clientProp.getName(), 2298 clientProp.getStructureValue(), 2299 clientProp.getResourceValue()); 2300 result.add(prop); 2301 } 2302 } 2303 if (!hasTitle) { 2304 result.add(new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, change.getName(), null)); 2305 } 2306 return result; 2307 } 2308 2309 /** 2310 * Generates a list of property values inherited to the site-map root entry.<p> 2311 * 2312 * @param rootPath the root entry name 2313 * 2314 * @return the list of property values inherited to the site-map root entry 2315 * 2316 * @throws CmsException if something goes wrong reading the properties 2317 */ 2318 private Map<String, CmsClientProperty> generateParentProperties(String rootPath) throws CmsException { 2319 2320 CmsObject cms = getCmsObject(); 2321 if (rootPath == null) { 2322 rootPath = cms.getRequestContext().addSiteRoot("/"); 2323 } 2324 CmsObject rootCms = OpenCms.initCmsObject(cms); 2325 rootCms.getRequestContext().setSiteRoot(""); 2326 String parentRootPath = CmsResource.getParentFolder(rootPath); 2327 2328 Map<String, CmsClientProperty> result = new HashMap<String, CmsClientProperty>(); 2329 if (parentRootPath != null) { 2330 List<CmsProperty> props = rootCms.readPropertyObjects(parentRootPath, true); 2331 for (CmsProperty prop : props) { 2332 CmsClientProperty clientProp = createClientProperty(prop, true); 2333 result.put(clientProp.getName(), clientProp); 2334 } 2335 } 2336 return result; 2337 } 2338 2339 /** 2340 * Returns the sitemap children for the given path with all descendants up to the given level or to the given target path, ie. 2341 * <dl><dt>levels=1 <dd>only children<dt>levels=2<dd>children and great children</dl> 2342 * and so on.<p> 2343 * 2344 * @param root the site relative root 2345 * @param levels the levels to recurse 2346 * @param targetPath the target path 2347 * 2348 * @return the sitemap children 2349 */ 2350 private List<CmsClientSitemapEntry> getChildren(String root, int levels, String targetPath) { 2351 2352 List<CmsClientSitemapEntry> children = new ArrayList<CmsClientSitemapEntry>(); 2353 int i = 0; 2354 for (CmsJspNavElement navElement : getNavBuilder().getNavigationForFolder( 2355 root, 2356 Visibility.all, 2357 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 2358 try { 2359 CmsClientSitemapEntry child = toClientEntry(navElement, false); 2360 if (child != null) { 2361 child.setPosition(i); 2362 children.add(child); 2363 int nextLevels = levels; 2364 if ((nextLevels == 2) && (targetPath != null) && targetPath.startsWith(child.getSitePath())) { 2365 nextLevels = 3; 2366 } 2367 if (child.isFolderType() && ((nextLevels > 1) || (nextLevels == -1)) && !isSubSitemap(navElement)) { 2368 2369 child.setSubEntries(getChildren(child.getSitePath(), nextLevels - 1, targetPath), null); 2370 child.setChildrenLoadedInitially(true); 2371 } 2372 i++; 2373 } 2374 } catch (CmsException e) { 2375 LOG.error("Could not read sitemap entry.", e); 2376 } 2377 } 2378 return children; 2379 } 2380 2381 /** 2382 * Returns the clipboard data from the current user.<p> 2383 * 2384 * @return the clipboard data 2385 */ 2386 private CmsSitemapClipboardData getClipboardData() { 2387 2388 CmsSitemapClipboardData result = new CmsSitemapClipboardData(); 2389 result.setModifications(getModifiedList()); 2390 result.setDeletions(getDeletedList()); 2391 return result; 2392 } 2393 2394 /** 2395 * Returns the deleted list from the current user.<p> 2396 * 2397 * @return the deleted list 2398 */ 2399 private LinkedHashMap<CmsUUID, CmsClientSitemapEntry> getDeletedList() { 2400 2401 CmsObject cms = getCmsObject(); 2402 CmsUser user = cms.getRequestContext().getCurrentUser(); 2403 Object obj = user.getAdditionalInfo(ADDINFO_ADE_DELETED_LIST); 2404 LinkedHashMap<CmsUUID, CmsClientSitemapEntry> result = new LinkedHashMap<CmsUUID, CmsClientSitemapEntry>(); 2405 if (obj instanceof String) { 2406 try { 2407 JSONArray array = new JSONArray((String)obj); 2408 for (int i = 0; i < array.length(); i++) { 2409 try { 2410 CmsUUID delId = new CmsUUID(array.getString(i)); 2411 CmsResource res = cms.readResource(delId, CmsResourceFilter.ALL); 2412 if (res.getState().isDeleted()) { 2413 // make sure resource is still deleted 2414 CmsClientSitemapEntry delEntry = new CmsClientSitemapEntry(); 2415 delEntry.setSitePath(cms.getSitePath(res)); 2416 delEntry.setOwnProperties(getClientProperties(cms, res, false)); 2417 delEntry.setName(res.getName()); 2418 delEntry.setVfsPath(cms.getSitePath(res)); 2419 delEntry.setResourceTypeName( 2420 OpenCms.getResourceManager().getResourceType(res).getTypeName()); 2421 delEntry.setEntryType( 2422 res.isFolder() 2423 ? EntryType.folder 2424 : isRedirectType(res.getTypeId()) ? EntryType.redirect : EntryType.leaf); 2425 delEntry.setNavModeIcon( 2426 CmsIconUtil.getIconClasses( 2427 delEntry.getResourceTypeName(), 2428 delEntry.getVfsPath(), 2429 false)); 2430 delEntry.setId(delId); 2431 result.put(delId, delEntry); 2432 } 2433 } catch (Throwable e) { 2434 // should never happen, catches wrong or no longer existing values 2435 LOG.warn(e.getLocalizedMessage()); 2436 } 2437 } 2438 } catch (Throwable e) { 2439 // should never happen, catches json parsing 2440 LOG.warn(e.getLocalizedMessage()); 2441 } 2442 } 2443 return result; 2444 } 2445 2446 /** 2447 * Gets the container name for function detail elements depending on the parent folder.<p> 2448 * 2449 * @param parent the parent folder 2450 * @return the name of the function detail container 2451 */ 2452 private String getFunctionDetailContainerName(CmsResource parent) { 2453 2454 CmsObject cms = getCmsObject(); 2455 String notFound = null; 2456 String containerInfo = OpenCms.getTemplateContextManager().readPropertyFromTemplate( 2457 cms, 2458 parent, 2459 CmsPropertyDefinition.PROPERTY_CONTAINER_INFO, 2460 notFound); 2461 if (containerInfo == notFound) { 2462 return null; 2463 } 2464 Map<String, String> attrs = CmsStringUtil.splitAsMap(containerInfo, "|", "="); //$NON-NLS-2$ 2465 String functionDetailContainerName = attrs.get(KEY_FUNCTION_DETAIL); 2466 return functionDetailContainerName; 2467 } 2468 2469 /** 2470 * Returns the galleries of the given sub site for the requested gallery type.<p> 2471 * 2472 * @param entryPointUri the sub site entry point 2473 * @param galleryType the gallery type 2474 * @param subSitePaths the sub site paths 2475 * 2476 * @return the gallery folder entries 2477 * 2478 * @throws CmsException if reading the resources fails 2479 */ 2480 private List<CmsGalleryFolderEntry> getGalleriesForType( 2481 String entryPointUri, 2482 CmsGalleryType galleryType, 2483 List<String> subSitePaths) 2484 throws CmsException { 2485 2486 List<CmsGalleryFolderEntry> galleries = new ArrayList<CmsGalleryFolderEntry>(); 2487 @SuppressWarnings("deprecation") 2488 List<CmsResource> galleryFolders = getCmsObject().readResources( 2489 entryPointUri, 2490 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryType.getTypeId())); 2491 for (CmsResource folder : galleryFolders) { 2492 try { 2493 if (!isInSubsite(subSitePaths, folder.getRootPath())) { 2494 galleries.add(readGalleryFolderEntry(folder, galleryType.getResourceType())); 2495 } 2496 } catch (CmsException ex) { 2497 log(ex.getLocalizedMessage(), ex); 2498 } 2499 } 2500 // create a tree structure 2501 Collections.sort(galleries, new Comparator<CmsGalleryFolderEntry>() { 2502 2503 public int compare(CmsGalleryFolderEntry o1, CmsGalleryFolderEntry o2) { 2504 2505 return o1.getSitePath().compareTo(o2.getSitePath()); 2506 } 2507 }); 2508 List<CmsGalleryFolderEntry> galleryTree = new ArrayList<CmsGalleryFolderEntry>(); 2509 for (int i = 0; i < galleries.size(); i++) { 2510 boolean isSubGallery = false; 2511 if (i > 0) { 2512 for (int j = i - 1; j >= 0; j--) { 2513 if (galleries.get(i).getSitePath().startsWith(galleries.get(j).getSitePath())) { 2514 galleries.get(j).addSubGallery(galleries.get(i)); 2515 isSubGallery = true; 2516 break; 2517 } 2518 } 2519 } 2520 if (!isSubGallery) { 2521 galleryTree.add(galleries.get(i)); 2522 } 2523 } 2524 return galleryTree; 2525 } 2526 2527 /** 2528 * Returns the modified list from the current user.<p> 2529 * 2530 * @return the modified list 2531 */ 2532 private LinkedHashMap<CmsUUID, CmsClientSitemapEntry> getModifiedList() { 2533 2534 CmsObject cms = getCmsObject(); 2535 CmsUser user = cms.getRequestContext().getCurrentUser(); 2536 Object obj = user.getAdditionalInfo(ADDINFO_ADE_MODIFIED_LIST); 2537 LinkedHashMap<CmsUUID, CmsClientSitemapEntry> result = new LinkedHashMap<CmsUUID, CmsClientSitemapEntry>(); 2538 if (obj instanceof String) { 2539 try { 2540 JSONArray array = new JSONArray((String)obj); 2541 for (int i = 0; i < array.length(); i++) { 2542 try { 2543 CmsUUID modId = new CmsUUID(array.getString(i)); 2544 CmsResource res = cms.readResource(modId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2545 String sitePath = cms.getSitePath(res); 2546 CmsJspNavElement navEntry = getNavBuilder().getNavigationForResource( 2547 sitePath, 2548 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2549 if (navEntry.isInNavigation()) { 2550 CmsClientSitemapEntry modEntry = toClientEntry(navEntry, false); 2551 result.put(modId, modEntry); 2552 } 2553 } catch (Throwable e) { 2554 // should never happen, catches wrong or no longer existing values 2555 LOG.warn(e.getLocalizedMessage()); 2556 } 2557 } 2558 } catch (Throwable e) { 2559 // should never happen, catches json parsing 2560 LOG.warn(e.getLocalizedMessage()); 2561 } 2562 } 2563 return result; 2564 } 2565 2566 /** 2567 * Returns a navigation builder reference.<p> 2568 * 2569 * @return the navigation builder 2570 */ 2571 private CmsJspNavBuilder getNavBuilder() { 2572 2573 if (m_navBuilder == null) { 2574 m_navBuilder = new CmsJspNavBuilder(getCmsObject()); 2575 } 2576 return m_navBuilder; 2577 } 2578 2579 /** 2580 * Returns the new resource infos.<p> 2581 * 2582 * @param cms the current CMS context 2583 * @param configData the configuration data from which the new resource infos should be read 2584 * @param locale locale used for retrieving descriptions/titles 2585 * 2586 * @return the new resource infos 2587 */ 2588 private List<CmsNewResourceInfo> getNewResourceInfos(CmsObject cms, CmsADEConfigData configData, Locale locale) { 2589 2590 List<CmsNewResourceInfo> result = new ArrayList<CmsNewResourceInfo>(); 2591 for (CmsModelPageConfig modelConfig : configData.getModelPages()) { 2592 try { 2593 CmsNewResourceInfo info = createNewResourceInfo(cms, modelConfig.getResource(), locale); 2594 info.setDefault(modelConfig.isDefault()); 2595 result.add(info); 2596 } catch (CmsException e) { 2597 LOG.debug(e.getLocalizedMessage(), e); 2598 } 2599 } 2600 Collections.sort(result, new Comparator<CmsNewResourceInfo>() { 2601 2602 public int compare(CmsNewResourceInfo a, CmsNewResourceInfo b) { 2603 2604 return ComparisonChain.start().compareTrueFirst(a.isDefault(), b.isDefault()).compare( 2605 a.getNavPos(), 2606 b.getNavPos(), 2607 Ordering.natural().nullsLast()).result(); 2608 } 2609 }); 2610 return result; 2611 } 2612 2613 /** 2614 * Gets the names of all available properties.<p> 2615 * 2616 * @param cms the CMS context 2617 * 2618 * @return the list of all property names 2619 * 2620 * @throws CmsException if something goes wrong 2621 */ 2622 private List<String> getPropertyNames(CmsObject cms) throws CmsException { 2623 2624 List<CmsPropertyDefinition> propDefs = cms.readAllPropertyDefinitions(); 2625 List<String> result = new ArrayList<String>(); 2626 for (CmsPropertyDefinition propDef : propDefs) { 2627 result.add(propDef.getName()); 2628 } 2629 return result; 2630 } 2631 2632 /** 2633 * Gets the resource type info beans for types for which new detail pages can be created.<p> 2634 * 2635 * @param cms the current CMS context 2636 * @param resourceTypeConfigs the resource type configurations 2637 * @param functionReferences the function references 2638 * @param dynamicFunctionRestriction 2639 * @param modelResource the model resource 2640 * @param locale the locale used for retrieving descriptions/titles 2641 * 2642 * @return the resource type info beans for types for which new detail pages can be created 2643 */ 2644 private List<CmsNewResourceInfo> getResourceTypeInfos( 2645 CmsObject cms, 2646 List<CmsResourceTypeConfig> resourceTypeConfigs, 2647 List<CmsFunctionReference> functionReferences, 2648 CmsFunctionAvailability dynamicFunctionAvailability, 2649 CmsResource modelResource, 2650 Locale locale) { 2651 2652 List<CmsNewResourceInfo> result = new ArrayList<CmsNewResourceInfo>(); 2653 CmsNewResourceInfo defaultPageInfo; 2654 if (modelResource != null) { 2655 defaultPageInfo = new CmsNewResourceInfo( 2656 modelResource.getTypeId(), 2657 CmsADEManager.DEFAULT_DETAILPAGE_TYPE, 2658 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_TITLE_0), 2659 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_DESCRIPTION_0), 2660 modelResource.getStructureId(), 2661 false, 2662 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_DESCRIPTION_0)); 2663 2664 } else { 2665 defaultPageInfo = new CmsNewResourceInfo( 2666 CmsResourceTypeXmlContainerPage.getContainerPageTypeIdSafely(), 2667 CmsADEManager.DEFAULT_DETAILPAGE_TYPE, 2668 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_TITLE_0), 2669 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_DESCRIPTION_0), 2670 null, 2671 false, 2672 Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_DEFAULT_DETAIL_PAGE_DESCRIPTION_0)); 2673 } 2674 2675 defaultPageInfo.setBigIconClasses( 2676 CmsIconUtil.getIconClasses(CmsResourceTypeXmlContainerPage.getStaticTypeName(), null, false)); 2677 result.add(defaultPageInfo); 2678 for (CmsResourceTypeConfig typeConfig : resourceTypeConfigs) { 2679 if (typeConfig.isDetailPagesDisabled()) { 2680 continue; 2681 } 2682 String typeName = typeConfig.getTypeName(); 2683 try { 2684 I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(typeName); 2685 result.add(createResourceTypeInfo(resourceType, modelResource)); 2686 } catch (CmsLoaderException e) { 2687 LOG.error(e.getLocalizedMessage(), e); 2688 } 2689 } 2690 for (CmsFunctionReference functionRef : functionReferences) { 2691 if (dynamicFunctionAvailability.isDefined()) { 2692 if (!dynamicFunctionAvailability.checkAvailable(functionRef.getStructureId())) { 2693 continue; 2694 } 2695 } 2696 try { 2697 CmsResource functionRes = cms.readResource(functionRef.getStructureId()); 2698 String description = cms.readPropertyObject( 2699 functionRes, 2700 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 2701 false).getValue(); 2702 String subtitle = description; 2703 try { 2704 CmsGallerySearchResult searchResult = CmsGallerySearch.searchById( 2705 cms, 2706 functionRef.getStructureId(), 2707 getWorkplaceLocale()); 2708 subtitle = searchResult.getDescription(); 2709 } catch (CmsException e) { 2710 LOG.warn(e.getLocalizedMessage(), e); 2711 } 2712 2713 CmsNewResourceInfo info = new CmsNewResourceInfo( 2714 modelResource.getTypeId(), 2715 CmsDetailPageInfo.FUNCTION_PREFIX + functionRef.getName(), 2716 functionRef.getName(), 2717 description, 2718 modelResource.getStructureId(), 2719 false, 2720 subtitle); 2721 info.setCreateParameter(functionRef.getStructureId().toString()); 2722 info.setIsFunction(true); 2723 info.setBigIconClasses( 2724 CmsIconUtil.getIconClasses(CmsXmlDynamicFunctionHandler.TYPE_FUNCTION, null, false)); 2725 result.add(info); 2726 } catch (CmsVfsResourceNotFoundException e) { 2727 LOG.warn(e.getLocalizedMessage(), e); 2728 } catch (CmsException e) { 2729 LOG.error(e.getLocalizedMessage(), e); 2730 } 2731 } 2732 return result; 2733 } 2734 2735 /** 2736 * Reeds the site root entry.<p> 2737 * 2738 * @param rootPath the root path of the sitemap root 2739 * @param targetPath the target path to open 2740 * 2741 * @return the site root entry 2742 * 2743 * @throws CmsSecurityException in case of insufficient permissions 2744 * @throws CmsException if something goes wrong 2745 */ 2746 private CmsClientSitemapEntry getRootEntry(String rootPath, String targetPath) 2747 throws CmsSecurityException, CmsException { 2748 2749 String sitePath = "/"; 2750 if ((rootPath != null)) { 2751 sitePath = getCmsObject().getRequestContext().removeSiteRoot(rootPath); 2752 } 2753 CmsJspNavElement navElement = getNavBuilder().getNavigationForResource( 2754 sitePath, 2755 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2756 CmsClientSitemapEntry result = toClientEntry(navElement, true); 2757 if (result != null) { 2758 result.setPosition(0); 2759 result.setChildrenLoadedInitially(true); 2760 result.setSubEntries(getChildren(sitePath, 2, targetPath), null); 2761 } 2762 return result; 2763 } 2764 2765 /** 2766 * Returns the sitemap info for the given base path.<p> 2767 * 2768 * @param basePath the base path 2769 * 2770 * @return the sitemap info 2771 * 2772 * @throws CmsException if something goes wrong reading the resources 2773 */ 2774 private CmsSitemapInfo getSitemapInfo(String basePath) throws CmsException { 2775 2776 CmsObject cms = getCmsObject(); 2777 CmsResource baseFolder = null; 2778 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(basePath)) { 2779 baseFolder = cms.readResource( 2780 cms.getRequestContext().removeSiteRoot(basePath), 2781 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2782 } else { 2783 // in case of an empty base path, use base folder of the current site 2784 basePath = "/"; 2785 baseFolder = cms.readResource("/"); 2786 } 2787 CmsResource defaultFile = cms.readDefaultFile(baseFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2788 String title = cms.readPropertyObject(baseFolder, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(); 2789 if (CmsStringUtil.isEmptyOrWhitespaceOnly(title) && (defaultFile != null)) { 2790 title = cms.readPropertyObject(defaultFile, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(); 2791 } 2792 String description = cms.readPropertyObject( 2793 baseFolder, 2794 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 2795 false).getValue(); 2796 if (CmsStringUtil.isEmptyOrWhitespaceOnly(description) && (defaultFile != null)) { 2797 description = cms.readPropertyObject( 2798 defaultFile, 2799 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 2800 false).getValue(); 2801 } 2802 return new CmsSitemapInfo( 2803 cms.getRequestContext().getCurrentProject().getName(), 2804 description, 2805 OpenCms.getLocaleManager().getDefaultLocale(cms, baseFolder).toString(), 2806 OpenCms.getSiteManager().getCurrentSite(cms).getUrl() 2807 + OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, basePath), 2808 title); 2809 } 2810 2811 /** 2812 * Gets the default type id for subsitemap folders.<p> 2813 * 2814 * @return the default type id for subsitemap folders 2815 * 2816 * @throws CmsRpcException in case of an error 2817 */ 2818 @SuppressWarnings("deprecation") 2819 private int getSubsitemapType() throws CmsRpcException { 2820 2821 try { 2822 return OpenCms.getResourceManager().getResourceType( 2823 CmsResourceTypeFolderSubSitemap.TYPE_SUBSITEMAP).getTypeId(); 2824 } catch (CmsLoaderException e) { 2825 error(e); 2826 } 2827 return CmsResourceTypeUnknownFolder.getStaticTypeId(); 2828 } 2829 2830 /** 2831 * Returns the workplace locale for the current user.<p> 2832 * 2833 * @return the workplace locale 2834 */ 2835 private Locale getWorkplaceLocale() { 2836 2837 Locale result = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject()); 2838 if (result == null) { 2839 result = CmsLocaleManager.getDefaultLocale(); 2840 } 2841 if (result == null) { 2842 result = Locale.getDefault(); 2843 } 2844 return result; 2845 } 2846 2847 /** 2848 * Checks whether the sitemap change has default file changes.<p> 2849 * 2850 * @param change a sitemap change 2851 * @return true if the change would change the default file 2852 */ 2853 private boolean hasDefaultFileChanges(CmsSitemapChange change) { 2854 2855 return (change.getDefaultFileId() != null) && !change.isNew(); 2856 } 2857 2858 /** 2859 * Checks whether the sitemap change has changes for the sitemap entry resource.<p> 2860 * 2861 * @param change the sitemap change 2862 * @return true if the change would change the original sitemap entry resource 2863 */ 2864 private boolean hasOwnChanges(CmsSitemapChange change) { 2865 2866 return !change.isNew(); 2867 } 2868 2869 /** 2870 * Checks whether a resource is a default file of a folder.<p> 2871 * 2872 * @param resource the resource to check 2873 * 2874 * @return true if the resource is the default file of a folder 2875 * 2876 * @throws CmsException if something goes wrong 2877 */ 2878 private boolean isDefaultFile(CmsResource resource) throws CmsException { 2879 2880 CmsObject cms = getCmsObject(); 2881 if (resource.isFolder()) { 2882 return false; 2883 } 2884 2885 CmsResource parent = cms.readResource( 2886 CmsResource.getParentFolder(cms.getSitePath(resource)), 2887 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2888 CmsResource defaultFile = cms.readDefaultFile(parent, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 2889 return resource.equals(defaultFile); 2890 } 2891 2892 /** 2893 * Checks if the toolbar should be displayed.<p> 2894 * 2895 * @param request the current request to get the default locale from 2896 * 2897 * @return <code>true</code> if the toolbar should be displayed 2898 */ 2899 private boolean isDisplayToolbar(HttpServletRequest request) { 2900 2901 // display the toolbar by default 2902 boolean displayToolbar = true; 2903 if (CmsHistoryResourceHandler.isHistoryRequest(request)) { 2904 // we do not want to display the toolbar in case of an historical request 2905 displayToolbar = false; 2906 } 2907 return displayToolbar; 2908 } 2909 2910 /** 2911 * Returns if the given path is located below one of the given sub site paths.<p> 2912 * 2913 * @param subSitePaths the sub site root paths 2914 * @param path the root path to check 2915 * 2916 * @return <code>true</code> if the given path is located below one of the given sub site paths 2917 */ 2918 private boolean isInSubsite(List<String> subSitePaths, String path) { 2919 2920 boolean result = false; 2921 for (String subSite : subSitePaths) { 2922 if (path.startsWith(subSite)) { 2923 result = true; 2924 break; 2925 } 2926 } 2927 return result; 2928 } 2929 2930 /** 2931 * Returns if the given type id matches the xml-redirect resource type.<p> 2932 * 2933 * @param typeId the resource type id 2934 * 2935 * @return <code>true</code> if the given type id matches the xml-redirect resource type 2936 */ 2937 @SuppressWarnings("deprecation") 2938 private boolean isRedirectType(int typeId) { 2939 2940 try { 2941 return typeId == OpenCms.getResourceManager().getResourceType(RECOURCE_TYPE_NAME_REDIRECT).getTypeId(); 2942 } catch (Exception e) { 2943 return false; 2944 } 2945 } 2946 2947 /** 2948 * Returns if the given nav-element resembles a sub-sitemap entry-point.<p> 2949 * 2950 * @param navElement the nav-element 2951 * 2952 * @return <code>true</code> if the given nav-element resembles a sub-sitemap entry-point.<p> 2953 */ 2954 private boolean isSubSitemap(CmsJspNavElement navElement) { 2955 2956 return CmsResourceTypeFolderSubSitemap.isSubSitemap(navElement.getResource()); 2957 } 2958 2959 /** 2960 * Checks if the given open path is valid.<p> 2961 * 2962 * @param cms the cms context 2963 * @param openPath the open path 2964 * 2965 * @return <code>true</code> if the given open path is valid 2966 */ 2967 private boolean isValidOpenPath(CmsObject cms, String openPath) { 2968 2969 if (CmsStringUtil.isEmptyOrWhitespaceOnly(openPath)) { 2970 return false; 2971 } 2972 if (!cms.existsResource(openPath)) { 2973 // in case of a detail-page check the parent folder 2974 String parent = CmsResource.getParentFolder(openPath); 2975 if (CmsStringUtil.isEmptyOrWhitespaceOnly(parent) || !cms.existsResource(parent)) { 2976 return false; 2977 } 2978 } 2979 return true; 2980 } 2981 2982 /** 2983 * Returns if the given return code is valid.<p> 2984 * 2985 * @param returnCode the return code to check 2986 * 2987 * @return <code>true</code> if the return code is valid 2988 */ 2989 private boolean isValidReturnCode(String returnCode) { 2990 2991 if (CmsStringUtil.isEmptyOrWhitespaceOnly(returnCode)) { 2992 return false; 2993 } 2994 int pos = returnCode.indexOf(":"); 2995 if (pos > 0) { 2996 return CmsUUID.isValidUUID(returnCode.substring(0, pos)) 2997 && CmsUUID.isValidUUID(returnCode.substring(pos + 1)); 2998 } else { 2999 return CmsUUID.isValidUUID(returnCode); 3000 } 3001 } 3002 3003 /** 3004 * Applys the given changes to the entry.<p> 3005 * 3006 * @param change the change to apply 3007 * 3008 * @throws CmsException if something goes wrong 3009 */ 3010 private void modifyEntry(CmsSitemapChange change) throws CmsException { 3011 3012 CmsObject cms = getCmsObject(); 3013 CmsResource entryPage = null; 3014 CmsResource entryFolder = null; 3015 3016 CmsResource ownRes = null; 3017 CmsResource defaultFileRes = null; 3018 try { 3019 // lock all resources necessary first to avoid doing changes only half way through 3020 3021 if (hasOwnChanges(change)) { 3022 ownRes = cms.readResource(change.getEntryId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3023 boolean shallow = !change.hasChangedName() && !change.hasChangedPosition() && !change.hasNewParent(); 3024 3025 ensureLock(ownRes, shallow); 3026 } 3027 3028 if (hasDefaultFileChanges(change)) { 3029 defaultFileRes = cms.readResource(change.getDefaultFileId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3030 ensureLock(defaultFileRes, false); 3031 } 3032 3033 if ((ownRes != null) && ownRes.isFolder()) { 3034 entryFolder = ownRes; 3035 } 3036 3037 if ((ownRes != null) && ownRes.isFile()) { 3038 entryPage = ownRes; 3039 } 3040 3041 if (defaultFileRes != null) { 3042 entryPage = defaultFileRes; 3043 } 3044 3045 if (change.isLeafType()) { 3046 entryFolder = entryPage; 3047 } 3048 3049 String moveSrc = null; 3050 String moveDest = null; 3051 3052 if (entryFolder != null) { 3053 if (change.hasNewParent() || change.hasChangedName()) { 3054 String destinationPath; 3055 if (change.hasNewParent()) { 3056 CmsResource futureParent = cms.readResource( 3057 change.getParentId(), 3058 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3059 destinationPath = CmsStringUtil.joinPaths(cms.getSitePath(futureParent), change.getName()); 3060 } else { 3061 destinationPath = CmsStringUtil.joinPaths( 3062 CmsResource.getParentFolder(cms.getSitePath(entryFolder)), 3063 change.getName()); 3064 } 3065 if (change.isLeafType() && destinationPath.endsWith("/")) { 3066 destinationPath = destinationPath.substring(0, destinationPath.length() - 1); 3067 } 3068 // only if the site-path has really changed 3069 if (!CmsFileUtil.removeTrailingSeparator(cms.getSitePath(entryFolder)).equals( 3070 CmsFileUtil.removeTrailingSeparator(destinationPath))) { 3071 moveSrc = cms.getSitePath(entryFolder); 3072 moveDest = CmsFileUtil.removeTrailingSeparator(destinationPath); 3073 } 3074 } 3075 } 3076 if ((moveDest != null) && cms.existsResource(moveDest, CmsResourceFilter.IGNORE_EXPIRATION)) { 3077 throw new CmsVfsResourceAlreadyExistsException( 3078 org.opencms.db.generic.Messages.get().container( 3079 org.opencms.db.generic.Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1, 3080 moveDest)); 3081 } 3082 3083 updateProperties(cms, ownRes, defaultFileRes, change.getPropertyChanges()); 3084 if (change.hasChangedPosition()) { 3085 updateNavPos(ownRes, change); 3086 } 3087 3088 if (moveDest != null) { 3089 cms.moveResource(moveSrc, moveDest); 3090 } 3091 entryFolder = cms.readResource(entryFolder.getStructureId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3092 3093 } finally { 3094 if (entryPage != null) { 3095 tryUnlock(entryPage); 3096 } 3097 if (entryFolder != null) { 3098 tryUnlock(entryFolder); 3099 } 3100 } 3101 } 3102 3103 /** 3104 * Reads the gallery folder properties.<p> 3105 * 3106 * @param folder the folder resource 3107 * @param typeName the resource type name 3108 * 3109 * @return the folder entry data 3110 * 3111 * @throws CmsException if the folder properties can not be read 3112 */ 3113 private CmsGalleryFolderEntry readGalleryFolderEntry(CmsResource folder, String typeName) throws CmsException { 3114 3115 CmsObject cms = getCmsObject(); 3116 CmsGalleryFolderEntry folderEntry = new CmsGalleryFolderEntry(); 3117 folderEntry.setResourceType(typeName); 3118 folderEntry.setSitePath(cms.getSitePath(folder)); 3119 folderEntry.setStructureId(folder.getStructureId()); 3120 folderEntry.setOwnProperties(getClientProperties(cms, folder, false)); 3121 folderEntry.setIconClasses(CmsIconUtil.getIconClasses(typeName, null, false)); 3122 return folderEntry; 3123 } 3124 3125 /** 3126 * Helper method for removing all locales except one from a container page.<p> 3127 * 3128 * @param page the container page to proces 3129 * @param localeToKeep the locale which should be kept 3130 * 3131 * @throws CmsXmlException if something goes wrong 3132 */ 3133 private void removeAllLocalesExcept(CmsXmlContainerPage page, Locale localeToKeep) throws CmsXmlException { 3134 3135 List<Locale> locales = page.getLocales(); 3136 for (Locale locale : locales) { 3137 if (!locale.equals(localeToKeep)) { 3138 page.removeLocale(locale); 3139 } 3140 } 3141 } 3142 3143 /** 3144 * Applys the given remove change.<p> 3145 * 3146 * @param change the change to apply 3147 * 3148 * @return the changed client sitemap entry or <code>null</code> 3149 * 3150 * @throws CmsException if something goes wrong 3151 */ 3152 private CmsSitemapChange removeEntryFromNavigation(CmsSitemapChange change) throws CmsException { 3153 3154 CmsObject cms = getCmsObject(); 3155 CmsResource entryFolder = cms.readResource(change.getEntryId(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3156 ensureLock(entryFolder); 3157 List<CmsProperty> properties = new ArrayList<CmsProperty>(); 3158 properties.add( 3159 new CmsProperty( 3160 CmsPropertyDefinition.PROPERTY_NAVTEXT, 3161 CmsProperty.DELETE_VALUE, 3162 CmsProperty.DELETE_VALUE)); 3163 properties.add( 3164 new CmsProperty(CmsPropertyDefinition.PROPERTY_NAVPOS, CmsProperty.DELETE_VALUE, CmsProperty.DELETE_VALUE)); 3165 cms.writePropertyObjects(cms.getSitePath(entryFolder), properties); 3166 tryUnlock(entryFolder); 3167 return change; 3168 } 3169 3170 /** 3171 * Saves the detail page information of a sitemap to the sitemap's configuration file.<p> 3172 * 3173 * @param detailPages saves the detailpage configuration 3174 * @param resource the configuration file resource 3175 * @param newId the structure id to use for new detail page entries 3176 * @param updateEntry the new detail page entry 3177 * 3178 * @throws CmsException if something goes wrong 3179 */ 3180 private void saveDetailPages( 3181 List<CmsDetailPageInfo> detailPages, 3182 CmsResource resource, 3183 CmsUUID newId, 3184 CmsClientSitemapEntry updateEntry) 3185 throws CmsException { 3186 3187 CmsObject cms = getCmsObject(); 3188 if (updateEntry != null) { 3189 for (CmsDetailPageInfo info : detailPages) { 3190 if (info.getId() == null) { 3191 updateEntry.setDetailpageTypeName(info.getType()); 3192 break; 3193 } 3194 } 3195 } 3196 CmsDetailPageConfigurationWriter writer = new CmsDetailPageConfigurationWriter(cms, resource); 3197 writer.updateAndSave(detailPages, newId); 3198 } 3199 3200 /** 3201 * Saves the given clipboard data to the session.<p> 3202 * 3203 * @param clipboardData the clipboard data to save 3204 * 3205 * @throws CmsException if something goes wrong writing the user 3206 */ 3207 private void setClipboardData(CmsSitemapClipboardData clipboardData) throws CmsException { 3208 3209 CmsObject cms = getCmsObject(); 3210 CmsUser user = cms.getRequestContext().getCurrentUser(); 3211 if (clipboardData != null) { 3212 JSONArray modified = new JSONArray(); 3213 if (clipboardData.getModifications() != null) { 3214 for (CmsUUID id : clipboardData.getModifications().keySet()) { 3215 if (id != null) { 3216 modified.put(id.toString()); 3217 } 3218 } 3219 } 3220 user.setAdditionalInfo(ADDINFO_ADE_MODIFIED_LIST, modified.toString()); 3221 JSONArray deleted = new JSONArray(); 3222 if (clipboardData.getDeletions() != null) { 3223 for (CmsUUID id : clipboardData.getDeletions().keySet()) { 3224 if (id != null) { 3225 deleted.put(id.toString()); 3226 } 3227 } 3228 } 3229 user.setAdditionalInfo(ADDINFO_ADE_DELETED_LIST, deleted.toString()); 3230 cms.writeUser(user); 3231 } 3232 } 3233 3234 /** 3235 * Determines if the title property of the default file should be changed.<p> 3236 * 3237 * @param properties the current default file properties 3238 * @param folderNavtext the 'NavText' property of the folder 3239 * 3240 * @return <code>true</code> if the title property should be changed 3241 */ 3242 private boolean shouldChangeDefaultFileTitle(Map<String, CmsProperty> properties, CmsProperty folderNavtext) { 3243 3244 return (properties == null) 3245 || (properties.get(CmsPropertyDefinition.PROPERTY_TITLE) == null) 3246 || (properties.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue() == null) 3247 || ((folderNavtext != null) 3248 && properties.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue().equals(folderNavtext.getValue())); 3249 } 3250 3251 /** 3252 * Determines if the title property should be changed in case of a 'NavText' change.<p> 3253 * 3254 * @param properties the current resource properties 3255 * 3256 * @return <code>true</code> if the title property should be changed in case of a 'NavText' change 3257 */ 3258 private boolean shouldChangeTitle(Map<String, CmsProperty> properties) { 3259 3260 return (properties == null) 3261 || (properties.get(CmsPropertyDefinition.PROPERTY_TITLE) == null) 3262 || (properties.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue() == null) 3263 || ((properties.get(CmsPropertyDefinition.PROPERTY_NAVTEXT) != null) 3264 && properties.get(CmsPropertyDefinition.PROPERTY_TITLE).getValue().equals( 3265 properties.get(CmsPropertyDefinition.PROPERTY_NAVTEXT).getValue())); 3266 } 3267 3268 /** 3269 * 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. 3270 * 3271 * @param resource the resource 3272 * @param oldNavText the NavText before editing the properties 3273 * @param newNavText the NavText after editing the properties (may be the same as oldNavText) 3274 * @throws CmsException if something goes wrong 3275 */ 3276 private void synchTitleFromNavText(CmsResource resource, String oldNavText, String newNavText) throws CmsException { 3277 3278 CmsObject cms = getCmsObject(); 3279 3280 if (CmsStringUtil.isEmpty(newNavText)) { 3281 return; 3282 } 3283 CmsProperty titleProp = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, false); 3284 String title = titleProp.getValue(); 3285 if (title == null) { 3286 title = ""; 3287 } 3288 // We don't check if oldNavText is different from newNavText, because we also want the synchronization to happen 3289 // when we don't actually change the NavText, but e.g. when we change the title to an empty string. 3290 if (CmsStringUtil.isEmpty(title) || title.equals(oldNavText)) { 3291 if (!newNavText.equals(title)) { 3292 cms.writePropertyObjects( 3293 resource, 3294 Arrays.asList(new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, newNavText, null))); 3295 } 3296 } 3297 } 3298 3299 /** 3300 * Converts a jsp navigation element into a client sitemap entry.<p> 3301 * 3302 * @param navElement the jsp navigation element 3303 * @param isRoot true if the entry is a root entry 3304 * 3305 * @return the client sitemap entry 3306 * 3307 * @throws CmsException if something goes wrong 3308 */ 3309 private CmsClientSitemapEntry toClientEntry(CmsJspNavElement navElement, boolean isRoot) throws CmsException { 3310 3311 CmsResource entryPage = null; 3312 CmsObject cms = getCmsObject(); 3313 CmsClientSitemapEntry clientEntry = new CmsClientSitemapEntry(); 3314 CmsResource entryFolder = null; 3315 3316 CmsResource ownResource = navElement.getResource(); 3317 clientEntry.setResourceState(ownResource.getState()); 3318 CmsResource defaultFileResource = null; 3319 if (ownResource.isFolder() && !navElement.isNavigationLevel()) { 3320 defaultFileResource = cms.readDefaultFile(ownResource, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3321 } 3322 3323 Map<String, CmsClientProperty> ownProps = getClientProperties(cms, ownResource, false); 3324 3325 Map<String, CmsClientProperty> defaultFileProps = null; 3326 if (defaultFileResource != null) { 3327 defaultFileProps = getClientProperties(cms, defaultFileResource, false); 3328 clientEntry.setDefaultFileId(defaultFileResource.getStructureId()); 3329 clientEntry.setDefaultFileType( 3330 OpenCms.getResourceManager().getResourceType(defaultFileResource.getTypeId()).getTypeName()); 3331 clientEntry.setDefaultFileReleased(defaultFileResource.isReleasedAndNotExpired(System.currentTimeMillis())); 3332 } else { 3333 defaultFileProps = new HashMap<String, CmsClientProperty>(); 3334 } 3335 boolean isDefault = isDefaultFile(ownResource); 3336 clientEntry.setId(ownResource.getStructureId()); 3337 clientEntry.setResourceTypeId(ownResource.getTypeId()); 3338 clientEntry.setFolderDefaultPage(isDefault); 3339 if (navElement.getResource().isFolder()) { 3340 entryFolder = navElement.getResource(); 3341 entryPage = defaultFileResource; 3342 clientEntry.setName(entryFolder.getName()); 3343 if (entryPage == null) { 3344 entryPage = entryFolder; 3345 } 3346 if (!isRoot && isSubSitemap(navElement)) { 3347 clientEntry.setEntryType(EntryType.subSitemap); 3348 clientEntry.setDefaultFileType(null); 3349 } else if (navElement.isNavigationLevel()) { 3350 clientEntry.setEntryType(EntryType.navigationLevel); 3351 } 3352 CmsLock folderLock = cms.getLock(entryFolder); 3353 clientEntry.setHasForeignFolderLock( 3354 !folderLock.isUnlocked() && !folderLock.isOwnedBy(cms.getRequestContext().getCurrentUser())); 3355 if (!cms.getRequestContext().getCurrentProject().isOnlineProject()) { 3356 List<CmsResource> blockingChildren = cms.getBlockingLockedResources(entryFolder); 3357 clientEntry.setBlockingLockedChildren((blockingChildren != null) && !blockingChildren.isEmpty()); 3358 } 3359 } else { 3360 entryPage = navElement.getResource(); 3361 clientEntry.setName(entryPage.getName()); 3362 if (isRedirectType(entryPage.getTypeId())) { 3363 clientEntry.setEntryType(EntryType.redirect); 3364 CmsFile file = getCmsObject().readFile(entryPage); 3365 I_CmsXmlDocument content = CmsXmlContentFactory.unmarshal(getCmsObject(), file); 3366 I_CmsXmlContentValue linkValue = content.getValue( 3367 REDIRECT_LINK_TARGET_XPATH, 3368 getCmsObject().getRequestContext().getLocale()); 3369 String link = linkValue != null 3370 ? linkValue.getStringValue(getCmsObject()) 3371 : Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_REDIRECT_SUB_LEVEL_0); 3372 clientEntry.setRedirectTarget(link); 3373 } else { 3374 clientEntry.setEntryType(EntryType.leaf); 3375 } 3376 } 3377 if (entryPage.isFile()) { 3378 List<CmsAlias> aliases = OpenCms.getAliasManager().getAliasesForStructureId( 3379 getCmsObject(), 3380 entryPage.getStructureId()); 3381 if (!aliases.isEmpty()) { 3382 List<String> aliasList = new ArrayList<String>(); 3383 for (CmsAlias alias : aliases) { 3384 String aliasPath = alias.getAliasPath(); 3385 aliasList.add(aliasPath); 3386 } 3387 clientEntry.setAliases(aliasList); 3388 } 3389 } 3390 long dateExpired = navElement.getResource().getDateExpired(); 3391 if (dateExpired != CmsResource.DATE_EXPIRED_DEFAULT) { 3392 clientEntry.setDateExpired( 3393 CmsDateUtil.getDate(new Date(dateExpired), DateFormat.SHORT, getWorkplaceLocale())); 3394 } 3395 long dateReleased = navElement.getResource().getDateReleased(); 3396 if (dateReleased != CmsResource.DATE_RELEASED_DEFAULT) { 3397 clientEntry.setDateReleased( 3398 CmsDateUtil.getDate(new Date(dateReleased), DateFormat.SHORT, getWorkplaceLocale())); 3399 } 3400 clientEntry.setResleasedAndNotExpired( 3401 navElement.getResource().isReleasedAndNotExpired(System.currentTimeMillis())); 3402 String path = cms.getSitePath(entryPage); 3403 clientEntry.setVfsPath(path); 3404 clientEntry.setOwnProperties(ownProps); 3405 clientEntry.setDefaultFileProperties(defaultFileProps); 3406 clientEntry.setSitePath(entryFolder != null ? cms.getSitePath(entryFolder) : path); 3407 clientEntry.setLock(generateClientLock(entryPage)); 3408 clientEntry.setInNavigation(isRoot || navElement.isInNavigation()); 3409 String type = OpenCms.getResourceManager().getResourceType(ownResource).getTypeName(); 3410 clientEntry.setResourceTypeName(type); 3411 clientEntry.setVfsModeIcon(CmsIconUtil.getIconClasses(type, ownResource.getName(), false)); 3412 3413 if (!clientEntry.isSubSitemapType()) { 3414 if (clientEntry.isNavigationLevelType()) { 3415 clientEntry.setNavModeIcon(CmsIconUtil.ICON_NAV_LEVEL_BIG); 3416 } else if (defaultFileResource != null) { 3417 clientEntry.setNavModeIcon( 3418 CmsIconUtil.getIconClasses(clientEntry.getDefaultFileType(), defaultFileResource.getName(), false)); 3419 } 3420 } 3421 clientEntry.setPermissionInfo(OpenCms.getADEManager().getPermissionInfo(cms, ownResource, null)); 3422 return clientEntry; 3423 } 3424 3425 /** 3426 * Un-deletes a resource according to the change data.<p> 3427 * 3428 * @param change the change data 3429 * 3430 * @return the changed entry or <code>null</code> 3431 * 3432 * @throws CmsException if something goes wrong 3433 */ 3434 private CmsSitemapChange undelete(CmsSitemapChange change) throws CmsException { 3435 3436 CmsObject cms = getCmsObject(); 3437 CmsResource deleted = cms.readResource(change.getEntryId(), CmsResourceFilter.ALL); 3438 if (deleted.getState().isDeleted()) { 3439 ensureLock(deleted); 3440 cms.undeleteResource(getCmsObject().getSitePath(deleted), true); 3441 tryUnlock(deleted); 3442 } 3443 String parentPath = CmsResource.getParentFolder(cms.getSitePath(deleted)); 3444 CmsJspNavElement navElement = getNavBuilder().getNavigationForResource( 3445 parentPath, 3446 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 3447 CmsClientSitemapEntry entry = toClientEntry(navElement, navElement.isInNavigation()); 3448 entry.setSubEntries(getChildren(parentPath, 2, null), null); 3449 change.setUpdatedEntry(entry); 3450 change.setParentId(cms.readParentFolder(deleted.getStructureId()).getStructureId()); 3451 return change; 3452 } 3453 3454 /** 3455 * Updates the navigation position for a resource.<p> 3456 * 3457 * @param res the resource for which to update the navigation position 3458 * @param change the sitemap change 3459 * 3460 * @throws CmsException if something goes wrong 3461 */ 3462 private void updateNavPos(CmsResource res, CmsSitemapChange change) throws CmsException { 3463 3464 if (change.hasChangedPosition()) { 3465 applyNavigationChanges(change, res); 3466 } 3467 } 3468 3469 /** 3470 * Updates properties for a resource and possibly its detail page.<p> 3471 * 3472 * @param cms the CMS context 3473 * @param ownRes the resource 3474 * @param defaultFileRes the default file resource (possibly null) 3475 * @param propertyModifications the property modifications 3476 * 3477 * @throws CmsException if something goes wrong 3478 */ 3479 private void updateProperties( 3480 CmsObject cms, 3481 CmsResource ownRes, 3482 CmsResource defaultFileRes, 3483 List<CmsPropertyModification> propertyModifications) 3484 throws CmsException { 3485 3486 Map<String, CmsProperty> ownProps = getPropertiesByName(cms.readPropertyObjects(ownRes, false)); 3487 String oldNavText = null; 3488 if (ownProps.containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT)) { 3489 oldNavText = ownProps.get(CmsPropertyDefinition.PROPERTY_NAVTEXT).getValue(); 3490 } 3491 if (oldNavText == null) { 3492 oldNavText = ""; 3493 } 3494 Map<String, CmsProperty> defaultFileProps = Maps.newHashMap(); 3495 if (defaultFileRes != null) { 3496 defaultFileProps = getPropertiesByName(cms.readPropertyObjects(defaultFileRes, false)); 3497 } 3498 String newNavText = oldNavText; 3499 List<CmsProperty> ownPropertyChanges = new ArrayList<CmsProperty>(); 3500 List<CmsProperty> defaultFilePropertyChanges = new ArrayList<CmsProperty>(); 3501 for (CmsPropertyModification propMod : propertyModifications) { 3502 CmsProperty propToModify = null; 3503 Map<String, CmsProperty> propMap = null; 3504 List<CmsProperty> changeList = null; 3505 3506 if (ownRes.getStructureId().equals(propMod.getId())) { 3507 if (CmsPropertyDefinition.PROPERTY_NAVTEXT.equals(propMod.getName())) { 3508 newNavText = propMod.getValue(); 3509 } 3510 propMap = ownProps; 3511 changeList = ownPropertyChanges; 3512 } else { 3513 propMap = defaultFileProps; 3514 changeList = defaultFilePropertyChanges; 3515 } 3516 propToModify = propMap.get(propMod.getName()); 3517 if (propToModify == null) { 3518 propToModify = new CmsProperty(propMod.getName(), null, null); 3519 } 3520 String newValue = propMod.getValue(); 3521 if (newValue == null) { 3522 newValue = ""; 3523 } 3524 if (propMod.isStructureValue()) { 3525 propToModify.setStructureValue(newValue); 3526 } else { 3527 propToModify.setResourceValue(newValue); 3528 } 3529 changeList.add(propToModify); 3530 } 3531 3532 if (!ownPropertyChanges.isEmpty()) { 3533 cms.writePropertyObjects(ownRes, ownPropertyChanges); 3534 } 3535 if (!defaultFilePropertyChanges.isEmpty() && (defaultFileRes != null)) { 3536 cms.writePropertyObjects(defaultFileRes, defaultFilePropertyChanges); 3537 } 3538 synchTitleFromNavText(ownRes, oldNavText, newNavText); 3539 if (defaultFileRes != null) { 3540 synchTitleFromNavText(defaultFileRes, oldNavText, newNavText); 3541 } 3542 } 3543 3544}