Search in sources :

Example 41 with NoSuchItemException

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

the class Mailbox method alterTag.

public void alterTag(OperationContext octxt, int[] itemIds, MailItem.Type type, String tagName, boolean addTag, TargetConstraint tcon) throws ServiceException {
    AlterItemTag redoRecorder = new AlterItemTag(mId, itemIds, type, tagName, addTag, tcon);
    boolean success = false;
    try {
        beginTransaction("alterTag", octxt, redoRecorder);
        setOperationTargetConstraint(tcon);
        Tag tag;
        try {
            tag = getTagByName(tagName);
        } catch (NoSuchItemException nsie) {
            if (tagName.startsWith(Tag.FLAG_NAME_PREFIX)) {
                throw nsie;
            }
            Tag.NormalizedTags ntags = new NormalizedTags(this, new String[] { tagName }, addTag);
            if (ntags.getTags().length == 0) {
                success = true;
                return;
            }
            tag = getTagByName(ntags.getTags()[0]);
        }
        alterTag(itemIds, type, tag, addTag);
        success = true;
    } finally {
        endTransaction(success);
    }
}
Also used : NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag)

Example 42 with NoSuchItemException

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

the class Mailbox method addMessageInternal.

private Message addMessageInternal(OperationContext octxt, ParsedMessage pm, int folderId, boolean noICal, int flags, String[] tags, int conversationId, String rcptEmail, Message.DraftInfo dinfo, CustomMetadata customData, DeliveryContext dctxt, StagedBlob staged) throws IOException, ServiceException {
    assert lock.isWriteLockedByCurrentThread();
    if (pm == null) {
        throw ServiceException.INVALID_REQUEST("null ParsedMessage when adding message to mailbox " + mId, null);
    }
    if (Math.abs(conversationId) <= HIGHEST_SYSTEM_ID) {
        conversationId = ID_AUTO_INCREMENT;
    }
    CreateMessage redoPlayer = (octxt == null ? null : (CreateMessage) octxt.getPlayer());
    boolean needRedo = needRedo(octxt, redoPlayer);
    boolean isRedo = redoPlayer != null;
    Blob blob = dctxt.getIncomingBlob();
    if (blob == null) {
        throw ServiceException.FAILURE("Incoming blob not found.", null);
    }
    // make sure we're parsing headers using the target account's charset
    pm.setDefaultCharset(getAccount().getPrefMailDefaultCharset());
    // quick check to make sure we don't deliver 5 copies of the same message
    String msgidHeader = pm.getMessageID();
    boolean isSent = ((flags & Flag.BITMASK_FROM_ME) != 0);
    if (!isRedo && msgidHeader != null && !isSent && mSentMessageIDs.containsKey(msgidHeader)) {
        Integer sentMsgID = mSentMessageIDs.get(msgidHeader);
        if (conversationId == ID_AUTO_INCREMENT) {
            conversationId = getConversationIdFromReferent(pm.getMimeMessage(), sentMsgID.intValue());
            ZimbraLog.mailbox.debug("duplicate detected but not deduped (%s); will try to slot into conversation %d", msgidHeader, conversationId);
        }
    }
    // caller can't set system flags other than \Draft, \Sent and \Post
    flags &= ~Flag.FLAGS_SYSTEM | Flag.BITMASK_DRAFT | Flag.BITMASK_FROM_ME | Flag.BITMASK_POST;
    // caller can't specify non-message flags
    flags &= Flag.FLAGS_GENERIC | Flag.FLAGS_MESSAGE;
    String digest;
    int msgSize;
    try {
        digest = blob.getDigest();
        msgSize = (int) blob.getRawSize();
    } catch (IOException e) {
        throw ServiceException.FAILURE("Unable to get message properties.", e);
    }
    CreateMessage redoRecorder = new CreateMessage(mId, rcptEmail, pm.getReceivedDate(), dctxt.getShared(), digest, msgSize, folderId, noICal, flags, tags, customData);
    StoreIncomingBlob storeRedoRecorder = null;
    // strip out unread flag for internal storage (don't do this before redoRecorder initialization)
    boolean unread = (flags & Flag.BITMASK_UNREAD) > 0;
    flags &= ~Flag.BITMASK_UNREAD;
    // "having attachments" is currently tracked via flags
    if (pm.hasAttachments()) {
        flags |= Flag.BITMASK_ATTACHED;
    } else {
        flags &= ~Flag.BITMASK_ATTACHED;
    }
    // priority is calculated from headers
    flags &= ~(Flag.BITMASK_HIGH_PRIORITY | Flag.BITMASK_LOW_PRIORITY);
    flags |= pm.getPriorityBitmask();
    boolean isSpam = folderId == ID_FOLDER_SPAM;
    boolean isDraft = (flags & Flag.BITMASK_DRAFT) != 0;
    // draft replies get slotted in the same conversation as their parent, if possible
    if (isDraft && !isRedo && conversationId == ID_AUTO_INCREMENT && dinfo != null && !Strings.isNullOrEmpty(dinfo.origId)) {
        try {
            ItemId iid = new ItemId(dinfo.origId, getAccountId());
            if (iid.getId() > 0 && iid.belongsTo(this)) {
                conversationId = getMessageById(octxt, iid.getId()).getConversationId();
            }
        } catch (ServiceException e) {
        }
    }
    Message msg = null;
    boolean success = false;
    CustomMetadata.CustomMetadataList extended = MetadataCallback.preDelivery(pm);
    if (customData != null) {
        if (extended == null) {
            extended = customData.asList();
        } else {
            extended.addSection(customData);
        }
    }
    Threader threader = pm.getThreader(this);
    String subject = pm.getNormalizedSubject();
    try {
        beginTransaction("addMessage", octxt, redoRecorder);
        if (isRedo) {
            rcptEmail = redoPlayer.getRcptEmail();
        }
        Tag.NormalizedTags ntags = new Tag.NormalizedTags(this, tags);
        Folder folder = getFolderById(folderId);
        // step 0: preemptively check for quota issues (actual update is done in Message.create)
        if (!getAccount().isMailAllowReceiveButNotSendWhenOverQuota()) {
            checkSizeChange(getSize() + staged.getSize());
        }
        // step 1: get an ID assigned for the new message
        int messageId = getNextItemId(!isRedo ? ID_AUTO_INCREMENT : redoPlayer.getMessageId());
        List<Conversation> mergeConvs = null;
        if (isRedo) {
            conversationId = redoPlayer.getConvId();
            // fetch the conversations that were merged in as a result of the original delivery...
            List<Integer> mergeConvIds = redoPlayer.getMergedConvIds();
            mergeConvs = new ArrayList<Conversation>(mergeConvIds.size());
            for (int mergeId : mergeConvIds) {
                try {
                    mergeConvs.add(getConversationById(mergeId));
                } catch (NoSuchItemException nsie) {
                    ZimbraLog.mailbox.debug("could not find merge conversation %d", mergeId);
                }
            }
        }
        // step 2: figure out where the message belongs
        Conversation conv = null;
        if (threader.isEnabled()) {
            boolean isReply = pm.isReply();
            if (conversationId != ID_AUTO_INCREMENT) {
                try {
                    // fetch the requested conversation
                    //   (we'll ensure that it's receiving new mail after the new message is added to it)
                    conv = getConversationById(conversationId);
                    ZimbraLog.mailbox.debug("fetched explicitly-specified conversation %d", conv.getId());
                } catch (NoSuchItemException nsie) {
                    if (!isRedo) {
                        ZimbraLog.mailbox.debug("could not find explicitly-specified conversation %d", conversationId);
                        conversationId = ID_AUTO_INCREMENT;
                    }
                }
            } else if (!isRedo && !isSpam && (isReply || (!isSent && !subject.isEmpty()))) {
                List<Conversation> matches = threader.lookupConversation();
                if (matches != null && !matches.isEmpty()) {
                    // file the message into the largest conversation, then later merge any other matching convs
                    Collections.sort(matches, new MailItem.SortSizeDescending());
                    conv = matches.remove(0);
                    mergeConvs = matches;
                }
            }
        }
        if (conv != null && conv.isTagged(Flag.FlagInfo.MUTED)) {
            // adding a message to a muted conversation marks it muted and read
            unread = false;
            flags |= Flag.BITMASK_MUTED;
        }
        // step 3: create the message and update the cache
        //         and if the message is also an invite, deal with the calendar item
        Conversation convTarget = conv instanceof VirtualConversation ? null : conv;
        if (convTarget != null) {
            ZimbraLog.mailbox.debug("  placing message in existing conversation %d", convTarget.getId());
        }
        CalendarPartInfo cpi = pm.getCalendarPartInfo();
        ZVCalendar iCal = null;
        if (cpi != null && CalendarItem.isAcceptableInvite(getAccount(), cpi)) {
            iCal = cpi.cal;
        }
        msg = Message.create(messageId, folder, convTarget, pm, staged, unread, flags, ntags, dinfo, noICal, iCal, extended);
        redoRecorder.setMessageId(msg.getId());
        // step 4: create a conversation for the message, if necessary
        if (threader.isEnabled() && convTarget == null) {
            if (conv == null && conversationId == ID_AUTO_INCREMENT) {
                conv = VirtualConversation.create(this, msg);
                ZimbraLog.mailbox.debug("placed message %d in vconv %d", msg.getId(), conv.getId());
                redoRecorder.setConvFirstMsgId(-1);
            } else {
                Message[] contents = null;
                VirtualConversation vconv = null;
                if (!isRedo) {
                    vconv = (VirtualConversation) conv;
                    contents = (vconv == null ? new Message[] { msg } : new Message[] { vconv.getMessage(), msg });
                } else {
                    // Executing redo.
                    int convFirstMsgId = redoPlayer.getConvFirstMsgId();
                    Message convFirstMsg = null;
                    // If there was a virtual conversation, then...
                    if (convFirstMsgId > 0) {
                        try {
                            convFirstMsg = getMessageById(octxt, redoPlayer.getConvFirstMsgId());
                        } catch (MailServiceException e) {
                            if (!MailServiceException.NO_SUCH_MSG.equals(e.getCode())) {
                                throw e;
                            }
                        // The first message of conversation may have been deleted
                        // by user between the time of original operation and redo.
                        // Handle the case by skipping the updating of its
                        // conversation ID.
                        }
                        // if it is still a standalone message.
                        if (convFirstMsg != null && convFirstMsg.getConversationId() < 0) {
                            contents = new Message[] { convFirstMsg, msg };
                            vconv = new VirtualConversation(this, convFirstMsg);
                        }
                    }
                    if (contents == null) {
                        contents = new Message[] { msg };
                    }
                }
                redoRecorder.setConvFirstMsgId(vconv != null ? vconv.getMessageId() : -1);
                conv = createConversation(conversationId, contents);
                if (vconv != null) {
                    ZimbraLog.mailbox.debug("removed vconv %d", vconv.getId());
                    vconv.removeChild(vconv.getMessage());
                }
                //   associate the first message's reference hashes with the new conversation
                if (contents.length == 2) {
                    threader.changeThreadingTargets(contents[0], conv);
                }
            }
        } else {
            // conversation feature turned off
            redoRecorder.setConvFirstMsgId(-1);
        }
        redoRecorder.setConvId(conv != null && !(conv instanceof VirtualConversation) ? conv.getId() : -1);
        // if we're threading by references, associate the new message's reference hashes with its conversation
        if (!isSpam && !isDraft) {
            threader.recordAddedMessage(conv);
        }
        if (conv != null && mergeConvs != null) {
            redoRecorder.setMergedConversations(mergeConvs);
            for (Conversation smaller : mergeConvs) {
                ZimbraLog.mailbox.info("merging conversation %d for references threading", smaller.getId());
                //                    try {
                conv.merge(smaller);
            //                    } catch (ServiceException e) {
            //                        if (!e.getCode().equals(MailServiceException.NO_SUCH_MSG)) {
            //                            throw e;
            //                        }
            //                    }
            }
        }
        // conversations may have shifted, so the threader's cached state is now questionable
        threader.reset();
        // step 5: write the redolog entries
        if (dctxt.getShared()) {
            if (dctxt.isFirst() && needRedo) {
                // Log entry in redolog for blob save.  Blob bytes are logged in the StoreIncoming entry.
                // Subsequent CreateMessage ops will reference this blob.
                storeRedoRecorder = new StoreIncomingBlob(digest, msgSize, dctxt.getMailboxIdList());
                storeRedoRecorder.start(getOperationTimestampMillis());
                storeRedoRecorder.setBlobBodyInfo(blob.getFile());
                storeRedoRecorder.log();
            }
            // Link to the file created by StoreIncomingBlob.
            redoRecorder.setMessageLinkInfo(blob.getPath());
        } else {
            // Store the blob data inside the CreateMessage op.
            redoRecorder.setMessageBodyInfo(blob.getFile());
        }
        // step 6: link to existing blob
        MailboxBlob mblob = StoreManager.getInstance().link(staged, this, messageId, getOperationChangeID());
        markOtherItemDirty(mblob);
        // when we created the Message, we used the staged locator/size/digest;
        //   make sure that data actually matches the final blob in the store
        msg.updateBlobData(mblob);
        if (dctxt.getMailboxBlob() == null) {
            // Set mailbox blob for in case we want to add the message to the
            // message cache after delivery.
            dctxt.setMailboxBlob(mblob);
        }
        // step 7: queue new message for indexing
        index.add(msg);
        success = true;
        // step 8: send lawful intercept message
        try {
            Notification.getInstance().interceptIfNecessary(this, pm.getMimeMessage(), "add message", folder);
        } catch (ServiceException e) {
            ZimbraLog.mailbox.error("unable to send legal intercept message", e);
        }
    } finally {
        if (storeRedoRecorder != null) {
            if (success) {
                storeRedoRecorder.commit();
            } else {
                storeRedoRecorder.abort();
            }
        }
        endTransaction(success);
        if (success) {
            // Everything worked.  Update the blob field in ParsedMessage
            // so the next recipient in the multi-recipient case will link
            // to this blob as opposed to saving its own copy.
            dctxt.setFirst(false);
        }
    }
    // step 8: remember the Message-ID header so that we can avoid receiving duplicates
    if (isSent && !isRedo && msgidHeader != null) {
        mSentMessageIDs.put(msgidHeader, msg.getId());
    }
    return msg;
}
Also used : ImapMessage(com.zimbra.cs.imap.ImapMessage) Pop3Message(com.zimbra.cs.pop3.Pop3Message) MimeMessage(javax.mail.internet.MimeMessage) CreateMessage(com.zimbra.cs.redolog.op.CreateMessage) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) CreateFolder(com.zimbra.cs.redolog.op.CreateFolder) ZFolder(com.zimbra.client.ZFolder) CalendarPartInfo(com.zimbra.cs.mime.ParsedMessage.CalendarPartInfo) ItemId(com.zimbra.cs.service.util.ItemId) ZVCalendar(com.zimbra.common.calendar.ZCalendar.ZVCalendar) StoreIncomingBlob(com.zimbra.cs.redolog.op.StoreIncomingBlob) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) LinkedList(java.util.LinkedList) ArrayList(java.util.ArrayList) List(java.util.List) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) StoreIncomingBlob(com.zimbra.cs.redolog.op.StoreIncomingBlob) StagedBlob(com.zimbra.cs.store.StagedBlob) MailboxBlob(com.zimbra.cs.store.MailboxBlob) Blob(com.zimbra.cs.store.Blob) MailboxBlob(com.zimbra.cs.store.MailboxBlob) IOException(java.io.IOException) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) 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) CustomMetadata(com.zimbra.cs.mailbox.MailItem.CustomMetadata)

Example 43 with NoSuchItemException

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

the class Mailbox method getItemById.

MailItem getItemById(int id, MailItem.Type type, boolean fromDumpster) throws ServiceException {
    if (fromDumpster) {
        MailItem item = null;
        try {
            item = MailItem.getById(this, id, type, true);
            if (item != null && !isVisibleInDumpster(item)) {
                item = null;
            }
        } catch (NoSuchItemException e) {
        }
        // fault.
        if (item == null) {
            throw MailItem.noSuchItem(id, type);
        }
        return item;
    }
    // try the cache first
    MailItem item = getCachedItem(Integer.valueOf(id), type);
    if (item != null) {
        return item;
    }
    // the tag and folder caches contain ALL tags and folders, so cache miss == doesn't exist
    if (isCachedType(type)) {
        throw MailItem.noSuchItem(id, type);
    }
    boolean virtualConv = false;
    boolean cachedMsg = true;
    boolean sameId = true;
    if (id <= -FIRST_USER_ID) {
        virtualConv = true;
        ZimbraLog.mailbox.debug("getting virtual conversation");
        // special-case virtual conversations
        if (type != MailItem.Type.CONVERSATION && type != MailItem.Type.UNKNOWN) {
            throw MailItem.noSuchItem(id, type);
        }
        Message msg = getCachedMessage(Integer.valueOf(-id));
        if (msg == null) {
            ZimbraLog.mailbox.debug("message not cached");
            cachedMsg = false;
            msg = getMessageById(-id);
        }
        int convId = msg.getConversationId();
        if (msg.getConversationId() != id) {
            ZimbraLog.mailbox.debug("message(%d) conv id(%d) != id(%d), getting parent", msg.getId(), msg.getConversationId(), id);
            sameId = false;
            item = msg.getParent();
            if (item == null) {
                ZimbraLog.mailbox.warn("got null parent for message id [%d] conv id [%d] (before condition [%d]) != id [%d]. equality? [%s:%s] in dumpster? [%s]", msg.getId(), msg.getConversationId(), convId, id, convId == id, msg.getConversationId() == id, msg.inDumpster());
            }
        } else {
            ZimbraLog.mailbox.debug("returning normal virtual conv");
            item = new VirtualConversation(this, msg);
        }
    } else {
        // cache miss, so fetch from the database
        item = MailItem.getById(this, id, type);
    }
    if (item == null) {
        ZimbraLog.mailbox.warn("item is null for id [%d] in mailbox [%d]. Virtual conv? [%s] cachedMsg? [%s] sameId? [%s]", id, this.mId, virtualConv, cachedMsg, sameId);
        throw MailItem.noSuchItem(id, type);
    }
    return item;
}
Also used : DbMailItem(com.zimbra.cs.db.DbMailItem) ImapMessage(com.zimbra.cs.imap.ImapMessage) Pop3Message(com.zimbra.cs.pop3.Pop3Message) MimeMessage(javax.mail.internet.MimeMessage) CreateMessage(com.zimbra.cs.redolog.op.CreateMessage) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint)

Example 44 with NoSuchItemException

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

the class CreateDataSource method validateFolderId.

/**
     * Confirms that the folder attribute specifies a valid folder id and is not
     * within the subtree of another datasource
     */
static void validateFolderId(Account account, Mailbox mbox, Element eDataSource, DataSourceType dsType) throws ServiceException {
    int folderId = eDataSource.getAttributeInt(MailConstants.A_FOLDER);
    String id = eDataSource.getAttribute(MailConstants.A_ID, null);
    try {
        mbox.getFolderById(null, folderId);
    } catch (NoSuchItemException e) {
        throw ServiceException.INVALID_REQUEST("Invalid folder id: " + folderId, null);
    }
    for (DataSource ds : account.getAllDataSources()) {
        if (id != null && ds.getId().equals(id))
            continue;
        try {
            for (Folder fldr : mbox.getFolderById(null, ds.getFolderId()).getSubfolderHierarchy()) {
                if (fldr.getId() == folderId)
                    if ((DataSourceType.pop3.equals(dsType)) && (DataSourceType.pop3.equals(ds.getType()))) {
                    // Allows unified inbox to work for more than one Pop3 datasource
                    } else {
                        throw ServiceException.INVALID_REQUEST("Folder location conflict: " + fldr.getPath(), null);
                    }
            }
        } catch (NoSuchItemException ignored) {
        }
    }
}
Also used : Folder(com.zimbra.cs.mailbox.Folder) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) DataSource(com.zimbra.cs.account.DataSource)

Example 45 with NoSuchItemException

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

the class CalDavDataImport method applyRemoteItem.

private MailItem applyRemoteItem(RemoteItem remoteItem, Folder where) throws ServiceException, IOException {
    if (!(remoteItem instanceof RemoteCalendarItem)) {
        ZimbraLog.datasource.warn("applyRemoteItem: not a calendar item: %s", remoteItem);
        return null;
    }
    RemoteCalendarItem item = (RemoteCalendarItem) remoteItem;
    DataSource ds = getDataSource();
    DataSourceItem dsItem = DbDataSource.getReverseMapping(ds, item.href);
    OperationContext octxt = new OperationContext(mbox);
    MailItem mi = null;
    boolean isStale = false;
    boolean isCreate = false;
    if (dsItem.md == null && item.status != Status.deleted) {
        dsItem.md = new Metadata();
        dsItem.md.put(METADATA_KEY_TYPE, METADATA_TYPE_APPOINTMENT);
    }
    if (dsItem.itemId == 0) {
        isStale = true;
        isCreate = true;
    } else {
        String etag = dsItem.md.get(METADATA_KEY_ETAG, null);
        try {
            mi = mbox.getItemById(octxt, dsItem.itemId, MailItem.Type.UNKNOWN);
        } catch (MailServiceException.NoSuchItemException se) {
            ZimbraLog.datasource.warn("applyRemoteItem: calendar item not found: ", remoteItem);
        }
        if (item.etag == null) {
            ZimbraLog.datasource.warn("No Etag returned for item %s", item.href);
            isStale = true;
        } else if (etag == null) {
            ZimbraLog.datasource.warn("Empty etag for item %d", dsItem.itemId);
            isStale = true;
        } else {
            isStale = !item.etag.equals(etag);
        }
        if (mi == null)
            isStale = true;
    }
    if (item.status == Status.deleted) {
        ZimbraLog.datasource.debug("Deleting appointment %s", item.href);
        try {
            mi = mbox.getItemById(octxt, item.itemId, MailItem.Type.UNKNOWN);
        } catch (NoSuchItemException se) {
            mi = null;
        }
        try {
            mbox.delete(octxt, item.itemId, MailItem.Type.UNKNOWN);
        } catch (ServiceException se) {
            ZimbraLog.datasource.warn("Error deleting remotely deleted item %d (%s)", item.itemId, dsItem.remoteId);
        }
    } else if (isStale) {
        ZimbraLog.datasource.debug("Updating stale appointment %s", item.href);
        ZCalendar.ZVCalendar vcalendar;
        SetCalendarItemData main = new SetCalendarItemData();
        SetCalendarItemData[] exceptions = null;
        CalDavClient client = null;
        try {
            client = getClient();
        } catch (DavException e) {
            throw ServiceException.FAILURE("error creating CalDAV client", e);
        }
        Appointment appt = client.getCalendarData(new Appointment(item.href, item.etag));
        if (appt.data == null) {
            ZimbraLog.datasource.warn("No appointment found at " + item.href);
            return null;
        }
        dsItem.md.put(METADATA_KEY_ETAG, appt.etag);
        try {
            vcalendar = ZCalendar.ZCalendarBuilder.build(appt.data);
            List<Invite> invites = Invite.createFromCalendar(mbox.getAccount(), null, vcalendar, true);
            if (invites.size() > 1)
                exceptions = new SetCalendarItemData[invites.size() - 1];
            int pos = 0;
            boolean first = true;
            for (Invite i : invites) {
                if (first) {
                    main.invite = i;
                    first = false;
                } else {
                    SetCalendarItemData scid = new SetCalendarItemData();
                    scid.invite = i;
                    exceptions[pos++] = scid;
                }
            }
        } catch (Exception e) {
            ZimbraLog.datasource.warn("Error parsing appointment ", e);
            return null;
        }
        mi = mbox.setCalendarItem(octxt, where.getId(), 0, null, main, exceptions, null, CalendarItem.NEXT_ALARM_KEEP_CURRENT);
        dsItem.itemId = mi.getId();
        dsItem.folderId = mi.getFolderId();
        if (isCreate) {
            DbDataSource.addMapping(ds, dsItem);
        } else {
            DbDataSource.updateMapping(ds, dsItem);
        }
    } else {
        ZimbraLog.datasource.debug("Appointment up to date %s", item.href);
        try {
            mi = mbox.getItemById(octxt, dsItem.itemId, MailItem.Type.UNKNOWN);
        } catch (NoSuchItemException se) {
            // item not found.  delete the mapping so it can be downloaded again if needed.
            ArrayList<Integer> deletedIds = new ArrayList<Integer>();
            deletedIds.add(dsItem.itemId);
            DbDataSource.deleteMappings(ds, deletedIds);
        }
    }
    return mi;
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) Appointment(com.zimbra.cs.dav.client.CalDavClient.Appointment) DavException(com.zimbra.cs.dav.DavException) Metadata(com.zimbra.cs.mailbox.Metadata) ArrayList(java.util.ArrayList) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) CalDavClient(com.zimbra.cs.dav.client.CalDavClient) ServiceException(com.zimbra.common.service.ServiceException) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) IOException(java.io.IOException) DavException(com.zimbra.cs.dav.DavException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) DbDataSource(com.zimbra.cs.db.DbDataSource) DataSource(com.zimbra.cs.account.DataSource) SetCalendarItemData(com.zimbra.cs.mailbox.Mailbox.SetCalendarItemData) MailItem(com.zimbra.cs.mailbox.MailItem) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ArrayList(java.util.ArrayList) List(java.util.List) DataSourceItem(com.zimbra.cs.db.DbDataSource.DataSourceItem) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Aggregations

NoSuchItemException (com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException)50 Mailbox (com.zimbra.cs.mailbox.Mailbox)21 ServiceException (com.zimbra.common.service.ServiceException)20 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)15 MailItem (com.zimbra.cs.mailbox.MailItem)11 Test (org.junit.Test)11 Account (com.zimbra.cs.account.Account)10 OperationContext (com.zimbra.cs.mailbox.OperationContext)10 ItemId (com.zimbra.cs.service.util.ItemId)10 Folder (com.zimbra.cs.mailbox.Folder)9 MimeMessage (javax.mail.internet.MimeMessage)8 Element (com.zimbra.common.soap.Element)7 Mountpoint (com.zimbra.cs.mailbox.Mountpoint)7 IOException (java.io.IOException)7 AccountServiceException (com.zimbra.cs.account.AccountServiceException)6 ParsedMessage (com.zimbra.cs.mime.ParsedMessage)6 ArrayList (java.util.ArrayList)6 DbMailItem (com.zimbra.cs.db.DbMailItem)5 DbTag (com.zimbra.cs.db.DbTag)5 Document (com.zimbra.cs.mailbox.Document)5