001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.gwt; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.containerpage.CmsContainerpageService; 032import org.opencms.ade.containerpage.CmsDetailOnlyContainerUtil; 033import org.opencms.ade.containerpage.CmsRelationTargetListBean; 034import org.opencms.file.CmsFile; 035import org.opencms.file.CmsObject; 036import org.opencms.file.CmsProperty; 037import org.opencms.file.CmsPropertyDefinition; 038import org.opencms.file.CmsResource; 039import org.opencms.file.CmsResourceFilter; 040import org.opencms.file.CmsUser; 041import org.opencms.file.CmsVfsResourceNotFoundException; 042import org.opencms.file.types.CmsResourceTypeJsp; 043import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 044import org.opencms.file.types.CmsResourceTypeXmlContent; 045import org.opencms.file.types.I_CmsResourceType; 046import org.opencms.gwt.shared.CmsGwtConstants; 047import org.opencms.gwt.shared.CmsListInfoBean; 048import org.opencms.gwt.shared.CmsPermissionInfo; 049import org.opencms.gwt.shared.CmsResourceStatusBean; 050import org.opencms.gwt.shared.CmsResourceStatusRelationBean; 051import org.opencms.gwt.shared.CmsResourceStatusTabId; 052import org.opencms.i18n.CmsLocaleManager; 053import org.opencms.i18n.CmsMessageContainer; 054import org.opencms.jsp.CmsJspTagDisplay; 055import org.opencms.lock.CmsLock; 056import org.opencms.main.CmsException; 057import org.opencms.main.CmsLog; 058import org.opencms.main.OpenCms; 059import org.opencms.relations.CmsRelation; 060import org.opencms.relations.CmsRelationFilter; 061import org.opencms.relations.CmsRelationType; 062import org.opencms.relations.I_CmsLinkParseable; 063import org.opencms.search.galleries.CmsGallerySearch; 064import org.opencms.search.galleries.CmsGallerySearchResult; 065import org.opencms.security.CmsRole; 066import org.opencms.site.CmsSite; 067import org.opencms.util.CmsStringUtil; 068import org.opencms.util.CmsUUID; 069import org.opencms.workplace.CmsWorkplace; 070import org.opencms.workplace.explorer.CmsResourceUtil; 071import org.opencms.xml.containerpage.CmsContainerElementBean; 072import org.opencms.xml.containerpage.I_CmsFormatterBean; 073import org.opencms.xml.content.CmsXmlContent; 074import org.opencms.xml.content.CmsXmlContentFactory; 075 076import java.util.ArrayList; 077import java.util.Arrays; 078import java.util.Collections; 079import java.util.Comparator; 080import java.util.HashMap; 081import java.util.Iterator; 082import java.util.LinkedHashMap; 083import java.util.List; 084import java.util.Locale; 085import java.util.Map; 086import java.util.Set; 087 088import javax.servlet.http.HttpServletRequest; 089 090import org.apache.commons.logging.Log; 091 092import com.google.common.base.Optional; 093import com.google.common.collect.ComparisonChain; 094import com.google.common.collect.Maps; 095import com.google.common.collect.Sets; 096 097/** 098 * Helper class to generate all the data which is necessary for the resource status dialog(s).<p> 099 */ 100public class CmsDefaultResourceStatusProvider { 101 102 /** 103 * Exception class for signalling that there are too many relations to process. 104 */ 105 static class TooManyRelationsException extends Exception { 106 107 /** Serial version id. */ 108 private static final long serialVersionUID = 1L; 109 110 /** 111 * Creates a new instance. 112 */ 113 public TooManyRelationsException() { 114 115 super(); 116 } 117 } 118 119 /** The detail container path pattern. */ 120 private static final String DETAIL_CONTAINER_PATTERN = ".*\\/\\.detailContainers\\/.*"; 121 122 /** The log instance for this class. */ 123 private static final Log LOG = CmsLog.getLog(CmsDefaultResourceStatusProvider.class); 124 125 /** Maximum relation count that is still displayed. */ 126 public static final long MAX_RELATIONS = 500; 127 128 /** 129 * Gets the relation targets for a resource.<p> 130 * 131 * @param cms the current CMS context 132 * @param source the structure id of the resource for which we want the relation targets 133 * @param additionalIds the structure ids of additional resources to include with the relation targets 134 * @param cancelIfChanged if this is true, this method will stop immediately if it finds a changed resource among the relation targets 135 * 136 * @return a bean containing a list of relation targets 137 * 138 * @throws CmsException if something goes wrong 139 */ 140 public static CmsRelationTargetListBean getContainerpageRelationTargets( 141 CmsObject cms, 142 CmsUUID source, 143 List<CmsUUID> additionalIds, 144 boolean cancelIfChanged) 145 throws CmsException { 146 147 CmsRelationTargetListBean result = new CmsRelationTargetListBean(); 148 CmsResource content = cms.readResource(source, CmsResourceFilter.ALL); 149 boolean isContainerPage = CmsResourceTypeXmlContainerPage.isContainerPage(content); 150 if (additionalIds != null) { 151 for (CmsUUID structureId : additionalIds) { 152 try { 153 CmsResource res = cms.readResource(structureId, CmsResourceFilter.ALL); 154 result.add(res); 155 if (res.getState().isChanged() && cancelIfChanged) { 156 return result; 157 } 158 } catch (CmsException e) { 159 LOG.error(e.getLocalizedMessage(), e); 160 } 161 } 162 } 163 List<CmsRelation> relations = cms.readRelations(CmsRelationFilter.relationsFromStructureId(source)); 164 for (CmsRelation relation : relations) { 165 if (relation.getType() == CmsRelationType.XSD) { 166 continue; 167 } 168 try { 169 CmsResource target = relation.getTarget(cms, CmsResourceFilter.ALL); 170 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(target); 171 if (isContainerPage && (type instanceof CmsResourceTypeJsp)) { 172 // ignore formatters for container pages, as the normal user probably doesn't want to deal with them 173 continue; 174 } 175 result.add(target); 176 if (target.getState().isChanged() && cancelIfChanged) { 177 return result; 178 } 179 } catch (CmsException e) { 180 LOG.debug(e.getLocalizedMessage(), e); 181 } 182 } 183 184 return result; 185 } 186 187 /** 188 * Gets the relation targets for a resource.<p> 189 * 190 * @param cms the current CMS context 191 * @param source the structure id of the resource for which we want the relation targets 192 * @param additionalIds the structure ids of additional resources to include with the relation targets 193 * @param cancelIfChanged if this is true, this method will stop immediately if it finds a changed resource among the relation targets 194 * 195 * @return a bean containing a list of relation targets 196 * 197 * @throws CmsException if something goes wrong 198 * @throws TooManyRelationsException if too many relations are found 199 */ 200 public static CmsRelationTargetListBean getContainerpageRelationTargetsLimited( 201 CmsObject cms, 202 CmsUUID source, 203 List<CmsUUID> additionalIds, 204 boolean cancelIfChanged) 205 throws CmsException, TooManyRelationsException { 206 207 CmsRelationTargetListBean result = new CmsRelationTargetListBean(); 208 CmsResource content = cms.readResource(source, CmsResourceFilter.ALL); 209 boolean isContainerPage = CmsResourceTypeXmlContainerPage.isContainerPage(content); 210 if (additionalIds != null) { 211 for (CmsUUID structureId : additionalIds) { 212 try { 213 CmsResource res = cms.readResource(structureId, CmsResourceFilter.ALL); 214 result.add(res); 215 if (res.getState().isChanged() && cancelIfChanged) { 216 return result; 217 } 218 } catch (CmsException e) { 219 LOG.error(e.getLocalizedMessage(), e); 220 } 221 } 222 } 223 List<CmsRelation> relations = cms.readRelations(CmsRelationFilter.relationsFromStructureId(source)); 224 if (relations.size() > MAX_RELATIONS) { 225 throw new TooManyRelationsException(); 226 227 } else { 228 for (CmsRelation relation : relations) { 229 if (relation.getType() == CmsRelationType.XSD) { 230 continue; 231 } 232 try { 233 CmsResource target = relation.getTarget(cms, CmsResourceFilter.ALL); 234 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(target); 235 if (isContainerPage && (type instanceof CmsResourceTypeJsp)) { 236 // ignore formatters for container pages, as the normal user probably doesn't want to deal with them 237 continue; 238 } 239 result.add(target); 240 if (target.getState().isChanged() && cancelIfChanged) { 241 return result; 242 } 243 } catch (CmsException e) { 244 LOG.debug(e.getLocalizedMessage(), e); 245 } 246 } 247 } 248 return result; 249 } 250 251 /** 252 * Gets the additional information related to the formatter. 253 * 254 * @param cms the CMS context 255 * @param bean the formatter bean 256 * @return the additional information about the formatter 257 */ 258 public static Map<String, String> getFormatterInfo(CmsObject cms, I_CmsFormatterBean bean) { 259 260 Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 261 Map<String, String> result = new LinkedHashMap<>(); 262 if (bean != null) { 263 String label = org.opencms.ade.containerpage.Messages.get().getBundle(locale).key( 264 org.opencms.ade.containerpage.Messages.GUI_ADDINFO_FORMATTER_0); 265 result.put(label, bean.getJspRootPath()); 266 String locationLabel = org.opencms.ade.containerpage.Messages.get().getBundle(locale).key( 267 org.opencms.ade.containerpage.Messages.GUI_ADDINFO_FORMATTER_LOCATION_0); 268 269 String location = bean.getLocation(); 270 if (location != null) { 271 result.put(locationLabel, location); 272 } 273 String key = bean.getKeyOrId(); 274 String keyLabel = org.opencms.ade.containerpage.Messages.get().getBundle(locale).key( 275 org.opencms.ade.containerpage.Messages.GUI_ADDINFO_FORMATTER_KEY_0); 276 277 if (key != null) { 278 result.put(keyLabel, key); 279 } 280 281 } 282 return result; 283 284 } 285 286 /** 287 * Collects all the data to display in the resource status dialog.<p> 288 * 289 * @param request the current request 290 * @param cms the current CMS context 291 * @param structureId the structure id of the resource for which we want the information 292 * @param contentLocale the content locale 293 * @param includeTargets true if relation targets should be included 294 * @param detailContentId the structure id of the detail content if present 295 * @param additionalStructureIds structure ids of additional resources to include with the relation targets 296 * @param context context parameters used for displaying additional infos 297 * 298 * @return the resource status information 299 * @throws CmsException if something goes wrong 300 */ 301 public CmsResourceStatusBean getResourceStatus( 302 HttpServletRequest request, 303 CmsObject cms, 304 CmsUUID structureId, 305 String contentLocale, 306 boolean includeTargets, 307 CmsUUID detailContentId, 308 List<CmsUUID> additionalStructureIds, 309 Map<String, String> context) 310 throws CmsException { 311 312 Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 313 cms.getRequestContext().setLocale(locale); 314 CmsResource resource = cms.readResource(structureId, CmsResourceFilter.ALL); 315 String localizedTitle = null; 316 Locale realLocale = null; 317 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(contentLocale)) { 318 realLocale = CmsLocaleManager.getLocale(contentLocale); 319 CmsGallerySearchResult result = CmsGallerySearch.searchById(cms, structureId, realLocale); 320 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(result.getTitle())) { 321 localizedTitle = result.getTitle(); 322 } 323 } 324 CmsResourceUtil resourceUtil = new CmsResourceUtil(cms, resource); 325 List<CmsProperty> properties = cms.readPropertyObjects(resource, false); 326 CmsResourceStatusBean result = new CmsResourceStatusBean(); 327 result.setDateCreated(CmsVfsService.formatDateTime(cms, resource.getDateCreated())); 328 long dateExpired = resource.getDateExpired(); 329 if (dateExpired != CmsResource.DATE_EXPIRED_DEFAULT) { 330 result.setDateExpired(CmsVfsService.formatDateTime(cms, dateExpired)); 331 } 332 result.setDateLastModified(CmsVfsService.formatDateTime(cms, resource.getDateLastModified())); 333 long dateReleased = resource.getDateReleased(); 334 if (dateReleased != CmsResource.DATE_RELEASED_DEFAULT) { 335 result.setDateReleased(CmsVfsService.formatDateTime(cms, dateReleased)); 336 } 337 String lastProject = resourceUtil.getLockedInProjectName(); 338 if ("".equals(lastProject)) { 339 lastProject = null; 340 } 341 result.setLastProject(lastProject); 342 343 result.setListInfo(CmsVfsService.getPageInfo(cms, resource)); 344 Map<String, String> contextualAddInfos = createContextInfos(cms, request, resource, context); 345 for (Map.Entry<String, String> entry : contextualAddInfos.entrySet()) { 346 result.getListInfo().addAdditionalInfo(entry.getKey(), entry.getValue()); 347 } 348 349 CmsLock lock = cms.getLock(resource); 350 CmsUser lockOwner = null; 351 if (!lock.isUnlocked()) { 352 lockOwner = cms.readUser(lock.getUserId()); 353 result.setLockState( 354 org.opencms.workplace.list.Messages.get().getBundle(locale).key( 355 org.opencms.workplace.list.Messages.GUI_EXPLORER_LIST_ACTION_LOCK_NAME_2, 356 lockOwner.getName(), 357 lastProject)); 358 } else { 359 result.setLockState( 360 org.opencms.workplace.list.Messages.get().getBundle(locale).key( 361 org.opencms.workplace.list.Messages.GUI_EXPLORER_LIST_ACTION_UNLOCK_NAME_0)); 362 } 363 364 CmsProperty navText = CmsProperty.get(CmsPropertyDefinition.PROPERTY_NAVTEXT, properties); 365 if (navText != null) { 366 result.setNavText(navText.getValue()); 367 } 368 result.setPermissions(resourceUtil.getPermissionString()); 369 result.setSize(resource.getLength()); 370 result.setStateBean(resource.getState()); 371 CmsProperty title = CmsProperty.get(CmsPropertyDefinition.PROPERTY_TITLE, properties); 372 if (localizedTitle != null) { 373 result.setTitle(localizedTitle); 374 result.getListInfo().setTitle(localizedTitle); 375 } else if (title != null) { 376 result.setTitle(title.getValue()); 377 } 378 result.setUserCreated(resourceUtil.getUserCreated()); 379 result.setUserLastModified(resourceUtil.getUserLastModified()); 380 381 I_CmsResourceType resType = OpenCms.getResourceManager().getResourceType(resource); 382 result.setResourceType(resType.getTypeName()); 383 384 result.setStructureId(resource.getStructureId()); 385 if (resType instanceof CmsResourceTypeXmlContent) { 386 CmsFile file = cms.readFile(resource); 387 CmsXmlContent content = CmsXmlContentFactory.unmarshal(cms, file); 388 List<Locale> locales = content.getLocales(); 389 List<String> localeStrings = new ArrayList<String>(); 390 for (Locale l : locales) { 391 localeStrings.add(l.toString()); 392 } 393 result.setLocales(localeStrings); 394 } 395 Map<String, String> additionalAttributes = new LinkedHashMap<String, String>(); 396 additionalAttributes.put( 397 Messages.get().getBundle(locale).key(Messages.GUI_STATUS_PERMALINK_0), 398 OpenCms.getLinkManager().getPermalink(cms, cms.getSitePath(resource), detailContentId)); 399 400 if (OpenCms.getRoleManager().hasRole(cms, CmsRole.ADMINISTRATOR)) { 401 additionalAttributes.put( 402 Messages.get().getBundle(locale).key(Messages.GUI_STATUS_STRUCTURE_ID_0), 403 resource.getStructureId().toString()); 404 additionalAttributes.put( 405 Messages.get().getBundle(locale).key(Messages.GUI_STATUS_RESOURCE_ID_0), 406 resource.getResourceId().toString()); 407 } 408 409 result.setAdditionalAttributes(additionalAttributes); 410 411 List<CmsRelation> relations = cms.readRelations( 412 CmsRelationFilter.relationsToStructureId(resource.getStructureId())); 413 Map<CmsUUID, CmsResource> relationSources = new HashMap<CmsUUID, CmsResource>(); 414 415 if (CmsResourceTypeXmlContainerPage.isContainerPage(resource)) { 416 // People may link to the folder of a container page instead of the page itself 417 try { 418 CmsResource parent = cms.readParentFolder(resource.getStructureId()); 419 List<CmsRelation> parentRelations = cms.readRelations( 420 CmsRelationFilter.relationsToStructureId(parent.getStructureId())); 421 relations.addAll(parentRelations); 422 } catch (CmsException e) { 423 LOG.error(e.getLocalizedMessage(), e); 424 } 425 } 426 427 if (relations.size() > MAX_RELATIONS) { 428 String errorMessage = Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key( 429 Messages.GUI_TOO_MANY_RELATIONS_1, 430 "" + MAX_RELATIONS); 431 result.setSourcesError(errorMessage); 432 } else { 433 // find all distinct relation sources 434 for (CmsRelation relation : relations) { 435 try { 436 CmsResource currentSource = relation.getSource(cms, CmsResourceFilter.ALL); 437 relationSources.put(currentSource.getStructureId(), currentSource); 438 } catch (CmsException e) { 439 LOG.error(e.getLocalizedMessage(), e); 440 } 441 } 442 443 for (CmsResource relationResource : relationSources.values()) { 444 try { 445 CmsPermissionInfo permissionInfo = OpenCms.getADEManager().getPermissionInfo( 446 cms, 447 relationResource, 448 resource.getRootPath()); 449 if (permissionInfo.hasViewPermission()) { 450 CmsResourceStatusRelationBean relationBean = createRelationBean( 451 cms, 452 contentLocale, 453 relationResource, 454 permissionInfo); 455 CmsSite site = OpenCms.getSiteManager().getSiteForRootPath(relationResource.getRootPath()); 456 if ((site != null) 457 && !CmsStringUtil.isPrefixPath( 458 cms.getRequestContext().getSiteRoot(), 459 relationResource.getRootPath())) { 460 String siteTitle = site.getTitle(); 461 if (siteTitle == null) { 462 siteTitle = site.getUrl(); 463 } else { 464 siteTitle = CmsWorkplace.substituteSiteTitleStatic( 465 siteTitle, 466 OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)); 467 } 468 relationBean.setSiteRoot(site.getSiteRoot()); 469 result.getOtherSiteRelationSources().add(relationBean); 470 relationBean.getInfoBean().setTitle( 471 "[" + siteTitle + "] " + relationBean.getInfoBean().getTitle()); 472 } else { 473 result.getRelationSources().add(relationBean); 474 } 475 476 } 477 } catch (CmsVfsResourceNotFoundException notfound) { 478 LOG.error(notfound.getLocalizedMessage(), notfound); 479 continue; 480 } 481 } 482 sortRelations(cms, result); 483 } 484 if (includeTargets) { 485 try { 486 result.getRelationTargets().addAll(getTargets(cms, contentLocale, resource, additionalStructureIds)); 487 if ((detailContentId != null) && (realLocale != null)) { 488 // try to add detail only contents 489 try { 490 CmsResource detailContent = cms.readResource(detailContentId, CmsResourceFilter.ALL); 491 Optional<CmsResource> detailOnlyPage = CmsDetailOnlyContainerUtil.getDetailOnlyResource( 492 cms, 493 realLocale.toString(), 494 detailContent, 495 resource); 496 if (detailOnlyPage.isPresent()) { 497 result.getRelationTargets().addAll( 498 getTargets( 499 cms, 500 contentLocale, 501 detailOnlyPage.get(), 502 Arrays.asList(detailOnlyPage.get().getStructureId()))); 503 } 504 505 } catch (CmsException e) { 506 LOG.error(e.getLocalizedMessage(), e); 507 } 508 } 509 Iterator<CmsResourceStatusRelationBean> iter = result.getRelationTargets().iterator(); 510 // Remove duplicates 511 Set<CmsUUID> visitedIds = Sets.newHashSet(); 512 while (iter.hasNext()) { 513 CmsResourceStatusRelationBean bean = iter.next(); 514 if (visitedIds.contains(bean.getStructureId())) { 515 iter.remove(); 516 } 517 visitedIds.add(bean.getStructureId()); 518 } 519 } catch (TooManyRelationsException e) { 520 result.setTargetsError( 521 Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key( 522 Messages.GUI_TOO_MANY_RELATIONS_1, 523 "" + MAX_RELATIONS)); 524 } 525 } 526 result.getSiblings().addAll(getSiblings(cms, contentLocale, resource)); 527 LinkedHashMap<CmsResourceStatusTabId, String> tabMap = new LinkedHashMap<CmsResourceStatusTabId, String>(); 528 Map<CmsResourceStatusTabId, CmsMessageContainer> tabs; 529 CmsResourceStatusTabId startTab = CmsResourceStatusTabId.tabRelationsFrom; 530 if (CmsResourceTypeXmlContainerPage.isContainerPage(resource)) { 531 tabs = CmsResourceStatusConstants.STATUS_TABS_CONTAINER_PAGE; 532 } else if (OpenCms.getResourceManager().getResourceType(resource) instanceof I_CmsLinkParseable) { 533 tabs = CmsResourceStatusConstants.STATUS_TABS_CONTENT; 534 } else { 535 tabs = CmsResourceStatusConstants.STATUS_TABS_OTHER; 536 startTab = CmsResourceStatusTabId.tabStatus; 537 } 538 for (Map.Entry<CmsResourceStatusTabId, CmsMessageContainer> entry : tabs.entrySet()) { 539 tabMap.put(entry.getKey(), entry.getValue().key(locale)); 540 } 541 542 result.setTabs(tabMap); 543 result.setStartTab(startTab); 544 return result; 545 } 546 547 /** 548 * Sorts relation beans from other sites by site order.<p> 549 * 550 * @param cms the current CMS context 551 * @param resStatus the bean in which to sort the relation beans 552 */ 553 public void sortRelations(CmsObject cms, CmsResourceStatusBean resStatus) { 554 555 final List<CmsSite> sites = OpenCms.getSiteManager().getAvailableSites( 556 cms, 557 false, 558 false, 559 cms.getRequestContext().getOuFqn()); 560 Collections.sort(resStatus.getOtherSiteRelationSources(), new Comparator<CmsResourceStatusRelationBean>() { 561 562 private Map<String, Integer> m_rankCache = Maps.newHashMap(); 563 564 public int compare(CmsResourceStatusRelationBean o1, CmsResourceStatusRelationBean o2) { 565 566 return ComparisonChain.start().compare(rank(o1), rank(o2)).compare( 567 o1.getSitePath(), 568 o2.getSitePath()).result(); 569 570 } 571 572 public int rank(CmsResourceStatusRelationBean r) { 573 574 if (m_rankCache.containsKey(r.getSiteRoot())) { 575 return m_rankCache.get(r.getSiteRoot()).intValue(); 576 } 577 578 int j = 0; 579 int result = Integer.MAX_VALUE; 580 for (CmsSite site : sites) { 581 if (site.getSiteRoot().equals(r.getSiteRoot())) { 582 result = j; 583 break; 584 } 585 j += 1; 586 } 587 588 m_rankCache.put(r.getSiteRoot(), Integer.valueOf(result)); 589 return result; 590 } 591 }); 592 // sort relation sources by path, make sure all resources within .detailContainer folders show last 593 Collections.sort(resStatus.getRelationSources(), new Comparator<CmsResourceStatusRelationBean>() { 594 595 public int compare(CmsResourceStatusRelationBean arg0, CmsResourceStatusRelationBean arg1) { 596 597 if (arg0.getSitePath().matches(DETAIL_CONTAINER_PATTERN)) { 598 if (!arg1.getSitePath().matches(DETAIL_CONTAINER_PATTERN)) { 599 return 1; 600 } 601 } else if (arg1.getSitePath().matches(DETAIL_CONTAINER_PATTERN)) { 602 return -1; 603 } 604 return arg0.getSitePath().compareTo(arg1.getSitePath()); 605 } 606 607 }); 608 } 609 610 /** 611 * Gets beans which represents the siblings of a resource.<p> 612 * 613 * @param cms the CMS ccontext 614 * @param locale the locale 615 * @param resource the resource 616 * @return the list of sibling beans 617 * 618 * @throws CmsException if something goes wrong 619 */ 620 protected List<CmsResourceStatusRelationBean> getSiblings(CmsObject cms, String locale, CmsResource resource) 621 throws CmsException { 622 623 List<CmsResourceStatusRelationBean> result = new ArrayList<CmsResourceStatusRelationBean>(); 624 for (CmsResource sibling : cms.readSiblings(resource, CmsResourceFilter.ALL)) { 625 if (sibling.getStructureId().equals(resource.getStructureId())) { 626 continue; 627 } 628 try { 629 CmsPermissionInfo permissionInfo = OpenCms.getADEManager().getPermissionInfo( 630 cms, 631 sibling, 632 resource.getRootPath()); 633 if (permissionInfo.hasViewPermission()) { 634 CmsResourceStatusRelationBean relationBean = createRelationBean( 635 cms, 636 locale, 637 sibling, 638 permissionInfo); 639 result.add(relationBean); 640 } 641 } catch (CmsException e) { 642 LOG.error(e.getLocalizedMessage(), e); 643 } 644 } 645 return result; 646 } 647 648 /** 649 * Gets the list of relation targets for a resource.<p> 650 * 651 * @param cms the current CMS context 652 * @param locale the locale 653 * @param resource the resource for which we want the relation targets 654 * @param additionalStructureIds structure ids of additional resources to include with the relation target 655 * 656 * @return the list of relation beans for the relation targets 657 * 658 * @throws CmsException if something goes wrong 659 * @throws TooManyRelationsException if too many relations are found 660 */ 661 protected List<CmsResourceStatusRelationBean> getTargets( 662 CmsObject cms, 663 String locale, 664 CmsResource resource, 665 List<CmsUUID> additionalStructureIds) 666 throws CmsException, TooManyRelationsException { 667 668 CmsRelationTargetListBean listBean = getContainerpageRelationTargetsLimited( 669 cms, 670 resource.getStructureId(), 671 additionalStructureIds, 672 false); 673 List<CmsResourceStatusRelationBean> result = new ArrayList<CmsResourceStatusRelationBean>(); 674 for (CmsResource target : listBean.getResources()) { 675 try { 676 CmsPermissionInfo permissionInfo = OpenCms.getADEManager().getPermissionInfo( 677 cms, 678 target, 679 resource.getRootPath()); 680 if (permissionInfo.hasViewPermission()) { 681 CmsResourceStatusRelationBean relationBean = createRelationBean( 682 cms, 683 locale, 684 target, 685 permissionInfo); 686 result.add(relationBean); 687 } 688 } catch (CmsException e) { 689 LOG.error(e.getLocalizedMessage(), e); 690 } 691 } 692 return result; 693 694 } 695 696 /** 697 * Creates a bean for a single resource which is part of a relation list.<p> 698 * 699 * @param cms the current CMS context 700 * @param locale the locale 701 * @param relationResource the resource 702 * @param permissionInfo the permission info 703 * 704 * @return the status bean for the resource 705 * 706 * @throws CmsException if something goes wrong 707 */ 708 CmsResourceStatusRelationBean createRelationBean( 709 CmsObject cms, 710 String locale, 711 CmsResource relationResource, 712 CmsPermissionInfo permissionInfo) 713 throws CmsException { 714 715 CmsListInfoBean sourceBean = CmsVfsService.getPageInfo(cms, relationResource); 716 sourceBean.setMarkChangedState(true); 717 sourceBean.setResourceState(relationResource.getState()); 718 719 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(locale)) { 720 Locale realLocale = CmsLocaleManager.getLocale(locale); 721 CmsGallerySearchResult result = CmsGallerySearch.searchById( 722 cms, 723 relationResource.getStructureId(), 724 realLocale); 725 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(result.getTitle())) { 726 sourceBean.setTitle(result.getTitle()); 727 } 728 } 729 String link = null; 730 try { 731 link = OpenCms.getLinkManager().substituteLink(cms, relationResource); 732 } catch (Exception e) { 733 LOG.warn(e.getLocalizedMessage(), e); 734 } 735 CmsResourceStatusRelationBean relationBean = new CmsResourceStatusRelationBean( 736 sourceBean, 737 link, 738 relationResource.getStructureId(), 739 permissionInfo); 740 if (CmsResourceTypeXmlContent.isXmlContent(relationResource)) { 741 relationBean.setIsXmlContent(true); 742 } 743 String sitePath = cms.getSitePath(relationResource); 744 relationBean.setSitePath(sitePath); 745 return relationBean; 746 } 747 748 /** 749 * Creates the additional infos from the context parameters.<p> 750 * 751 * @param cms the current CMS object 752 * @param request the current request 753 * @param resource the resource for which to generate additional infos 754 * @param context the context parameters 755 * @return the additional infos (keys are labels) 756 * 757 */ 758 private Map<String, String> createContextInfos( 759 CmsObject cms, 760 HttpServletRequest request, 761 CmsResource resource, 762 Map<String, String> context) { 763 764 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration( 765 cms, 766 cms.getRequestContext().getRootUri()); 767 Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 768 Map<String, String> additionalAttributes = new LinkedHashMap<String, String>(); 769 try { 770 try { 771 CmsRelationFilter filter = CmsRelationFilter.relationsFromStructureId( 772 resource.getStructureId()).filterType(CmsRelationType.XSD); 773 String schema = null; 774 String label = org.opencms.ade.containerpage.Messages.get().getBundle(locale).key( 775 org.opencms.ade.containerpage.Messages.GUI_ADDINFO_SCHEMA_0); 776 777 for (CmsRelation relation : cms.readRelations(filter)) { 778 CmsResource target = relation.getTarget(cms, CmsResourceFilter.IGNORE_EXPIRATION); 779 schema = target.getRootPath(); 780 break; 781 } 782 if (schema != null) { 783 additionalAttributes.put(label, schema); 784 } 785 } catch (CmsException e) { 786 LOG.error(e.getLocalizedMessage(), e); 787 } 788 789 String elementId = context.get(CmsGwtConstants.ATTR_ELEMENT_ID); 790 String pageRootPath = context.get(CmsGwtConstants.ATTR_PAGE_ROOT_PATH); 791 String containr = context.get(CmsGwtConstants.ATTR_CONTAINER_ID); 792 // We need to handle the case of normal formatter element vs display formatter differently, 793 // because in the former case the jsp id is sometimes incorrect (i.e. inconsistent with the formatter configured in the settings) 794 if ((elementId != null) && (containr != null)) { 795 CmsContainerpageService pageService = new CmsContainerpageService(); 796 pageService.setCms(cms); 797 pageService.setRequest(request); 798 CmsContainerElementBean elementBean = pageService.getCachedElement(elementId, pageRootPath); 799 for (Map.Entry<String, String> entry : elementBean.getSettings().entrySet()) { 800 if (entry.getKey().contains(containr)) { 801 String formatterId = entry.getValue(); 802 I_CmsFormatterBean formatter = config.findFormatter(formatterId); 803 for (Map.Entry<String, String> entry1 : getFormatterInfo(cms, formatter).entrySet()) { 804 additionalAttributes.put(entry1.getKey(), entry1.getValue()); 805 } 806 } 807 } 808 } else if ((elementId != null) && (pageRootPath != null)) { 809 CmsContainerpageService pageService = new CmsContainerpageService(); 810 pageService.setCms(cms); 811 pageService.setRequest(request); 812 CmsContainerElementBean elementBean = pageService.getCachedElement(elementId, pageRootPath); 813 String displayFormatterKey = elementBean.getSettings().get(CmsJspTagDisplay.DISPLAY_FORMATTER_SETTING); 814 boolean foundFormatterInfo = false; 815 if (displayFormatterKey != null) { 816 I_CmsFormatterBean formatter = config.findFormatter(displayFormatterKey); 817 if (formatter != null) { 818 foundFormatterInfo = true; 819 Map<String, String> formatterInfo = getFormatterInfo(cms, formatter); 820 for (Map.Entry<String, String> infoEntry : formatterInfo.entrySet()) { 821 additionalAttributes.put(infoEntry.getKey(), infoEntry.getValue()); 822 } 823 } 824 } 825 if (!foundFormatterInfo) { 826 CmsUUID formatterId = elementBean.getFormatterId(); 827 try { 828 CmsResource formatterRes = cms.readResource(formatterId, CmsResourceFilter.IGNORE_EXPIRATION); 829 String path = formatterRes.getRootPath(); 830 String label = org.opencms.ade.containerpage.Messages.get().getBundle(locale).key( 831 org.opencms.ade.containerpage.Messages.GUI_ADDINFO_FORMATTER_0); 832 additionalAttributes.put(label, path); 833 } catch (CmsVfsResourceNotFoundException e) { 834 // ignore 835 } catch (CmsException e) { 836 LOG.error(e.getLocalizedMessage(), e); 837 } 838 } 839 } 840 } catch (Exception e) { 841 LOG.error(e.getLocalizedMessage(), e); 842 } 843 844 return additionalAttributes; 845 } 846}