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();
}
}
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;
}
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");
}
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;
}
Aggregations