mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ALF-11237 - imap folders and modification.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32796 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -85,6 +85,7 @@ import org.alfresco.service.cmr.model.FileNotFoundException;
|
|||||||
import org.alfresco.service.cmr.model.SubFolderFilter;
|
import org.alfresco.service.cmr.model.SubFolderFilter;
|
||||||
import org.alfresco.service.cmr.preference.PreferenceService;
|
import org.alfresco.service.cmr.preference.PreferenceService;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||||
@@ -97,6 +98,7 @@ import org.alfresco.service.cmr.security.PermissionService;
|
|||||||
import org.alfresco.service.cmr.site.SiteInfo;
|
import org.alfresco.service.cmr.site.SiteInfo;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.EqualsHelper;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
import org.alfresco.util.MaxSizeMap;
|
import org.alfresco.util.MaxSizeMap;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
@@ -141,7 +143,8 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
private NamespaceService namespaceService;
|
private NamespaceService namespaceService;
|
||||||
private SearchService searchService;
|
private SearchService searchService;
|
||||||
|
|
||||||
// Note that this cache need not be cluster synchronized, as it is keyed by the cluster-safe change token
|
// Note that this cache need not be cluster synchronized, as it is keyed by the cluster-safe
|
||||||
|
// change token. Key is username, changeToken
|
||||||
private Map<Pair<String, String>, FolderStatus> folderCache;
|
private Map<Pair<String, String>, FolderStatus> folderCache;
|
||||||
private int folderCacheSize = 1000;
|
private int folderCacheSize = 1000;
|
||||||
private ReentrantReadWriteLock folderCacheLock = new ReentrantReadWriteLock();
|
private ReentrantReadWriteLock folderCacheLock = new ReentrantReadWriteLock();
|
||||||
@@ -730,7 +733,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug("Search mails contextNodeRef=" + contextNodeRef + ", viewMode=" + viewMode);
|
logger.debug("getFolderStatus contextNodeRef=" + contextNodeRef + ", viewMode=" + viewMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to ACL check the change token read
|
// No need to ACL check the change token read
|
||||||
@@ -838,11 +841,19 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
FolderStatus oldResult = this.folderCache.get(cacheKey);
|
FolderStatus oldResult = this.folderCache.get(cacheKey);
|
||||||
if (oldResult != null)
|
if (oldResult != null)
|
||||||
{
|
{
|
||||||
|
if(logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("At end of getFolderStatus. Found info in cache, changeToken:" + changeToken);
|
||||||
|
}
|
||||||
|
|
||||||
return oldResult;
|
return oldResult;
|
||||||
}
|
}
|
||||||
this.folderCache.put(cacheKey, result);
|
this.folderCache.put(cacheKey, result);
|
||||||
|
|
||||||
logger.debug("Found files:" + currentSearch.size());
|
if(logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("At end of getFolderStatus. Found files:" + currentSearch.size() + ", changeToken:" + changeToken);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -944,6 +955,10 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("set flag nodeRef:" + nodeRef + ",flag:" + flagToQname.get(flag) + ", value:" + value);
|
||||||
|
}
|
||||||
nodeService.setProperty(nodeRef, flagToQname.get(flag), value);
|
nodeService.setProperty(nodeRef, flagToQname.get(flag), value);
|
||||||
}
|
}
|
||||||
messageCache.remove(nodeRef);
|
messageCache.remove(nodeRef);
|
||||||
@@ -1598,14 +1613,53 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdateProperties(final NodeRef nodeRef, Map<QName, Serializable> before,
|
public void onUpdateProperties(final NodeRef nodeRef, final Map<QName, Serializable> before,
|
||||||
Map<QName, Serializable> after)
|
final Map<QName, Serializable> after)
|
||||||
{
|
{
|
||||||
doAsSystem(new RunAsWork<Void>()
|
doAsSystem(new RunAsWork<Void>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void doWork() throws Exception
|
public Void doWork() throws Exception
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Imap only cares about a few properties however if those properties
|
||||||
|
* change then the uidvalidity needs to be reset otherwise the new content
|
||||||
|
* won't get re-loaded. This is nonsense for an email server, but needed for
|
||||||
|
* modifiable repository. Also we need to ignore certain properties.
|
||||||
|
*/
|
||||||
|
boolean hasChanged = false;
|
||||||
|
|
||||||
|
if(!hasChanged)
|
||||||
|
{
|
||||||
|
hasChanged = !EqualsHelper.nullSafeEquals(before.get(ContentModel.PROP_NAME), after.get(ContentModel.PROP_NAME));
|
||||||
|
}
|
||||||
|
if(!hasChanged)
|
||||||
|
{
|
||||||
|
hasChanged = !EqualsHelper.nullSafeEquals(before.get(ContentModel.PROP_AUTHOR), after.get(ContentModel.PROP_AUTHOR));
|
||||||
|
}
|
||||||
|
if(!hasChanged)
|
||||||
|
{
|
||||||
|
hasChanged = !EqualsHelper.nullSafeEquals(before.get(ContentModel.PROP_TITLE), after.get(ContentModel.PROP_TITLE));
|
||||||
|
}
|
||||||
|
if(!hasChanged)
|
||||||
|
{
|
||||||
|
hasChanged = !EqualsHelper.nullSafeEquals(before.get(ContentModel.PROP_DESCRIPTION), after.get(ContentModel.PROP_DESCRIPTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!hasChanged)
|
||||||
|
{
|
||||||
|
Serializable s1 = before.get(ContentModel.PROP_CONTENT);
|
||||||
|
Serializable s2 = after.get(ContentModel.PROP_CONTENT);
|
||||||
|
|
||||||
|
if(s1 != null && s2 != null)
|
||||||
|
{
|
||||||
|
ContentData c1 = (ContentData)s1;
|
||||||
|
ContentData c2 = (ContentData)s2;
|
||||||
|
|
||||||
|
hasChanged = !EqualsHelper.nullSafeEquals(c1.getContentUrl(), c2.getContentUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (ChildAssociationRef parentAssoc : nodeService.getParentAssocs(nodeRef))
|
for (ChildAssociationRef parentAssoc : nodeService.getParentAssocs(nodeRef))
|
||||||
{
|
{
|
||||||
NodeRef folderRef = parentAssoc.getParentRef();
|
NodeRef folderRef = parentAssoc.getParentRef();
|
||||||
@@ -1613,8 +1667,15 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
{
|
{
|
||||||
messageCache.remove(nodeRef);
|
messageCache.remove(nodeRef);
|
||||||
|
|
||||||
// Force generation of a new change token
|
// Force generation of a new change token for the parent folders
|
||||||
getUidValidityTransactionListener(folderRef);
|
UidValidityTransactionListener listener = getUidValidityTransactionListener(folderRef);
|
||||||
|
|
||||||
|
// if we have a significant change then we need to force a new uidvalidity.
|
||||||
|
if(hasChanged)
|
||||||
|
{
|
||||||
|
logger.debug("message has changed - force new uidvalidity for the parent folder");
|
||||||
|
listener.forceNewUidvalidity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -1669,6 +1730,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
private NodeRef folderNodeRef;
|
private NodeRef folderNodeRef;
|
||||||
private Long minUid;
|
private Long minUid;
|
||||||
private Long maxUid;
|
private Long maxUid;
|
||||||
|
private boolean forceNewUidValidity = false;
|
||||||
|
|
||||||
public UidValidityTransactionListener(NodeRef folderNodeRef, NodeService nodeService)
|
public UidValidityTransactionListener(NodeRef folderNodeRef, NodeService nodeService)
|
||||||
{
|
{
|
||||||
@@ -1676,6 +1738,11 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
this.nodeService = nodeService;
|
this.nodeService = nodeService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void forceNewUidvalidity()
|
||||||
|
{
|
||||||
|
this.forceNewUidValidity = true;
|
||||||
|
}
|
||||||
|
|
||||||
public void recordNewUid(long newUid)
|
public void recordNewUid(long newUid)
|
||||||
{
|
{
|
||||||
if (this.minUid == null)
|
if (this.minUid == null)
|
||||||
@@ -1705,23 +1772,26 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
@Override
|
@Override
|
||||||
public Void doWork() throws Exception
|
public Void doWork() throws Exception
|
||||||
{
|
{
|
||||||
if (UidValidityTransactionListener.this.minUid != null)
|
if (UidValidityTransactionListener.this.forceNewUidValidity || UidValidityTransactionListener.this.minUid != null)
|
||||||
{
|
{
|
||||||
long modifDate = System.currentTimeMillis();
|
long modifDate = System.currentTimeMillis();
|
||||||
Long oldMax = (Long)UidValidityTransactionListener.this.nodeService.getProperty(folderNodeRef, ImapModel.PROP_MAXUID);
|
Long oldMax = (Long)UidValidityTransactionListener.this.nodeService.getProperty(folderNodeRef, ImapModel.PROP_MAXUID);
|
||||||
// Only update UIDVALIDITY if a new node has and ID that is smaller than the old maximum (as UIDs are always meant to increase)
|
// Only update UIDVALIDITY if a new node has and ID that is smaller than the old maximum (as UIDs are always meant to increase)
|
||||||
if (oldMax == null || UidValidityTransactionListener.this.minUid < oldMax)
|
if (UidValidityTransactionListener.this.forceNewUidValidity || oldMax == null || UidValidityTransactionListener.this.minUid < oldMax)
|
||||||
{
|
{
|
||||||
UidValidityTransactionListener.this.nodeService.setProperty(folderNodeRef, ImapModel.PROP_UIDVALIDITY, modifDate);
|
UidValidityTransactionListener.this.nodeService.setProperty(folderNodeRef, ImapModel.PROP_UIDVALIDITY, modifDate);
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug("UIDVALIDITY was modified for " + folderNodeRef);
|
logger.debug("UIDVALIDITY was modified for folder, nodeRef:" + folderNodeRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UidValidityTransactionListener.this.nodeService.setProperty(folderNodeRef, ImapModel.PROP_MAXUID, UidValidityTransactionListener.this.maxUid);
|
if(UidValidityTransactionListener.this.maxUid != null)
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
{
|
||||||
logger.debug("MAXUID was modified for " + folderNodeRef);
|
UidValidityTransactionListener.this.nodeService.setProperty(folderNodeRef, ImapModel.PROP_MAXUID, UidValidityTransactionListener.this.maxUid);
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("MAXUID was modified for folder, nodeRef:" + folderNodeRef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UidValidityTransactionListener.this.nodeService.setProperty(folderNodeRef, ImapModel.PROP_CHANGE_TOKEN, changeToken);
|
UidValidityTransactionListener.this.nodeService.setProperty(folderNodeRef, ImapModel.PROP_CHANGE_TOKEN, changeToken);
|
||||||
|
Reference in New Issue
Block a user