Search in sources :

Example 6 with BaseItemInfo

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;
}
Also used : CreateItemNotification(com.zimbra.soap.mail.type.CreateItemNotification) BaseItemInfo(com.zimbra.common.mailbox.BaseItemInfo) ZimbraTag(com.zimbra.common.mailbox.ZimbraTag) Type(com.zimbra.cs.mailbox.MailItem.Type) RenameFolderNotification(com.zimbra.soap.mail.type.ModifyNotification.RenameFolderNotification) MailItem(com.zimbra.cs.mailbox.MailItem) ZimbraMailItem(com.zimbra.common.mailbox.ZimbraMailItem) DeleteItemNotification(com.zimbra.soap.mail.type.DeleteItemNotification) ModifyItemNotification(com.zimbra.soap.mail.type.ModifyNotification.ModifyItemNotification) ModifyTagNotification(com.zimbra.soap.mail.type.ModifyNotification.ModifyTagNotification)

Example 7 with BaseItemInfo

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;
}
Also used : BaseItemInfo(com.zimbra.common.mailbox.BaseItemInfo) ArrayList(java.util.ArrayList) Folder(com.zimbra.cs.mailbox.Folder) Type(com.zimbra.cs.mailbox.MailItem.Type) MailItem(com.zimbra.cs.mailbox.MailItem) ZimbraMailItem(com.zimbra.common.mailbox.ZimbraMailItem) DeleteItemNotification(com.zimbra.soap.mail.type.DeleteItemNotification) Tag(com.zimbra.cs.mailbox.Tag) ModifyTagNotification(com.zimbra.soap.mail.type.ModifyNotification.ModifyTagNotification) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) PendingFolderModifications(com.zimbra.soap.mail.type.PendingFolderModifications)

Example 8 with BaseItemInfo

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;
}
Also used : PendingLocalModifications(com.zimbra.cs.session.PendingLocalModifications) DbMailItem(com.zimbra.cs.db.DbMailItem) ZimbraMailItem(com.zimbra.common.mailbox.ZimbraMailItem) BaseItemInfo(com.zimbra.common.mailbox.BaseItemInfo) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag) Change(com.zimbra.cs.session.PendingModifications.Change) CreateFolder(com.zimbra.cs.redolog.op.CreateFolder) ZFolder(com.zimbra.client.ZFolder) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ConcurrentLinkedHashMap(com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap) IcalXmlStrMap(com.zimbra.cs.mailbox.calendar.IcalXmlStrMap) HashMap(java.util.HashMap) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap)

Example 9 with BaseItemInfo

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);
            }
        }
    }
}
Also used : BaseItemInfo(com.zimbra.common.mailbox.BaseItemInfo) Change(com.zimbra.cs.session.PendingModifications.Change)

Example 10 with BaseItemInfo

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());
                }
            }
        }
    }
}
Also used : BaseItemInfo(com.zimbra.common.mailbox.BaseItemInfo) Change(com.zimbra.cs.session.PendingModifications.Change) CreateFolder(com.zimbra.cs.redolog.op.CreateFolder) ZFolder(com.zimbra.client.ZFolder) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) DbMailItem(com.zimbra.cs.db.DbMailItem) ZimbraMailItem(com.zimbra.common.mailbox.ZimbraMailItem) SoapSession(com.zimbra.cs.session.SoapSession) RedoableOp(com.zimbra.cs.redolog.op.RedoableOp) CreateMessage(com.zimbra.cs.redolog.op.CreateMessage) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag) DbSession(com.zimbra.cs.db.DbSession) Session(com.zimbra.cs.session.Session) SoapSession(com.zimbra.cs.session.SoapSession)

Aggregations

BaseItemInfo (com.zimbra.common.mailbox.BaseItemInfo)17 Change (com.zimbra.cs.session.PendingModifications.Change)10 MailItem (com.zimbra.cs.mailbox.MailItem)8 HashMap (java.util.HashMap)8 Map (java.util.Map)8 ServiceException (com.zimbra.common.service.ServiceException)7 ZimbraMailItem (com.zimbra.common.mailbox.ZimbraMailItem)6 ModificationKey (com.zimbra.cs.session.PendingModifications.ModificationKey)6 Mailbox (com.zimbra.cs.mailbox.Mailbox)5 Folder (com.zimbra.cs.mailbox.Folder)4 Type (com.zimbra.cs.mailbox.MailItem.Type)4 LinkedHashMap (java.util.LinkedHashMap)4 ZFolder (com.zimbra.client.ZFolder)3 ZimbraTag (com.zimbra.common.mailbox.ZimbraTag)3 DbTag (com.zimbra.cs.db.DbTag)3 Message (com.zimbra.cs.mailbox.Message)3 MemcachedMap (com.zimbra.common.util.memcached.MemcachedMap)2 DbMailItem (com.zimbra.cs.db.DbMailItem)2 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)2 AlterItemTag (com.zimbra.cs.redolog.op.AlterItemTag)2