use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.
the class ScheduleOutbox method handleFreebusyRequest.
private void handleFreebusyRequest(DavContext ctxt, ZComponent vfreebusy, String originator, String rcpt, Element resp) throws DavException, ServiceException {
ZProperty dtstartProp = vfreebusy.getProperty(ICalTok.DTSTART);
ZProperty dtendProp = vfreebusy.getProperty(ICalTok.DTEND);
ZProperty durationProp = vfreebusy.getProperty(ICalTok.DURATION);
if (dtstartProp == null || dtendProp == null && durationProp == null)
throw new DavException("missing dtstart or dtend/duration in the schedule request", HttpServletResponse.SC_BAD_REQUEST, null);
long start, end;
try {
ParsedDateTime startTime = ParsedDateTime.parseUtcOnly(dtstartProp.getValue());
start = startTime.getUtcTime();
if (dtendProp != null) {
end = ParsedDateTime.parseUtcOnly(dtendProp.getValue()).getUtcTime();
} else {
ParsedDuration dur = ParsedDuration.parse(durationProp.getValue());
ParsedDateTime endTime = startTime.add(dur);
end = endTime.getUtcTime();
}
} catch (ParseException pe) {
throw new DavException("can't parse date", HttpServletResponse.SC_BAD_REQUEST, pe);
}
ZimbraLog.dav.debug("rcpt: " + rcpt + ", start: " + new Date(start) + ", end: " + new Date(end));
FreeBusy fb = null;
if (ctxt.isFreebusyEnabled()) {
FreeBusyQuery fbQuery = new FreeBusyQuery(ctxt.getRequest(), ctxt.getAuthAccount(), start, end, null);
fbQuery.addEmailAddress(getAddressFromPrincipalURL(rcpt), FreeBusyQuery.CALENDAR_FOLDER_ALL);
java.util.Collection<FreeBusy> fbResult = fbQuery.getResults();
if (fbResult.size() > 0)
fb = fbResult.iterator().next();
}
if (fb != null) {
String fbMsg = fb.toVCalendar(FreeBusy.Method.REPLY, originator, rcpt, null);
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("2.0;Success");
resp.addElement(DavElements.E_CALENDAR_DATA).setText(fbMsg);
} else {
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("5.3;No f/b for the user");
}
}
use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.
the class CalendarItem method decodeMetadata.
@Override
void decodeMetadata(Metadata meta) throws ServiceException {
super.decodeMetadata(meta);
mUid = Invite.fixupIfOutlookUid(meta.get(Metadata.FN_UID, null));
mInvites = new ArrayList<Invite>();
ICalTimeZone accountTZ = Util.getAccountTimeZone(getMailbox().getAccount());
if (meta.containsKey(Metadata.FN_TZMAP)) {
try {
Set<String> tzids = new HashSet<String>();
mTzMap = Util.decodeFromMetadata(meta.getMap(Metadata.FN_TZMAP), accountTZ);
// appointment/task start and end
mStartTime = meta.getLong(Metadata.FN_CALITEM_START, 0);
mEndTime = meta.getLong(Metadata.FN_CALITEM_END, 0);
// invite ID's
long numComp = meta.getLong(Metadata.FN_NUM_COMPONENTS);
for (int i = 0; i < numComp; i++) {
Metadata md = meta.getMap(Metadata.FN_INV + i);
Invite inv = Invite.decodeMetadata(getMailboxId(), md, this, accountTZ);
mInvites.add(inv);
tzids.addAll(inv.getReferencedTZIDs());
mTzMap.add(inv.getTimeZoneMap());
}
Metadata metaRecur = meta.getMap(FN_CALITEM_RECURRENCE, true);
if (metaRecur != null) {
mRecurrence = Recurrence.decodeMetadata(metaRecur, mTzMap);
if (mRecurrence != null) {
tzids.addAll(Recurrence.getReferencedTZIDs(mRecurrence));
}
}
if (meta.containsKey(Metadata.FN_REPLY_LIST)) {
mReplyList = ReplyList.decodeFromMetadata(meta.getMap(Metadata.FN_REPLY_LIST), mTzMap);
// Get all TZIDs referenced by replies.
for (ReplyInfo ri : mReplyList.mReplies) {
if (ri.mRecurId != null) {
ParsedDateTime dt = ri.mRecurId.getDt();
if (dt != null && dt.hasTime()) {
ICalTimeZone tz = dt.getTimeZone();
if (tz != null)
tzids.add(tz.getID());
}
}
}
} else {
mReplyList = new ReplyList();
}
Metadata metaAlarmData = meta.getMap(Metadata.FN_ALARM_DATA, true);
if (metaAlarmData != null)
mAlarmData = AlarmData.decodeMetadata(metaAlarmData);
// Reduce tzmap to minimal set of TZIDs referenced by invites, recurrence, and replies.
mTzMap.reduceTo(tzids);
} catch (ServiceException se) {
if (ServiceException.INVALID_REQUEST.equals(se.getCode()) && this.getChangeDate() < new GregorianCalendar(2006, 0, 1).getTimeInMillis()) {
//could have been metadata version 3, 4 or 5.
//All of those versions have FN_TZMAP, but different format for other fields
//these are edge cases that should only appear in dev/df/cf
mStartTime = 0;
mEndTime = 0;
} else {
throw se;
}
}
} else {
//version 2 or earlier
mStartTime = 0;
mEndTime = 0;
}
}
use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.
the class CalendarItem method instancesNear.
/**
* Find instances within 24 hours either side. Assumption is that any timezone related problems
* causing {@code recurId} to be incorrect will only be relevant to times within that window.
* @param recurId
* @return
* @throws ServiceException
*/
private Collection<Instance> instancesNear(RecurId recurId) throws ServiceException {
if (recurId == null) {
return Collections.emptyList();
}
ParsedDateTime dt = recurId.getDt();
if (dt == null) {
return Collections.emptyList();
}
long utcTime = dt.getUtcTime();
return this.expandInstances(utcTime - MILLIS_IN_DAY, utcTime + MILLIS_IN_DAY, false);
}
use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.
the class CalendarItem method createPseudoExceptionForSingleInstanceReplyIfNecessary.
/**
* Bug 94018 - Need an exception to represent a reply to a single instance of an exception, otherwise a decline
* to a single instance gets forgotten in some cases where the series partstat is used instead.
* Assumption - already checked that there isn't a matching exception instance already
* Caller is responsible for ensuring changed MetaData is written through to SQL sending notification of change.
*/
private void createPseudoExceptionForSingleInstanceReplyIfNecessary(Invite reply) throws ServiceException {
if ((reply == null) || reply.getRecurId() == null) {
// reply isn't to a single instance
return;
}
Recurrence.RecurrenceRule recurrenceRule = null;
if ((mRecurrence == null) || !(mRecurrence instanceof Recurrence.RecurrenceRule)) {
return;
}
recurrenceRule = (Recurrence.RecurrenceRule) mRecurrence;
Collection<Instance> instancesNear = instancesNear(reply.getRecurId());
if (!instancesNear.isEmpty()) {
/* we need a new exception to handle the difference in attendee status */
for (int i = 0; i < numInvites(); i++) {
Invite cur = getInvite(i);
if (cur.getRecurId() == null) {
try {
ParsedDateTime pdt = ParsedDateTime.parseUtcOnly(reply.getRecurId().getDtZ());
Invite localException = cur.makeInstanceInvite(pdt);
localException.setDtStamp(System.currentTimeMillis());
localException.updateMatchingAttendeesFromReply(reply);
// flag as organizer change
localException.setClassPropSetByMe(true);
mInvites.add(localException);
// create a fake ExceptionRule wrapper around the single-instance
recurrenceRule.addException(new Recurrence.ExceptionRule(reply.getRecurId(), localException.getStartTime(), localException.getEffectiveDuration(), new InviteInfo(localException)));
} catch (ParseException e) {
sLog.debug("Unexpected exception - not updating calendar invite with pseudo exception", e);
}
break;
}
}
}
}
use of com.zimbra.common.calendar.ParsedDateTime in project zm-mailbox by Zimbra.
the class Appointment method makeReplyInvite.
private Invite makeReplyInvite(Account account, Account authAccount, Locale lc, boolean onBehalfOf, boolean allowPrivateAccess, Invite inv, RecurId rid, Verb verb) throws ServiceException {
boolean hidePrivate = !inv.isPublic() && !allowPrivateAccess;
String subject;
if (hidePrivate)
subject = L10nUtil.getMessage(MsgKey.calendarSubjectWithheld, lc);
else
subject = inv.getName();
String replySubject = CalendarMailSender.getReplySubject(verb, subject, lc);
ParsedDateTime ridDt = rid != null ? rid.getDt() : null;
Invite replyInv = CalendarMailSender.replyToInvite(account, authAccount, onBehalfOf, allowPrivateAccess, inv, verb, replySubject, ridDt);
return replyInv;
}
Aggregations