Merged V3.4 to HEAD (3.4.7)

32598: ALF-11522 IMAP: Generic AlfrescoImapFolderException error is a bit misleading
      Text was duplicated - previously modified text was not being used
   32690: Merged V3.4-BUG-FIX to V3.4
      32689: ALF-11603: Use different UIDVALIDITY values for different mounts of the same folder in IMAP to force client to fetch in both locations   
   32691: Merged PATCHES/V3.4.6 to V3.4
      32397: ALF-9878 / ALF-11727 CLONE - Pending Invite Search doesn't return anything if there's more than 1000 pending invites across all sites.
         Return first 200 invitations (similar to 4.0 paging)
         Transaction used by the invites.get is now read only so does not force a flush of caches.
      32404: ALF-9878 / ALF-11727 CLONE - Pending Invite Search doesn't return anything if there's more than 1000 pending invites across all sites.
         Removed read only transaction from invites.get.desc.xml as it broke InviteServiceTest testRejectInvite
      32501: ALF-9878 / ALF-11727: Reinstated read-only transaction around invites.get and prevented it from trying to lazily create persons from rejected invites that had previously been deleted by InviteHelper.cleanUpStaleInviteeResources!
      32617: ALF-11977 / ALF-11879: IMAP performance
      - Fix node batch loading - batch load ContentData to avoid N+1 problem with content properties
      - During cache preloading, use distinct transactions for each folder search, thus avoiding blowing the transactional caches
      32619: ALF-11977 / ALF-11879: Fixed typo
      32652: ALF-11977 / ALF-11879: Deactivate auto-versioning and auditing (and run as system) whilst setting magic IMAP aspect properties
      32683: ALF-11978 / ALF-11915: iBatis synchronizes on the ClassInfo class during high concurrency
         Similar change made to ibatis ClassInfo.java as was made to mybatis (in 4.0) for ALF-11894
         src.diff is diff from new SVN location at http://mybatis.googlecode.com/svn/tags/java_release_2.3.4-726/ibatis-2-core hence the revision number changes
         modified the pom to use Java 1.5 (1.6 does not work due to changes in abstract sql packages) and removed a plugin that no longer works
   32721: ALF-11913 Search in Explorer does not find documents found by Share
      Correct bug introduced by ALF-11435 'support for hidden files'
   32735: ALF-12021: Merged PATCHES/V3.4.5 to V3.4
      32513: ALF-11720: Merged HEAD to PATCHES/V3.4.5
         32330: Merged DEV to HEAD
            32207: Fix ALF-11644: AVM cleanup jobs run when WCM is not installed
                - Moved scheduled jobs to installable wcm-bootstrap-context.xml
                - Also got rid of orphan reaper warnings when running in a cluster (not ALF-11720, but mentioned in it)   
         32329: Fix ALF-11734: Concurrency conditions not handled correctly for ACL persistence
            - Struggled to get reproducible test in code
            - If this doesn't fix the problem fully, then at least it'll push it up a level,
              however the higher caches already have pessimistic removal of entries, so should be OK
            - In the same way, this could fix ALF-11720: WCM: OrphanReaper contention throws error (3.4.x)   
         32381: Minor follow up on 32329: ALF-11734: Concurrency conditions not handled correctly for ACL persistence
            - Pessimistically throw away the node cache entry referencing the ACL   
   32737: ALF-9878: Reverse merged following revisions from failed hotfix - deferred to 3.4.8
      32397: ALF-11727 CLONE - Pending Invite Search doesn't return anything if there's more than 1000 pending invites across all sites.
         Return first 200 invitations (similar to 4.0 paging)
         Transaction used by the invites.get is now read only so does not force a flush of caches.
      32404: ALF-11727 CLONE - Pending Invite Search doesn't return anything if there's more than 1000 pending invites across all sites.
         Removed read only transaction from invites.get.desc.xml as it broke InviteServiceTest testRejectInvite
      32501: ALF-11727: Reinstated read-only transaction around invites.get and prevented it from trying to lazily create persons from rejected invites that had previously been deleted by InviteHelper.cleanUpStaleInviteeResources!

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32743 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2011-12-13 19:58:59 +00:00
parent 443a0167bc
commit 3d77cab121
4 changed files with 45 additions and 27 deletions

View File

@@ -110,7 +110,10 @@
</property> </property>
</bean> </bean>
<bean id="NodeService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <bean id="NodeService_transaction" class="org.alfresco.repo.transaction.RetryingTransactionInterceptor">
<property name="transactionService">
<ref bean="TransactionService"/>
</property>
<property name="transactionManager"> <property name="transactionManager">
<ref bean="transactionManager"/> <ref bean="transactionManager"/>
</property> </property>

View File

@@ -26,6 +26,7 @@ import javax.mail.Flags;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import javax.mail.search.SearchTerm; import javax.mail.search.SearchTerm;
import org.alfresco.repo.imap.exception.AlfrescoImapFolderException;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
@@ -108,7 +109,7 @@ public abstract class AbstractImapFolder implements MailFolder
if (toImapMailFolder.isReadOnly()) if (toImapMailFolder.isReadOnly())
{ {
throw new FolderException("Can't create folder - Permission denied"); throw new FolderException(AlfrescoImapFolderException.PERMISSION_DENIED);
} }
CommandCallback<Object> command = new CommandCallback<Object>() CommandCallback<Object> command = new CommandCallback<Object>()

View File

@@ -84,6 +84,8 @@ public class AlfrescoImapFolder extends AbstractImapFolder implements Serializab
private final String userName; private final String userName;
private final int mountPointId;
/** /**
* Defines view mode. * Defines view mode.
*/ */
@@ -127,7 +129,7 @@ public class AlfrescoImapFolder extends AbstractImapFolder implements Serializab
*/ */
AlfrescoImapFolder(String userName, ServiceRegistry serviceRegistry) AlfrescoImapFolder(String userName, ServiceRegistry serviceRegistry)
{ {
this(null, userName, "", "", null, serviceRegistry, false, false); this(null, userName, "", "", null, serviceRegistry, false, false, 0);
} }
@@ -148,9 +150,10 @@ public class AlfrescoImapFolder extends AbstractImapFolder implements Serializab
String folderPath, String folderPath,
ImapViewMode viewMode, ImapViewMode viewMode,
boolean extractAttachmentsEnabled, boolean extractAttachmentsEnabled,
ServiceRegistry serviceRegistry) ServiceRegistry serviceRegistry,
int mountPointId)
{ {
this(folderInfo, userName, folderName, folderPath, viewMode, serviceRegistry, null, extractAttachmentsEnabled); this(folderInfo, userName, folderName, folderPath, viewMode, serviceRegistry, null, extractAttachmentsEnabled, mountPointId);
} }
/** /**
@@ -173,7 +176,8 @@ public class AlfrescoImapFolder extends AbstractImapFolder implements Serializab
ImapViewMode viewMode, ImapViewMode viewMode,
ServiceRegistry serviceRegistry, ServiceRegistry serviceRegistry,
Boolean selectable, Boolean selectable,
boolean extractAttachmentsEnabled) boolean extractAttachmentsEnabled,
int mountPointId)
{ {
super(serviceRegistry); super(serviceRegistry);
this.folderInfo = folderInfo; this.folderInfo = folderInfo;
@@ -213,6 +217,8 @@ public class AlfrescoImapFolder extends AbstractImapFolder implements Serializab
{ {
this.selectable = false; this.selectable = false;
} }
this.mountPointId = mountPointId;
} }
/* /*
@@ -613,7 +619,7 @@ public class AlfrescoImapFolder extends AbstractImapFolder implements Serializab
@Override @Override
public long getUidValidity() public long getUidValidity()
{ {
return getFolderStatus().uidValidity; return getFolderStatus().uidValidity + mountPointId;
} }
/** /**

View File

@@ -147,6 +147,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
private ReentrantReadWriteLock folderCacheLock = new ReentrantReadWriteLock(); private ReentrantReadWriteLock folderCacheLock = new ReentrantReadWriteLock();
private SimpleCache<NodeRef, CacheItem> messageCache; private SimpleCache<NodeRef, CacheItem> messageCache;
private Map<String, ImapConfigMountPointsBean> imapConfigMountPoints; private Map<String, ImapConfigMountPointsBean> imapConfigMountPoints;
private Map<String, Integer> mountPointIds;
private RepositoryFolderConfigBean[] ignoreExtractionFoldersBeans; private RepositoryFolderConfigBean[] ignoreExtractionFoldersBeans;
private RepositoryFolderConfigBean imapHomeConfigBean; private RepositoryFolderConfigBean imapHomeConfigBean;
@@ -315,10 +316,14 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
public void setImapConfigMountPoints(ImapConfigMountPointsBean[] imapConfigMountPointsBeans) public void setImapConfigMountPoints(ImapConfigMountPointsBean[] imapConfigMountPointsBeans)
{ {
this.imapConfigMountPoints = new LinkedHashMap<String, ImapConfigMountPointsBean>(imapConfigMountPointsBeans.length * 2); this.imapConfigMountPoints = new LinkedHashMap<String, ImapConfigMountPointsBean>(
for (ImapConfigMountPointsBean bean : imapConfigMountPointsBeans) imapConfigMountPointsBeans.length * 2);
this.mountPointIds = new HashMap<String, Integer>(imapConfigMountPointsBeans.length * 2);
for (int i = 0; i < imapConfigMountPointsBeans.length; i++)
{ {
this.imapConfigMountPoints.put(bean.getMountPointName(), bean); String name = imapConfigMountPointsBeans[i].getMountPointName();
this.imapConfigMountPoints.put(name, imapConfigMountPointsBeans[i]);
this.mountPointIds.put(name, i + 1);
} }
} }
@@ -555,6 +560,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
final List<String> pathElements; final List<String> pathElements;
ImapViewMode viewMode = ImapViewMode.ARCHIVE; ImapViewMode viewMode = ImapViewMode.ARCHIVE;
int index = mailboxName.indexOf(AlfrescoImapConst.HIERARCHY_DELIMITER); int index = mailboxName.indexOf(AlfrescoImapConst.HIERARCHY_DELIMITER);
int mountPointId = 0;
if (index < 0) if (index < 0)
{ {
root = getUserImapHomeRef(user.getLogin()); root = getUserImapHomeRef(user.getLogin());
@@ -566,6 +572,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
ImapConfigMountPointsBean imapConfigMountPoint = this.imapConfigMountPoints.get(rootPath); ImapConfigMountPointsBean imapConfigMountPoint = this.imapConfigMountPoints.get(rootPath);
if (imapConfigMountPoint != null) if (imapConfigMountPoint != null)
{ {
mountPointId = this.mountPointIds.get(rootPath);
root = imapConfigMountPoint.getFolderPath(serviceRegistry.getNamespaceService(), nodeService, searchService, fileFolderService); root = imapConfigMountPoint.getFolderPath(serviceRegistry.getNamespaceService(), nodeService, searchService, fileFolderService);
pathElements = Arrays.asList(mailboxName.substring(index + 1).split( pathElements = Arrays.asList(mailboxName.substring(index + 1).split(
String.valueOf(AlfrescoImapConst.HIERARCHY_DELIMITER))); String.valueOf(AlfrescoImapConst.HIERARCHY_DELIMITER)));
@@ -612,7 +619,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
} }
} }
return new AlfrescoImapFolder(mailFolder, user.getLogin(), pathElements.get(pathElements.size() - 1), mailboxName, viewMode, return new AlfrescoImapFolder(mailFolder, user.getLogin(), pathElements.get(pathElements.size() - 1), mailboxName, viewMode,
serviceRegistry, true, isExtractionEnabled(mailFolder.getNodeRef())); serviceRegistry, true, isExtractionEnabled(mailFolder.getNodeRef()), mountPointId);
} }
public void deleteMailbox(AlfrescoImapUser user, String mailboxName) public void deleteMailbox(AlfrescoImapUser user, String mailboxName)
@@ -965,6 +972,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
NodeRef mountPoint = getMountPoint(mountPointName); NodeRef mountPoint = getMountPoint(mountPointName);
if (mountPoint != null) if (mountPoint != null)
{ {
int mountPointId = mountPointIds.get(mountPointName);
FileInfo mountPointFileInfo = fileFolderService.getFileInfo(mountPoint); FileInfo mountPointFileInfo = fileFolderService.getFileInfo(mountPoint);
ImapViewMode viewMode = imapConfigMountPoints.get(mountPointName).getMode(); ImapViewMode viewMode = imapConfigMountPoints.get(mountPointName).getMode();
if (index < 0) if (index < 0)
@@ -973,22 +981,22 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
if (!listSubscribed || isSubscribed(mountPointFileInfo, userName)) if (!listSubscribed || isSubscribed(mountPointFileInfo, userName))
{ {
result.add(new AlfrescoImapFolder(mountPointFileInfo, userName, mountPointName, mountPointName, viewMode, result.add(new AlfrescoImapFolder(mountPointFileInfo, userName, mountPointName, mountPointName, viewMode,
isExtractionEnabled(mountPointFileInfo.getNodeRef()), serviceRegistry)); isExtractionEnabled(mountPointFileInfo.getNodeRef()), serviceRegistry, mountPointId));
} }
else if (rootPath.endsWith("%") && !expandFolder(mountPoint, user, mountPointName, "%", true, viewMode).isEmpty()) // \NoSelect else if (rootPath.endsWith("%") && !expandFolder(mountPoint, user, mountPointName, "%", true, viewMode, mountPointId).isEmpty()) // \NoSelect
{ {
result.add(new AlfrescoImapFolder(mountPointFileInfo, userName, mountPointName, mountPointName, viewMode, result.add(new AlfrescoImapFolder(mountPointFileInfo, userName, mountPointName, mountPointName, viewMode,
serviceRegistry, false, isExtractionEnabled(mountPointFileInfo.getNodeRef()))); serviceRegistry, false, isExtractionEnabled(mountPointFileInfo.getNodeRef()), mountPointId));
} }
if (rootPath.endsWith("*")) if (rootPath.endsWith("*"))
{ {
result.addAll(expandFolder(mountPoint, user, mountPointName, "*", listSubscribed, viewMode)); result.addAll(expandFolder(mountPoint, user, mountPointName, "*", listSubscribed, viewMode, mountPointId));
} }
} }
else else
{ {
result.addAll(expandFolder(mountPoint, user, mountPointName, result.addAll(expandFolder(mountPoint, user, mountPointName,
mailboxPattern.substring(index + 1), listSubscribed, viewMode)); mailboxPattern.substring(index + 1), listSubscribed, viewMode, mountPointId));
} }
} }
// If we had an exact match, there is no point continuing to search // If we had an exact match, there is no point continuing to search
@@ -1004,7 +1012,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
if (!found) if (!found)
{ {
NodeRef root = getUserImapHomeRef(user.getLogin()); NodeRef root = getUserImapHomeRef(user.getLogin());
result.addAll(expandFolder(root, user, "", mailboxPattern, listSubscribed, ImapViewMode.ARCHIVE)); result.addAll(expandFolder(root, user, "", mailboxPattern, listSubscribed, ImapViewMode.ARCHIVE, 0));
} }
logger.debug("listMailboxes returning size:" + result.size()); logger.debug("listMailboxes returning size:" + result.size());
@@ -1023,7 +1031,8 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
String rootPath, String rootPath,
String mailboxPattern, String mailboxPattern,
boolean listSubscribed, boolean listSubscribed,
ImapViewMode viewMode) ImapViewMode viewMode,
int mountPointId)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
@@ -1078,16 +1087,16 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
if (!listSubscribed || isSubscribed(fileInfo, userName)) if (!listSubscribed || isSubscribed(fileInfo, userName))
{ {
fullList.add(new AlfrescoImapFolder(fileInfo, userName, fileInfo.getName(), folderPath, viewMode, fullList.add(new AlfrescoImapFolder(fileInfo, userName, fileInfo.getName(), folderPath, viewMode,
isExtractionEnabled(fileInfo.getNodeRef()), serviceRegistry)); isExtractionEnabled(fileInfo.getNodeRef()), serviceRegistry, mountPointId));
} }
else if (name.endsWith("%") && !expandFolder(fileInfo.getNodeRef(), user, folderPath, "%", true, viewMode).isEmpty()) // \NoSelect else if (name.endsWith("%") && !expandFolder(fileInfo.getNodeRef(), user, folderPath, "%", true, viewMode, mountPointId).isEmpty()) // \NoSelect
{ {
fullList.add(new AlfrescoImapFolder(fileInfo, userName, fileInfo.getName(), folderPath, viewMode, fullList.add(new AlfrescoImapFolder(fileInfo, userName, fileInfo.getName(), folderPath, viewMode,
serviceRegistry, false, isExtractionEnabled(fileInfo.getNodeRef()))); serviceRegistry, false, isExtractionEnabled(fileInfo.getNodeRef()), mountPointId));
} }
if (name.endsWith("*")) if (name.endsWith("*"))
{ {
fullList.addAll(expandFolder(fileInfo.getNodeRef(), user, folderPath, "*", listSubscribed, viewMode)); fullList.addAll(expandFolder(fileInfo.getNodeRef(), user, folderPath, "*", listSubscribed, viewMode, mountPointId));
} }
} }
} }
@@ -1101,7 +1110,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
continue; continue;
} }
fullList.addAll(expandFolder(folder.getNodeRef(), user, rootPathPrefix + folder.getName(), fullList.addAll(expandFolder(folder.getNodeRef(), user, rootPathPrefix + folder.getName(),
mailboxPattern.substring(index + 1), listSubscribed, viewMode)); mailboxPattern.substring(index + 1), listSubscribed, viewMode, mountPointId));
} }
} }
return fullList; return fullList;
@@ -1616,7 +1625,6 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
@Override @Override
public void beforeDeleteNode(final NodeRef nodeRef) public void beforeDeleteNode(final NodeRef nodeRef)
{ {
// RUN AS SYSTEM due to Node Service archive permissions problem ALF-11103
doAsSystem(new RunAsWork<Void>() doAsSystem(new RunAsWork<Void>()
{ {
@Override @Override
@@ -1630,11 +1638,11 @@ 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
getUidValidityTransactionListener(folderRef); getUidValidityTransactionListener(folderRef);
} }
} }
return null; return null;
} }
}); });
} }