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