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
This commit is contained in:
Roy Wetherall
2014-07-18 04:17:45 +00:00
parent 60ab1304bd
commit 0431f25865
10 changed files with 198 additions and 136 deletions

View File

@@ -18,6 +18,8 @@
*/ */
package org.alfresco.module.org_alfresco_module_rm.capability; package org.alfresco.module.org_alfresco_module_rm.capability;
import java.util.Map;
import net.sf.acegisecurity.vote.AccessDecisionVoter; import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.error.AlfrescoRuntimeException; 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.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport; 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.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; 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.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.util.Pair;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -192,48 +196,82 @@ public class RMSecurityCommon
} }
/** /**
* Core RM read check
* *
* @param nodeRef * @param nodeRef node reference
* @return * @return int see {@link AccessDecisionVoter}
*/ */
public int checkRmRead(NodeRef nodeRef) public int checkRmRead(NodeRef nodeRef)
{ {
int result = getTransactionCache("checkRmRead", nodeRef); int result = AccessDecisionVoter.ACCESS_ABSTAIN;
if (result != NOSET_VALUE)
{ Map<Pair<String, NodeRef>, Integer> transactionCache = TransactionalResourceHelper.getMap("rm.security.checkRMRead");
return result; Pair<String, NodeRef> key = new Pair<String, NodeRef>(AuthenticationUtil.getRunAsUser(), nodeRef);
}
if (transactionCache.containsKey(key))
if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED) {
{ result = transactionCache.get(key);
if (logger.isDebugEnabled()) }
{ else
logger.debug("\t\tUser does not have read record permission on node, access denied. (nodeRef=" + nodeRef.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")"); {
} if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED)
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); {
} if (logger.isDebugEnabled())
{
// Get the file plan for the node logger.debug("\t\tUser does not have read record permission on node, access denied. (nodeRef=" + nodeRef.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")");
NodeRef filePlan = filePlanService.getFilePlan(nodeRef); }
result = AccessDecisionVoter.ACCESS_DENIED;
if (permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS) == AccessStatus.DENIED) }
{ else
if (logger.isDebugEnabled()) {
{ // Get the file plan for the node
logger.debug("\t\tUser does not have view records capability permission on node, access denied. (filePlan=" + filePlan.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")"); NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
} if (hasViewCapability(filePlan) == AccessStatus.DENIED)
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); {
} if (logger.isDebugEnabled())
{
if (caveatConfigComponent.hasAccess(nodeRef)) 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_GRANTED); result = AccessDecisionVoter.ACCESS_DENIED;
} }
else else if (!caveatConfigComponent.hasAccess(nodeRef))
{ {
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); 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<Pair<String, NodeRef>, AccessStatus> transactionCache = TransactionalResourceHelper.getMap("rm.security.hasViewCapability");
Pair<String, NodeRef> key = new Pair<String, NodeRef>(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") @SuppressWarnings("rawtypes")

View File

@@ -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.RecordsManagementSearchService;
import org.alfresco.module.org_alfresco_module_rm.search.SavedSearchDetailsCompatibility; import org.alfresco.module.org_alfresco_module_rm.search.SavedSearchDetailsCompatibility;
import org.alfresco.service.cmr.dictionary.DictionaryService; 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.ContentData;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; 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.cmr.site.SiteService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.extensions.webscripts.Cache; import org.springframework.extensions.webscripts.Cache;
@@ -199,20 +198,20 @@ public class RMSearchGet extends DeclarativeWebScript
} }
// Execute search // Execute search
List<NodeRef> results = recordsManagementSearchService.search(siteId, query, searchParameters); List<Pair<NodeRef, NodeRef>> results = recordsManagementSearchService.search(siteId, query, searchParameters);
// Reset person data cache // Reset person data cache
personDataCache = new HashMap<String, String>(57); personDataCache = new HashMap<String, String>(57);
// Process the result items // Process the result items
List<Item> items = new ArrayList<Item>(results.size()); List<Item> items = new ArrayList<Item>(results.size());
for (NodeRef nodeRef : results) for (Pair<NodeRef, NodeRef> pair : results)
{ {
// FIXME: This is a workaround for DOD Recert // FIXME: This is a workaround for DOD Recert
// TC 3-3 Create User Groups // TC 3-3 Create User Groups
try try
{ {
Item item = new Item(nodeRef); Item item = new Item(pair.getFirst(), pair.getSecond());
items.add(item); items.add(item);
} }
catch(Exception e) {} catch(Exception e) {}
@@ -245,7 +244,7 @@ public class RMSearchGet extends DeclarativeWebScript
private Map<QName, Serializable> nodeProperties; private Map<QName, Serializable> nodeProperties;
private Map<String, Serializable> properties; private Map<String, Serializable> properties;
public Item(NodeRef nodeRef) public Item(NodeRef parent, NodeRef nodeRef)
{ {
// Set node ref // Set node ref
this.nodeRef = nodeRef; this.nodeRef = nodeRef;
@@ -265,12 +264,12 @@ public class RMSearchGet extends DeclarativeWebScript
} }
// Get parent node reference // Get parent node reference
NodeRef parent = null; // NodeRef parent = null;
ChildAssociationRef assoc = nodeService.getPrimaryParent(nodeRef); // ChildAssociationRef assoc = nodeService.getPrimaryParent(nodeRef);
if (assoc != null) // if (assoc != null)
{ // {
parent = assoc.getParentRef(); // parent = assoc.getParentRef();
} // }
if (isContainer == true) if (isContainer == true)
{ {
@@ -334,16 +333,6 @@ public class RMSearchGet extends DeclarativeWebScript
if (NamespaceService.SYSTEM_MODEL_1_0_URI.equals(qName.getNamespaceURI()) == false) if (NamespaceService.SYSTEM_MODEL_1_0_URI.equals(qName.getNamespaceURI()) == false)
{ {
String prefixName = qName.getPrefixString().replace(":", "_"); 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()); properties.put(prefixName, entry.getValue());
} }
} }

View File

@@ -21,6 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.search;
import java.util.List; import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair;
/** /**
* Records management search service. * Records management search service.
@@ -33,10 +34,10 @@ public interface RecordsManagementSearchService
* Execute a records management search * Execute a records management search
* @param siteId the id of the rm site to query * @param siteId the id of the rm site to query
* @param query search query string * @param query search query string
* @param searchParameters search parameters * @param searchParameters search parameters
* @return {@link List}<{@link NodeRef}> search results * @return {@link List}<{@link Pair}<{@link NodeRef}, {@link NodeRef}> search results as pairs for parent and child nodes
*/ */
List<NodeRef> search(String siteId, String query, RecordsManagementSearchParameters searchParameters); List<Pair<NodeRef, NodeRef>> search(String siteId, String query, RecordsManagementSearchParameters searchParameters);
/** /**
* Get all the searches saved on the given records management site. * Get all the searches saved on the given records management site.

View File

@@ -30,6 +30,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo; 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.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef; 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.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075; import org.alfresco.util.ISO9075;
import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; 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) * @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 @Override
public List<NodeRef> search(String siteId, String query, RecordsManagementSearchParameters rmSearchParameters) public List<Pair<NodeRef, NodeRef>> search(String siteId, String query, RecordsManagementSearchParameters rmSearchParameters)
{ {
// build the full RM query // build the full RM query
StringBuilder fullQuery = new StringBuilder(1024); StringBuilder fullQuery = new StringBuilder(1024);
@@ -206,9 +208,16 @@ public class RecordsManagementSearchServiceImpl implements RecordsManagementSear
// execute query // execute query
ResultSet resultSet = searchService.query(searchParameters); ResultSet resultSet = searchService.query(searchParameters);
// process results
List<Pair<NodeRef, NodeRef>> result = new ArrayList<Pair<NodeRef, NodeRef>>(resultSet.length());
for (ChildAssociationRef childAssoc : resultSet.getChildAssocRefs())
{
result.add(new Pair<NodeRef, NodeRef>(childAssoc.getParentRef(), childAssoc.getChildRef()));
}
// return results // return results
return resultSet.getNodeRefs(); return result;
} }
/** /**

View File

@@ -49,4 +49,13 @@ public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicA
{ {
return getExtendedSecurityService().getExtendedReaders(nodeRef); return getExtendedSecurityService().getExtendedReaders(nodeRef);
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
*/
@Override
protected String getTransactionCacheName()
{
return "rm.extendedreaderdynamicauthority";
}
} }

View File

@@ -28,6 +28,7 @@ import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.util.Pair;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
@@ -42,9 +43,6 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
RecordsManagementModel, RecordsManagementModel,
ApplicationContextAware ApplicationContextAware
{ {
/** transaction cache key */
private static final String KEY_HAS_AUTHORITY_CACHE = "rm.transaction.hasAuthority";
/** Authority service */ /** Authority service */
private AuthorityService authorityService; private AuthorityService authorityService;
@@ -95,6 +93,11 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
} }
return nodeService; return nodeService;
} }
/**
* @return String transaction cache name
*/
protected abstract String getTransactionCacheName();
/** /**
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
@@ -122,51 +125,38 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
{ {
boolean result = false; boolean result = false;
if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY) == true) Map<Pair<NodeRef, String>, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName());
Pair<NodeRef, String> key = new Pair<NodeRef, String>(nodeRef, userName);
if (transactionCache.containsKey(key))
{ {
Set<String> authorities = getAuthorites(nodeRef); result = transactionCache.get(key);
if (authorities != null) }
{ else
for (String authority : authorities) {
{ if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY) == true)
if ("GROUP_EVERYONE".equals(authority) == true) {
{ Set<String> authorities = getAuthorites(nodeRef);
// 'eveyone' is there so break if (authorities != null)
result = true; {
break; // check for everyone or the user
} if (authorities.contains("GROUP_EVEYONE") ||
else if (authority.startsWith("GROUP_") == true) authorities.contains(userName))
{ {
Map<String, Boolean> transactionCache = TransactionalResourceHelper.getMap(KEY_HAS_AUTHORITY_CACHE); result = true;
String key = authority + "|" + userName; }
if (transactionCache.containsKey(key)) else
{
{ // determine whether any of the users groups are in the extended security
result = transactionCache.get(key); Set<String> contained = getAuthorityService().getAuthoritiesForUser(userName);
break; authorities.retainAll(contained);
} result = (authorities.size() != 0);
else }
{ }
Set<String> contained = getAuthorityService().getAuthoritiesForUser(userName); }
if (contained.contains(authority))
{ // cache result
result = true; transactionCache.put(key, result);
transactionCache.put(key, result);
break;
}
}
}
else
{
// presume we have a user
if (authority.equals(userName) == true)
{
result = true;
break;
}
}
}
}
} }
return result; return result;

View File

@@ -48,5 +48,14 @@ public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicA
protected Set<String> getAuthorites(NodeRef nodeRef) protected Set<String> getAuthorites(NodeRef nodeRef)
{ {
return getExtendedSecurityService().getExtendedWriters(nodeRef); return getExtendedSecurityService().getExtendedWriters(nodeRef);
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
*/
@Override
protected String getTransactionCacheName()
{
return "rm.extendedwriterdynamicauthority";
}
} }

View File

@@ -338,24 +338,35 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
public NodeRef getFilePlan(final NodeRef nodeRef) public NodeRef getFilePlan(final NodeRef nodeRef)
{ {
NodeRef result = null; NodeRef result = null;
if (nodeRef != null) if (nodeRef != null)
{ {
result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF); Map<NodeRef, NodeRef> transactionCache = TransactionalResourceHelper.getMap("rm.servicebase.getFilePlan");
if (result == null || !instanceOf(result, TYPE_FILE_PLAN)) if (transactionCache.containsKey(nodeRef))
{ {
if (instanceOf(nodeRef, TYPE_FILE_PLAN)) result = transactionCache.get(nodeRef);
{ }
result = nodeRef; else
} {
else result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF);
{ if (result == null || !instanceOf(result, TYPE_FILE_PLAN))
ChildAssociationRef parentAssocRef = getInternalNodeService().getPrimaryParent(nodeRef); {
if (parentAssocRef != null) if (instanceOf(nodeRef, TYPE_FILE_PLAN))
{ {
result = getFilePlan(parentAssocRef.getParentRef()); 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; return result;

View File

@@ -294,10 +294,12 @@ public class RecordServiceImplTest extends BaseRMTestCase
// create record from document // create record from document
doTestInTransaction(new Test<Void>() doTestInTransaction(new Test<Void>()
{ {
private NodeRef originalLocation;
@Override @Override
public Void run() public Void run()
{ {
NodeRef originalLocation = nodeService.getPrimaryParent(dmDocument).getParentRef(); originalLocation = nodeService.getPrimaryParent(dmDocument).getParentRef();
assertFalse(recordService.isRecord(dmDocument)); assertFalse(recordService.isRecord(dmDocument));
assertFalse(extendedSecurityService.hasExtendedSecurity(dmDocument)); assertFalse(extendedSecurityService.hasExtendedSecurity(dmDocument));
@@ -318,7 +320,12 @@ public class RecordServiceImplTest extends BaseRMTestCase
AccessStatus.DENIED); // doc/record AccessStatus.DENIED); // doc/record
recordService.createRecord(filePlan, dmDocument); recordService.createRecord(filePlan, dmDocument);
return null;
}
public void test(Void result)
{
checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file
// plan // plan
AccessStatus.ALLOWED, // unfiled container AccessStatus.ALLOWED, // unfiled container
@@ -367,8 +374,6 @@ public class RecordServiceImplTest extends BaseRMTestCase
Capability updateProperties = capabilityService.getCapability("UpdateProperties"); Capability updateProperties = capabilityService.getCapability("UpdateProperties");
assertEquals(AccessStatus.ALLOWED, updateProperties.hasPermission(dmDocument)); assertEquals(AccessStatus.ALLOWED, updateProperties.hasPermission(dmDocument));
return null;
} }
}, dmCollaborator); }, dmCollaborator);

View File

@@ -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.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.util.Pair;
import org.alfresco.util.TestWithUserUtils; import org.alfresco.util.TestWithUserUtils;
/** /**
@@ -151,7 +152,7 @@ public class RecordsManagementSearchServiceImplTest extends BaseRMTestCase
String query = "keywords:\"elephant\""; String query = "keywords:\"elephant\"";
RecordsManagementSearchParameters params = new RecordsManagementSearchParameters(); RecordsManagementSearchParameters params = new RecordsManagementSearchParameters();
params.setIncludeUndeclaredRecords(true); params.setIncludeUndeclaredRecords(true);
List<NodeRef> results = rmSearchService.search(siteId, query, params); List<Pair<NodeRef, NodeRef>> results = rmSearchService.search(siteId, query, params);
assertNotNull(results); assertNotNull(results);
assertEquals(2, results.size()); assertEquals(2, results.size());