diff --git a/config/alfresco/site-services-context.xml b/config/alfresco/site-services-context.xml index 07dc859e18..a46d03834a 100644 --- a/config/alfresco/site-services-context.xml +++ b/config/alfresco/site-services-context.xml @@ -170,6 +170,7 @@ + diff --git a/source/java/org/alfresco/repo/site/SiteServiceImpl.java b/source/java/org/alfresco/repo/site/SiteServiceImpl.java index bd2c011ef2..2230fe2662 100644 --- a/source/java/org/alfresco/repo/site/SiteServiceImpl.java +++ b/source/java/org/alfresco/repo/site/SiteServiceImpl.java @@ -25,6 +25,8 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -51,6 +53,7 @@ import org.alfresco.query.PagingResults; import org.alfresco.repo.activities.ActivityType; import org.alfresco.repo.admin.SysAdminParams; import org.alfresco.repo.cache.SimpleCache; +import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.events.EventPreparator; import org.alfresco.repo.events.EventPublisher; import org.alfresco.repo.node.NodeArchiveServicePolicies; @@ -189,9 +192,12 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic private SitesPermissionCleaner sitesPermissionsCleaner; private PolicyComponent policyComponent; private PublicServiceAccessService publicServiceAccessService; + private NodeDAO nodeDAO; private EventPublisher eventPublisher; private NamedObjectRegistry> cannedQueryRegistry; + + private static int GET_CHILD_ASSOCS_PAGE_SIZE = 512; /** * Set the path to the location of the sites root folder. For example: @@ -367,6 +373,11 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic { this.publicServiceAccessService = publicServiceAccessService; } + + public void setNodeDAO(NodeDAO nodeDAO) + { + this.nodeDAO = nodeDAO; + } /** * Set the registry of {@link CannedQueryFactory canned queries} @@ -3037,52 +3048,78 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic } @Override - public List listSiteMemberships (String userName, int size) + public List listSiteMemberships(String userName, int size) { - final int maxResults = size > 0 ? size : 1000; - final Set siteNames = new TreeSet(); + final List siteNames = new LinkedList(); Map roleSitePairs = new HashMap(); - // MNT-13198 - use the bridge table + + String actualUserName = personService.getUserIdentifier(userName); - if(actualUserName != null) + if(actualUserName == null) { - Set containingAuthorities = authorityService.getContainingAuthorities(AuthorityType.GROUP, actualUserName, false); - for(String authority : containingAuthorities) - { - if (siteNames.size() < maxResults) + return Collections.emptyList(); + } + + /* Get the site names and the map between the site name and the role + MNT-13198 - use the bridge table */ + Set containingAuthorities = authorityService.getContainingAuthorities(AuthorityType.GROUP, actualUserName, false); + for(String authority : containingAuthorities) + { + String siteName = resolveSite(authority); + if(siteName == null) { - String siteName = resolveSite(authority); - // MNT-10836 fix, after MNT-10109 we should also check site existence - // A simple exists check would be better than getting the site properties etc - profiling suggests x2 faster - if ((siteName != null) && hasSite(siteName)) + continue; + } + + /* if the size is not 0 check site existence */ + if(size > 0) + { + /* if we found enough sites ignore the others */ + if(siteNames.size() >= size) { - String role = resolveRole(authority); - if (role != null) - { - siteNames.add(siteName); - roleSitePairs.put(siteName, role); - } + break; + } + + /* MNT-10836 fix, after MNT-10109 we should also check site existence. + A simple exists check would be better than getting the site properties etc - profiling suggests x2 faster. + If size = -1 the sites that don't exist will be removed when getting the child associations. */ + if(!hasSite(siteName)) + { + // if the site doesn't exist skip the current authority + continue; } } - else + + /* resolve the role */ + String role = resolveRole(authority); + if (role != null) { - break; + siteNames.add(siteName); + roleSitePairs.put(siteName, role); } - } } + if (siteNames.isEmpty()) { return Collections.emptyList(); } - List assocs = this.nodeService.getChildrenByName( - getSiteRoot(), - ContentModel.ASSOC_CONTAINS, - siteNames); - List result = new ArrayList(assocs.size()); + + /* Get the child associations */ + List assocs = getSitesAssocsByName(siteNames); + + /* Get the node refs and preload the nodes to get the properties faster */ + List siteNodes = new LinkedList(); for (ChildAssociationRef assoc : assocs) { - // Ignore any node that is not a "site" type - NodeRef site = assoc.getChildRef(); + siteNodes.add(assoc.getChildRef()); + } + nodeDAO.cacheNodes(siteNodes); + + /* Compute the site membership objects */ + List result = new LinkedList(); + for (NodeRef site : siteNodes) + { + /* Ignore any node that is not a "site" type */ QName siteClassName = this.directNodeService.getType(site); if (this.dictionaryService.isSubClass(siteClassName, SiteModel.TYPE_SITE)) { @@ -3090,12 +3127,53 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic result.add(new SiteMembership(siteInfo, userName, roleSitePairs.get(siteInfo.getShortName()))); } } + return result; } - public PagingResults listSitesPaged(final String userName, List> sortProps, final PagingRequest pagingRequest) - { - List siteMembers = listSiteMemberships (userName, -1); + /** + * Retrieves the child associations for requested site names + * @param siteNames names of the sites to be retrieved + * @return list of child associations between the site root and sites having the requested site names + */ + private List getSitesAssocsByName(final List siteNames) + { + Iterator sitesIterator = siteNames.iterator(); + List iterationPage = new LinkedList(); + List assocs = new LinkedList(); + List childRefPage; + + NodeRef siteRoot = getSiteRoot(); + + /* iterate the results and retrieve child associations for batches of 512 elements */ + while(sitesIterator.hasNext()) + { + String element = sitesIterator.next(); + iterationPage.add(element); + + /* when the page is full, get the child associations and clean the page */ + if(iterationPage.size() >= GET_CHILD_ASSOCS_PAGE_SIZE) + { + /* get the child associations for the current page having siteRoot as parent + use directNodeService to avoid permission check */ + childRefPage = directNodeService.getChildrenByName(siteRoot, ContentModel.ASSOC_CONTAINS, iterationPage); + assocs.addAll(childRefPage); + iterationPage.clear(); + } + } + if(iterationPage.size() > 0) + { + /* use directNodeService to avoid permission check */ + childRefPage = directNodeService.getChildrenByName(siteRoot, ContentModel.ASSOC_CONTAINS, iterationPage); + assocs.addAll(childRefPage); + } + + return assocs; + } + + public PagingResults listSitesPaged(final String userName, List> sortProps, final PagingRequest pagingRequest) + { + List siteMembers = listSiteMemberships (userName, 0); final int totalSize = siteMembers.size(); final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); final List resultList; diff --git a/source/java/org/alfresco/service/cmr/site/SiteService.java b/source/java/org/alfresco/service/cmr/site/SiteService.java index d6790ecdc1..946ec147f0 100644 --- a/source/java/org/alfresco/service/cmr/site/SiteService.java +++ b/source/java/org/alfresco/service/cmr/site/SiteService.java @@ -226,7 +226,7 @@ public interface SiteService * Lists all the memberships in sites that the specified user is in. * * @param userName String - * @param size int + * @param size list maximum size or zero for all * @return a list of SiteMembership objects */ @NotAuditable