From 0431f2586590407a9eeb96870b34038fb1c6cf47 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Fri, 18 Jul 2014 04:17:45 +0000 Subject: [PATCH] RM performance enhancements * serach improvements * in-place record browse improvements * saved search via file plan browse improvements git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.1.0.x@76850 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../capability/RMSecurityCommon.java | 116 ++++++++++++------ .../script/slingshot/RMSearchGet.java | 33 ++--- .../RecordsManagementSearchService.java | 7 +- .../RecordsManagementSearchServiceImpl.java | 13 +- .../ExtendedReaderDynamicAuthority.java | 9 ++ .../ExtendedSecurityBaseDynamicAuthority.java | 84 ++++++------- .../ExtendedWriterDynamicAuthority.java | 11 +- .../util/ServiceBaseImpl.java | 45 ++++--- .../test/service/RecordServiceImplTest.java | 13 +- ...ecordsManagementSearchServiceImplTest.java | 3 +- 10 files changed, 198 insertions(+), 136 deletions(-) diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMSecurityCommon.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMSecurityCommon.java index 51c70b7bfc..ec1181efb5 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMSecurityCommon.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMSecurityCommon.java @@ -18,6 +18,8 @@ */ package org.alfresco.module.org_alfresco_module_rm.capability; +import java.util.Map; + import net.sf.acegisecurity.vote.AccessDecisionVoter; import org.alfresco.error.AlfrescoRuntimeException; @@ -27,6 +29,7 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; @@ -34,6 +37,7 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.util.Pair; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -192,48 +196,82 @@ public class RMSecurityCommon } /** + * Core RM read check * - * @param nodeRef - * @return + * @param nodeRef node reference + * @return int see {@link AccessDecisionVoter} */ public int checkRmRead(NodeRef nodeRef) - { - int result = getTransactionCache("checkRmRead", nodeRef); - if (result != NOSET_VALUE) - { - return result; - } - - if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED) - { - if (logger.isDebugEnabled()) - { - logger.debug("\t\tUser does not have read record permission on node, access denied. (nodeRef=" + nodeRef.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")"); - } - return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); - } - - // Get the file plan for the node - NodeRef filePlan = filePlanService.getFilePlan(nodeRef); - - if (permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS) == AccessStatus.DENIED) - { - if (logger.isDebugEnabled()) - { - logger.debug("\t\tUser does not have view records capability permission on node, access denied. (filePlan=" + filePlan.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")"); - } - return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); - } - - if (caveatConfigComponent.hasAccess(nodeRef)) - { - return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_GRANTED); - } - else - { - return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); - } - + { + int result = AccessDecisionVoter.ACCESS_ABSTAIN; + + Map, Integer> transactionCache = TransactionalResourceHelper.getMap("rm.security.checkRMRead"); + Pair key = new Pair(AuthenticationUtil.getRunAsUser(), nodeRef); + + if (transactionCache.containsKey(key)) + { + result = transactionCache.get(key); + } + else + { + if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED) + { + if (logger.isDebugEnabled()) + { + logger.debug("\t\tUser does not have read record permission on node, access denied. (nodeRef=" + nodeRef.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")"); + } + result = AccessDecisionVoter.ACCESS_DENIED; + } + else + { + // Get the file plan for the node + NodeRef filePlan = filePlanService.getFilePlan(nodeRef); + if (hasViewCapability(filePlan) == AccessStatus.DENIED) + { + if (logger.isDebugEnabled()) + { + logger.debug("\t\tUser does not have view records capability permission on node, access denied. (filePlan=" + filePlan.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")"); + } + result = AccessDecisionVoter.ACCESS_DENIED; + } + else if (!caveatConfigComponent.hasAccess(nodeRef)) + { + result = AccessDecisionVoter.ACCESS_DENIED; + } + else + { + result = AccessDecisionVoter.ACCESS_GRANTED; + } + } + + // cache result + transactionCache.put(key, result); + } + + return result; + } + + /** + * Helper method to determine whether the current user has view capability on the file plan + * + * @param filePlan file plan + * @return {@link AccessStatus} + */ + private AccessStatus hasViewCapability(NodeRef filePlan) + { + Map, AccessStatus> transactionCache = TransactionalResourceHelper.getMap("rm.security.hasViewCapability"); + Pair key = new Pair(AuthenticationUtil.getRunAsUser(), filePlan); + + if (transactionCache.containsKey(key)) + { + return transactionCache.get(key); + } + else + { + AccessStatus result = permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS); + transactionCache.put(key, result); + return result; + } } @SuppressWarnings("rawtypes") diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java index eb46eb54fb..117289965f 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java @@ -33,9 +33,7 @@ import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearch import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService; import org.alfresco.module.org_alfresco_module_rm.search.SavedSearchDetailsCompatibility; import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -44,6 +42,7 @@ import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.springframework.extensions.webscripts.Cache; @@ -199,20 +198,20 @@ public class RMSearchGet extends DeclarativeWebScript } // Execute search - List results = recordsManagementSearchService.search(siteId, query, searchParameters); + List> results = recordsManagementSearchService.search(siteId, query, searchParameters); // Reset person data cache personDataCache = new HashMap(57); // Process the result items List items = new ArrayList(results.size()); - for (NodeRef nodeRef : results) + for (Pair pair : results) { // FIXME: This is a workaround for DOD Recert // TC 3-3 Create User Groups try { - Item item = new Item(nodeRef); + Item item = new Item(pair.getFirst(), pair.getSecond()); items.add(item); } catch(Exception e) {} @@ -245,7 +244,7 @@ public class RMSearchGet extends DeclarativeWebScript private Map nodeProperties; private Map properties; - public Item(NodeRef nodeRef) + public Item(NodeRef parent, NodeRef nodeRef) { // Set node ref this.nodeRef = nodeRef; @@ -265,12 +264,12 @@ public class RMSearchGet extends DeclarativeWebScript } // Get parent node reference - NodeRef parent = null; - ChildAssociationRef assoc = nodeService.getPrimaryParent(nodeRef); - if (assoc != null) - { - parent = assoc.getParentRef(); - } +// NodeRef parent = null; +// ChildAssociationRef assoc = nodeService.getPrimaryParent(nodeRef); +// if (assoc != null) +// { +// parent = assoc.getParentRef(); +// } if (isContainer == true) { @@ -334,16 +333,6 @@ public class RMSearchGet extends DeclarativeWebScript if (NamespaceService.SYSTEM_MODEL_1_0_URI.equals(qName.getNamespaceURI()) == false) { String prefixName = qName.getPrefixString().replace(":", "_"); - Serializable value = entry.getValue(); - if (value instanceof NodeRef) - { - value = value.toString(); - } - else if (value instanceof ContentData) - { - ContentReader contentReader = contentService.getReader(nodeRef, qName); - value = contentReader.getContentString(); - } properties.put(prefixName, entry.getValue()); } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/search/RecordsManagementSearchService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/search/RecordsManagementSearchService.java index b4e971bae5..76ece11e65 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/search/RecordsManagementSearchService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/search/RecordsManagementSearchService.java @@ -21,6 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.search; import java.util.List; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.Pair; /** * Records management search service. @@ -33,10 +34,10 @@ public interface RecordsManagementSearchService * Execute a records management search * @param siteId the id of the rm site to query * @param query search query string - * @param searchParameters search parameters - * @return {@link List}<{@link NodeRef}> search results + * @param searchParameters search parameters + * @return {@link List}<{@link Pair}<{@link NodeRef}, {@link NodeRef}> search results as pairs for parent and child nodes */ - List search(String siteId, String query, RecordsManagementSearchParameters searchParameters); + List> search(String siteId, String query, RecordsManagementSearchParameters searchParameters); /** * Get all the searches saved on the given records management site. diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/search/RecordsManagementSearchServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/search/RecordsManagementSearchServiceImpl.java index 6383d99598..96a1b995d1 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/search/RecordsManagementSearchServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/search/RecordsManagementSearchServiceImpl.java @@ -30,6 +30,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; @@ -41,6 +42,7 @@ import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.ISO9075; +import org.alfresco.util.Pair; import org.alfresco.util.ParameterCheck; import org.json.JSONArray; import org.json.JSONException; @@ -173,7 +175,7 @@ public class RecordsManagementSearchServiceImpl implements RecordsManagementSear * @see org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService#search(java.lang.String, java.lang.String, org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchParameters) */ @Override - public List search(String siteId, String query, RecordsManagementSearchParameters rmSearchParameters) + public List> search(String siteId, String query, RecordsManagementSearchParameters rmSearchParameters) { // build the full RM query StringBuilder fullQuery = new StringBuilder(1024); @@ -206,9 +208,16 @@ public class RecordsManagementSearchServiceImpl implements RecordsManagementSear // execute query ResultSet resultSet = searchService.query(searchParameters); + + // process results + List> result = new ArrayList>(resultSet.length()); + for (ChildAssociationRef childAssoc : resultSet.getChildAssocRefs()) + { + result.add(new Pair(childAssoc.getParentRef(), childAssoc.getChildRef())); + } // return results - return resultSet.getNodeRefs(); + return result; } /** diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java index 4673d5256b..f3d4a8b6a6 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java @@ -49,4 +49,13 @@ public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicA { return getExtendedSecurityService().getExtendedReaders(nodeRef); } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName() + */ + @Override + protected String getTransactionCacheName() + { + return "rm.extendedreaderdynamicauthority"; + } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java index 2c439c3519..c1627476a8 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java @@ -28,6 +28,7 @@ import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.util.Pair; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -42,9 +43,6 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut RecordsManagementModel, ApplicationContextAware { - /** transaction cache key */ - private static final String KEY_HAS_AUTHORITY_CACHE = "rm.transaction.hasAuthority"; - /** Authority service */ private AuthorityService authorityService; @@ -95,6 +93,11 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut } return nodeService; } + + /** + * @return String transaction cache name + */ + protected abstract String getTransactionCacheName(); /** * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) @@ -122,51 +125,38 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut { boolean result = false; - if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY) == true) + Map, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName()); + Pair key = new Pair(nodeRef, userName); + + if (transactionCache.containsKey(key)) { - Set authorities = getAuthorites(nodeRef); - if (authorities != null) - { - for (String authority : authorities) - { - if ("GROUP_EVERYONE".equals(authority) == true) - { - // 'eveyone' is there so break - result = true; - break; - } - else if (authority.startsWith("GROUP_") == true) - { - Map transactionCache = TransactionalResourceHelper.getMap(KEY_HAS_AUTHORITY_CACHE); - String key = authority + "|" + userName; - if (transactionCache.containsKey(key)) - - { - result = transactionCache.get(key); - break; - } - else - { - Set contained = getAuthorityService().getAuthoritiesForUser(userName); - if (contained.contains(authority)) - { - result = true; - transactionCache.put(key, result); - break; - } - } - } - else - { - // presume we have a user - if (authority.equals(userName) == true) - { - result = true; - break; - } - } - } - } + result = transactionCache.get(key); + } + else + { + if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY) == true) + { + Set authorities = getAuthorites(nodeRef); + if (authorities != null) + { + // check for everyone or the user + if (authorities.contains("GROUP_EVEYONE") || + authorities.contains(userName)) + { + result = true; + } + else + { + // determine whether any of the users groups are in the extended security + Set contained = getAuthorityService().getAuthoritiesForUser(userName); + authorities.retainAll(contained); + result = (authorities.size() != 0); + } + } + } + + // cache result + transactionCache.put(key, result); } return result; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java index 24ff81ed13..af4eb53ad7 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java @@ -48,5 +48,14 @@ public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicA protected Set getAuthorites(NodeRef nodeRef) { return getExtendedSecurityService().getExtendedWriters(nodeRef); - } + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName() + */ + @Override + protected String getTransactionCacheName() + { + return "rm.extendedwriterdynamicauthority"; + } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java index 1dfe8d7010..21e1e349c6 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java @@ -338,24 +338,35 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte public NodeRef getFilePlan(final NodeRef nodeRef) { NodeRef result = null; - if (nodeRef != null) + if (nodeRef != null) { - result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF); - if (result == null || !instanceOf(result, TYPE_FILE_PLAN)) - { - if (instanceOf(nodeRef, TYPE_FILE_PLAN)) - { - result = nodeRef; - } - else - { - ChildAssociationRef parentAssocRef = getInternalNodeService().getPrimaryParent(nodeRef); - if (parentAssocRef != null) - { - result = getFilePlan(parentAssocRef.getParentRef()); - } - } - } + Map transactionCache = TransactionalResourceHelper.getMap("rm.servicebase.getFilePlan"); + if (transactionCache.containsKey(nodeRef)) + { + result = transactionCache.get(nodeRef); + } + else + { + result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF); + if (result == null || !instanceOf(result, TYPE_FILE_PLAN)) + { + if (instanceOf(nodeRef, TYPE_FILE_PLAN)) + { + result = nodeRef; + } + else + { + ChildAssociationRef parentAssocRef = getInternalNodeService().getPrimaryParent(nodeRef); + if (parentAssocRef != null) + { + result = getFilePlan(parentAssocRef.getParentRef()); + } + } + } + + // cache result in transaction + transactionCache.put(nodeRef, result); + } } return result; diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java index d964e145f9..2b4d918d26 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordServiceImplTest.java @@ -294,10 +294,12 @@ public class RecordServiceImplTest extends BaseRMTestCase // create record from document doTestInTransaction(new Test() { + private NodeRef originalLocation; + @Override public Void run() { - NodeRef originalLocation = nodeService.getPrimaryParent(dmDocument).getParentRef(); + originalLocation = nodeService.getPrimaryParent(dmDocument).getParentRef(); assertFalse(recordService.isRecord(dmDocument)); assertFalse(extendedSecurityService.hasExtendedSecurity(dmDocument)); @@ -318,7 +320,12 @@ public class RecordServiceImplTest extends BaseRMTestCase AccessStatus.DENIED); // doc/record recordService.createRecord(filePlan, dmDocument); - + + return null; + } + + public void test(Void result) + { checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file // plan AccessStatus.ALLOWED, // unfiled container @@ -367,8 +374,6 @@ public class RecordServiceImplTest extends BaseRMTestCase Capability updateProperties = capabilityService.getCapability("UpdateProperties"); assertEquals(AccessStatus.ALLOWED, updateProperties.hasPermission(dmDocument)); - - return null; } }, dmCollaborator); diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementSearchServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementSearchServiceImplTest.java index 0917fadb3e..8fbafad26e 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementSearchServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/service/RecordsManagementSearchServiceImplTest.java @@ -26,6 +26,7 @@ import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.util.Pair; import org.alfresco.util.TestWithUserUtils; /** @@ -151,7 +152,7 @@ public class RecordsManagementSearchServiceImplTest extends BaseRMTestCase String query = "keywords:\"elephant\""; RecordsManagementSearchParameters params = new RecordsManagementSearchParameters(); params.setIncludeUndeclaredRecords(true); - List results = rmSearchService.search(siteId, query, params); + List> results = rmSearchService.search(siteId, query, params); assertNotNull(results); assertEquals(2, results.size());