Search in sources :

Example 31 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore in project zm-mailbox by Zimbra.

the class ImapSessionManager method openFolder.

protected FolderDetails openFolder(ImapPath path, byte params, ImapHandler handler) throws ServiceException {
    ZimbraLog.imap.debug("opening folder: %s", path);
    if (!path.isSelectable()) {
        throw ServiceException.PERM_DENIED("cannot select folder: " + path);
    }
    if ((params & ImapFolder.SELECT_CONDSTORE) != 0) {
        handler.activateExtension(ImapExtension.CONDSTORE);
    }
    FolderStore folder = path.getFolder();
    String folderIdAsString = folder.getFolderIdAsString();
    int folderId = folder.getFolderIdInOwnerMailbox();
    MailboxStore mbox = folder.getMailboxStore();
    ImapMailboxStore imapStore = ImapMailboxStore.get(mbox);
    // don't have a session when the folder is loaded...
    OperationContext octxt = handler.getCredentials().getContext();
    List<ImapMessage> i4list = null;
    // *always* recalculate the contents of search folders
    if (folder instanceof SearchFolderStore) {
        i4list = loadVirtualFolder(octxt, (SearchFolderStore) folder);
    } else {
        waitForWaitSetNotifications(imapStore, folder);
    }
    mbox.lock(true);
    try {
        // need mInitialRecent to be set *before* loading the folder so we can determine what's \Recent
        if (!(folder instanceof ZSharedFolder)) {
            folder = mbox.getFolderById(octxt, folderIdAsString);
            if (folder == null) {
                throw MailServiceException.NO_SUCH_FOLDER(path.asImapPath());
            }
        }
        int recentCutoff = imapStore.getImapRECENTCutoff(folder);
        if (i4list == null) {
            List<ImapListener> listners = imapStore.getListeners(folder);
            // first option is to duplicate an existing registered session
            // (could try to just activate an inactive session, but this logic is simpler for now)
            i4list = duplicateExistingSession(folderId, listners);
            // no matching session means we next check for serialized folder data
            if (i4list == null) {
                i4list = duplicateSerializedFolder(folder);
            } else if (CONSISTENCY_CHECK) {
                Collections.sort(i4list);
            // sort only if using list from duplicated session which may be out of order
            // if loaded from serialized folder order _should_ already be OK since no changes have occurred
            }
            // do the consistency check, if requested
            if (CONSISTENCY_CHECK) {
                i4list = consistencyCheck(i4list, imapStore, octxt, folder);
            }
            // no matching serialized session means we have to go to the DB to get the messages
            if (i4list == null) {
                ItemIdentifier ident;
                if (folder instanceof MountpointStore) {
                    ident = ((MountpointStore) folder).getTargetItemIdentifier();
                } else {
                    ident = folder.getFolderItemIdentifier();
                }
                i4list = imapStore.openImapFolder(octxt, ident);
            }
        }
        Collections.sort(i4list);
        // check messages for imapUid <= 0 and assign new IMAP IDs if necessary
        renumberMessages(octxt, mbox, i4list);
        ImapFolder i4folder = new ImapFolder(path, params, handler);
        // don't rely on the <code>Folder</code> object being updated in place
        if (!(folder instanceof ZSharedFolder)) {
            folder = mbox.getFolderById(octxt, folderIdAsString);
        }
        // can't set these until *after* loading the folder because UID renumbering affects them
        InitialFolderValues initial = new InitialFolderValues(folder);
        for (ImapMessage i4msg : i4list) {
            i4folder.cache(i4msg, i4msg.imapUid > recentCutoff);
            if (initial.firstUnread == -1 && (i4msg.flags & Flag.BITMASK_UNREAD) != 0) {
                initial.firstUnread = i4msg.sequence;
            }
        }
        i4folder.setInitialSize();
        ZimbraLog.imap.debug("ImapSessionManager.openFolder.  Folder with id=%s added message list %s", folderIdAsString, i4list);
        ImapListener session = null;
        try {
            session = imapStore.createListener(i4folder, handler);
            session.register();
            sessions.put(session, session);
            imapStore.registerWithImapServerListener(session);
            return new FolderDetails(session, initial);
        } catch (ServiceException e) {
            if (session != null) {
                session.unregister();
            }
            throw e;
        }
    } finally {
        mbox.unlock();
    }
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) MailboxStore(com.zimbra.common.mailbox.MailboxStore) FolderStore(com.zimbra.common.mailbox.FolderStore) SearchFolderStore(com.zimbra.common.mailbox.SearchFolderStore) ZSharedFolder(com.zimbra.client.ZSharedFolder) ItemIdentifier(com.zimbra.common.mailbox.ItemIdentifier) SearchFolderStore(com.zimbra.common.mailbox.SearchFolderStore) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) MountpointStore(com.zimbra.common.mailbox.MountpointStore)

Example 32 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore in project zm-mailbox by Zimbra.

the class ImapSessionManager method loadVirtualFolder.

/**
 * Fetches the messages contained within a search folder.  When a search folder is IMAP-visible, it appears in
 * folder listings, is SELECTable READ-ONLY, and appears to have all matching messages as its contents.
 * If it is not visible, it will be completely hidden from all IMAP commands.
 * @param octxt   Encapsulation of the authenticated user.
 * @param search  The search folder being exposed.
 */
private static List<ImapMessage> loadVirtualFolder(OperationContext octxt, SearchFolderStore search) throws ServiceException {
    List<ImapMessage> i4list = Lists.newArrayList();
    Set<MailItemType> types = ImapFolder.getMailItemTypeConstraint(search);
    if (types.isEmpty()) {
        return i4list;
    }
    MailboxStore mbox = search.getMailboxStore();
    ZimbraSearchParams params = mbox.createSearchParams(search.getQuery());
    params.setIncludeTagDeleted(true);
    params.setMailItemTypes(types);
    params.setZimbraSortBy(ZimbraSortBy.dateAsc);
    params.setLimit(1000);
    params.setZimbraFetchMode(ZimbraFetchMode.IMAP);
    try {
        ZimbraQueryHitResults zqr = mbox.searchImap(octxt, params);
        try {
            for (ZimbraQueryHit hit = zqr.getNext(); hit != null; hit = zqr.getNext()) {
                i4list.add(new ImapMessage(hit));
            }
        } finally {
            zqr.close();
        }
    } catch (ServiceException e) {
        throw e;
    } catch (Exception e) {
        throw ServiceException.FAILURE("failure opening search folder", e);
    }
    return i4list;
}
Also used : ZimbraQueryHitResults(com.zimbra.common.mailbox.ZimbraQueryHitResults) MailboxStore(com.zimbra.common.mailbox.MailboxStore) ZimbraSearchParams(com.zimbra.common.mailbox.ZimbraSearchParams) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ZimbraQueryHit(com.zimbra.common.mailbox.ZimbraQueryHit) MailItemType(com.zimbra.common.mailbox.MailItemType) ServiceException(com.zimbra.common.service.ServiceException) MailboxInMaintenanceException(com.zimbra.cs.mailbox.MailServiceException.MailboxInMaintenanceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException)

Example 33 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore in project zm-mailbox by Zimbra.

the class ImapURL method getContentAsStream.

public InputStreamWithSize getContentAsStream(ImapHandler handler, ImapCredentials creds, String tag) throws ImapException {
    ImapHandler.State state = handler.getState();
    if (state == ImapHandler.State.NOT_AUTHENTICATED) {
        throw new ImapUrlException(tag, mURL, "must be in AUTHENTICATED state");
    }
    try {
        Account acct = Provisioning.getInstance().get(AccountBy.name, mUsername);
        if (acct == null) {
            throw new ImapUrlException(tag, mURL, "cannot find user: " + mUsername);
        }
        ImapListener i4session = handler.getCurrentImapListener();
        OperationContext octxt = creds.getContext().setSession(i4session);
        InputStreamWithSize content = null;
        // special-case the situation where the relevant folder is already SELECTed
        ImapFolder i4folder = handler.getSelectedFolder();
        if (state == ImapHandler.State.SELECTED && (i4session != null) && (i4folder != null) && acct.getId().equals(i4session.getTargetAccountId()) && mPath.isEquivalent(i4folder.getPath())) {
            ImapMessage i4msg = i4folder.getByImapId(mUid);
            if (i4msg == null || i4msg.isExpunged()) {
                throw new ImapUrlException(tag, mURL, "no such message");
            }
            MailboxStore i4Mailbox = i4folder.getMailbox();
            ZimbraMailItem item = i4Mailbox.getItemById(octxt, ItemIdentifier.fromAccountIdAndItemId(i4Mailbox.getAccountId(), i4msg.msgId), i4msg.getMailItemType());
            content = ImapMessage.getContent(item);
        }
        // if not, have to fetch by IMAP UID if we're local or handle off-server URLs
        if (content == null) {
            ImapMailboxStore mbox = mPath.getOwnerImapMailboxStore();
            content = mbox.getByImapId(octxt, mUid, mPath.getFolder().getFolderIdAsString(), mPath.asResolvedPath());
            if (null == content) {
                throw new ImapUrlException(tag, mURL, "no such message");
            }
        }
        // fetch the content of the message
        if (mPart == null) {
            return content;
        }
        // and return the appropriate subpart of the selected message
        MimeMessage mm;
        try {
            mm = new Mime.FixedMimeMessage(JMSession.getSession(), content.stream);
        } finally {
            content.stream.close();
        }
        InputStreamWithSize part = mPart.getContentOctetRange(mm);
        if (part == null) {
            throw new ImapUrlException(tag, mURL, "no such part");
        }
        return part;
    } catch (NoSuchItemException e) {
        ZimbraLog.imap.info("no such message", e);
    } catch (ServiceException | MessagingException | BinaryDecodingException e) {
        ZimbraLog.imap.info("can't fetch content from IMAP URL", e);
    } catch (IOException e) {
        ZimbraLog.imap.info("error reading content from IMAP URL", e);
    }
    throw new ImapUrlException(tag, mURL, "error fetching IMAP URL content");
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) Account(com.zimbra.cs.account.Account) MailboxStore(com.zimbra.common.mailbox.MailboxStore) MessagingException(javax.mail.MessagingException) IOException(java.io.IOException) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) Mime(com.zimbra.cs.mime.Mime) BinaryDecodingException(com.zimbra.cs.imap.ImapPartSpecifier.BinaryDecodingException) ServiceException(com.zimbra.common.service.ServiceException) MimeMessage(javax.mail.internet.MimeMessage) InputStreamWithSize(com.zimbra.common.util.InputStreamWithSize) ZimbraMailItem(com.zimbra.common.mailbox.ZimbraMailItem)

Example 34 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore in project zm-mailbox by Zimbra.

the class Session method unregister.

/**
 * Unregisters the session as a listener on the target mailbox and removes
 *  it from the session cache.  When a session is removed from the cache,
 *  its session ID is nulled out.
 *
 * @see #isMailboxListener()
 * @see #isRegisteredInCache()
 */
public Session unregister() {
    // locking order is always Mailbox then Session
    MailboxStore mboxStore = mailbox;
    if (null != mboxStore) {
        if (mboxStore instanceof Mailbox) {
            Mailbox mbox = (Mailbox) mboxStore;
            assert (mbox.lock.isWriteLockedByCurrentThread() || !Thread.holdsLock(this));
            if (isMailboxListener()) {
                mbox.removeListener(this);
                mailbox = null;
            }
        } else if (isMailboxListener()) {
            throw new UnsupportedOperationException(String.format("Session unregister only supports Mailbox currently can't handle %s", mboxStore.getClass().getName()));
        }
    }
    removeFromSessionCache();
    mIsRegistered = false;
    return this;
}
Also used : MailboxStore(com.zimbra.common.mailbox.MailboxStore) Mailbox(com.zimbra.cs.mailbox.Mailbox)

Aggregations

MailboxStore (com.zimbra.common.mailbox.MailboxStore)34 ServiceException (com.zimbra.common.service.ServiceException)22 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)17 AccountServiceException (com.zimbra.cs.account.AccountServiceException)14 SearchFolderStore (com.zimbra.common.mailbox.SearchFolderStore)10 FolderStore (com.zimbra.common.mailbox.FolderStore)9 ArrayList (java.util.ArrayList)6 ItemIdentifier (com.zimbra.common.mailbox.ItemIdentifier)5 Account (com.zimbra.cs.account.Account)4 ZimbraMailItem (com.zimbra.common.mailbox.ZimbraMailItem)3 ImapMessageSet (com.zimbra.cs.imap.ImapMessage.ImapMessageSet)3 Mailbox (com.zimbra.cs.mailbox.Mailbox)3 IOException (java.io.IOException)3 ZMailbox (com.zimbra.client.ZMailbox)2 ZSharedFolder (com.zimbra.client.ZSharedFolder)2 MountpointStore (com.zimbra.common.mailbox.MountpointStore)2 ZimbraQueryHit (com.zimbra.common.mailbox.ZimbraQueryHit)2 ZimbraQueryHitResults (com.zimbra.common.mailbox.ZimbraQueryHitResults)2 ZimbraSearchParams (com.zimbra.common.mailbox.ZimbraSearchParams)2 GuestAccount (com.zimbra.cs.account.GuestAccount)2