mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-30 18:15:39 +00:00
28993: HomeFolderProviderSynchronizer: Provider used for LDAP to continue to use username as home folder name directly under .../app:company_home/app:user_homes Property spaces.user_homes.regex.pattern now set to "" rather than "^(..)" which would have given a single level hash structure. 28970: Merge DEV/ALAN/HOME_FOLDER to DEV/V3.4-BUG-FIX 28947: - Introduction of version 2 HomeFolderProvider2 and re-factor of version 1 so that the code used to create the folders is now in the HomeFolderManager. - Re-factor homeFolderProviderSynchronizer to handle HomeFolderProvider2. - Addition of AbstractHomeFolderProvider.V2Adaptor to allow external providers that extend AbstractHomeFolderPathProvider to be handled by homeFolderProviderSynchronizer. 28860: Minor change to class comment and removed unused imports 28858: ALF-4727 Hashed home folder provider added and used by default for LDAP sync users - based on Romain Guinot work. ALF-7797 HomeFolderProviderSynchronizer added to move existing users (normally those added by LDAP sync) into location preferred by home folder provider. - HomeFolderProviderSynchronizer bug fixes - tenant accounts supported for first time - addition of a phase to create parent folders before moving home folder to avoid a race condition - check for conditions that would result in FileExistExceptions as we don't want a the transaction to be discarded as this results in retries. - HomeFolderProviderSynchronizerTest integration test including tenant services - HomeFolderManager now sets the HOME_FOLDER_PROVIDER if it uses a default when HOME_FOLDER_PROVIDER is not set. - AbstractHomeFolderProvider clears cache when path reset as it will be invalid. - UIDBasedHomeFolderProvider.createNewParent creates its own mutable List as the one passed in may not be mutable. 28580: Save code changes - added comments to do with LDAP syn overriding the HFP value and related to this added a global property to keep empty parent folders. 28347: HomeFolderProviderSynchronizer - issue to do with new run of sync having created a user via UI that has a home folder as one of the parent folders. - issue to do with catching exception when creating temporary folder - transaction is gone - give up if error in any phase 28298: Addition of HomeFolderPathProvider (based on Romain's work) and addition of HomeFolderProviderSynchronizer. 28956: Merged DEV to V3.4-BUG-FIX ALF-9428: Multitenancy users not preserved after upgrade from 3.2.2.7 to 3.4.2 - Provide correct RunAs context in FixUserQNamesPatch batching. 28941: ALF-9361 : CLONE -sync Flat IMAP client with Alfresco is slow and inaccurate 28916: ALF-9421 The AlfrescoJavaScript action now includes company home in the JavaScript scope. 28879: Fixed ALF-9296: Alfresco Dashboard: Impossible to approve/reject task from My Tasks dashlet on My Alfresco 28875: Fixed ALF-6329: SPANISH - Share, translation on Transfer Target configuration 28864: Message: ALF-9430: RuntimeExec waitForCompletion logic is obscure - Only a single flag 'isCompleted' - Set flag in try-finally - Added notify() However, the wait() code doesn't, in practice, get called because the waitForCompletion is synchronized with the run() and is called a while after the reading thread is triggered. So the logic is less obscure and safer for the finally. 28800: File for rev 28799: ALF-9240 28799: Merged DEV to V3.4-BUG-FIX 28797: ALF-9240: Issue with adding an aspect with large multivalued list Added unit test to stress, but could not reproduce git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28995 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
225 lines
10 KiB
Java
225 lines
10 KiB
Java
package org.alfresco.repo.imap;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
|
|
import junit.framework.TestCase;
|
|
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
|
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
|
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.ContentService;
|
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.service.cmr.repository.StoreRef;
|
|
import org.alfresco.service.cmr.search.SearchService;
|
|
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
|
import org.alfresco.service.namespace.NamespaceService;
|
|
import org.alfresco.util.ApplicationContextHelper;
|
|
import org.alfresco.util.config.RepositoryFolderConfigBean;
|
|
import org.springframework.context.ApplicationContext;
|
|
|
|
import com.icegreen.greenmail.store.SimpleStoredMessage;
|
|
|
|
/**
|
|
* Unit test for cache implementation in the ImapServiceImpl. Based on ImapServiceImplTest, but
|
|
* we need this separate test because we need to get transactions to commit to trigger behaviours in ImapServiceImpl.
|
|
*
|
|
* @author ArsenyKo
|
|
*/
|
|
public class ImapServiceImplCacheTest extends TestCase
|
|
{
|
|
private static final String USER_NAME = "admin";
|
|
private static final String USER_PASSWORD = "admin";
|
|
|
|
private static final String TEST_IMAP_FOLDER_NAME = "aaa";
|
|
|
|
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
|
private NodeService nodeService;
|
|
private MutableAuthenticationService authenticationService;
|
|
private SearchService searchService;
|
|
private NamespaceService namespaceService;
|
|
private FileFolderService fileFolderService;
|
|
private ContentService contentService;
|
|
|
|
private ImapService imapService;
|
|
|
|
private NodeRef testImapFolderNodeRef;
|
|
|
|
@Override
|
|
public void setUp() throws Exception
|
|
{
|
|
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean("ServiceRegistry");
|
|
nodeService = serviceRegistry.getNodeService();
|
|
authenticationService = serviceRegistry.getAuthenticationService();
|
|
imapService = serviceRegistry.getImapService();
|
|
searchService = serviceRegistry.getSearchService();
|
|
namespaceService = serviceRegistry.getNamespaceService();
|
|
fileFolderService = serviceRegistry.getFileFolderService();
|
|
contentService = serviceRegistry.getContentService();
|
|
|
|
authenticationService.authenticate(USER_NAME, USER_PASSWORD.toCharArray());
|
|
|
|
String storePath = "workspace://SpacesStore";
|
|
String companyHomePathInStore = "/app:company_home";
|
|
|
|
StoreRef storeRef = new StoreRef(storePath);
|
|
|
|
NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
|
|
|
|
List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
|
|
NodeRef companyHomeNodeRef = nodeRefs.get(0);
|
|
|
|
ChildApplicationContextFactory imap = (ChildApplicationContextFactory) ctx.getBean("imap");
|
|
ApplicationContext imapCtx = imap.getApplicationContext();
|
|
ImapServiceImpl imapServiceImpl = (ImapServiceImpl)imapCtx.getBean("imapService");
|
|
|
|
// Creating IMAP test folder for IMAP root
|
|
LinkedList<String> folders = new LinkedList<String>();
|
|
folders.add(TEST_IMAP_FOLDER_NAME);
|
|
FileFolderServiceImpl.makeFolders(fileFolderService, companyHomeNodeRef, folders, ContentModel.TYPE_FOLDER);
|
|
|
|
// Setting IMAP root
|
|
RepositoryFolderConfigBean imapHome = new RepositoryFolderConfigBean();
|
|
imapHome.setStore(storePath);
|
|
imapHome.setRootPath(companyHomePathInStore);
|
|
imapHome.setFolderPath(TEST_IMAP_FOLDER_NAME);
|
|
imapServiceImpl.setImapHome(imapHome);
|
|
|
|
// Starting IMAP
|
|
imapServiceImpl.startup();
|
|
|
|
nodeRefs = searchService.selectNodes(storeRootNodeRef,
|
|
companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + TEST_IMAP_FOLDER_NAME,
|
|
null,
|
|
namespaceService,
|
|
false);
|
|
testImapFolderNodeRef = nodeRefs.get(0);
|
|
|
|
}
|
|
|
|
public void tearDown() throws Exception
|
|
{
|
|
fileFolderService.delete(testImapFolderNodeRef);
|
|
}
|
|
|
|
|
|
public void testRepoBehaviourWithFoldersCache() throws Exception
|
|
{
|
|
AlfrescoImapUser localUser = new AlfrescoImapUser(USER_NAME + "@alfresco.com", USER_NAME, USER_PASSWORD);
|
|
String folderName = "ALF9361";
|
|
String mailbox = "Alfresco IMAP" + AlfrescoImapConst.HIERARCHY_DELIMITER +
|
|
TEST_IMAP_FOLDER_NAME + AlfrescoImapConst.HIERARCHY_DELIMITER +
|
|
folderName;
|
|
int contentItemsCount = 3;
|
|
// Create a tree like ALF9361/ALF9361_0/sub_0
|
|
// Mailbox path with default mount point should be like 'Alfresco IMAP/aaa/ALF9361/ALF9361_0/sub_0
|
|
FileInfo localRootFolder = fileFolderService.create(testImapFolderNodeRef, folderName, ContentModel.TYPE_FOLDER);
|
|
List<FileInfo> subFolders = new ArrayList<FileInfo>(10);
|
|
for(int i = 0; i < 3; i++)
|
|
{
|
|
String childMailbox = folderName + "_" + i;
|
|
FileInfo subFolder = fileFolderService.create(localRootFolder.getNodeRef(), childMailbox, ContentModel.TYPE_FOLDER);
|
|
for(int j = 0; j < 3; j++)
|
|
{
|
|
String subChildMailbox = "sub_" + j;
|
|
fileFolderService.create(subFolder.getNodeRef(), subChildMailbox, ContentModel.TYPE_FOLDER);
|
|
}
|
|
subFolders.add(subFolder);
|
|
}
|
|
// Create content within 'Alfresco IMAP/aaa/ALF9361'
|
|
createTestContent(localRootFolder, contentItemsCount);
|
|
// Load the cache
|
|
imapService.listMailboxes(localUser, "*");
|
|
imapService.listSubscribedMailboxes(localUser, "*");
|
|
// Get the folder to examine
|
|
AlfrescoImapFolder folder = imapService.getFolder(localUser, mailbox);
|
|
// Check the folder exist via IMAP
|
|
assertNotNull("Folder wasn't successfully gotten from IMAP", folder);
|
|
assertEquals(contentItemsCount, folder.getMessageCount());
|
|
// Check UIDVALIDITY
|
|
long uidValidityBefore = folder.getUidValidity();
|
|
// Delete first childMailbox 'ALF9361/ALF9361_0'
|
|
//System.out.println(" --------------------- DELETE FOLDER --------------------");
|
|
//System.out.println(" Parent " + localRootFolder.getNodeRef());
|
|
fileFolderService.delete(subFolders.get(0).getNodeRef());
|
|
// Get the folder once more and check it was changed since child was removed
|
|
folder = imapService.getFolder(localUser, mailbox);
|
|
// Content count should be the same since we havn't deleted a content yet
|
|
assertEquals(contentItemsCount, folder.getMessageCount());
|
|
long uidValidity = folder.getUidValidity();
|
|
assertTrue("UIDVALIDITY wasn't incremented", (uidValidity - uidValidityBefore) > 0);
|
|
uidValidityBefore = uidValidity;
|
|
// Try to get deleted child
|
|
try
|
|
{
|
|
String subFolderName = mailbox + AlfrescoImapConst.HIERARCHY_DELIMITER + folderName + "_0";
|
|
folder = imapService.getFolder(localUser, subFolderName);
|
|
fail("The folder still in the cache");
|
|
}
|
|
catch (RuntimeException e)
|
|
{
|
|
// expected
|
|
}
|
|
// Try to get deleted sub child. If the cache wasn't invalidated we will get it
|
|
// But it should be connected to AlfrescoImapFolder.isStale() method.
|
|
// ArsenyKo: I think we should avoid repo API invocation like isStale...
|
|
try
|
|
{
|
|
String subSubFolderName = mailbox + AlfrescoImapConst.HIERARCHY_DELIMITER + mailbox + "_0" + AlfrescoImapConst.HIERARCHY_DELIMITER + "sub_0";
|
|
folder = imapService.getFolder(localUser, subSubFolderName);
|
|
fail("The folder still in the cache");
|
|
}
|
|
catch (RuntimeException e)
|
|
{
|
|
// expected
|
|
}
|
|
// Do manipulations with a content in the folder to check the cache behaviour
|
|
folder = imapService.getFolder(localUser, mailbox);
|
|
SimpleStoredMessage message = folder.getMessages().get(0);
|
|
AbstractMimeMessage alfrescoMessage = (AbstractMimeMessage) message.getMimeMessage();
|
|
long uid = message.getUid();
|
|
//System.out.println(" --------------------- DELETE FILE --------------------");
|
|
//System.out.println(" Parent " + folder.getFolderInfo().getNodeRef());
|
|
// Delete a content
|
|
fileFolderService.delete(alfrescoMessage.getMessageInfo().getNodeRef());
|
|
// Get a folder once again. We expect that the folder would be retrieved from the repo,
|
|
// since its' cache should be invalidated
|
|
folder = imapService.getFolder(localUser, mailbox);
|
|
// Get UIDVALIDITY. It should be changed, since we removed a message form the mailbox.
|
|
uidValidity = folder.getUidValidity();
|
|
assertTrue("UIDVALIDITY wasn't incremented", (uidValidity - uidValidityBefore) > 0);
|
|
// Additional check whether messages cache is valid. Messages cache should be recreated
|
|
//with the new inctance of AlfrescoImapMessage
|
|
assertTrue("Messages cache is stale", contentItemsCount > folder.getMessageCount());
|
|
long[] uids = folder.getMessageUids();
|
|
Arrays.sort(uids);
|
|
assertFalse("Messages msn cache is stale", Arrays.binarySearch(uids, uid) > 0);
|
|
assertNull("Message is still in the messages cache", folder.getMessage(uid));
|
|
//System.out.println(" --------------------- THE END --------------------");
|
|
fileFolderService.delete(localRootFolder.getNodeRef());
|
|
|
|
}
|
|
|
|
private List<FileInfo> createTestContent(FileInfo parent, int count)
|
|
{
|
|
List<FileInfo> result = new ArrayList<FileInfo>(count);
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
FileInfo contentItem = fileFolderService.create(parent.getNodeRef(), "content_" + i, ContentModel.TYPE_CONTENT, ContentModel.ASSOC_CONTAINS);
|
|
ContentWriter contentWriter = contentService.getWriter(contentItem.getNodeRef(), ContentModel.PROP_CONTENT, false);
|
|
contentWriter.setEncoding("UTF-8");
|
|
contentWriter.putContent("TEST" + i);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
}
|