Merged V1.3 to HEAD (3180:3203, 3204:3217)

svn merge svn://www.alfresco.org:3691/alfresco/BRANCHES/V1.3@3180 svn://www.alfresco.org:3691/alfresco/BRANCHES/V1.3@3203 .
   svn merge svn://www.alfresco.org:3691/alfresco/BRANCHES/V1.3@3204 svn://www.alfresco.org:3691/alfresco/BRANCHES/V1.3@3217 .


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3407 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2006-07-26 11:00:06 +00:00
parent 595556f3c5
commit f4e00169ab
40 changed files with 1155 additions and 643 deletions

View File

@@ -20,6 +20,7 @@ import java.security.NoSuchAlgorithmException;
import net.sf.acegisecurity.Authentication;
import org.alfresco.filesys.server.SrvSession;
import org.alfresco.filesys.server.auth.AuthContext;
import org.alfresco.filesys.server.auth.CifsAuthenticator;
import org.alfresco.filesys.server.auth.ClientInfo;
import org.alfresco.filesys.server.auth.NTLanManAuthContext;
@@ -182,26 +183,22 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
}
/**
* Generate a challenge key
* Return an authentication context for the new session
*
* @param sess SrvSession
* @return byte[]
* @return AuthContext
*/
public byte[] getChallengeKey(SrvSession sess)
public AuthContext getAuthContext( SMBSrvSession sess)
{
// In MD4 mode we generate the challenge locally
byte[] key = null;
// Check if the client is already authenticated, and it is not a null logon
AuthContext authCtx = null;
if ( sess.hasAuthenticationContext() && sess.hasAuthenticationToken() &&
sess.getClientInformation().getLogonType() != ClientInfo.LogonNull)
{
// Return the previous challenge, user is already authenticated
NTLanManAuthContext authCtx = (NTLanManAuthContext) sess.getAuthenticationContext();
key = authCtx.getChallenge();
authCtx = (NTLanManAuthContext) sess.getAuthenticationContext();
// DEBUG
@@ -210,11 +207,10 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
}
else if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
{
// Generate a new challenge key, pack the key and return
key = new byte[8];
DataPacker.putIntelLong(m_random.nextLong(), key, 0);
// Create a new authentication context for the session
authCtx = new NTLanManAuthContext();
sess.setAuthenticationContext( authCtx);
}
else
{
@@ -233,14 +229,17 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
// Get the challenge from the token
if ( authToken.getChallenge() != null)
key = authToken.getChallenge().getBytes();
{
authCtx = new NTLanManAuthContext( authToken.getChallenge().getBytes());
sess.setAuthenticationContext( authCtx);
}
}
// Return the challenge
// Return the authentication context
return key;
return authCtx;
}
/**
* Perform MD4 user authentication
*

View File

@@ -236,10 +236,8 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL
}
else
{
// Set using the user name, lowercase the name if the person service is case insensitive
// Set using the user name
if ( m_personService.getUserNamesAreCaseSensitive() == false)
username = username.toLowerCase();
m_authComponent.setCurrentUser( username);
// DEBUG

View File

@@ -19,7 +19,9 @@ package org.alfresco.filesys.smb.server.repo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.List;
import javax.transaction.UserTransaction;
@@ -352,7 +354,22 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface
URL appURL = this.getClass().getClassLoader().getResource(appPath.getValue());
if ( appURL == null)
throw new DeviceContextException("Failed to find drag and drop application, " + appPath.getValue());
File appFile = new File(appURL.getFile());
// Decode the URL path, it might contain escaped characters
String appURLPath = null;
try
{
appURLPath = URLDecoder.decode( appURL.getFile(), "UTF-8");
}
catch ( UnsupportedEncodingException ex)
{
throw new DeviceContextException("Failed to decode drag/drop path, " + ex.getMessage());
}
// Check that the drag/drop file exists
File appFile = new File(appURLPath);
if ( appFile.exists() == false)
throw new DeviceContextException("Drag and drop application not found, " + appPath.getValue());

View File

@@ -146,8 +146,8 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest
TestWithUserUtils.authenticateUser(this.userName, PWD, this.rootNodeRef, this.authenticationService);
this.userNodeRef = TestWithUserUtils.getCurrentUser(this.authenticationService);
permissionService.setPermission(this.rootNodeRef, this.userName.toLowerCase(), PermissionService.ALL_PERMISSIONS, true);
permissionService.setPermission(this.nodeRef, this.userName.toLowerCase(), PermissionService.ALL_PERMISSIONS, true);
permissionService.setPermission(this.rootNodeRef, this.userName, PermissionService.ALL_PERMISSIONS, true);
permissionService.setPermission(this.nodeRef, this.userName, PermissionService.ALL_PERMISSIONS, true);
}
/**

View File

@@ -44,6 +44,7 @@ import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -58,7 +59,7 @@ import org.springframework.core.io.Resource;
*
* @author David Caruana
*/
public class DescriptorServiceImpl implements DescriptorService, ApplicationListener, InitializingBean, ApplicationContextAware
public class DescriptorServiceImpl implements DescriptorService, ApplicationListener, InitializingBean, ApplicationContextAware, DisposableBean
{
private static Log logger = LogFactory.getLog(DescriptorServiceImpl.class);
@@ -201,6 +202,13 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
serverDescriptor = createServerDescriptor();
}
/**
* Destruction hook
*/
public void destroy() throws Exception
{
}
/**
* Create server descriptor
*
@@ -710,5 +718,4 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
return serverProperties.getProperty(key, "");
}
}
}

View File

@@ -149,12 +149,19 @@ public class ChildAssocImpl implements ChildAssoc, Serializable
return false;
}
ChildAssoc that = (ChildAssoc) obj;
return (
EqualsHelper.nullSafeEquals(this.getTypeQName(), that.getTypeQName())
&& EqualsHelper.nullSafeEquals(this.getQname(), that.getQname())
&& EqualsHelper.nullSafeEquals(this.getParent(), that.getParent())
&& EqualsHelper.nullSafeEquals(this.getChild(), that.getChild())
);
if (EqualsHelper.nullSafeEquals(id, that.getId()))
{
return true;
}
else
{
return (
EqualsHelper.nullSafeEquals(this.getChild().getId(), that.getChild().getId())
&& EqualsHelper.nullSafeEquals(this.getQname(), that.getQname())
&& EqualsHelper.nullSafeEquals(this.getParent().getId(), that.getParent().getId())
&& EqualsHelper.nullSafeEquals(this.getTypeQName(), that.getTypeQName())
);
}
}
public int hashCode()

View File

@@ -79,8 +79,15 @@ public class DbAccessControlEntryImpl extends LifecycleAdapter
return false;
}
DbAccessControlEntry other = (DbAccessControlEntry) o;
return (EqualsHelper.nullSafeEquals(this.permission, other.getPermission())
&& EqualsHelper.nullSafeEquals(this.authority, other.getAuthority()));
if (EqualsHelper.nullSafeEquals(id, other.getId()))
{
return true;
}
else
{
return (EqualsHelper.nullSafeEquals(this.permission, other.getPermission())
&& EqualsHelper.nullSafeEquals(this.authority, other.getAuthority()));
}
}
@Override

View File

@@ -137,8 +137,14 @@ public class NodeImpl extends LifecycleAdapter implements Node, Serializable
return false;
}
Node that = (Node) obj;
return (EqualsHelper.nullSafeEquals(getStore(), that.getStore())
&& EqualsHelper.nullSafeEquals(getUuid(), that.getUuid()));
if (EqualsHelper.nullSafeEquals(id, that.getId()))
{
return true;
}
else
{
return (this.getNodeRef().equals(that.getNodeRef()));
}
}
public int hashCode()

View File

@@ -135,8 +135,8 @@ public class LockBehaviourImplTest extends BaseSpringTest
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
permissionService.setPermission(rootNodeRef, GOOD_USER_NAME.toLowerCase(), PermissionService.ALL_PERMISSIONS, true);
permissionService.setPermission(rootNodeRef, BAD_USER_NAME.toLowerCase(), PermissionService.READ, true);
permissionService.setPermission(rootNodeRef, GOOD_USER_NAME, PermissionService.ALL_PERMISSIONS, true);
permissionService.setPermission(rootNodeRef, BAD_USER_NAME, PermissionService.READ, true);
}
/**

View File

@@ -31,6 +31,7 @@ import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
import org.alfresco.service.ServiceRegistry;
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.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -236,10 +237,80 @@ public class FileFolderPerformanceTester extends TestCase
}
}
public void test_2_ordered_1_10() throws Exception
private void readStructure(
final NodeRef parentNodeRef,
final int threadCount,
final int repetitions,
final double[] dumpPoints)
{
buildStructure(rootFolderRef, 2, false, 1, 10, null);
final List<ChildAssociationRef> children = nodeService.getChildAssocs(parentNodeRef);
Runnable runnable = new Runnable()
{
public void run()
{
// authenticate
authenticationComponent.setSystemUserAsCurrentUser();
for (int i = 0; i < repetitions; i++)
{
// read the contents of each folder
for (ChildAssociationRef childAssociationRef : children)
{
final NodeRef folderRef = childAssociationRef.getChildRef();
TransactionWork<Object> readWork = new TransactionWork<Object>()
{
public Object doWork() throws Exception
{
// read the child associations of the folder
nodeService.getChildAssocs(folderRef);
// get the type
nodeService.getType(folderRef);
// done
return null;
};
};
TransactionUtil.executeInUserTransaction(transactionService, readWork, true);
}
}
}
};
// kick off the required number of threads
logger.debug("\n" +
"Starting " + threadCount +
" threads reading properties and children of " + children.size() +
" folder " + repetitions +
" times.");
ThreadGroup threadGroup = new ThreadGroup(getName());
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++)
{
threads[i] = new Thread(threadGroup, runnable, String.format("FileReader-%02d", i));
threads[i].start();
}
// join each thread so that we wait for them all to finish
for (int i = 0; i < threads.length; i++)
{
try
{
threads[i].join();
}
catch (InterruptedException e)
{
// not too serious - the worker threads are non-daemon
}
}
}
public void test_1_ordered_1_10() throws Exception
{
buildStructure(rootFolderRef, 1, false, 1, 10, null);
}
// public void test_1_ordered_1_10_read() throws Exception
// {
// buildStructure(rootFolderRef, 1, false, 50, 1, null);
// readStructure(rootFolderRef, 50, 1000, null);
// }
//
// public void test_4_ordered_10_100() throws Exception
// {
@@ -250,24 +321,34 @@ public class FileFolderPerformanceTester extends TestCase
// {
// buildStructure(rootFolderRef, 4, true, 10, 100, new double[] {0.25, 0.50, 0.75});
// }
public void test_4_shuffled_100_100() throws Exception
// public void test_1_ordered_100_100() throws Exception
// {
// buildStructure(
// rootFolderRef,
// 1,
// false,
// 100,
// 100,
// new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
// }
public void test_1_shuffled_10_400() throws Exception
{
buildStructure(
rootFolderRef,
1,
true,
10,
400,
new double[] {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
}
public void test_4_shuffled_10_100() throws Exception
{
buildStructure(
rootFolderRef,
4,
true,
10,
100,
100,
new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
new double[] {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
}
// public void test_4_shuffled_1000_1000() throws Exception
// {
// buildStructure(
// rootFolderRef,
// 4,
// true,
// 1000,
// 1000,
// new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
// }
}

View File

@@ -45,6 +45,9 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.search.QueryParameterDefinition;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
@@ -59,17 +62,6 @@ import org.apache.commons.logging.LogFactory;
*/
public class FileFolderServiceImpl implements FileFolderService
{
/** Shallow search for all files */
private static final String XPATH_QUERY_SHALLOW_FILES =
"./*" +
"[(subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
/** Shallow search for all folder */
private static final String XPATH_QUERY_SHALLOW_FOLDERS =
"./*" +
"[not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "'))]";
/** Shallow search for files and folders with a name pattern */
private static final String XPATH_QUERY_SHALLOW_ALL =
"./*" +
@@ -77,6 +69,23 @@ public class FileFolderServiceImpl implements FileFolderService
" and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
/** Shallow search for all files and folders */
private static final String LUCENE_QUERY_SHALLOW_ALL =
"+PARENT:\"${cm:parent}\"" +
"-TYPE:\"" + ContentModel.TYPE_SYSTEM_FOLDER + "\" ";
/** Shallow search for all files and folders */
private static final String LUCENE_QUERY_SHALLOW_FOLDERS =
"+PARENT:\"${cm:parent}\"" +
"-TYPE:\"" + ContentModel.TYPE_SYSTEM_FOLDER + "\" " +
"+TYPE:\"" + ContentModel.TYPE_FOLDER + "\" ";
/** Shallow search for all files and folders */
private static final String LUCENE_QUERY_SHALLOW_FILES =
"+PARENT:\"${cm:parent}\"" +
"-TYPE:\"" + ContentModel.TYPE_SYSTEM_FOLDER + "\" " +
"+TYPE:\"" + ContentModel.TYPE_CONTENT + "\" ";
/** Deep search for files and folders with a name pattern */
private static final String XPATH_QUERY_DEEP_ALL =
".//*" +
@@ -85,8 +94,8 @@ public class FileFolderServiceImpl implements FileFolderService
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
/** empty parameters */
private static final QueryParameterDefinition[] PARAMS_EMPTY = new QueryParameterDefinition[0];
private static final QueryParameterDefinition[] PARAMS_ANY_NAME = new QueryParameterDefinition[1];
private static final QName PARAM_QNAME_PARENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "parent");
private static Log logger = LogFactory.getLog(FileFolderServiceImpl.class);
@@ -100,6 +109,7 @@ public class FileFolderServiceImpl implements FileFolderService
// TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
private List systemPaths;
private DataTypeDefinition dataTypeNodeRef;
/**
* Default constructor
@@ -157,6 +167,7 @@ public class FileFolderServiceImpl implements FileFolderService
dictionaryService.getDataType(DataTypeDefinition.TEXT),
true,
"%");
dataTypeNodeRef = dictionaryService.getDataType(DataTypeDefinition.NODE_REF);
}
/**
@@ -202,12 +213,17 @@ public class FileFolderServiceImpl implements FileFolderService
private void checkExists(NodeRef parentFolderRef, String name)
throws FileExistsException
{
// check for existing file or folder
List<FileInfo> existingFileInfos = this.search(parentFolderRef, name, true, true, false);
if (existingFileInfos.size() > 0)
// the name is never a wildcard, so we can perform an exact search
List<NodeRef> nodeRefs = searchInternal(parentFolderRef, name, true, true, false);
if (nodeRefs.size() == 0)
{
throw new FileExistsException(existingFileInfos.get(0));
// no match
return;
}
// we found a match, so raise the exception
NodeRef duplicateNodeRef = nodeRefs.get(0);
FileInfo duplicateFileInfo = toFileInfo(duplicateNodeRef);
throw new FileExistsException(duplicateFileInfo);
}
/**
@@ -258,18 +274,10 @@ public class FileFolderServiceImpl implements FileFolderService
}
}
/**
* TODO: Use Lucene search to get file attributes without having to visit the node service
*/
public List<FileInfo> list(NodeRef contextNodeRef)
{
// execute the query
List<NodeRef> nodeRefs = searchService.selectNodes(
contextNodeRef,
XPATH_QUERY_SHALLOW_ALL,
PARAMS_ANY_NAME,
namespaceService,
false);
List<NodeRef> nodeRefs = luceneSearch(contextNodeRef, true, true);
// convert the noderefs
List<FileInfo> results = toFileInfo(nodeRefs);
// done
@@ -282,18 +290,10 @@ public class FileFolderServiceImpl implements FileFolderService
return results;
}
/**
* TODO: Use Lucene search to get file attributes without having to visit the node service
*/
public List<FileInfo> listFiles(NodeRef contextNodeRef)
{
// execute the query
List<NodeRef> nodeRefs = searchService.selectNodes(
contextNodeRef,
XPATH_QUERY_SHALLOW_FILES,
PARAMS_EMPTY,
namespaceService,
false);
List<NodeRef> nodeRefs = luceneSearch(contextNodeRef, false, true);
// convert the noderefs
List<FileInfo> results = toFileInfo(nodeRefs);
// done
@@ -306,18 +306,10 @@ public class FileFolderServiceImpl implements FileFolderService
return results;
}
/**
* TODO: Use Lucene search to get file attributes without having to visit the node service
*/
public List<FileInfo> listFolders(NodeRef contextNodeRef)
{
// execute the query
List<NodeRef> nodeRefs = searchService.selectNodes(
contextNodeRef,
XPATH_QUERY_SHALLOW_FOLDERS,
PARAMS_EMPTY,
namespaceService,
false);
List<NodeRef> nodeRefs = luceneSearch(contextNodeRef, true, false);
// convert the noderefs
List<FileInfo> results = toFileInfo(nodeRefs);
// done
@@ -338,6 +330,7 @@ public class FileFolderServiceImpl implements FileFolderService
return search(contextNodeRef, namePattern, true, true, includeSubFolders);
}
private static final String LUCENE_MULTI_CHAR_WILDCARD = "*";
/**
* Full search with all options
*/
@@ -348,50 +341,9 @@ public class FileFolderServiceImpl implements FileFolderService
boolean folderSearch,
boolean includeSubFolders)
{
// shortcut if the search is requesting nothing
if (!fileSearch && !folderSearch)
{
return Collections.emptyList();
}
// get the raw nodeRefs
List<NodeRef> nodeRefs = searchInternal(contextNodeRef, namePattern, fileSearch, folderSearch, includeSubFolders);
// if the name pattern is null, then we use the ANY pattern
QueryParameterDefinition[] params = null;
if (namePattern != null)
{
// the interface specifies the Lucene syntax, so perform a conversion
namePattern = SearchLanguageConversion.convert(
SearchLanguageConversion.DEF_LUCENE,
SearchLanguageConversion.DEF_XPATH_LIKE,
namePattern);
params = new QueryParameterDefinition[1];
params[0] = new QueryParameterDefImpl(
ContentModel.PROP_NAME,
dictionaryService.getDataType(DataTypeDefinition.TEXT),
true,
namePattern);
}
else
{
params = PARAMS_ANY_NAME;
}
// determine the correct query to use
String query = null;
if (includeSubFolders)
{
query = XPATH_QUERY_DEEP_ALL;
}
else
{
query = XPATH_QUERY_SHALLOW_ALL;
}
// execute the query
List<NodeRef> nodeRefs = searchService.selectNodes(
contextNodeRef,
query,
params,
namespaceService,
false);
List<FileInfo> results = toFileInfo(nodeRefs);
// eliminate unwanted files/folders
Iterator<FileInfo> iterator = results.iterator();
@@ -420,6 +372,133 @@ public class FileFolderServiceImpl implements FileFolderService
}
return results;
}
/**
* Performs a full search, but doesn't translate the node references into
* file info objects. This allows {@link #checkExists(NodeRef, String)} to
* bypass the retrieval of node properties.
*/
public List<NodeRef> searchInternal(
NodeRef contextNodeRef,
String namePattern,
boolean fileSearch,
boolean folderSearch,
boolean includeSubFolders)
{
// shortcut if the search is requesting nothing
if (!fileSearch && !folderSearch)
{
return Collections.emptyList();
}
if (namePattern == null)
{
namePattern = LUCENE_MULTI_CHAR_WILDCARD; // default to wildcard
}
// now check if we can use Lucene to handle this query
boolean useLucene = false;
boolean anyName = namePattern.equals(LUCENE_MULTI_CHAR_WILDCARD);
if (!includeSubFolders && anyName)
{
// Lucene only handles any name or exact name
useLucene = true;
}
List<NodeRef> nodeRefs = null;
if (!useLucene) // go with the XPath queries
{
// if the name pattern is null, then we use the ANY pattern
QueryParameterDefinition[] params = null;
if (namePattern != null)
{
// the interface specifies the Lucene syntax, so perform a conversion
namePattern = SearchLanguageConversion.convert(
SearchLanguageConversion.DEF_LUCENE,
SearchLanguageConversion.DEF_XPATH_LIKE,
namePattern);
params = new QueryParameterDefinition[1];
params[0] = new QueryParameterDefImpl(
ContentModel.PROP_NAME,
dictionaryService.getDataType(DataTypeDefinition.TEXT),
true,
namePattern);
}
else
{
params = PARAMS_ANY_NAME;
}
// determine the correct query to use
String query = null;
if (includeSubFolders)
{
query = XPATH_QUERY_DEEP_ALL;
}
else
{
query = XPATH_QUERY_SHALLOW_ALL;
}
// execute the query
nodeRefs = searchService.selectNodes(
contextNodeRef,
query,
params,
namespaceService,
false);
}
else // go with Lucene queries
{
nodeRefs = luceneSearch(contextNodeRef, folderSearch, fileSearch);
}
// done
return nodeRefs;
}
private List<NodeRef> luceneSearch(NodeRef contextNodeRef, boolean folders, boolean files)
{
SearchParameters params = new SearchParameters();
params.setLanguage(SearchService.LANGUAGE_LUCENE);
params.addStore(contextNodeRef.getStoreRef());
// set the parent parameter
QueryParameterDefinition parentParamDef = new QueryParameterDefImpl(
PARAM_QNAME_PARENT,
dataTypeNodeRef,
true,
contextNodeRef.toString());
params.addQueryParameterDefinition(parentParamDef);
if (folders && files) // search for both files and folders
{
params.setQuery(LUCENE_QUERY_SHALLOW_ALL);
}
else if (folders) // search for folders only
{
params.setQuery(LUCENE_QUERY_SHALLOW_FOLDERS);
}
else if (files) // search for files only
{
params.setQuery(LUCENE_QUERY_SHALLOW_FILES);
}
else
{
throw new IllegalArgumentException("Must search for either files or folders or both");
}
ResultSet rs = searchService.query(params);
int length = rs.length();
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(length);
try
{
for (ResultSetRow row : rs)
{
nodeRefs.add(row.getNodeRef());
}
}
finally
{
rs.close();
}
// done
return nodeRefs;
}
/**
* @see #move(NodeRef, NodeRef, String)
@@ -467,10 +546,10 @@ public class FileFolderServiceImpl implements FileFolderService
targetParentRef = assocRef.getParentRef();
}
// there is nothing to do if both the name and parent folder haven't changed
boolean checkExists = true;
if (targetParentRef.equals(assocRef.getParentRef()))
{
// there is nothing to do if both the name and parent folder haven't changed
if (newName.equals(beforeFileInfo.getName()))
{
if (logger.isDebugEnabled())
@@ -484,17 +563,15 @@ public class FileFolderServiceImpl implements FileFolderService
}
else if (newName.equalsIgnoreCase(beforeFileInfo.getName()))
{
// name has only changed case so don't bother with exists check
checkExists = false;
}
}
// check for existing file or folder (if name has changed)
// check for existing file or folder
if (checkExists)
{
checkExists(targetParentRef, newName);
}
QName qname = QName.createQName(
NamespaceService.CONTENT_MODEL_1_0_URI,

View File

@@ -417,19 +417,20 @@ public class FileFolderServiceImplTest extends TestCase
{
// create a completely new path below the root
List<String> namePath = new ArrayList<String>(4);
namePath.add("A");
namePath.add("B");
namePath.add("C");
namePath.add("D");
namePath.add("AAA");
namePath.add("BBB");
namePath.add("CCC");
namePath.add("DDD");
FileInfo lastFileInfo = fileFolderService.makeFolders(rootNodeRef, namePath, ContentModel.TYPE_FOLDER);
assertNotNull("First makeFolder failed", lastFileInfo);
// check that a repeat works
FileInfo lastFileInfoAgain = fileFolderService.makeFolders(rootNodeRef, namePath, ContentModel.TYPE_FOLDER);
assertNotNull("Repeat makeFolders failed", lastFileInfoAgain);
assertEquals("Repeat created new leaf", lastFileInfo.getNodeRef(), lastFileInfoAgain.getNodeRef());
// check that it worked
List<FileInfo> checkInfos = fileFolderService.search(rootNodeRef, "D", false, true, true);
List<FileInfo> checkInfos = fileFolderService.search(rootNodeRef, "DDD", false, true, true);
assertEquals("Expected to find a result", 1, checkInfos.size());
// get the path
List<FileInfo> checkPathInfos = fileFolderService.getNamePath(rootNodeRef, checkInfos.get(0).getNodeRef());
@@ -442,6 +443,27 @@ public class FileFolderServiceImplTest extends TestCase
}
}
/**
* Lucene only indexes terms that are 3 characters or more
*/
public void testMakeFoldersShortNames() throws Exception
{
// create a completely new path below the root
List<String> namePath = new ArrayList<String>(4);
namePath.add("A");
namePath.add("B");
namePath.add("C");
namePath.add("D");
FileInfo lastFileInfo = fileFolderService.makeFolders(rootNodeRef, namePath, ContentModel.TYPE_FOLDER);
assertNotNull("First makeFolder failed", lastFileInfo);
// check that a repeat works
FileInfo lastFileInfoAgain = fileFolderService.makeFolders(rootNodeRef, namePath, ContentModel.TYPE_FOLDER);
assertNotNull("Repeat makeFolders failed", lastFileInfoAgain);
assertEquals("Repeat created new leaf", lastFileInfo.getNodeRef(), lastFileInfoAgain.getNodeRef());
}
public void testGetNamePath() throws Exception
{
FileInfo fileInfo = getByName(NAME_L1_FILE_A, false);

View File

@@ -42,6 +42,7 @@ import org.alfresco.repo.node.NodeServicePolicies.OnCreateStorePolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnDeleteAssociationPolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnDeleteChildAssociationPolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnDeleteNodePolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnUpdateNodePolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy;
@@ -96,6 +97,7 @@ public abstract class AbstractNodeServiceImpl implements NodeService
private ClassPolicyDelegate<OnCreateStorePolicy> onCreateStoreDelegate;
private ClassPolicyDelegate<BeforeCreateNodePolicy> beforeCreateNodeDelegate;
private ClassPolicyDelegate<OnCreateNodePolicy> onCreateNodeDelegate;
private ClassPolicyDelegate<OnMoveNodePolicy> onMoveNodeDelegate;
private ClassPolicyDelegate<BeforeUpdateNodePolicy> beforeUpdateNodeDelegate;
private ClassPolicyDelegate<OnUpdateNodePolicy> onUpdateNodeDelegate;
private ClassPolicyDelegate<OnUpdatePropertiesPolicy> onUpdatePropertiesDelegate;
@@ -161,6 +163,7 @@ public abstract class AbstractNodeServiceImpl implements NodeService
onCreateStoreDelegate = policyComponent.registerClassPolicy(NodeServicePolicies.OnCreateStorePolicy.class);
beforeCreateNodeDelegate = policyComponent.registerClassPolicy(NodeServicePolicies.BeforeCreateNodePolicy.class);
onCreateNodeDelegate = policyComponent.registerClassPolicy(NodeServicePolicies.OnCreateNodePolicy.class);
onMoveNodeDelegate = policyComponent.registerClassPolicy(NodeServicePolicies.OnMoveNodePolicy.class);
beforeUpdateNodeDelegate = policyComponent.registerClassPolicy(NodeServicePolicies.BeforeUpdateNodePolicy.class);
onUpdateNodeDelegate = policyComponent.registerClassPolicy(NodeServicePolicies.OnUpdateNodePolicy.class);
onUpdatePropertiesDelegate = policyComponent.registerClassPolicy(NodeServicePolicies.OnUpdatePropertiesPolicy.class);
@@ -227,6 +230,19 @@ public abstract class AbstractNodeServiceImpl implements NodeService
policy.onCreateNode(childAssocRef);
}
/**
* @see NodeServicePolicies.OnMoveNodePolicy#onMoveNode(ChildAssociationRef, ChildAssociationRef)
*/
protected void invokeOnMoveNode(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef)
{
NodeRef childNodeRef = newChildAssocRef.getChildRef();
// get qnames to invoke against
Set<QName> qnames = getTypeAndAspectQNames(childNodeRef);
// execute policy for node type and aspects
NodeServicePolicies.OnMoveNodePolicy policy = onMoveNodeDelegate.get(childNodeRef, qnames);
policy.onMoveNode(oldChildAssocRef, newChildAssocRef);
}
/**
* @see NodeServicePolicies.BeforeUpdateNodePolicy#beforeUpdateNode(NodeRef)
*/

View File

@@ -1153,6 +1153,17 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
RegexQNamePattern.MATCH_ALL);
}
public static class MovePolicyTester implements NodeServicePolicies.OnMoveNodePolicy
{
public List<ChildAssociationRef> policyAssocRefs = new ArrayList<ChildAssociationRef>(2);
public void onMoveNode(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef)
{
policyAssocRefs.add(oldChildAssocRef);
policyAssocRefs.add(newChildAssocRef);
}
};
public void testMoveNode() throws Exception
{
Map<QName, ChildAssociationRef> assocRefs = buildNodeGraph();
@@ -1163,12 +1174,24 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
NodeRef n5Ref = n5pn7Ref.getParentRef();
NodeRef n6Ref = n6pn8Ref.getParentRef();
NodeRef n8Ref = n6pn8Ref.getChildRef();
MovePolicyTester policy = new MovePolicyTester();
// bind to listen to the deletion of a node
policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onMoveNode"),
policy,
new JavaBehaviour(policy, "onMoveNode"));
// move n8 to n5
ChildAssociationRef assocRef = nodeService.moveNode(
n8Ref,
n5Ref,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName(BaseNodeServiceTest.NAMESPACE, "n5_p_n8"));
// check that the move policy was fired
assertEquals("Move policy not fired", 2, policy.policyAssocRefs.size());
// check that n6 is no longer the parent
List<ChildAssociationRef> n6ChildRefs = nodeService.getChildAssocs(
n6Ref,

View File

@@ -82,6 +82,17 @@ public interface NodeServicePolicies
public void onCreateNode(ChildAssociationRef childAssocRef);
}
public interface OnMoveNodePolicy extends ClassPolicy
{
/**
* Called when a node has been moved.
*
* @param oldChildAssocRef the child association reference prior to the move
* @param newChildAssocRef the child association reference after the move
*/
public void onMoveNode(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef);
}
public interface BeforeUpdateNodePolicy extends ClassPolicy
{
/**

View File

@@ -434,6 +434,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
nodeDaoService.deleteChildAssoc(oldAssoc, false);
// create a new assoc
ChildAssoc newAssoc = nodeDaoService.newChildAssoc(newParentNode, nodeToMove, true, assocTypeQName, assocQName);
ChildAssociationRef newAssocRef = newAssoc.getChildAssocRef();
// If the node is moving stores, then drag the node hierarchy with it
if (movingStore)
@@ -463,6 +464,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
invokeOnUpdateNode(oldParentNode.getNodeRef());
invokeOnUpdateNode(newParentRef);
}
invokeOnMoveNode(oldAssocRef, newAssocRef);
// update the node status
nodeDaoService.recordChangeId(nodeToMoveRef);

View File

@@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.search.impl.lucene.analysis.PathAnalyser;
import org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
@@ -117,8 +118,23 @@ public class LuceneAnalyser extends Analyzer
{
QName propertyQName = QName.createQName(fieldName.substring(1));
PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName);
DataTypeDefinition dataType = (propertyDef == null) ? dictionaryService.getDataType(DataTypeDefinition.TEXT) : propertyDef.getDataType();
analyser = loadAnalyzer(dataType);
if (propertyDef != null)
{
if (propertyDef.isTokenisedInIndex())
{
DataTypeDefinition dataType = propertyDef.getDataType();
analyser = loadAnalyzer(dataType);
}
else
{
analyser = new VerbatimAnalyser();
}
}
else
{
DataTypeDefinition dataType = dictionaryService.getDataType(DataTypeDefinition.TEXT);
analyser = loadAnalyzer(dataType);
}
}
else
{
@@ -127,28 +143,31 @@ public class LuceneAnalyser extends Analyzer
analysers.put(fieldName, analyser);
return analyser;
}
private Analyzer loadAnalyzer(DataTypeDefinition dataType)
{
String analyserClassName = dataType.getAnalyserClassName();
try
{
Class<?> clazz = Class.forName(analyserClassName);
Analyzer analyser = (Analyzer)clazz.newInstance();
Analyzer analyser = (Analyzer) clazz.newInstance();
return analyser;
}
catch (ClassNotFoundException e)
{
throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using " + analyserClassName);
throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using "
+ analyserClassName);
}
catch (InstantiationException e)
{
throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using " + analyserClassName);
throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using "
+ analyserClassName);
}
catch (IllegalAccessException e)
{
throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using " + analyserClassName);
throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using "
+ analyserClassName);
}
}
}

View File

@@ -264,6 +264,7 @@ public class LuceneTest extends TestCase
testProperties.put(QName.createQName(TEST_NAMESPACE, "category-ista"), new NodeRef(storeRef, "CategoryId"));
testProperties.put(QName.createQName(TEST_NAMESPACE, "noderef-ista"), n1);
testProperties.put(QName.createQName(TEST_NAMESPACE, "path-ista"), nodeService.getPath(n3));
testProperties.put(QName.createQName(TEST_NAMESPACE, "verbatim"), " ");
testProperties.put(QName.createQName(TEST_NAMESPACE, "null"), null);
testProperties.put(QName.createQName(TEST_NAMESPACE, "list"), new ArrayList());
ArrayList<Object> testList = new ArrayList<Object>();
@@ -1855,6 +1856,19 @@ public class LuceneTest extends TestCase
assertNotNull(results.getRow(0).getValue(QName.createQName(TEST_NAMESPACE, "path-ista")));
results.close();
results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "\\@"
+ escapeQName(QName.createQName(TEST_NAMESPACE, "verbatim")) + ":\" \"",
null, null);
assertEquals(1, results.length());
assertNotNull(results.getRow(0).getValue(QName.createQName(TEST_NAMESPACE, "verbatim")));
results.close();
results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "\\@"
+ escapeQName(QName.createQName(TEST_NAMESPACE, "verbatim")) + ":\" \"",
null, null);
assertEquals(0, results.length());
results.close();
results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "TYPE:\"" + testType.toString() + "\"", null,
null);
assertEquals(1, results.length());

View File

@@ -14,217 +14,176 @@
<namespace uri="http://www.alfresco.org/test/lucenetest" prefix="test"/>
</namespaces>
<types>
<type name="test:testSuperType">
<title>Test Super Type</title>
<parent>sys:container</parent>
<properties>
<property name="test:createdDate">
<type>d:date</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:orderDouble">
<type>d:double</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:orderFloat">
<type>d:float</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:orderLong">
<type>d:long</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:orderInt">
<type>d:int</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
</properties>
<associations>
<child-association name="test:assoc">
<source>
<mandatory>false</mandatory>
<many>true</many>
</source>
<target>
<class>sys:base</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</child-association>
</associations>
</type>
<type name="test:testType">
<title>Test Type</title>
<parent>test:testSuperType</parent>
<properties>
<property name="test:text-indexed-stored-tokenised-atomic">
<type>d:text</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:text-indexed-unstored-tokenised-atomic">
<type>d:text</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>false</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:text-indexed-stored-tokenised-nonatomic">
<type>d:text</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>false</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:int-ista">
<type>d:int</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:long-ista">
<type>d:long</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:float-ista">
<type>d:float</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:double-ista">
<type>d:double</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:date-ista">
<type>d:date</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:datetime-ista">
<type>d:datetime</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:boolean-ista">
<type>d:boolean</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:qname-ista">
<type>d:qname</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:category-ista">
<type>d:category</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:noderef-ista">
<type>d:noderef</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
</properties>
<mandatory-aspects>
<aspect>test:testAspect</aspect>
</mandatory-aspects>
</type>
</types>
<types>
<type name="test:testSuperType">
<title>Test Super Type</title>
<parent>sys:container</parent>
<associations>
<child-association name="test:assoc">
<source>
<mandatory>false</mandatory>
<many>true</many>
</source>
<target>
<class>sys:base</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</child-association>
</associations>
</type>
<type name="test:testType">
<title>Test Type</title>
<parent>test:testSuperType</parent>
<properties>
<property name="test:text-indexed-stored-tokenised-atomic">
<type>d:text</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:text-indexed-unstored-tokenised-atomic">
<type>d:text</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>false</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:text-indexed-stored-tokenised-nonatomic">
<type>d:text</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>false</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:int-ista">
<type>d:int</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:long-ista">
<type>d:long</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:float-ista">
<type>d:float</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:double-ista">
<type>d:double</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:date-ista">
<type>d:date</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:datetime-ista">
<type>d:datetime</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:boolean-ista">
<type>d:boolean</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:qname-ista">
<type>d:qname</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:category-ista">
<type>d:category</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:noderef-ista">
<type>d:noderef</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>true</tokenised>
</index>
</property>
<property name="test:verbatim">
<type>d:text</type>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>true</stored>
<tokenised>false</tokenised>
</index>
</property>
</properties>
<mandatory-aspects>
<aspect>test:testAspect</aspect>
</mandatory-aspects>
</type>
</types>
>>>>>>> .merge-right.r3203
<aspects>
<aspect name="test:testSuperAspect">

View File

@@ -0,0 +1,22 @@
package org.alfresco.repo.search.impl.lucene.analysis;
import java.io.Reader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
public class VerbatimAnalyser
extends Analyzer
{
public VerbatimAnalyser()
{
super();
}
public TokenStream tokenStream(String fieldName, Reader reader)
{
return new VerbatimTokenFilter(reader);
}
}

View File

@@ -0,0 +1,42 @@
package org.alfresco.repo.search.impl.lucene.analysis;
import java.io.IOException;
import java.io.Reader;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.Tokenizer;
public class VerbatimTokenFilter extends Tokenizer
{
boolean readInput = true;
VerbatimTokenFilter(Reader in)
{
super(in);
}
@Override
public Token next() throws IOException
{
if (readInput)
{
readInput = false;
StringBuilder buffer = new StringBuilder();
int current;
char c;
while ((current = input.read()) != -1)
{
c = (char) current;
buffer.append(c);
}
String token = buffer.toString();
return new Token(token, 0, token.length() - 1, "VERBATIM");
}
else
{
return null;
}
}
}

View File

@@ -39,7 +39,6 @@ import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.providers.dao.SaltSource;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.permissions.PermissionServiceSPI;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -89,8 +88,6 @@ public class AuthenticationTest extends TestCase
private AuthenticationComponent authenticationComponent;
private PermissionServiceSPI permissionServiceSPI;
private UserTransaction userTransaction;
private AuthenticationComponent authenticationComponentImpl;
@@ -117,7 +114,8 @@ public class AuthenticationTest extends TestCase
pubAuthenticationService = (AuthenticationService) ctx.getBean("AuthenticationService");
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
authenticationComponentImpl = (AuthenticationComponent) ctx.getBean("authenticationComponentImpl");
permissionServiceSPI = (PermissionServiceSPI) ctx.getBean("permissionService");
// permissionServiceSPI = (PermissionServiceSPI)
// ctx.getBean("permissionService");
dao = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
authenticationManager = (AuthenticationManager) ctx.getBean("authenticationManager");
@@ -181,7 +179,6 @@ public class AuthenticationTest extends TestCase
public void xtestScalability()
{
long create = 0;
long count = 0;
long start;
long end;
@@ -207,6 +204,49 @@ public class AuthenticationTest extends TestCase
authenticationComponent.clearCurrentSecurityContext();
}
public void c()
{
try
{
authenticationService.authenticate("", "".toCharArray());
}
catch (AuthenticationException e)
{
// Expected
}
}
public void testCreateUsers()
{
authenticationService.createAuthentication("GUEST", "".toCharArray());
authenticationService.authenticate("GUEST", "".toCharArray());
// Guest is reported as lower case and the authentication basically
// ignored at the moment
assertEquals("guest", authenticationService.getCurrentUserName());
authenticationService.createAuthentication("Andy", "".toCharArray());
authenticationService.authenticate("Andy", "".toCharArray());
assertEquals("Andy", authenticationService.getCurrentUserName());
authenticationService.createAuthentication("Mr.Woof.Banana@chocolate.chip.cookie.com", "".toCharArray());
authenticationService.authenticate("Mr.Woof.Banana@chocolate.chip.cookie.com", "".toCharArray());
assertEquals("Mr.Woof.Banana@chocolate.chip.cookie.com", authenticationService.getCurrentUserName());
authenticationService.createAuthentication("Andy_Woof/Domain", "".toCharArray());
authenticationService.authenticate("Andy_Woof/Domain", "".toCharArray());
assertEquals("Andy_Woof/Domain", authenticationService.getCurrentUserName());
authenticationService.createAuthentication("Andy_ Woof/Domain", "".toCharArray());
authenticationService.authenticate("Andy_ Woof/Domain", "".toCharArray());
assertEquals("Andy_ Woof/Domain", authenticationService.getCurrentUserName());
authenticationService.createAuthentication("Andy `\u00ac\u00a6!\u00a3$%^&*()-_=+\t\n\u0000[]{};'#:@~,./<>?\\|", "".toCharArray());
authenticationService.authenticate("Andy `\u00ac\u00a6!\u00a3$%^&*()-_=+\t\n\u0000[]{};'#:@~,./<>?\\|", "".toCharArray());
assertEquals("Andy `\u00ac\u00a6!\u00a3$%^&*()-_=+\t\n\u0000[]{};'#:@~,./<>?\\|", authenticationService.getCurrentUserName());
}
public void testCreateAndyUserAndOtherCRUD() throws NoSuchAlgorithmException, UnsupportedEncodingException
{
RepositoryAuthenticationDao dao = new RepositoryAuthenticationDao();
@@ -225,7 +265,7 @@ public class AuthenticationTest extends TestCase
UserDetails AndyDetails = (UserDetails) dao.loadUserByUsername("Andy");
assertNotNull(AndyDetails);
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", AndyDetails.getUsername());
assertEquals("Andy", AndyDetails.getUsername());
// assertNotNull(dao.getSalt(AndyDetails));
assertTrue(AndyDetails.isAccountNonExpired());
assertTrue(AndyDetails.isAccountNonLocked());
@@ -240,7 +280,7 @@ public class AuthenticationTest extends TestCase
dao.updateUser("Andy", "carrot".toCharArray());
UserDetails newDetails = (UserDetails) dao.loadUserByUsername("Andy");
assertNotNull(newDetails);
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", newDetails.getUsername());
assertEquals("Andy", newDetails.getUsername());
// assertNotNull(dao.getSalt(newDetails));
assertTrue(newDetails.isAccountNonExpired());
assertTrue(newDetails.isAccountNonLocked());
@@ -624,7 +664,7 @@ public class AuthenticationTest extends TestCase
authenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
authenticationService.clearCurrentSecurityContext();
@@ -660,7 +700,7 @@ public class AuthenticationTest extends TestCase
authenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
authenticationService.clearCurrentSecurityContext();
@@ -696,7 +736,7 @@ public class AuthenticationTest extends TestCase
authenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
authenticationService.clearCurrentSecurityContext();
@@ -742,7 +782,7 @@ public class AuthenticationTest extends TestCase
authenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
authenticationService.clearCurrentSecurityContext();
@@ -798,7 +838,7 @@ public class AuthenticationTest extends TestCase
authenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
authenticationService.clearCurrentSecurityContext();
@@ -857,7 +897,7 @@ public class AuthenticationTest extends TestCase
authenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
authenticationService.clearCurrentSecurityContext();
@@ -918,7 +958,7 @@ public class AuthenticationTest extends TestCase
pubAuthenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
pubAuthenticationService.clearCurrentSecurityContext();
@@ -966,7 +1006,7 @@ public class AuthenticationTest extends TestCase
pubAuthenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
pubAuthenticationService.clearCurrentSecurityContext();
@@ -1013,7 +1053,7 @@ public class AuthenticationTest extends TestCase
pubAuthenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
pubAuthenticationService.clearCurrentSecurityContext();
@@ -1085,7 +1125,7 @@ public class AuthenticationTest extends TestCase
pubAuthenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
pubAuthenticationService.clearCurrentSecurityContext();
@@ -1114,7 +1154,7 @@ public class AuthenticationTest extends TestCase
pubAuthenticationService.invalidateTicket(ticket);
}
public void testPubAuthenticationService0()
{
// pubAuthenticationService.authenticateAsGuest();
@@ -1145,7 +1185,7 @@ public class AuthenticationTest extends TestCase
pubAuthenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// delete the user authentication object
pubAuthenticationService.clearCurrentSecurityContext();
@@ -1172,21 +1212,21 @@ public class AuthenticationTest extends TestCase
// destroy the ticket instance
pubAuthenticationService.invalidateTicket(ticket);
authenticationComponent.clearCurrentSecurityContext();
pubAuthenticationService.authenticate("Andy", "auth3".toCharArray());
pubAuthenticationService.updateAuthentication("Andy", "auth3".toCharArray(), "auth4".toCharArray());
pubAuthenticationService.authenticate("Andy", "auth4".toCharArray());
try
{
pubAuthenticationService.updateAuthentication("Andy", "auth3".toCharArray(), "auth4".toCharArray());
fail("Should not be able to update");
pubAuthenticationService.updateAuthentication("Andy", "auth3".toCharArray(), "auth4".toCharArray());
fail("Should not be able to update");
}
catch(AuthenticationException ae)
catch (AuthenticationException ae)
{
}
}
@@ -1202,7 +1242,7 @@ public class AuthenticationTest extends TestCase
authenticationService.createAuthentication("Andy", "auth1".toCharArray());
authenticationComponent.setCurrentUser("Andy");
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
assertEquals("Andy", authenticationService.getCurrentUserName());
// authenticationService.deleteAuthentication("andy");
}

View File

@@ -22,7 +22,6 @@ import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.StoreRef;
import org.springframework.dao.DataAccessException;
/**
@@ -246,16 +245,6 @@ public class DefaultMutableAuthenticationDao implements MutableAuthenticationDao
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Are user names case sensitive?
*
* @return
*/
public boolean getUserNamesAreCaseSensitive()
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Return the user details for the specified user

View File

@@ -184,11 +184,4 @@ public interface MutableAuthenticationDao extends AuthenticationDao, SaltSource
*/
public String getMD4HashedPassword(String userName);
/**
* Are user names case sensitive?
*
* @return
*/
public boolean getUserNamesAreCaseSensitive();
}

View File

@@ -31,6 +31,7 @@ import net.sf.acegisecurity.providers.encoding.PasswordEncoder;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParser;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -54,6 +55,7 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
private NamespacePrefixResolver namespacePrefixResolver;
@SuppressWarnings("unused")
private DictionaryService dictionaryService;
private SearchService searchService;
@@ -97,20 +99,23 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
this.searchService = searchService;
}
public UserDetails loadUserByUsername(String caseSensitiveUserName) throws UsernameNotFoundException,
public UserDetails loadUserByUsername(String incomingUserName) throws UsernameNotFoundException,
DataAccessException
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName : caseSensitiveUserName.toLowerCase();
NodeRef userRef = getUserOrNull(userName);
NodeRef userRef = getUserOrNull(incomingUserName);
if (userRef == null)
{
throw new UsernameNotFoundException("Could not find user by userName: " + caseSensitiveUserName);
throw new UsernameNotFoundException("Could not find user by userName: " + incomingUserName);
}
Map<QName, Serializable> properties = nodeService.getProperties(userRef);
String password = DefaultTypeConverter.INSTANCE.convert(String.class, properties
.get(ContentModel.PROP_PASSWORD));
// Report back the user name as stored on the user
String userName = DefaultTypeConverter.INSTANCE.convert(String.class, properties
.get(ContentModel.PROP_USER_USERNAME));
GrantedAuthority[] gas = new GrantedAuthority[1];
gas[0] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED");
@@ -119,12 +124,20 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
return ud;
}
public NodeRef getUserOrNull(String caseSensitiveUserName)
public NodeRef getUserOrNull(String searchUserName)
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName : caseSensitiveUserName.toLowerCase();
if(searchUserName == null)
{
return null;
}
if(searchUserName.length() == 0)
{
return null;
}
SearchParameters sp = new SearchParameters();
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery("@usr\\:username:" + userName);
sp.setQuery("@usr\\:username:\"" + searchUserName + "\"");
sp.addStore(STOREREF_USERS);
sp.excludeDataInTheCurrentTransaction(false);
@@ -134,6 +147,8 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
{
rs = searchService.query(sp);
NodeRef returnRef = null;
for (ResultSetRow row : rs)
{
@@ -142,12 +157,39 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
{
String realUserName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(
nodeRef, ContentModel.PROP_USER_USERNAME));
if (realUserName.equals(userName))
if (userNamesAreCaseSensitive)
{
return nodeRef;
if (realUserName.equals(searchUserName))
{
if(returnRef == null)
{
returnRef = nodeRef;
}
else
{
throw new AlfrescoRuntimeException("Found more than one user for "+searchUserName+ " (case sensitive)");
}
}
}
else
{
if (realUserName.equalsIgnoreCase(searchUserName))
{
if(returnRef == null)
{
returnRef = nodeRef;
}
else
{
throw new AlfrescoRuntimeException("Found more than one user for "+searchUserName+ " (case insensitive)");
}
}
}
}
}
return returnRef;
}
finally
{
@@ -156,21 +198,18 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
rs.close();
}
}
return null;
}
public void createUser(String caseSensitiveUserName, char[] rawPassword) throws AuthenticationException
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName : caseSensitiveUserName.toLowerCase();
NodeRef userRef = getUserOrNull(userName);
NodeRef userRef = getUserOrNull(caseSensitiveUserName);
if (userRef != null)
{
throw new AuthenticationException("User already exists: " + userName);
throw new AuthenticationException("User already exists: " + caseSensitiveUserName);
}
NodeRef typesNode = getUserFolderLocation();
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
properties.put(ContentModel.PROP_USER_USERNAME, userName);
properties.put(ContentModel.PROP_USER_USERNAME, caseSensitiveUserName);
String salt = null; // GUID.generate();
properties.put(ContentModel.PROP_SALT, salt);
properties.put(ContentModel.PROP_PASSWORD, passwordEncoder.encodePassword(new String(rawPassword), salt));
@@ -178,11 +217,7 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
properties.put(ContentModel.PROP_CREDENTIALS_EXPIRE, Boolean.valueOf(false));
properties.put(ContentModel.PROP_ENABLED, Boolean.valueOf(true));
properties.put(ContentModel.PROP_ACCOUNT_LOCKED, Boolean.valueOf(false));
nodeService.createNode(
typesNode,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_USER,
ContentModel.TYPE_USER,
nodeService.createNode(typesNode, ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_USER, ContentModel.TYPE_USER,
properties);
}
@@ -190,11 +225,10 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
private NodeRef getUserFolderLocation()
{
QName qnameAssocSystem = QName.createQName("sys", "system", namespacePrefixResolver);
QName qnameAssocUsers = QName.createQName("sys", "people", namespacePrefixResolver); // see AR-527
QName qnameAssocUsers = QName.createQName("sys", "people", namespacePrefixResolver); // see
// AR-527
NodeRef rootNode = nodeService.getRootNode(STOREREF_USERS);
List<ChildAssociationRef> results = nodeService.getChildAssocs(
rootNode,
RegexQNamePattern.MATCH_ALL,
List<ChildAssociationRef> results = nodeService.getChildAssocs(rootNode, RegexQNamePattern.MATCH_ALL,
qnameAssocSystem);
NodeRef sysNodeRef = null;
if (results.size() == 0)
@@ -205,10 +239,7 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
{
sysNodeRef = results.get(0).getChildRef();
}
results = nodeService.getChildAssocs(
sysNodeRef,
RegexQNamePattern.MATCH_ALL,
qnameAssocUsers);
results = nodeService.getChildAssocs(sysNodeRef, RegexQNamePattern.MATCH_ALL, qnameAssocUsers);
NodeRef userNodeRef = null;
if (results.size() == 0)
{

View File

@@ -19,7 +19,6 @@ package org.alfresco.repo.security.authentication.ldap;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.HashMap;

View File

@@ -662,10 +662,9 @@ public class NTLMAuthenticationComponentImpl extends AbstractAuthenticationCompo
}
else
{
// Set using the user name, lowercase the name if hte person service is case insensitive
// Set using the user name
if ( m_personService.getUserNamesAreCaseSensitive() == false)
username = username.toLowerCase();
setCurrentUser( username);
// DEBUG
@@ -838,10 +837,8 @@ public class NTLMAuthenticationComponentImpl extends AbstractAuthenticationCompo
}
else
{
// Set using the user name, lowercase the name if the person service is case insensitive
// Set using the user name
if ( m_personService.getUserNamesAreCaseSensitive() == false)
username = username.toLowerCase();
setCurrentUser( username);
// DEBUG

View File

@@ -294,18 +294,6 @@ public class NullMutableAuthenticationDao implements MutableAuthenticationDao
// return null;
}
/**
* Are user names case sensitive?
*
* @return
*/
public boolean getUserNamesAreCaseSensitive()
{
throw new AlfrescoRuntimeException("Not implemented");
// return false;
}
/**
* Return the user details for the specified user

View File

@@ -118,7 +118,7 @@ public class AuthorityDAOImpl implements AuthorityDAO
nodeService.setProperty(parentRef, ContentModel.PROP_MEMBERS, members);
userToAuthorityCache.remove(childName);
}
else
else if (AuthorityType.getAuthorityType(childName).equals(AuthorityType.GROUP))
{
NodeRef childRef = getAuthorityOrNull(childName);
if (childRef == null)
@@ -128,6 +128,10 @@ public class AuthorityDAOImpl implements AuthorityDAO
nodeService.addChild(parentRef, childRef, ContentModel.ASSOC_MEMBER, QName.createQName("usr", childName,
namespacePrefixResolver));
}
else
{
throw new AlfrescoRuntimeException("Authorities of the type "+AuthorityType.getAuthorityType(childName)+" may not be added to other authorities");
}
}

View File

@@ -156,6 +156,13 @@ public class AuthorityServiceImpl implements AuthorityService
public void addAuthority(String parentName, String childName)
{
if (AuthorityType.getAuthorityType(childName).equals(AuthorityType.USER))
{
if(!personService.personExists(childName))
{
throw new AuthorityException("The person "+childName+" does not exist and can not be added to a group");
}
}
authorityDAO.addAuthority(parentName, childName);
}

View File

@@ -310,6 +310,8 @@ public class AuthorityServiceTest extends TestCase
public void testCreateAuthTree()
{
personService.getPerson("andy");
String auth1;
String auth2;
String auth3;
@@ -339,12 +341,12 @@ public class AuthorityServiceTest extends TestCase
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
pubAuthorityService.addAuthority(auth5, "andy");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(2, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
@@ -362,7 +364,7 @@ public class AuthorityServiceTest extends TestCase
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(0, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertEquals(1, pubAuthorityService.getContainingAuthorities(null, auth5, false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, auth5, false).contains(auth2));
@@ -375,6 +377,8 @@ public class AuthorityServiceTest extends TestCase
public void testCreateAuthNet()
{
personService.getPerson("andy");
String auth1;
String auth2;
String auth3;
@@ -399,14 +403,14 @@ public class AuthorityServiceTest extends TestCase
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
pubAuthorityService.addAuthority(auth5, "andy");
pubAuthorityService.addAuthority(auth1, "andy");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
@@ -425,7 +429,7 @@ public class AuthorityServiceTest extends TestCase
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(2, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
@@ -440,6 +444,8 @@ public class AuthorityServiceTest extends TestCase
public void testCreateAuthNet2()
{
personService.getPerson("andy");
String auth1;
String auth2;
String auth3;
@@ -464,14 +470,14 @@ public class AuthorityServiceTest extends TestCase
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
pubAuthorityService.addAuthority(auth5, "andy");
pubAuthorityService.addAuthority(auth1, "andy");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
@@ -491,7 +497,7 @@ public class AuthorityServiceTest extends TestCase
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(4, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));

View File

@@ -26,6 +26,8 @@ public class ExtendedPermissionServiceTest extends AbstractPermissionTest
{
public void testGroupPermission()
{
personService.getPerson("andy");
runAs("andy");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef, getPermission(PermissionService.READ),
@@ -41,6 +43,8 @@ public class ExtendedPermissionServiceTest extends AbstractPermissionTest
public void testDeletePermissionByRecipient()
{
personService.getPerson("andy");
runAs("andy");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef, getPermission(PermissionService.READ),

View File

@@ -1505,6 +1505,59 @@ public class PermissionServiceTest extends AbstractPermissionTest
assertFalse(permissionService.hasPermission(n2, getPermission(PermissionService.READ_CONTENT)) == AccessStatus.ALLOWED);
}
public void testPermissionCase()
{
runAs("andy");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CHILDREN)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CONTENT)) == AccessStatus.ALLOWED);
runAs("lemur");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CHILDREN)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CONTENT)) == AccessStatus.ALLOWED);
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef,
getPermission(PermissionService.READ_CHILDREN), "Andy", AccessStatus.ALLOWED));
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef,
getPermission(PermissionService.READ_PROPERTIES), "ANDY", AccessStatus.ALLOWED));
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef,
getPermission(PermissionService.READ_CONTENT), "AnDy", AccessStatus.ALLOWED));
runAs("andy");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CHILDREN)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CONTENT)) == AccessStatus.ALLOWED);
runAs("lemur");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CHILDREN)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CONTENT)) == AccessStatus.ALLOWED);
// permissionService.setPermission(new SimplePermissionEntry(rootNodeRef,
// getPermission(PermissionService.READ_CHILDREN), "andy", AccessStatus.ALLOWED));
// permissionService.setPermission(new SimplePermissionEntry(rootNodeRef,
// getPermission(PermissionService.READ_PROPERTIES), "andy", AccessStatus.ALLOWED));
// permissionService.setPermission(new SimplePermissionEntry(rootNodeRef,
// getPermission(PermissionService.READ_CONTENT), "andy", AccessStatus.ALLOWED));
//
//
// runAs("andy");
// assertTrue(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
// assertTrue(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED);
// assertTrue(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CHILDREN)) == AccessStatus.ALLOWED);
// assertTrue(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CONTENT)) == AccessStatus.ALLOWED);
// runAs("lemur");
// assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
// assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED);
// assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CHILDREN)) == AccessStatus.ALLOWED);
// assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CONTENT)) == AccessStatus.ALLOWED);
}
public void testEffectiveComposite()
{

View File

@@ -116,11 +116,11 @@ public class PermissionModel implements ModelDAO, InitializingBean
private HashMap<String, PermissionReference> permissionReferenceMap;
private Map<QName, Set<PermissionReference>> cachedTypePermissionsExposed =
new HashMap<QName, Set<PermissionReference>>(128, 1.0f);
private Map<QName, LinkedHashSet<PermissionReference>> cachedTypePermissionsExposed =
new HashMap<QName, LinkedHashSet<PermissionReference>>(128, 1.0f);
private Map<QName, Set<PermissionReference>> cachedTypePermissionsUnexposed =
new HashMap<QName, Set<PermissionReference>>(128, 1.0f);
private Map<QName, LinkedHashSet<PermissionReference>> cachedTypePermissionsUnexposed =
new HashMap<QName, LinkedHashSet<PermissionReference>>(128, 1.0f);
public PermissionModel()
{
@@ -284,9 +284,10 @@ public class PermissionModel implements ModelDAO, InitializingBean
return getAllPermissionsImpl(type, true);
}
@SuppressWarnings("unchecked")
private Set<PermissionReference> getAllPermissionsImpl(QName type, boolean exposedOnly)
{
Map<QName, Set<PermissionReference>> cache;
Map<QName, LinkedHashSet<PermissionReference>> cache;
if (exposedOnly)
{
cache = this.cachedTypePermissionsExposed;
@@ -295,7 +296,7 @@ public class PermissionModel implements ModelDAO, InitializingBean
{
cache = this.cachedTypePermissionsUnexposed;
}
Set<PermissionReference> permissions = cache.get(type);
LinkedHashSet<PermissionReference> permissions = cache.get(type);
if (permissions == null)
{
permissions = new LinkedHashSet<PermissionReference>();
@@ -310,7 +311,7 @@ public class PermissionModel implements ModelDAO, InitializingBean
}
cache.put(type, permissions);
}
return (Set<PermissionReference>)((LinkedHashSet)permissions).clone();
return (Set<PermissionReference>)permissions.clone();
}
/**

View File

@@ -55,23 +55,23 @@ public class PersonServiceImpl implements PersonService
private NodeService nodeService;
private SearchService searchService;
private AuthorityService authorityService;
private PermissionServiceSPI permissionServiceSPI;
private NamespacePrefixResolver namespacePrefixResolver;
private boolean createMissingPeople;
private boolean userNamesAreCaseSensitive;
private String companyHomePath;
private NodeRef companyHomeNodeRef;
private static Set<QName> mutableProperties;
private boolean userNamesAreCaseSensitive = false;
static
{
Set<QName> props = new HashSet<QName>();
@@ -99,9 +99,8 @@ public class PersonServiceImpl implements PersonService
this.userNamesAreCaseSensitive = userNamesAreCaseSensitive;
}
public NodeRef getPerson(String caseSensitiveUserName)
public NodeRef getPerson(String userName)
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName : caseSensitiveUserName.toLowerCase();
NodeRef personNode = getPersonOrNull(userName);
if (personNode == null)
{
@@ -126,12 +125,12 @@ public class PersonServiceImpl implements PersonService
return getPersonOrNull(caseSensitiveUserName) != null;
}
public NodeRef getPersonOrNull(String caseSensitiveUserName)
public NodeRef getPersonOrNull(String searchUserName)
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName : caseSensitiveUserName.toLowerCase();
SearchParameters sp = new SearchParameters();
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery("TYPE:\\{http\\://www.alfresco.org/model/content/1.0\\}person +@cm\\:userName:\"" + userName + "\"");
sp.setQuery("TYPE:\\{http\\://www.alfresco.org/model/content/1.0\\}person +@cm\\:userName:\"" + searchUserName
+ "\"");
sp.addStore(storeRef);
sp.excludeDataInTheCurrentTransaction(false);
@@ -141,22 +140,51 @@ public class PersonServiceImpl implements PersonService
{
rs = searchService.query(sp);
NodeRef returnRef = null;
for (ResultSetRow row : rs)
{
NodeRef nodeRef = row.getNodeRef();
if (nodeService.exists(nodeRef))
{
String realUserName = DefaultTypeConverter.INSTANCE.convert(
String.class,
nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME));
realUserName = userNamesAreCaseSensitive ? realUserName : realUserName.toLowerCase();
if (realUserName.equals(userName))
String realUserName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(
nodeRef, ContentModel.PROP_USERNAME));
if (userNamesAreCaseSensitive)
{
return nodeRef;
if (realUserName.equals(searchUserName))
{
if (returnRef == null)
{
returnRef = nodeRef;
}
else
{
throw new AlfrescoRuntimeException("Found more than one user for " + searchUserName
+ " (case sensitive)");
}
}
}
else
{
if (realUserName.equalsIgnoreCase(searchUserName))
{
if (returnRef == null)
{
returnRef = nodeRef;
}
else
{
throw new AlfrescoRuntimeException("Found more than one user for " + searchUserName
+ " (case insensitive)");
}
}
}
}
}
return returnRef;
}
finally
{
@@ -165,8 +193,6 @@ public class PersonServiceImpl implements PersonService
rs.close();
}
}
return null;
}
public boolean createMissingPeople()
@@ -179,9 +205,8 @@ public class PersonServiceImpl implements PersonService
return mutableProperties;
}
public void setPersonProperties(String caseSensitiveUserName, Map<QName, Serializable> properties)
public void setPersonProperties(String userName, Map<QName, Serializable> properties)
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName : caseSensitiveUserName.toLowerCase();
NodeRef personNode = getPersonOrNull(userName);
if (personNode == null)
{
@@ -195,8 +220,12 @@ public class PersonServiceImpl implements PersonService
}
}
properties.put(ContentModel.PROP_USERNAME, userName);
else
{
String realUserName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(personNode,
ContentModel.PROP_USERNAME));
properties.put(ContentModel.PROP_USERNAME, realUserName);
}
nodeService.setProperties(personNode, properties);
}
@@ -231,26 +260,17 @@ public class PersonServiceImpl implements PersonService
public NodeRef createPerson(Map<QName, Serializable> properties)
{
String caseSensitiveUserName = DefaultTypeConverter.INSTANCE.convert(String.class, properties
String userName = DefaultTypeConverter.INSTANCE.convert(String.class, properties
.get(ContentModel.PROP_USERNAME));
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName : caseSensitiveUserName.toLowerCase();
properties.put(ContentModel.PROP_USERNAME, userName);
return nodeService.createNode(
getPeopleContainer(),
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_PERSON,
ContentModel.TYPE_PERSON,
properties).getChildRef();
return nodeService.createNode(getPeopleContainer(), ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_PERSON,
ContentModel.TYPE_PERSON, properties).getChildRef();
}
public NodeRef getPeopleContainer()
{
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
List<NodeRef> results = searchService.selectNodes(
rootNodeRef,
PEOPLE_FOLDER,
null,
namespacePrefixResolver,
List<NodeRef> results = searchService.selectNodes(rootNodeRef, PEOPLE_FOLDER, null, namespacePrefixResolver,
false);
if (results.size() == 0)
{
@@ -265,25 +285,22 @@ public class PersonServiceImpl implements PersonService
public void deletePerson(String userName)
{
NodeRef personNodeRef = getPersonOrNull(userName);
// delete the person
if (personNodeRef != null)
{
nodeService.deleteNode(personNodeRef);
}
// translate username based on user name case sensitivity
String authorityName = userNamesAreCaseSensitive ? userName : userName.toLowerCase();
// remove user from any containing authorities
Set<String> containerAuthorities = authorityService.getContainingAuthorities(null, userName, true);
for (String containerAuthority : containerAuthorities)
{
authorityService.removeAuthority(containerAuthority, authorityName);
authorityService.removeAuthority(containerAuthority, userName);
}
// remove any user permissions
permissionServiceSPI.deletePermissions(authorityName);
permissionServiceSPI.deletePermissions(userName);
}
public Set<NodeRef> getAllPeople()
@@ -301,7 +318,6 @@ public class PersonServiceImpl implements PersonService
{
rs = searchService.query(sp);
for (ResultSetRow row : rs)
{
@@ -341,7 +357,7 @@ public class PersonServiceImpl implements PersonService
{
this.permissionServiceSPI = permissionServiceSPI;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
@@ -377,6 +393,18 @@ public class PersonServiceImpl implements PersonService
return companyHomeNodeRef;
}
public String getUserIdentifier(String caseSensitiveUserName)
{
NodeRef nodeRef = getPersonOrNull(caseSensitiveUserName);
if ((nodeRef != null) && nodeService.exists(nodeRef))
{
String realUserName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef,
ContentModel.PROP_USERNAME));
return realUserName;
}
return null;
}
// IOC Setters
}

View File

@@ -28,6 +28,7 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.EqualsHelper;
public class PersonTest extends BaseSpringTest
{
@@ -51,8 +52,8 @@ public class PersonTest extends BaseSpringTest
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
rootNodeRef = nodeService.getRootNode(storeRef);
for(NodeRef nodeRef: personService.getAllPeople())
for (NodeRef nodeRef : personService.getAllPeople())
{
nodeService.deleteNode(nodeRef);
}
@@ -67,44 +68,40 @@ public class PersonTest extends BaseSpringTest
public void xtestPerformance()
{
personService.setCreateMissingPeople(false);
personService.createPerson(createDefaultProperties("derek", "Derek", "Hulley", "dh@dh",
"alfresco", rootNodeRef));
personService
.createPerson(createDefaultProperties("derek", "Derek", "Hulley", "dh@dh", "alfresco", rootNodeRef));
long create = 0;
long count = 0;
long start;
long end;
for(int i = 0; i < 10000; i++)
for (int i = 0; i < 10000; i++)
{
String id = "TestUser-"+i;
String id = "TestUser-" + i;
start = System.nanoTime();
personService.createPerson(createDefaultProperties(id, id, id, id,
id, rootNodeRef));
personService.createPerson(createDefaultProperties(id, id, id, id, id, rootNodeRef));
end = System.nanoTime();
create += (end - start);
if((i > 0) && (i % 100 == 0))
if ((i > 0) && (i % 100 == 0))
{
System.out.println("Count = "+i);
System.out.println("Average create : "+(create/i/1000000.0f));
System.out.println("Count = " + i);
System.out.println("Average create : " + (create / i / 1000000.0f));
start = System.nanoTime();
personService.personExists(id);
end = System.nanoTime();
System.out.println("Exists : "+((end-start)/1000000.0f));
System.out.println("Exists : " + ((end - start) / 1000000.0f));
start = System.nanoTime();
int size = personService.getAllPeople().size();
end = System.nanoTime();
System.out.println("Size ("+size+") : "+((end-start)/1000000.0f));
System.out.println("Size (" + size + ") : " + ((end - start) / 1000000.0f));
}
}
}
public void testCreateMissingPeople1()
{
personService.setCreateMissingPeople(false);
@@ -122,9 +119,9 @@ public class PersonTest extends BaseSpringTest
catch (PersonException pe)
{
}
}
}
public void testCreateMissingPeople2()
{
personService.setCreateMissingPeople(false);
@@ -137,6 +134,17 @@ public class PersonTest extends BaseSpringTest
assertNotNull(nodeRef);
testProperties(nodeRef, "andy", "andy", "", "", "");
nodeRef = personService.getPerson("Andy");
assertNotNull(nodeRef);
if (personService.getUserIdentifier("Andy").equals("Andy"))
{
testProperties(nodeRef, "Andy", "Andy", "", "", "");
}
else
{
testProperties(nodeRef, "andy", "andy", "", "", "");
}
personService.setCreateMissingPeople(false);
try
{
@@ -149,8 +157,7 @@ public class PersonTest extends BaseSpringTest
}
}
public void testCreateMissingPeople()
{
personService.setCreateMissingPeople(false);
@@ -173,7 +180,7 @@ public class PersonTest extends BaseSpringTest
assertEquals(2, personService.getAllPeople().size());
assertTrue(personService.getAllPeople().contains(personService.getPerson("andy")));
assertTrue(personService.getAllPeople().contains(personService.getPerson("derek")));
}
public void testMutableProperties()
@@ -184,7 +191,7 @@ public class PersonTest extends BaseSpringTest
assertTrue(personService.getMutableProperties().contains(ContentModel.PROP_LASTNAME));
assertTrue(personService.getMutableProperties().contains(ContentModel.PROP_EMAIL));
assertTrue(personService.getMutableProperties().contains(ContentModel.PROP_ORGID));
}
public void testPersonCRUD1()
@@ -200,27 +207,27 @@ public class PersonTest extends BaseSpringTest
}
}
public void testPersonCRUD2()
{
personService.setCreateMissingPeople(false);
personService.createPerson(createDefaultProperties("derek", "Derek", "Hulley", "dh@dh",
"alfresco", rootNodeRef));
personService
.createPerson(createDefaultProperties("derek", "Derek", "Hulley", "dh@dh", "alfresco", rootNodeRef));
testProperties(personService.getPerson("derek"), "derek", "Derek", "Hulley", "dh@dh", "alfresco");
personService.setPersonProperties("derek", createDefaultProperties("derek", "Derek_", "Hulley_", "dh@dh_",
"alfresco_", rootNodeRef));
"alfresco_", rootNodeRef));
testProperties(personService.getPerson("derek"), "derek", "Derek_", "Hulley_", "dh@dh_", "alfresco_");
personService.setPersonProperties("derek", createDefaultProperties("derek", "Derek", "Hulley", "dh@dh",
"alfresco", rootNodeRef));
testProperties(personService.getPerson("derek"), "derek", "Derek", "Hulley", "dh@dh", "alfresco");
assertEquals(1, personService.getAllPeople().size());
assertTrue(personService.getAllPeople().contains(personService.getPerson("derek")));
personService.deletePerson("derek");
assertEquals(0, personService.getAllPeople().size());
try
@@ -233,35 +240,39 @@ public class PersonTest extends BaseSpringTest
}
}
public void testPersonCRUD()
{
personService.setCreateMissingPeople(false);
personService.createPerson(createDefaultProperties("derek", "Derek", "Hulley", "dh@dh",
personService
.createPerson(createDefaultProperties("Derek", "Derek", "Hulley", "dh@dh", "alfresco", rootNodeRef));
testProperties(personService.getPerson("Derek"), "Derek", "Derek", "Hulley", "dh@dh", "alfresco");
personService.setPersonProperties("Derek", createDefaultProperties("derek", "Derek_", "Hulley_", "dh@dh_",
"alfresco_", rootNodeRef));
testProperties(personService.getPerson("Derek"), "Derek", "Derek_", "Hulley_", "dh@dh_", "alfresco_");
personService.setPersonProperties("Derek", createDefaultProperties("derek", "Derek", "Hulley", "dh@dh",
"alfresco", rootNodeRef));
testProperties(personService.getPerson("derek"), "derek", "Derek", "Hulley", "dh@dh", "alfresco");
personService.setPersonProperties("derek", createDefaultProperties("derek", "Derek_", "Hulley_", "dh@dh_",
"alfresco_", rootNodeRef));
testProperties(personService.getPerson("derek"), "derek", "Derek_", "Hulley_", "dh@dh_", "alfresco_");
personService.setPersonProperties("derek", createDefaultProperties("derek", "Derek", "Hulley", "dh@dh",
"alfresco", rootNodeRef));
testProperties(personService.getPerson("derek"), "derek", "Derek", "Hulley", "dh@dh", "alfresco");
testProperties(personService.getPerson("Derek"), "Derek", "Derek", "Hulley", "dh@dh", "alfresco");
assertEquals(1, personService.getAllPeople().size());
assertTrue(personService.getAllPeople().contains(personService.getPerson("derek")));
personService.deletePerson("derek");
assertTrue(personService.getAllPeople().contains(personService.getPerson("Derek")));
assertEquals(personService.personExists("derek"), EqualsHelper.nullSafeEquals(personService.getUserIdentifier("derek"), "Derek"));
assertEquals(personService.personExists("dEREK"), EqualsHelper.nullSafeEquals(personService.getUserIdentifier("dEREK"), "Derek"));
assertEquals(personService.personExists("DEREK"), EqualsHelper.nullSafeEquals(personService.getUserIdentifier("DEREK"), "Derek"));
personService.deletePerson("Derek");
assertEquals(0, personService.getAllPeople().size());
}
private void testProperties(NodeRef nodeRef, String userName, String firstName, String lastName, String email,
String orgId)
{
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
assertEquals(userName, DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef,
ContentModel.PROP_USERNAME)));
assertNotNull(nodeService.getProperty(nodeRef, ContentModel.PROP_HOMEFOLDER));
@@ -287,56 +298,63 @@ public class PersonTest extends BaseSpringTest
properties.put(ContentModel.PROP_ORGID, orgId);
return properties;
}
public void testCaseSensitive()
{
if(personService.getUserNamesAreCaseSensitive())
personService
.createPerson(createDefaultProperties("Derek", "Derek", "Hulley", "dh@dh", "alfresco", rootNodeRef));
try
{
personService.createPerson(createDefaultProperties("Derek", "Derek", "Hulley", "dh@dh",
"alfresco", rootNodeRef));
try
NodeRef nodeRef = personService.getPerson("derek");
if (personService.getUserIdentifier("derek").equals("Derek"))
{
assertNotNull(nodeRef);
}
else
{
personService.getPerson("derek");
assertNotNull(null);
}
catch (PersonException pe)
{
}
try
{
personService.getPerson("deRek");
assertNotNull(null);
}
catch (PersonException pe)
{
}
try
{
personService.getPerson("DEREK");
assertNotNull(null);
}
catch (PersonException pe)
{
}
personService.getPerson("Derek");
}
}
public void testCaseInsensitive()
{
if(!personService.getUserNamesAreCaseSensitive())
catch (PersonException pe)
{
personService.createPerson(createDefaultProperties("Derek", "Derek", "Hulley", "dh@dh",
"alfresco", rootNodeRef));
personService.getPerson("derek");
personService.getPerson("deRek");
personService.getPerson("Derek");
personService.getPerson("DEREK");
}
try
{
NodeRef nodeRef = personService.getPerson("deRek");
if (personService.getUserIdentifier("deRek").equals("Derek"))
{
assertNotNull(nodeRef);
}
else
{
assertNotNull(null);
}
}
catch (PersonException pe)
{
}
try
{
NodeRef nodeRef = personService.getPerson("DEREK");
if (personService.getUserIdentifier("DEREK").equals("Derek"))
{
assertNotNull(nodeRef);
}
else
{
assertNotNull(null);
}
}
catch (PersonException pe)
{
}
personService.getPerson("Derek");
}
}

View File

@@ -40,12 +40,16 @@ public interface PersonService
{
/**
* Get a person by userName. The person is store in the repository. The
* person may be created as a side effect of this call, depending on
* the setting to {@link #setCreateMissingPeople(boolean) create missing people or not}.
* person may be created as a side effect of this call, depending on the
* setting to
* {@link #setCreateMissingPeople(boolean) create missing people or not}.
*
* @param userName - the userName key to find the person
* @param userName -
* the userName key to find the person
* @return Returns the person node, either existing or new
* @throws NoSuchPersonException if the user doesn't exist and could not be created automatically
* @throws NoSuchPersonException
* if the user doesn't exist and could not be created
* automatically
*
* @see #setCreateMissingPeople(boolean)
* @see #createMissingPeople()
@@ -56,12 +60,13 @@ public interface PersonService
/**
* Check if a person exists.
*
* @param userName the user name
* @param userName
* the user name
* @return Returns true if the user exists, otherwise false
*/
@Auditable(parameters = {"userName"})
public boolean personExists(String userName);
/**
* Does this service create people on demand if they are missing. If this is
* true, a call to getPerson() will create a person if they are missing.
@@ -74,13 +79,14 @@ public interface PersonService
/**
* Set if missing people should be created.
*
* @param createMissing set to true to create people
* @param createMissing
* set to true to create people
*
* @see #getPerson(String)
*/
@Auditable(parameters = {"createMissing"})
public void setCreateMissingPeople(boolean createMissing);
/**
* Get the list of properties that are mutable. Some service may only allow
* a limited list of properties to be changed. This may be those persisted
@@ -96,8 +102,10 @@ public interface PersonService
* Set the properties on a person - some of these may be persisted in
* different locations.
*
* @param userName - the user for which the properties should be set.
* @param properties - the map of properties to set (as the NodeService)
* @param userName -
* the user for which the properties should be set.
* @param properties -
* the map of properties to set (as the NodeService)
*/
@Auditable(parameters = {"userName", "properties"})
public void setPersonProperties(String userName, Map<QName, Serializable> properties);
@@ -111,9 +119,8 @@ public interface PersonService
public boolean isMutable();
/**
* Create a new person with the given properties.
* The userName is one of the properties.
* Users with duplicate userNames are not allowed.
* Create a new person with the given properties. The userName is one of the
* properties. Users with duplicate userNames are not allowed.
*
* @param properties
* @return
@@ -128,15 +135,15 @@ public interface PersonService
*/
@Auditable(parameters = {"userName"})
public void deletePerson(String userName);
/**
* Get all the people we know about.
*
* @return a set of people in no specific order.
* @return a set of people in no specific order.
*/
@Auditable
public Set<NodeRef> getAllPeople();
/**
* Return the container that stores people.
*
@@ -152,4 +159,17 @@ public interface PersonService
*/
@Auditable
public boolean getUserNamesAreCaseSensitive();
/**
* Given the case sensitive user name find the approriate identifier from the person service.
* If the system is case sensitive it will return the same string.
* If case insentive it will return the common object.
* If the user does not exist it will return null;
*
* @param caseSensitiveUserName
* @return
*/
public String getUserIdentifier(String caseSensitiveUserName);
}