Search in sources :

Example 21 with Tag

use of com.zimbra.cs.mailbox.Tag in project zm-mailbox by Zimbra.

the class ImapHandler method doAPPEND.

boolean doAPPEND(String tag, ImapPath path, List<AppendMessage> appends) throws IOException, ImapException {
    checkCommandThrottle(new AppendCommand(path, appends));
    if (!checkState(tag, State.AUTHENTICATED)) {
        return true;
    }
    Object mboxobj = null;
    List<Tag> newTags = new ArrayList<Tag>();
    List<Integer> createdIds = new ArrayList<Integer>(appends.size());
    StringBuilder appendHint = extensionEnabled("UIDPLUS") ? new StringBuilder() : null;
    try {
        if (!path.isVisible()) {
            throw ImapServiceException.FOLDER_NOT_VISIBLE(path.asImapPath());
        } else if (!path.isWritable(ACL.RIGHT_INSERT)) {
            throw ImapServiceException.FOLDER_NOT_WRITABLE(path.asImapPath());
        }
        mboxobj = path.getOwnerMailbox();
        Object folderobj = path.getFolder();
        Mailbox mbox = mboxobj instanceof Mailbox ? (Mailbox) mboxobj : credentials.getMailbox();
        mbox.lock.lock();
        try {
            ImapFlagCache flagset = ImapFlagCache.getSystemFlags(mbox);
            ImapFlagCache tagset = mboxobj instanceof Mailbox ? new ImapFlagCache((Mailbox) mboxobj, getContext()) : new ImapFlagCache();
            for (AppendMessage append : appends) {
                append.checkFlags(mbox, flagset, tagset, newTags);
            }
        } finally {
            mbox.lock.release();
        }
        // Append message parts and check message content size
        for (AppendMessage append : appends) {
            append.checkContent();
        }
        for (AppendMessage append : appends) {
            int id = append.storeContent(mboxobj, folderobj);
            if (id > 0) {
                createdIds.add(id);
            }
        }
        int uvv = (folderobj instanceof Folder ? ImapFolder.getUIDValidity((Folder) folderobj) : ImapFolder.getUIDValidity((ZFolder) folderobj));
        if (appendHint != null && uvv > 0) {
            appendHint.append("[APPENDUID ").append(uvv).append(' ').append(ImapFolder.encodeSubsequence(createdIds)).append("] ");
        }
    } catch (ServiceException e) {
        for (AppendMessage append : appends) {
            append.cleanup();
        }
        deleteTags(newTags);
        deleteMessages(mboxobj, createdIds);
        String msg = "APPEND failed";
        if (e.getCode().equals(MailServiceException.NO_SUCH_FOLDER)) {
            ZimbraLog.imap.info("APPEND failed: no such folder: " + path);
            //          of the text of the tagged NO response."
            if (path.isCreatable()) {
                msg = "[TRYCREATE] APPEND failed: no such mailbox";
            }
        } else if (e.getCode().equals(MailServiceException.INVALID_NAME)) {
            ZimbraLog.imap.info("APPEND failed: " + e.getMessage());
        } else if (e.getCode().equals(ImapServiceException.FOLDER_NOT_VISIBLE)) {
            ZimbraLog.imap.info("APPEND failed: folder not visible: " + path);
        } else if (e.getCode().equals(ImapServiceException.FOLDER_NOT_WRITABLE)) {
            ZimbraLog.imap.info("APPEND failed: folder not writable: " + path);
        } else if (e.getCode().equals(MailServiceException.QUOTA_EXCEEDED)) {
            ZimbraLog.imap.info("APPEND failed: quota exceeded");
        } else {
            ZimbraLog.imap.warn("APPEND failed", e);
        }
        sendNO(tag, msg);
        return canContinue(e);
    }
    sendNotifications(true, false);
    sendOK(tag, (appendHint == null ? "" : appendHint.toString()) + "APPEND completed");
    return true;
}
Also used : ArrayList(java.util.ArrayList) SearchFolder(com.zimbra.cs.mailbox.SearchFolder) Folder(com.zimbra.cs.mailbox.Folder) ZFolder(com.zimbra.client.ZFolder) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZMailbox(com.zimbra.client.ZMailbox) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) Tag(com.zimbra.cs.mailbox.Tag)

Example 22 with Tag

use of com.zimbra.cs.mailbox.Tag in project zm-mailbox by Zimbra.

the class TestTags method cleanUp.

private void cleanUp() throws Exception {
    Set<Integer> messageIds = search("subject:\"Test tags\"", MailItem.Type.MESSAGE);
    for (int id : messageIds) {
        mMbox.delete(null, id, MailItem.Type.MESSAGE);
    }
    List<Tag> tags = mMbox.getTagList(null);
    if (tags == null) {
        return;
    }
    for (Tag tag : tags) {
        if (tag.getName().startsWith(TAG_PREFIX)) {
            mMbox.delete(null, tag.getId(), tag.getType());
        }
    }
    if (mountpoint != null) {
        try {
            mMbox.delete(null, mountpoint.getId(), MailItem.Type.MOUNTPOINT);
        } catch (Exception e) {
        }
        mountpoint = null;
    }
    try {
        TestUtil.deleteAccount(remoteUser);
    } catch (Exception e) {
    }
}
Also used : Tag(com.zimbra.cs.mailbox.Tag) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException)

Example 23 with Tag

use of com.zimbra.cs.mailbox.Tag in project zm-mailbox by Zimbra.

the class Sync method deltaSync.

private static String deltaSync(Element response, OperationContext octxt, ItemIdFormatter ifmt, Mailbox mbox, SyncToken syncToken, int deleteLimit, int changeLimit, boolean typedDeletes, Folder root, Set<Folder> visible, int messageSyncStart) throws ServiceException {
    int begin = syncToken.getChangeId();
    int deleteModSeqCutoff = syncToken.getDeleteModSeq();
    deleteModSeqCutoff = deleteModSeqCutoff <= 0 ? begin : deleteModSeqCutoff;
    int mboxLastChangeId = mbox.getLastChangeID();
    SyncToken newSyncToken = new SyncToken(mboxLastChangeId);
    if (begin >= mboxLastChangeId && deleteModSeqCutoff >= mboxLastChangeId) {
        return newSyncToken.toString();
    }
    int changeItemIdCutoff = syncToken.getOffsetInNext();
    int deleteItemIdCutoff = syncToken.getDeleteOffsetInNext();
    // first, fetch deleted items
    TypedIdList tombstones = mbox.getTombstones(deleteModSeqCutoff);
    Element eDeleted = response.addElement(MailConstants.E_DELETED);
    // then, put together the requested folder hierarchy in 2 different flavors
    List<Folder> hierarchy = (root == null || root.getId() == Mailbox.ID_FOLDER_USER_ROOT ? null : root.getSubfolderHierarchy());
    Set<Integer> targetIds = (root != null && root.getId() == Mailbox.ID_FOLDER_USER_ROOT ? null : new HashSet<Integer>(hierarchy == null ? 0 : hierarchy.size()));
    if (hierarchy != null) {
        for (Folder folder : hierarchy) {
            targetIds.add(folder.getId());
        }
    }
    // then, handle created/modified folders
    if (octxt.isDelegatedRequest(mbox)) {
        // first, make sure that something changed...
        if (!mbox.getModifiedFolders(begin).isEmpty() || !Collections.disjoint(tombstones.types(), FOLDER_TYPES)) {
            // special-case the folder hierarchy for delegated delta sync
            boolean anyFolders = folderSync(response, octxt, ifmt, mbox, root, visible, -1, messageSyncStart, SyncPhase.DELTA);
            // if no folders are visible, add an empty "<folder/>" as a hint
            if (!anyFolders) {
                response.addElement(MailConstants.E_FOLDER);
            }
        }
    } else {
        for (Folder folder : mbox.getModifiedFolders(begin)) {
            // no case of "synthetic tombstone" (item falling out of the tree being synced)
            if (targetIds == null || targetIds.contains(folder.getId())) {
                ToXML.encodeFolder(response, ifmt, octxt, folder, Change.ALL_FIELDS);
            } else {
                tombstones.add(folder.getType(), folder.getId(), folder.getUuid(), folder.getModifiedSequence());
            }
        }
    }
    // next, handle created/modified tags
    for (Tag tag : mbox.getModifiedTags(octxt, begin)) {
        ToXML.encodeTag(response, ifmt, octxt, tag, Change.ALL_FIELDS);
    }
    // finally, handle created/modified "other items"
    int itemCount = 0;
    Pair<List<Integer>, TypedIdList> changed = mbox.getModifiedItems(octxt, Math.min(begin, deleteModSeqCutoff), messageSyncStart, MailItem.Type.UNKNOWN, targetIds, deleteModSeqCutoff);
    List<Integer> modified = changed.getFirst();
    // items that have been altered in non-visible folders will be returned as "deleted" in order to handle moves
    if (changed.getSecond() != null) {
        tombstones.addAll(changed.getSecond());
    }
    delta: while (!modified.isEmpty()) {
        List<Integer> batch = modified.subList(0, Math.min(modified.size(), FETCH_BATCH_SIZE));
        for (MailItem item : mbox.getItemById(octxt, batch, MailItem.Type.UNKNOWN)) {
            // detect interrupted sync and resume from the appropriate place
            if ((item.getModifiedSequence() == begin + 1 && item.getId() < changeItemIdCutoff) || item.getModifiedSequence() <= begin) {
                //if interrupted delete and un-interrupted modifications.
                continue;
            }
            // if we've overflowed this sync response, set things up so that a subsequent sync starts from where we're cutting off
            if (itemCount >= changeLimit) {
                response.addAttribute(MailConstants.A_QUERY_MORE, true);
                newSyncToken.setChangeModSeq((item.getModifiedSequence() - 1));
                newSyncToken.setChangeItemId(item.getId());
                newSyncToken.setDeleteModSeq(mboxLastChangeId);
                break delta;
            }
            // For items in the system, if the content has changed since the user last sync'ed
            // (because it was edited or created), just send back the folder ID and saved date --
            // the client will request the whole object out of band -- potentially using the
            // content servlet's "include metadata in headers" hack.
            // If it's just the metadata that changed, send back the set of mutable attributes.
            boolean created = item.getSavedSequence() > begin;
            ToXML.encodeItem(response, ifmt, octxt, item, created ? Change.FOLDER | Change.CONFLICT | Change.DATE | Change.PARENT : MUTABLE_FIELDS);
            itemCount++;
        }
        batch.clear();
    }
    // cleanup: only return a <deleted> element if we're sending back deleted item ids
    if ((deleteLimit > 0 && tombstones.size() > deleteLimit) || deleteItemIdCutoff > 0) {
        PagedDelete pgDel = new PagedDelete(tombstones, typedDeletes);
        pgDel.removeBeforeCutoff(deleteItemIdCutoff, deleteModSeqCutoff);
        if (deleteLimit > 0) {
            pgDel.trimDeletesTillPageLimit(deleteLimit);
        }
        encodePagedDelete(eDeleted, pgDel, newSyncToken, tombstones, typedDeletes);
        if (pgDel.isDeleteOverFlow()) {
            response.addAttribute(MailConstants.A_QUERY_MORE, true);
            response.addAttribute(MailConstants.A_QUERY_MORE, true);
        }
    } else {
        encodeUnpagedDelete(eDeleted, tombstones, typedDeletes);
    }
    return newSyncToken.toString();
}
Also used : PagedDelete(com.zimbra.cs.mailbox.util.PagedDelete) Element(com.zimbra.common.soap.Element) Folder(com.zimbra.cs.mailbox.Folder) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) SyncToken(com.zimbra.cs.service.util.SyncToken) MailItem(com.zimbra.cs.mailbox.MailItem) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) List(java.util.List) Tag(com.zimbra.cs.mailbox.Tag) HashSet(java.util.HashSet)

Example 24 with Tag

use of com.zimbra.cs.mailbox.Tag in project zm-mailbox by Zimbra.

the class TestConcurrency method testTag.

@Test
public void testTag() throws Exception {
    int numThreads = 5;
    Thread[] threads = new Thread[numThreads];
    for (int i = 0; i < numThreads; i++) {
        Tag tag = mMbox.createTag(null, TAG_PREFIX + i + 1, (byte) 0);
        threads[i] = new Thread(new TagMessagesThread(tag, 5), "TagMessagesThread-" + i);
    }
    runThreads(threads);
}
Also used : Tag(com.zimbra.cs.mailbox.Tag) Test(org.junit.Test)

Example 25 with Tag

use of com.zimbra.cs.mailbox.Tag in project zm-mailbox by Zimbra.

the class TestConcurrency method tearDown.

@After
public void tearDown() throws Exception {
    // Delete tags - kept for testing purposes
    List<Tag> tagList = mMbox.getTagList(null);
    if (tagList != null) {
        Iterator<Tag> i = tagList.iterator();
        while (i.hasNext()) {
            Tag tag = i.next();
            if (tag.getName().startsWith(TAG_PREFIX)) {
                mMbox.delete(null, tag.getId(), tag.getType());
            }
        }
    }
    // Move items from temp folder back to inbox
    Folder folder = TestUtil.getFolderByPath(mMbox, FOLDER_NAME);
    if (folder != null) {
        List<MailItem> ids = mMbox.getItemList(null, MailItem.Type.MESSAGE, folder.getId());
        Iterator<MailItem> i = ids.iterator();
        while (i.hasNext()) {
            Message message = (Message) i.next();
            mMbox.move(null, message.getId(), MailItem.Type.MESSAGE, Mailbox.ID_FOLDER_INBOX);
        }
        mMbox.delete(null, folder.getId(), folder.getType());
    }
    cleanUp();
}
Also used : MailItem(com.zimbra.cs.mailbox.MailItem) Message(com.zimbra.cs.mailbox.Message) Tag(com.zimbra.cs.mailbox.Tag) Folder(com.zimbra.cs.mailbox.Folder) After(org.junit.After)

Aggregations

Tag (com.zimbra.cs.mailbox.Tag)26 Mailbox (com.zimbra.cs.mailbox.Mailbox)15 Folder (com.zimbra.cs.mailbox.Folder)10 Test (org.junit.Test)9 Element (com.zimbra.common.soap.Element)8 ServiceException (com.zimbra.common.service.ServiceException)7 Account (com.zimbra.cs.account.Account)7 MailItem (com.zimbra.cs.mailbox.MailItem)7 OperationContext (com.zimbra.cs.mailbox.OperationContext)6 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)5 Message (com.zimbra.cs.mailbox.Message)5 Mountpoint (com.zimbra.cs.mailbox.Mountpoint)5 ParsedMessage (com.zimbra.cs.mime.ParsedMessage)4 ItemId (com.zimbra.cs.service.util.ItemId)4 Flag (com.zimbra.cs.mailbox.Flag)3 ItemIdFormatter (com.zimbra.cs.service.util.ItemIdFormatter)3 ArrayList (java.util.ArrayList)3 ZMailbox (com.zimbra.client.ZMailbox)2 AccountServiceException (com.zimbra.cs.account.AccountServiceException)2 Contact (com.zimbra.cs.mailbox.Contact)2