use of com.zimbra.cs.redolog.op.CreateCalendarItemRecorder in project zm-mailbox by Zimbra.
the class Task method processPartStat.
@Override
protected String processPartStat(Invite invite, MimeMessage mmInv, boolean forCreate, String defaultPartStat) throws ServiceException {
Mailbox mbox = getMailbox();
OperationContext octxt = mbox.getOperationContext();
CreateCalendarItemPlayer player = octxt != null ? (CreateCalendarItemPlayer) octxt.getPlayer() : null;
String partStat = defaultPartStat;
if (player != null) {
String p = player.getCalendarItemPartStat();
if (p != null)
partStat = p;
}
CreateCalendarItemRecorder recorder = (CreateCalendarItemRecorder) mbox.getRedoRecorder();
recorder.setCalendarItemPartStat(partStat);
Account account = getMailbox().getAccount();
invite.updateMyPartStat(account, partStat);
if (forCreate) {
Invite defaultInvite = getDefaultInviteOrNull();
if (defaultInvite != null && !defaultInvite.equals(invite) && !partStat.equals(defaultInvite.getPartStat())) {
defaultInvite.updateMyPartStat(account, partStat);
saveMetadata();
}
}
return partStat;
}
use of com.zimbra.cs.redolog.op.CreateCalendarItemRecorder in project zm-mailbox by Zimbra.
the class Mailbox method createCalendarItem.
CalendarItem createCalendarItem(int folderId, int flags, Tag.NormalizedTags ntags, String uid, ParsedMessage pm, Invite invite, CustomMetadata custom) throws ServiceException {
// FIXME: assuming that we're in the middle of a AddInvite op
CreateCalendarItemPlayer redoPlayer = (CreateCalendarItemPlayer) currentChange().getRedoPlayer();
CreateCalendarItemRecorder redoRecorder = (CreateCalendarItemRecorder) currentChange().getRedoRecorder();
int newCalItemId = redoPlayer == null ? Mailbox.ID_AUTO_INCREMENT : redoPlayer.getCalendarItemId();
int createId = getNextItemId(newCalItemId);
CalendarItem calItem = CalendarItem.create(createId, getFolderById(folderId), flags, ntags, uid, pm, invite, CalendarItem.NEXT_ALARM_FROM_NOW, custom);
if (redoRecorder != null) {
redoRecorder.setCalendarItemAttrs(calItem.getId(), calItem.getFolderId());
}
return calItem;
}
use of com.zimbra.cs.redolog.op.CreateCalendarItemRecorder in project zm-mailbox by Zimbra.
the class Appointment method processPartStat.
@Override
protected String processPartStat(Invite invite, MimeMessage mmInv, boolean forCreate, String defaultPartStat) throws ServiceException {
Mailbox mbox = getMailbox();
OperationContext octxt = mbox.getOperationContext();
CreateCalendarItemPlayer player = octxt != null ? (CreateCalendarItemPlayer) octxt.getPlayer() : null;
long opTime = octxt != null ? octxt.getTimestamp() : System.currentTimeMillis();
Account account = getMailbox().getAccount();
boolean onBehalfOf = false;
Account authAcct = account;
if (octxt != null) {
Account authuser = octxt.getAuthenticatedUser();
if (authuser != null) {
onBehalfOf = !account.getId().equalsIgnoreCase(authuser.getId());
if (onBehalfOf)
authAcct = authuser;
}
}
boolean asAdmin = octxt != null ? octxt.isUsingAdminPrivileges() : false;
boolean allowPrivateAccess = allowPrivateAccess(authAcct, asAdmin);
String partStat = defaultPartStat;
if (player != null) {
String p = player.getCalendarItemPartStat();
if (p != null)
partStat = p;
}
// See if we have RSVP=FALSE for the attendee. Let's assume RSVP was requested unless it is
// explicitly set to FALSE.
boolean rsvpRequested = true;
ZAttendee attendee = invite.getMatchingAttendee(account);
if (attendee != null) {
Boolean rsvp = attendee.getRsvp();
if (rsvp != null)
rsvpRequested = rsvp.booleanValue();
}
RedoLogProvider redoProvider = RedoLogProvider.getInstance();
// Don't send reply emails if we're not on master (in redo-driven master/replica setup).
// Don't send reply emails if we're replaying redo for reasons other than crash recovery.
// In other words, we DO want to send emails during crash recovery, because we're completing
// an interrupted transaction. But we don't send emails during redo reply phase of restore.
// Also don't send emails for cancel invites. (Organizer doesn't expect reply for cancels.)
// And don't send emails for task requests.
// Don't send reply emails from a system account. (e.g. archiving, galsync, ham/spam)
boolean needReplyEmail = rsvpRequested && redoProvider.isMaster() && (player == null || redoProvider.getRedoLogManager().getInCrashRecovery()) && invite.hasOrganizer() && !invite.isCancel() && !invite.isTodo() && !account.isIsSystemResource();
if (invite.isOrganizer()) {
// Organizer always accepts.
partStat = IcalXmlStrMap.PARTSTAT_ACCEPTED;
} else if (account instanceof CalendarResource && octxt == null) {
// Auto accept/decline processing should only occur during email delivery. In particular,
// don't do it if we're here during ics import. We're in email delivery if octxt == null.
// (There needs to be a better way to determine that...)
boolean replySent = false;
CalendarResource resource = (CalendarResource) account;
Locale lc;
Account organizer = invite.getOrganizerAccount();
if (organizer != null)
lc = organizer.getLocale();
else
lc = resource.getLocale();
if (resource.autoAcceptDecline() || resource.autoDeclineIfBusy() || resource.autoDeclineRecurring()) {
boolean replyListUpdated = false;
// If auto-accept is enabled, assume it'll be accepted until it gets declined.
if (resource.autoAcceptDecline())
partStat = IcalXmlStrMap.PARTSTAT_ACCEPTED;
if (isRecurring() && resource.autoDeclineRecurring()) {
// Decline because resource is configured to decline all recurring appointments.
partStat = IcalXmlStrMap.PARTSTAT_DECLINED;
if (needReplyEmail) {
String reason = L10nUtil.getMessage(MsgKey.calendarResourceDeclineReasonRecurring, lc);
Invite replyInv = makeReplyInvite(account, authAcct, lc, onBehalfOf, allowPrivateAccess, invite, invite.getRecurId(), CalendarMailSender.VERB_DECLINE);
CalendarMailSender.sendResourceAutoReply(octxt, mbox, true, CalendarMailSender.VERB_DECLINE, false, reason + "\r\n", this, invite, new Invite[] { replyInv }, mmInv);
replySent = true;
}
} else if (resource.autoDeclineIfBusy()) {
// Auto decline is enabled. Let's check for conflicts.
int maxNumConflicts = resource.getMaxNumConflictsAllowed();
int maxPctConflicts = resource.getMaxPercentConflictsAllowed();
ConflictCheckResult checkResult = checkAvailability(opTime, invite, maxNumConflicts, maxPctConflicts);
if (checkResult != null) {
List<Conflict> conflicts = checkResult.getConflicts();
if (conflicts.size() > 0) {
if (invite.isRecurrence() && !checkResult.tooManyConflicts()) {
// There are some conflicts, but within resource's allowed limit.
if (resource.autoAcceptDecline()) {
// Let's accept partially. (Accept the series and decline conflicting instances.)
List<Invite> replyInvites = new ArrayList<Invite>();
// the REPLY for the ACCEPT of recurrence series
Invite acceptInv = makeReplyInvite(account, authAcct, lc, onBehalfOf, allowPrivateAccess, invite, invite.getRecurId(), CalendarMailSender.VERB_ACCEPT);
for (Conflict conflict : conflicts) {
Instance inst = conflict.getInstance();
InviteInfo invInfo = inst.getInviteInfo();
Invite inv = getInvite(invInfo.getMsgId(), invInfo.getComponentId());
RecurId rid = inst.makeRecurId(inv);
// Record the decline status in reply list.
getReplyList().modifyPartStat(resource, rid, null, resource.getName(), null, null, IcalXmlStrMap.PARTSTAT_DECLINED, false, invite.getSeqNo(), opTime);
replyListUpdated = true;
// Make REPLY VEVENT for the declined instance.
Invite replyInv = makeReplyInvite(account, authAcct, lc, onBehalfOf, allowPrivateAccess, inv, rid, CalendarMailSender.VERB_DECLINE);
replyInvites.add(replyInv);
}
if (needReplyEmail) {
ICalTimeZone tz = chooseReplyTZ(invite);
// Send one email to accept the series.
String declinedInstances = getDeclinedTimesString(octxt, mbox, conflicts, invite.isAllDayEvent(), tz, lc);
String msg = L10nUtil.getMessage(MsgKey.calendarResourceDeclinedInstances, lc) + "\r\n\r\n" + declinedInstances;
CalendarMailSender.sendResourceAutoReply(octxt, mbox, true, CalendarMailSender.VERB_ACCEPT, true, msg, this, invite, new Invite[] { acceptInv }, mmInv);
// Send another email to decline instances, all in one email.
String conflictingTimes = getBusyTimesString(octxt, mbox, conflicts, tz, lc, false);
msg = L10nUtil.getMessage(MsgKey.calendarResourceDeclinedInstances, lc) + "\r\n\r\n" + declinedInstances + "\r\n" + L10nUtil.getMessage(MsgKey.calendarResourceDeclineReasonConflict, lc) + "\r\n\r\n" + conflictingTimes;
CalendarMailSender.sendResourceAutoReply(octxt, mbox, true, CalendarMailSender.VERB_DECLINE, true, msg, this, invite, replyInvites.toArray(new Invite[0]), mmInv);
replySent = true;
}
} else {
// Auto-accept is not enabled. Auto-decline is enabled, but there weren't
// enough conflicting instances to decline outright. So we just stay
// silent and let the human admin deal with it. This case is rather
// ambiguous, and can be avoided by configuring the resource to allow
// zero conflicting instance.
}
} else {
// Too many conflicts. Decline outright.
partStat = IcalXmlStrMap.PARTSTAT_DECLINED;
if (needReplyEmail) {
ICalTimeZone tz = chooseReplyTZ(invite);
String msg = L10nUtil.getMessage(MsgKey.calendarResourceDeclineReasonConflict, lc) + "\r\n\r\n" + getBusyTimesString(octxt, mbox, conflicts, tz, lc, checkResult.hasMoreConflicts());
Invite replyInv = makeReplyInvite(account, authAcct, lc, onBehalfOf, allowPrivateAccess, invite, invite.getRecurId(), CalendarMailSender.VERB_DECLINE);
CalendarMailSender.sendResourceAutoReply(octxt, mbox, true, CalendarMailSender.VERB_DECLINE, false, msg, this, invite, new Invite[] { replyInv }, mmInv);
replySent = true;
}
}
}
}
}
if (!replySent && IcalXmlStrMap.PARTSTAT_ACCEPTED.equals(partStat)) {
if (needReplyEmail) {
Invite replyInv = makeReplyInvite(account, authAcct, lc, onBehalfOf, allowPrivateAccess, invite, invite.getRecurId(), CalendarMailSender.VERB_ACCEPT);
CalendarMailSender.sendResourceAutoReply(octxt, mbox, true, CalendarMailSender.VERB_ACCEPT, false, null, this, invite, new Invite[] { replyInv }, mmInv);
}
}
// Record the final outcome in the replies list.
if (IcalXmlStrMap.PARTSTAT_NEEDS_ACTION.equals(partStat)) {
getReplyList().modifyPartStat(resource, invite.getRecurId(), null, resource.getName(), null, null, partStat, false, invite.getSeqNo(), opTime);
replyListUpdated = true;
}
if (forCreate && replyListUpdated)
saveMetadata();
}
}
CreateCalendarItemRecorder recorder = (CreateCalendarItemRecorder) mbox.getRedoRecorder();
recorder.setCalendarItemPartStat(partStat);
invite.updateMyPartStat(account, partStat);
if (forCreate) {
Invite defaultInvite = getDefaultInviteOrNull();
if (defaultInvite != null && !defaultInvite.equals(invite) && !partStat.equals(defaultInvite.getPartStat())) {
defaultInvite.updateMyPartStat(account, partStat);
saveMetadata();
}
}
return partStat;
}
Aggregations