use of com.zimbra.common.mailbox.BaseItemInfo in project zm-mailbox by Zimbra.
the class PendingRemoteModifications method fromSOAP.
public static PendingRemoteModifications fromSOAP(PendingFolderModifications mods, Integer folderId, String acctId) {
PendingRemoteModifications prms = new PendingRemoteModifications();
for (CreateItemNotification createSpec : mods.getCreated()) {
prms.recordCreated(ModificationItem.itemUpdate(createSpec.getMessageInfo(), folderId, acctId));
}
for (ModifyItemNotification modifyItem : mods.getModifiedMsgs()) {
int change = modifyItem.getChangeBitmask();
BaseItemInfo itemUpdate = ModificationItem.itemUpdate(modifyItem.getMessageInfo(), folderId, acctId);
prms.recordModified(itemUpdate, change);
}
for (ModifyTagNotification modifyTag : mods.getModifiedTags()) {
int change = modifyTag.getChangeBitmask();
int tagId = modifyTag.getId();
String tagName = modifyTag.getName();
ZimbraTag tagRename = ModificationItem.tagRename(tagId, tagName);
prms.recordModified(tagRename, acctId, change);
}
for (RenameFolderNotification renamedFolder : mods.getRenamedFolders()) {
int change = renamedFolder.getChangeBitmask();
int renamedFolderId = renamedFolder.getFolderId();
String newPath = renamedFolder.getPath();
ModificationItem folderRename = ModificationItem.folderRename(renamedFolderId, newPath, acctId);
prms.recordModified(folderRename, change);
}
for (DeleteItemNotification delSpec : mods.getDeleted()) {
int id = delSpec.getId();
MailItem.Type type = MailItem.Type.of(delSpec.getType());
prms.recordDeleted(type, acctId, id);
}
return prms;
}
use of com.zimbra.common.mailbox.BaseItemInfo in project zm-mailbox by Zimbra.
the class PendingModifications method encodeIMAPFolderModifications.
@SuppressWarnings("rawtypes")
public static Map<Integer, PendingFolderModifications> encodeIMAPFolderModifications(PendingModifications accountMods, Set<Integer> folderInterests) throws ServiceException {
HashMap<Integer, PendingFolderModifications> folderMap = Maps.newHashMap();
if (accountMods != null && accountMods.created != null) {
for (Object mod : accountMods.created.values()) {
if (mod instanceof BaseItemInfo) {
Integer folderId = ((BaseItemInfo) mod).getFolderIdInMailbox();
if (folderInterests != null && !folderInterests.contains(folderId)) {
continue;
}
JaxbUtil.getFolderMods(folderId, folderMap).addCreatedItem(JaxbUtil.getCreatedItemSOAP((BaseItemInfo) mod));
}
}
}
if (accountMods != null && accountMods.modified != null) {
// aggregate tag changes so they are sent to each folder we are interested in
List<ModifyTagNotification> tagMods = new ArrayList<ModifyTagNotification>();
List<DeleteItemNotification> tagDeletes = new ArrayList<DeleteItemNotification>();
for (Object maybeTagChange : accountMods.modified.values()) {
if (maybeTagChange instanceof Change) {
Object maybeTag = ((Change) maybeTagChange).what;
if (maybeTag != null && maybeTag instanceof Tag) {
Tag tag = (Tag) maybeTag;
tagMods.add(new ModifyTagNotification(tag.getIdInMailbox(), tag.getName(), ((Change) maybeTagChange).why));
}
}
}
if (accountMods != null && accountMods.deleted != null) {
@SuppressWarnings("unchecked") Map<ModificationKey, Change> deletedMap = accountMods.deleted;
for (Map.Entry<ModificationKey, Change> entry : deletedMap.entrySet()) {
ModificationKey key = entry.getKey();
Change mod = entry.getValue();
if (mod instanceof Change) {
Object what = mod.what;
if (what != null && what instanceof MailItem.Type) {
if (what == MailItem.Type.TAG) {
// aggregate tag deletions so they are sent to each folder we are interested in
tagDeletes.add(JaxbUtil.getDeletedItemSOAP(key.getItemId(), what.toString()));
} else {
Integer folderId;
if (what == MailItem.Type.FOLDER) {
folderId = key.getItemId();
} else {
folderId = mod.getFolderId();
}
if (folderInterests != null && !folderInterests.contains(folderId)) {
continue;
}
JaxbUtil.getFolderMods(folderId, folderMap).addDeletedItem(JaxbUtil.getDeletedItemSOAP(key.getItemId(), what.toString()));
}
}
}
}
}
for (Object mod : accountMods.modified.values()) {
if (mod instanceof Change) {
Object what = ((Change) mod).what;
if (what != null && what instanceof BaseItemInfo) {
BaseItemInfo itemInfo = (BaseItemInfo) what;
Integer folderId = itemInfo.getFolderIdInMailbox();
if (itemInfo instanceof Folder) {
Integer itemId = itemInfo.getIdInMailbox();
if (folderInterests != null && !folderInterests.contains(folderId) && !folderInterests.contains(itemId)) {
continue;
}
if (!tagMods.isEmpty()) {
PendingFolderModifications folderMods = JaxbUtil.getFolderMods(itemId, folderMap);
for (ModifyTagNotification modTag : tagMods) {
folderMods.addModifiedTag(modTag);
}
} else if (!tagDeletes.isEmpty()) {
PendingFolderModifications folderMods = JaxbUtil.getFolderMods(itemId, folderMap);
for (DeleteItemNotification tagDelete : tagDeletes) {
folderMods.addDeletedItem(tagDelete);
}
}
} else if (!(itemInfo instanceof Tag)) {
if (folderInterests != null && !folderInterests.contains(folderId)) {
continue;
}
JaxbUtil.getFolderMods(folderId, folderMap).addModifiedMsg(JaxbUtil.getModifiedItemSOAP(itemInfo, ((Change) mod).why));
}
}
}
}
}
return folderMap;
}
use of com.zimbra.common.mailbox.BaseItemInfo in project zm-mailbox by Zimbra.
the class Mailbox method snapshotModifications.
/**
* Makes a deep copy of the {@code PendingLocalModifications} object with
* {@link Flag#BITMASK_UNCACHED} set on each {@code MailItem} present in
* the {@code created} and {@code modified} hashes. These copied {@code
* MailItem}s are not linked to their {@code Mailbox} and thus will not
* change when modifications are subsequently made to the contents of the
* {@code Mailbox}. The original {@code PendingLocalModifications} object and
* the {@code MailItem}s it references are unchanged.
* <p>
* This method should only be called <i>immediately</i> before notifying
* listeners of the changes from the currently-ending transaction.
*/
private PendingLocalModifications snapshotModifications(PendingLocalModifications pms) throws ServiceException {
if (pms == null) {
return null;
}
assert (currentChange().depth == 0);
ItemCache cache = mItemCache.get();
FolderCache folders = mFolderCache == null || Collections.disjoint(pms.changedTypes, FOLDER_TYPES) ? mFolderCache : snapshotFolders();
PendingLocalModifications snapshot = new PendingLocalModifications();
if (pms.deleted != null && !pms.deleted.isEmpty()) {
snapshot.recordDeleted(pms.deleted);
}
if (pms.created != null && !pms.created.isEmpty()) {
for (BaseItemInfo item : pms.created.values()) {
if (item instanceof Folder && folders != null) {
Folder folder = (Folder) item;
Folder snapshotted = folders.get(folder.getId());
if (snapshotted == null) {
ZimbraLog.mailbox.warn("folder missing from snapshotted folder set: %d", folder.getId());
snapshotted = folder;
}
snapshot.recordCreated(snapshotted);
} else if (item instanceof Tag) {
Tag tag = (Tag) item;
if (tag.isListed() || tag.isImapVisible()) {
snapshot.recordCreated(snapshotItem(tag));
}
} else if (item instanceof MailItem) {
MailItem mi = (MailItem) item;
// NOTE: if the folder cache is null, folders fall down here and should always get copy == false
if (cache != null && cache.contains(mi)) {
mi = snapshotItem(mi);
}
snapshot.recordCreated(mi);
}
}
}
if (pms.modified != null && !pms.modified.isEmpty()) {
for (Map.Entry<PendingModifications.ModificationKey, Change> entry : pms.modified.entrySet()) {
Change chg = entry.getValue();
if (!(chg.what instanceof MailItem)) {
snapshot.recordModified(entry.getKey(), chg);
continue;
}
MailItem item = (MailItem) chg.what;
if (item instanceof Folder && folders != null) {
Folder folder = folders.get(item.getId());
if (folder == null) {
ZimbraLog.mailbox.warn("folder missing from snapshotted folder set: %d", item.getId());
folder = (Folder) item;
}
snapshot.recordModified(folder, chg.why, (MailItem) chg.preModifyObj);
} else if (item instanceof Tag) {
if (((Tag) item).isListed()) {
snapshot.recordModified(snapshotItem(item), chg.why, (MailItem) chg.preModifyObj);
}
} else {
// NOTE: if the folder cache is null, folders fall down here and should always get copy == false
if (cache != null && cache.contains(item)) {
item = snapshotItem(item);
}
snapshot.recordModified(item, chg.why, (MailItem) chg.preModifyObj);
}
}
}
return snapshot;
}
use of com.zimbra.common.mailbox.BaseItemInfo in project zm-mailbox by Zimbra.
the class ShareStartStopListener method notify.
@Override
public void notify(ChangeNotification notification) {
if (notification.mods.created != null) {
// A new folder with non-empty ACL means start of sharing.
for (BaseItemInfo created : notification.mods.created.values()) {
if (created instanceof Folder) {
Folder folder = (Folder) created;
if (folder.getACL() != null) {
startShare(folder);
}
}
}
}
if (notification.mods.modified != null) {
// ACL change on folder can mean start or stop of sharing.
for (Change change : notification.mods.modified.values()) {
if ((change.why & Change.ACL) != 0 && change.preModifyObj instanceof Folder && change.what instanceof Folder) {
Folder before = (Folder) change.preModifyObj;
Folder after = (Folder) change.what;
boolean beforeHasACL = before.getACL() != null;
boolean afterHasACL = after.getACL() != null;
if (!beforeHasACL && afterHasACL) {
startShare(after);
} else if (beforeHasACL && !afterHasACL) {
stopShare(after);
}
// Note: No attempt is made to start/stop share based on the folder moving into
// or out of trash/spam folder. This is because no notification is generated
// when the folder crosses the boundary by virtue of one of its parent folders moving.
}
}
}
if (notification.mods.deleted != null) {
// Deletion of a folder with non-empty ACL stops sharing.
for (Change change : notification.mods.deleted.values()) {
Folder folder = null;
if (change.what instanceof Folder) {
folder = (Folder) change.what;
} else if (change.preModifyObj instanceof Folder) {
folder = (Folder) change.preModifyObj;
}
if (folder != null && folder.getACL() != null) {
stopShare(folder);
}
}
}
}
use of com.zimbra.common.mailbox.BaseItemInfo in project zm-mailbox by Zimbra.
the class Mailbox method snapshotCounts.
void snapshotCounts() throws ServiceException {
// for write ops, update the "new messages" count in the DB appropriately
OperationContext octxt = currentChange().octxt;
RedoableOp player = currentChange().getRedoPlayer();
RedoableOp recorder = currentChange().recorder;
if (recorder != null && (player == null || (octxt != null && !octxt.isRedo()))) {
assert (currentChange().writeChange);
boolean isNewMessage = recorder.getOperation() == MailboxOperation.CreateMessage;
if (isNewMessage) {
CreateMessage cm = (CreateMessage) recorder;
if (cm.getFolderId() == ID_FOLDER_SPAM || cm.getFolderId() == ID_FOLDER_TRASH) {
isNewMessage = false;
} else if ((cm.getFlags() & NON_DELIVERY_FLAGS) != 0) {
isNewMessage = false;
} else if (octxt != null && octxt.getSession() != null && !octxt.isDelegatedRequest(this)) {
isNewMessage = false;
}
if (isNewMessage) {
String folderList = getAccount().getPrefMailFoldersCheckedForNewMsgIndicator();
if (folderList != null) {
String[] folderIds = folderList.split(",");
isNewMessage = false;
for (int i = 0; i < folderIds.length; i++) {
if (cm.getFolderId() == Integer.parseInt(folderIds[i])) {
isNewMessage = true;
break;
}
}
}
}
}
if (isNewMessage) {
currentChange().recent = mData.recentMessages + 1;
} else if (octxt != null && mData.recentMessages != 0) {
Session s = octxt.getSession();
if (s instanceof SoapSession || (s instanceof SoapSession.DelegateSession && ((SoapSession.DelegateSession) s).getParentSession().isOfflineSoapSession())) {
currentChange().recent = 0;
}
}
}
if (currentChange().isMailboxRowDirty(mData)) {
assert (currentChange().writeChange);
if (currentChange().recent != MailboxChange.NO_CHANGE) {
ZimbraLog.mailbox.debug("setting recent count to %d", currentChange().recent);
}
DbMailbox.updateMailboxStats(this);
}
boolean foldersTagsDirty = false;
if (currentChange().dirty != null && currentChange().dirty.hasNotifications()) {
assert (currentChange().writeChange);
if (currentChange().dirty.created != null) {
for (BaseItemInfo item : currentChange().dirty.created.values()) {
if (item instanceof Folder) {
Folder folder = (Folder) item;
foldersTagsDirty = true;
if (folder.getSize() != 0) {
folder.saveFolderCounts(false);
}
} else if (item instanceof Tag) {
Tag tag = (Tag) item;
foldersTagsDirty = true;
if (tag.isUnread()) {
tag.saveTagCounts();
}
}
}
}
if (currentChange().dirty.modified != null) {
for (Change change : currentChange().dirty.modified.values()) {
if (change.what instanceof Folder) {
foldersTagsDirty = true;
if ((change.why & (Change.UNREAD | Change.SIZE)) != 0) {
((Folder) change.what).saveFolderCounts(false);
}
} else if (change.what instanceof Tag) {
foldersTagsDirty = true;
if ((change.why & Change.UNREAD | Change.SIZE) != 0) {
((Tag) change.what).saveTagCounts();
}
} else if ((change.what instanceof MailItem)) {
if (change.what instanceof Conversation) {
uncache((MailItem) change.what);
} else {
cache((MailItem) change.what);
}
}
}
}
if (currentChange().dirty.deleted != null) {
for (Change change : currentChange().dirty.deleted.values()) {
if (change.what instanceof Folder || change.what instanceof Tag) {
foldersTagsDirty = true;
break;
}
}
}
if (foldersTagsDirty) {
cacheFoldersTagsToMemcached();
}
}
if (DebugConfig.checkMailboxCacheConsistency && currentChange().dirty != null && currentChange().dirty.hasNotifications()) {
if (currentChange().dirty.created != null) {
for (BaseItemInfo item : currentChange().dirty.created.values()) {
if (item instanceof MailItem) {
MailItem mi = (MailItem) item;
DbMailItem.consistencyCheck(mi, mi.mData, mi.encodeMetadata().toString());
}
}
}
if (currentChange().dirty.modified != null) {
for (Change change : currentChange().dirty.modified.values()) {
if (change.what instanceof MailItem) {
MailItem item = (MailItem) change.what;
DbMailItem.consistencyCheck(item, item.mData, item.encodeMetadata().toString());
}
}
}
}
}
Aggregations