mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-08 14:51:49 +00:00
125788 rmunteanu: Merged 5.1.N (5.1.2) to 5.2.N (5.2.1) 125606 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2) 125515 slanglois: MNT-16155 Update source headers - add new Copyrights for Java and JSP source files + automatic check in the build git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@127810 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
388 lines
14 KiB
Java
388 lines
14 KiB
Java
/*
|
|
* #%L
|
|
* Alfresco Repository
|
|
* %%
|
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
|
* %%
|
|
* This file is part of the Alfresco software.
|
|
* If the software was purchased under a paid Alfresco license, the terms of
|
|
* the paid license agreement will prevail. Otherwise, the software is
|
|
* provided under the following open source license terms:
|
|
*
|
|
* Alfresco is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
* #L%
|
|
*/
|
|
package org.alfresco.repo.security.person;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.alfresco.error.AlfrescoRuntimeException;
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.query.AbstractCannedQuery;
|
|
import org.alfresco.query.CannedQueryParameters;
|
|
import org.alfresco.query.CannedQuerySortDetails;
|
|
import org.alfresco.query.CannedQuerySortDetails.SortOrder;
|
|
import org.alfresco.repo.domain.node.NodeDAO;
|
|
import org.alfresco.repo.domain.qname.QNameDAO;
|
|
import org.alfresco.repo.domain.query.CannedQueryDAO;
|
|
import org.alfresco.repo.tenant.TenantService;
|
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.service.cmr.repository.StoreRef;
|
|
import org.alfresco.service.cmr.security.AuthorityService;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.util.Pair;
|
|
import org.alfresco.util.ParameterCheck;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* GetPeople canned query
|
|
*
|
|
* To get paged list of children of a parent node filtered by child type.
|
|
* Also optionally filtered and/or sorted by one or more properties (up to three).
|
|
*
|
|
* @author janv
|
|
* @since 4.1.2
|
|
*/
|
|
public class GetPeopleCannedQuery extends AbstractCannedQuery<NodeRef>
|
|
{
|
|
private Log logger = LogFactory.getLog(getClass());
|
|
|
|
private static final String QUERY_NAMESPACE = "alfresco.query.people";
|
|
private static final String QUERY_SELECT_GET_PEOPLE = "select_GetPeopleCannedQuery";
|
|
|
|
public static final int MAX_FILTER_SORT_PROPS = 3;
|
|
|
|
private static final int MAX_EXPECTED_ADMINS = 5; // TODO refine non-admin paging
|
|
|
|
private NodeDAO nodeDAO;
|
|
private QNameDAO qnameDAO;
|
|
private CannedQueryDAO cannedQueryDAO;
|
|
private TenantService tenantService;
|
|
private NodeService nodeService;
|
|
private AuthorityService authorityService;
|
|
|
|
public GetPeopleCannedQuery(
|
|
NodeDAO nodeDAO,
|
|
QNameDAO qnameDAO,
|
|
CannedQueryDAO cannedQueryDAO,
|
|
TenantService tenantService,
|
|
NodeService nodeService,
|
|
AuthorityService authorityService,
|
|
CannedQueryParameters params)
|
|
{
|
|
super(params);
|
|
|
|
this.nodeDAO = nodeDAO;
|
|
this.qnameDAO = qnameDAO;
|
|
this.cannedQueryDAO = cannedQueryDAO;
|
|
this.tenantService = tenantService;
|
|
this.nodeService = nodeService;
|
|
this.authorityService = authorityService;
|
|
|
|
}
|
|
|
|
@Override
|
|
protected List<NodeRef> queryAndFilter(CannedQueryParameters parameters)
|
|
{
|
|
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
|
|
|
// Get parameters
|
|
GetPeopleCannedQueryParams paramBean = (GetPeopleCannedQueryParams)parameters.getParameterBean();
|
|
|
|
// Get parent node
|
|
NodeRef parentRef = paramBean.getParentRef();
|
|
ParameterCheck.mandatory("nodeRef", parentRef);
|
|
Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(parentRef);
|
|
if (nodePair == null)
|
|
{
|
|
throw new InvalidNodeRefException("Parent node does not exist: " + parentRef, parentRef);
|
|
}
|
|
Long parentNodeId = nodePair.getFirst();
|
|
|
|
// Set query params - note: currently using SortableChildEntity to hold (supplemental-) query params
|
|
FilterSortPersonEntity params = new FilterSortPersonEntity();
|
|
|
|
// Set parent node id
|
|
params.setParentNodeId(parentNodeId);
|
|
|
|
// Get filter details
|
|
final List<QName> filterProps = paramBean.getFilterProps();
|
|
|
|
// Get sort details
|
|
CannedQuerySortDetails sortDetails = parameters.getSortDetails();
|
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
final List<Pair<QName, SortOrder>> sortPairs = (List)sortDetails.getSortPairs();
|
|
|
|
String pattern = paramBean.getPattern();
|
|
if ((pattern == null) || (pattern.equals("")))
|
|
{
|
|
// note: although no pattern means no filtering required, set to match all in case sort required
|
|
pattern = "%";
|
|
}
|
|
else if ((! pattern.endsWith("%")) && (! pattern.endsWith("*")))
|
|
{
|
|
// implicit startsWith match
|
|
pattern = pattern + "%";
|
|
}
|
|
|
|
// Set filter pattern (should not be null)
|
|
params.setPattern(pattern);
|
|
|
|
if (paramBean.getExclusiveAspects() != null)
|
|
{
|
|
Set<Long> qnamesIds = qnameDAO.convertQNamesToIds(paramBean.getExclusiveAspects(), false);
|
|
params.setExcludeAspectIds(new ArrayList<Long>(qnamesIds));
|
|
}
|
|
|
|
if (paramBean.getInclusiveAspects() != null)
|
|
{
|
|
Set<Long> qnamesIds = qnameDAO.convertQNamesToIds(paramBean.getInclusiveAspects(), false);
|
|
params.setIncludeAspectIds(new ArrayList<Long>(qnamesIds));
|
|
}
|
|
|
|
// Set sort / filter params
|
|
// Note - need to keep the sort properties in their requested order
|
|
List<QName> sortFilterProps = new ArrayList<QName>(MAX_FILTER_SORT_PROPS);
|
|
Map<QName, Boolean> sortAsc = new HashMap<QName, Boolean>(MAX_FILTER_SORT_PROPS);
|
|
|
|
// add sort props first
|
|
for (Pair<QName, SortOrder> sort : sortPairs)
|
|
{
|
|
QName sortQName = sort.getFirst();
|
|
if ((filterProps.size() > 0) && (! filterProps.contains(sortQName)))
|
|
{
|
|
throw new AlfrescoRuntimeException("GetPeople: cannot sort by a non-filter property: "+sortQName+" (filterStringProps="+filterProps+")");
|
|
}
|
|
|
|
if (! sortFilterProps.contains(sortQName))
|
|
{
|
|
sortFilterProps.add(sortQName);
|
|
sortAsc.put(sortQName, sort.getSecond().equals(SortOrder.ASCENDING));
|
|
}
|
|
}
|
|
|
|
// add any additional filter props (not part of sort)
|
|
for (QName filterQName : filterProps)
|
|
{
|
|
if (! sortFilterProps.contains(filterQName))
|
|
{
|
|
sortFilterProps.add(filterQName);
|
|
sortAsc.put(filterQName, null);
|
|
}
|
|
}
|
|
|
|
int filterSortPropCnt = sortFilterProps.size();
|
|
|
|
if (filterSortPropCnt > MAX_FILTER_SORT_PROPS)
|
|
{
|
|
throw new AlfrescoRuntimeException("GetPeople: exceeded maximum number filter/sort properties: (max="+MAX_FILTER_SORT_PROPS+", actual="+filterSortPropCnt);
|
|
}
|
|
|
|
filterSortPropCnt = setFilterSortParams(sortFilterProps, sortAsc, params);
|
|
|
|
// filtered and/or sorted - note: permissions not applicable for getPeople
|
|
List<NodeRef> result = new ArrayList<NodeRef>(100);
|
|
final PersonQueryCallback c = new DefaultPersonQueryCallback(result, paramBean.getIncludeAdministrators());
|
|
PersonResultHandler resultHandler = new PersonResultHandler(c);
|
|
|
|
int offset = parameters.getPageDetails().getSkipResults();
|
|
int totalResultCountMax = parameters.getTotalResultCountMax();
|
|
|
|
int origOffset = offset;
|
|
int origLimit = totalResultCountMax > 0 ? totalResultCountMax : parameters.getPageDetails().getPageSize();
|
|
|
|
long newLimit = (long)origLimit;
|
|
|
|
// to enable hasMore flag
|
|
newLimit++;
|
|
|
|
boolean excludeAdmins = (! paramBean.getIncludeAdministrators());
|
|
if (excludeAdmins)
|
|
{
|
|
// TODO refine - non-admin paging
|
|
offset = 0;
|
|
newLimit = offset + (long)newLimit + MAX_EXPECTED_ADMINS;
|
|
}
|
|
|
|
if (newLimit > Integer.MAX_VALUE)
|
|
{
|
|
newLimit = Integer.MAX_VALUE;
|
|
}
|
|
|
|
cannedQueryDAO.executeQuery(QUERY_NAMESPACE, QUERY_SELECT_GET_PEOPLE, params, offset, (int)newLimit, resultHandler);
|
|
resultHandler.done();
|
|
|
|
if (start != null)
|
|
{
|
|
logger.debug("Base query: "+result.size()+" in "+(System.currentTimeMillis()-start)+" msecs");
|
|
}
|
|
|
|
if (excludeAdmins)
|
|
{
|
|
// TODO refine - non-admin paging
|
|
long max = origOffset + (long)origLimit;
|
|
if (max > result.size())
|
|
{
|
|
max = result.size();
|
|
}
|
|
result = result.subList(origOffset, (int)max);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Set filter/sort props (between 0 and 3)
|
|
private int setFilterSortParams(List<QName> filterSortProps, Map<QName, Boolean> sortAsc, FilterSortPersonEntity params)
|
|
{
|
|
int cnt = 0;
|
|
int propCnt = 0;
|
|
|
|
for (QName filterSortProp : filterSortProps)
|
|
{
|
|
Long sortQNameId = getQNameId(filterSortProp);
|
|
Boolean sortOrder = sortAsc.get(filterSortProp); // true = ascending, false = descending, null = unsorted
|
|
|
|
if (sortQNameId != null)
|
|
{
|
|
if (propCnt == 0)
|
|
{
|
|
params.setProp1qnameId(sortQNameId);
|
|
params.setSort1asc(sortOrder);
|
|
}
|
|
else if (propCnt == 1)
|
|
{
|
|
params.setProp2qnameId(sortQNameId);
|
|
params.setSort2asc(sortOrder);
|
|
}
|
|
else if (propCnt == 2)
|
|
{
|
|
params.setProp3qnameId(sortQNameId);
|
|
params.setSort3asc(sortOrder);
|
|
}
|
|
else
|
|
{
|
|
// belts and braces
|
|
throw new AlfrescoRuntimeException("GetPeople: unexpected - cannot set sort parameter: "+cnt);
|
|
}
|
|
|
|
propCnt++;
|
|
}
|
|
else
|
|
{
|
|
logger.warn("Skipping filter/sort param - cannot find: "+filterSortProp);
|
|
break;
|
|
}
|
|
|
|
cnt++;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
private Long getQNameId(QName sortPropQName)
|
|
{
|
|
Pair<Long, QName> qnamePair = qnameDAO.getQName(sortPropQName);
|
|
return (qnamePair == null ? null : qnamePair.getFirst());
|
|
}
|
|
|
|
@Override
|
|
protected boolean isApplyPostQuerySorting()
|
|
{
|
|
// note: sorted as part of the query impl
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
protected boolean isApplyPostQueryPermissions()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
protected boolean isApplyPostQueryPaging()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
protected Pair<Integer, Integer> getTotalResultCount(List<NodeRef> results)
|
|
{
|
|
int offset = super.getParameters().getPageDetails().getSkipResults();
|
|
Integer size = offset + results.size();
|
|
return new Pair<Integer, Integer>(size, size);
|
|
}
|
|
|
|
protected interface PersonQueryCallback
|
|
{
|
|
boolean handle(NodeRef personRef);
|
|
}
|
|
|
|
protected class DefaultPersonQueryCallback implements PersonQueryCallback
|
|
{
|
|
private List<NodeRef> children;
|
|
private boolean includeAdministrators;
|
|
|
|
public DefaultPersonQueryCallback(final List<NodeRef> children, boolean includeAdministrators)
|
|
{
|
|
this.children = children;
|
|
this.includeAdministrators = includeAdministrators;
|
|
}
|
|
|
|
@Override
|
|
public boolean handle(NodeRef personRef)
|
|
{
|
|
// TODO refine - return username as part of query
|
|
if (includeAdministrators == false)
|
|
{
|
|
String userName = (String) nodeService.getProperty(personRef, ContentModel.PROP_USERNAME);
|
|
if (authorityService.isAdminAuthority(userName))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
children.add(tenantService.getBaseName(personRef));
|
|
|
|
// More results
|
|
return true;
|
|
}
|
|
}
|
|
|
|
protected class PersonResultHandler implements CannedQueryDAO.ResultHandler<String>
|
|
{
|
|
private final PersonQueryCallback resultsCallback;
|
|
|
|
private PersonResultHandler(PersonQueryCallback resultsCallback)
|
|
{
|
|
this.resultsCallback = resultsCallback;
|
|
}
|
|
|
|
public boolean handleResult(String uuid)
|
|
{
|
|
// Call back
|
|
return resultsCallback.handle(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, uuid));
|
|
}
|
|
|
|
public void done()
|
|
{
|
|
}
|
|
}
|
|
} |