1
0
mirror of https://github.com/moparisthebest/davmail synced 2025-03-04 03:09:40 -05:00

Caldav: implement task support over EWS

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1736 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2011-07-16 16:41:00 +00:00
parent 6ce33f23b9
commit 7036f3fd51
5 changed files with 241 additions and 140 deletions

View File

@ -93,6 +93,7 @@ public abstract class ExchangeSession {
protected static final String PUBLIC_ROOT = "/public/"; protected static final String PUBLIC_ROOT = "/public/";
protected static final String CALENDAR = "calendar"; protected static final String CALENDAR = "calendar";
protected static final String TASKS = "tasks";
/** /**
* Contacts folder logical name * Contacts folder logical name
*/ */
@ -2602,22 +2603,30 @@ public abstract class ExchangeSession {
* @throws IOException on error * @throws IOException on error
*/ */
public List<Event> getAllEvents(String folderPath) throws IOException { public List<Event> getAllEvents(String folderPath) throws IOException {
int caldavPastDelay = Settings.getIntProperty("davmail.caldavPastDelay"); boolean caldavDisableTasks = Settings.getBooleanProperty("davmail.caldavDisableTasks");
List<Event> results = searchEvents(folderPath, getCalendarItemCondition(caldavDisableTasks, getPastDelayCondition()));
if (isMainCalendar(folderPath)) {
// retrieve tasks from main tasks folder
results.addAll(searchTasksOnly("tasks"));
}
return results;
}
protected abstract Condition getCalendarItemCondition(boolean excludeTasks, Condition dateCondition);
protected Condition getPastDelayCondition() throws IOException {
int caldavPastDelay = Settings.getIntProperty("davmail.caldavPastDelay");
Condition dateCondition = null; Condition dateCondition = null;
if (caldavPastDelay != 0) { if (caldavPastDelay != 0) {
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, -caldavPastDelay); cal.add(Calendar.DAY_OF_MONTH, -caldavPastDelay);
dateCondition = gt("dtstart", formatSearchDate(cal.getTime())); dateCondition = gt("dtstart", formatSearchDate(cal.getTime()));
} }
return dateCondition;
boolean caldavDisableTasks = Settings.getBooleanProperty("davmail.caldavDisableTasks");
Condition condition = getCalendarItemCondition(caldavDisableTasks, dateCondition);
return searchEvents(folderPath, condition);
} }
protected abstract Condition getCalendarItemCondition(boolean excludeTasks, Condition dateCondition);
protected Condition getRangeCondition(String timeRangeStart, String timeRangeEnd) throws IOException { protected Condition getRangeCondition(String timeRangeStart, String timeRangeEnd) throws IOException {
try { try {
SimpleDateFormat parser = getZuluDateFormat(); SimpleDateFormat parser = getZuluDateFormat();
@ -3042,6 +3051,14 @@ public abstract class ExchangeSession {
*/ */
public abstract boolean isSharedFolder(String folderPath); public abstract boolean isSharedFolder(String folderPath);
/**
* Test if folderPath is main calendar.
*
* @param folderPath absolute folder path
* @return true if folderPath is a public or shared folder
*/
public abstract boolean isMainCalendar(String folderPath);
static final String MAILBOX_BASE = "/cn="; static final String MAILBOX_BASE = "/cn=";
protected void getEmailAndAliasFromOptions() { protected void getEmailAndAliasFromOptions() {

View File

@ -91,7 +91,7 @@ public class VCalendar extends VObject {
@Override @Override
public void addVObject(VObject vObject) { public void addVObject(VObject vObject) {
super.addVObject(vObject); super.addVObject(vObject);
if (firstVevent == null && "VEVENT".equals(vObject.type)) { if (firstVevent == null && ("VEVENT".equals(vObject.type)|| "VTODO".equals(vObject.type))) {
firstVevent = vObject; firstVevent = vObject;
} }
if ("VTIMEZONE".equals(vObject.type)) { if ("VTIMEZONE".equals(vObject.type)) {
@ -536,6 +536,10 @@ public class VCalendar extends VObject {
firstVevent.addProperty(vProperty); firstVevent.addProperty(vProperty);
} }
public boolean isTodo() {
return "VTODO".equals(firstVevent.type);
}
/** /**
* VCalendar recipients for notifications * VCalendar recipients for notifications
*/ */

View File

@ -203,6 +203,17 @@ public class DavExchangeSession extends ExchangeSession {
return !getFolderPath(folderPath).toLowerCase().startsWith(mailPath.toLowerCase()); return !getFolderPath(folderPath).toLowerCase().startsWith(mailPath.toLowerCase());
} }
/**
* Test if folderPath is main calendar.
*
* @param folderPath absolute folder path
* @return true if folderPath is a public or shared folder
*/
@Override
public boolean isMainCalendar(String folderPath) {
return getFolderPath(folderPath).toLowerCase().equals(getFolderPath("calendar"));
}
/** /**
* Build base path for cmd commands (galfind, gallookup). * Build base path for cmd commands (galfind, gallookup).
* *

View File

@ -1180,7 +1180,10 @@ public class EwsExchangeSession extends ExchangeSession {
@Override @Override
public ItemResult createOrUpdate() throws IOException { public ItemResult createOrUpdate() throws IOException {
byte[] itemContent = Base64.encodeBase64(vCalendar.toString().getBytes("UTF-8")); if (vCalendar.isTodo() && isMainCalendar(folderPath)) {
// task item, move to tasks folder
folderPath = "tasks";
}
ItemResult itemResult = new ItemResult(); ItemResult itemResult = new ItemResult();
EWSMethod createOrUpdateItemMethod; EWSMethod createOrUpdateItemMethod;
@ -1207,82 +1210,105 @@ public class EwsExchangeSession extends ExchangeSession {
return itemResult; return itemResult;
} }
} }
if (vCalendar.isTodo()) {
if (currentItemId != null) { // create or update task method
/*Set<FieldUpdate> updates = new HashSet<FieldUpdate>(); EWSMethod.Item newItem = new EWSMethod.Item();
// TODO: update properties instead of brute force delete/add newItem.type = "Task";
updates.add(new FieldUpdate(Field.get("mimeContent"), new String(Base64.encodeBase64(itemContent)))); List<FieldUpdate> updates = new ArrayList<FieldUpdate>();
// update updates.add(Field.createFieldUpdate("calendaruid", vCalendar.getFirstVeventPropertyValue("UID")));
createOrUpdateItemMethod = new UpdateItemMethod(MessageDisposition.SaveOnly, // force urlcompname
ConflictResolution.AutoResolve, updates.add(Field.createFieldUpdate("urlcompname", convertItemNameToEML(itemName)));
SendMeetingInvitationsOrCancellations.SendToNone, updates.add(Field.createFieldUpdate("subject", vCalendar.getFirstVeventPropertyValue("SUMMARY")));
currentItemId, updates);*/ updates.add(Field.createFieldUpdate("description", vCalendar.getFirstVeventPropertyValue("DESCRIPTION")));
// hard method: delete/create on update if (currentItemId != null) {
DeleteItemMethod deleteItemMethod = new DeleteItemMethod(currentItemId, DeleteType.HardDelete, SendMeetingCancellations.SendToNone); // update
executeMethod(deleteItemMethod); createOrUpdateItemMethod = new UpdateItemMethod(MessageDisposition.SaveOnly,
} //else { ConflictResolution.AutoResolve,
// create SendMeetingInvitationsOrCancellations.SendToNone,
EWSMethod.Item newItem = new EWSMethod.Item(); currentItemId, updates);
newItem.type = "CalendarItem";
newItem.mimeContent = itemContent;
ArrayList<FieldUpdate> updates = new ArrayList<FieldUpdate>();
if (!vCalendar.hasVAlarm()) {
updates.add(Field.createFieldUpdate("reminderset", "false"));
}
//updates.add(Field.createFieldUpdate("outlookmessageclass", "IPM.Appointment"));
// force urlcompname
updates.add(Field.createFieldUpdate("urlcompname", convertItemNameToEML(itemName)));
if (vCalendar.isMeeting() && vCalendar.isMeetingOrganizer()) {
updates.add(Field.createFieldUpdate("apptstateflags", "1"));
} else {
updates.add(Field.createFieldUpdate("apptstateflags", "0"));
}
// store mozilla invitations option
String xMozSendInvitations = vCalendar.getFirstVeventPropertyValue("X-MOZ-SEND-INVITATIONS");
if (xMozSendInvitations != null) {
updates.add(Field.createFieldUpdate("xmozsendinvitations", xMozSendInvitations));
}
// handle mozilla alarm
String xMozLastack = vCalendar.getFirstVeventPropertyValue("X-MOZ-LASTACK");
if (xMozLastack != null) {
updates.add(Field.createFieldUpdate("xmozlastack", xMozLastack));
}
String xMozSnoozeTime = vCalendar.getFirstVeventPropertyValue("X-MOZ-SNOOZE-TIME");
if (xMozSnoozeTime != null) {
updates.add(Field.createFieldUpdate("xmozsnoozetime", xMozSnoozeTime));
}
if (vCalendar.isMeeting()) {
VCalendar.Recipients recipients = vCalendar.getRecipients(false);
if (recipients.attendees != null) {
updates.add(Field.createFieldUpdate("to", recipients.attendees));
}
if (recipients.optionalAttendees != null) {
updates.add(Field.createFieldUpdate("cc", recipients.optionalAttendees));
}
if (recipients.organizer != null && !vCalendar.isMeetingOrganizer()) {
updates.add(Field.createFieldUpdate("from", recipients.optionalAttendees));
}
}
// patch allday date values
if (vCalendar.isCdoAllDay()) {
updates.add(Field.createFieldUpdate("dtstart", convertCalendarDateToExchange(vCalendar.getFirstVeventPropertyValue("DTSTART"))));
updates.add(Field.createFieldUpdate("dtend", convertCalendarDateToExchange(vCalendar.getFirstVeventPropertyValue("DTEND"))));
}
updates.add(Field.createFieldUpdate("busystatus", "BUSY".equals(vCalendar.getFirstVeventPropertyValue("X-MICROSOFT-CDO-BUSYSTATUS")) ? "Busy" : "Free"));
if (vCalendar.isCdoAllDay()) {
if ("Exchange2010".equals(serverVersion)) {
updates.add(Field.createFieldUpdate("starttimezone", vCalendar.getVTimezone().getPropertyValue("TZID")));
} else { } else {
updates.add(Field.createFieldUpdate("meetingtimezone", vCalendar.getVTimezone().getPropertyValue("TZID"))); newItem.setFieldUpdates(updates);
// create
createOrUpdateItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, getFolderId(folderPath), newItem);
} }
} else {
if (currentItemId != null) {
/*Set<FieldUpdate> updates = new HashSet<FieldUpdate>();
// TODO: update properties instead of brute force delete/add
updates.add(new FieldUpdate(Field.get("mimeContent"), new String(Base64.encodeBase64(itemContent))));
// update
createOrUpdateItemMethod = new UpdateItemMethod(MessageDisposition.SaveOnly,
ConflictResolution.AutoResolve,
SendMeetingInvitationsOrCancellations.SendToNone,
currentItemId, updates);*/
// hard method: delete/create on update
DeleteItemMethod deleteItemMethod = new DeleteItemMethod(currentItemId, DeleteType.HardDelete, SendMeetingCancellations.SendToNone);
executeMethod(deleteItemMethod);
} //else {
// create
EWSMethod.Item newItem = new EWSMethod.Item();
newItem.type = "CalendarItem";
newItem.mimeContent = Base64.encodeBase64(vCalendar.toString().getBytes("UTF-8"));
ArrayList<FieldUpdate> updates = new ArrayList<FieldUpdate>();
if (!vCalendar.hasVAlarm()) {
updates.add(Field.createFieldUpdate("reminderset", "false"));
}
//updates.add(Field.createFieldUpdate("outlookmessageclass", "IPM.Appointment"));
// force urlcompname
updates.add(Field.createFieldUpdate("urlcompname", convertItemNameToEML(itemName)));
if (vCalendar.isMeeting() && vCalendar.isMeetingOrganizer()) {
updates.add(Field.createFieldUpdate("apptstateflags", "1"));
} else {
updates.add(Field.createFieldUpdate("apptstateflags", "0"));
}
// store mozilla invitations option
String xMozSendInvitations = vCalendar.getFirstVeventPropertyValue("X-MOZ-SEND-INVITATIONS");
if (xMozSendInvitations != null) {
updates.add(Field.createFieldUpdate("xmozsendinvitations", xMozSendInvitations));
}
// handle mozilla alarm
String xMozLastack = vCalendar.getFirstVeventPropertyValue("X-MOZ-LASTACK");
if (xMozLastack != null) {
updates.add(Field.createFieldUpdate("xmozlastack", xMozLastack));
}
String xMozSnoozeTime = vCalendar.getFirstVeventPropertyValue("X-MOZ-SNOOZE-TIME");
if (xMozSnoozeTime != null) {
updates.add(Field.createFieldUpdate("xmozsnoozetime", xMozSnoozeTime));
}
if (vCalendar.isMeeting()) {
VCalendar.Recipients recipients = vCalendar.getRecipients(false);
if (recipients.attendees != null) {
updates.add(Field.createFieldUpdate("to", recipients.attendees));
}
if (recipients.optionalAttendees != null) {
updates.add(Field.createFieldUpdate("cc", recipients.optionalAttendees));
}
if (recipients.organizer != null && !vCalendar.isMeetingOrganizer()) {
updates.add(Field.createFieldUpdate("from", recipients.optionalAttendees));
}
}
// patch allday date values
if (vCalendar.isCdoAllDay()) {
updates.add(Field.createFieldUpdate("dtstart", convertCalendarDateToExchange(vCalendar.getFirstVeventPropertyValue("DTSTART"))));
updates.add(Field.createFieldUpdate("dtend", convertCalendarDateToExchange(vCalendar.getFirstVeventPropertyValue("DTEND"))));
}
updates.add(Field.createFieldUpdate("busystatus", "BUSY".equals(vCalendar.getFirstVeventPropertyValue("X-MICROSOFT-CDO-BUSYSTATUS")) ? "Busy" : "Free"));
if (vCalendar.isCdoAllDay()) {
if ("Exchange2010".equals(serverVersion)) {
updates.add(Field.createFieldUpdate("starttimezone", vCalendar.getVTimezone().getPropertyValue("TZID")));
} else {
updates.add(Field.createFieldUpdate("meetingtimezone", vCalendar.getVTimezone().getPropertyValue("TZID")));
}
}
newItem.setFieldUpdates(updates);
createOrUpdateItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, getFolderId(folderPath), newItem);
//}
} }
newItem.setFieldUpdates(updates);
createOrUpdateItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, getFolderId(folderPath), newItem);
//}
executeMethod(createOrUpdateItemMethod); executeMethod(createOrUpdateItemMethod);
itemResult.status = createOrUpdateItemMethod.getStatusCode(); itemResult.status = createOrUpdateItemMethod.getStatusCode();
@ -1290,7 +1316,7 @@ public class EwsExchangeSession extends ExchangeSession {
//noinspection VariableNotUsedInsideIf //noinspection VariableNotUsedInsideIf
if (currentItemId == null) { if (currentItemId == null) {
itemResult.status = HttpStatus.SC_CREATED; itemResult.status = HttpStatus.SC_CREATED;
LOGGER.debug("Updated event " + getHref()); LOGGER.debug("Created event " + getHref());
} else { } else {
LOGGER.warn("Overwritten event " + getHref()); LOGGER.warn("Overwritten event " + getHref());
} }
@ -1313,8 +1339,16 @@ public class EwsExchangeSession extends ExchangeSession {
LOGGER.debug("Get event: " + itemName); LOGGER.debug("Get event: " + itemName);
} }
try { try {
GetItemMethod getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, itemId, true); GetItemMethod getItemMethod;
if (!"Message".equals(type)) { if ("Task".equals(type)) {
getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, itemId, false);
getItemMethod.addAdditionalProperty(Field.get("subject"));
getItemMethod.addAdditionalProperty(Field.get("created"));
getItemMethod.addAdditionalProperty(Field.get("lastmodified"));
getItemMethod.addAdditionalProperty(Field.get("calendaruid"));
getItemMethod.addAdditionalProperty(Field.get("description"));
} else if (!"Message".equals(type)) {
getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, itemId, true);
getItemMethod.addAdditionalProperty(Field.get("reminderset")); getItemMethod.addAdditionalProperty(Field.get("reminderset"));
getItemMethod.addAdditionalProperty(Field.get("calendaruid")); getItemMethod.addAdditionalProperty(Field.get("calendaruid"));
getItemMethod.addAdditionalProperty(Field.get("requiredattendees")); getItemMethod.addAdditionalProperty(Field.get("requiredattendees"));
@ -1323,67 +1357,86 @@ public class EwsExchangeSession extends ExchangeSession {
getItemMethod.addAdditionalProperty(Field.get("xmozlastack")); getItemMethod.addAdditionalProperty(Field.get("xmozlastack"));
getItemMethod.addAdditionalProperty(Field.get("xmozsnoozetime")); getItemMethod.addAdditionalProperty(Field.get("xmozsnoozetime"));
getItemMethod.addAdditionalProperty(Field.get("xmozsendinvitations")); getItemMethod.addAdditionalProperty(Field.get("xmozsendinvitations"));
} else {
getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, itemId, true);
} }
executeMethod(getItemMethod); executeMethod(getItemMethod);
content = getItemMethod.getMimeContent(); if ("Task".equals(type)) {
if (content == null) { VCalendar localVCalendar = new VCalendar();
throw new IOException("empty event body"); VObject vTodo = new VObject();
} vTodo.type = "VTODO";
if (!"CalendarItem".equals(type)) { vTodo.setPropertyValue("LAST-MODIFIED", convertDateFromExchange(getItemMethod.getResponseItem().get(Field.get("lastmodified").getResponseName())));
content = getICS(new SharedByteArrayInputStream(content)); vTodo.setPropertyValue("CREATED", convertDateFromExchange(getItemMethod.getResponseItem().get(Field.get("created").getResponseName())));
} String calendarUid = getItemMethod.getResponseItem().get(Field.get("calendaruid").getResponseName());
VCalendar localVCalendar = new VCalendar(content, email, getVTimezone()); if (calendarUid == null) {
// remove additional reminder // use item id as uid for Exchange created tasks
if (!"true".equals(getItemMethod.getResponseItem().get(Field.get("reminderset").getResponseName()))) { calendarUid = itemId.id;
localVCalendar.removeVAlarm();
}
String calendaruid = getItemMethod.getResponseItem().get(Field.get("calendaruid").getResponseName());
if (calendaruid != null) {
localVCalendar.setFirstVeventPropertyValue("UID", calendaruid);
}
List<EWSMethod.Attendee> attendees = getItemMethod.getResponseItem().getAttendees();
if (attendees != null) {
for (EWSMethod.Attendee attendee : attendees) {
VProperty attendeeProperty = new VProperty("ATTENDEE", "mailto:" + attendee.email);
attendeeProperty.addParam("CN", attendee.name);
attendeeProperty.addParam("PARTSTAT", attendee.partstat);
//attendeeProperty.addParam("RSVP", "TRUE");
attendeeProperty.addParam("ROLE", attendee.role);
localVCalendar.addFirstVeventProperty(attendeeProperty);
} }
} vTodo.setPropertyValue("UID", calendarUid);
// fix UID and RECURRENCE-ID, broken at least on Exchange 2007 vTodo.setPropertyValue("SUMMARY", getItemMethod.getResponseItem().get(Field.get("subject").getResponseName()));
List<EWSMethod.Occurrence> occurences = getItemMethod.getResponseItem().getOccurrences(); vTodo.setPropertyValue("DESCRIPTION", getItemMethod.getResponseItem().get(Field.get("description").getResponseName()));
if (occurences != null) { localVCalendar.addVObject(vTodo);
Iterator<VObject> modifiedOccurrencesIterator = localVCalendar.getModifiedOccurrences().iterator(); content = localVCalendar.toString().getBytes("UTF-8");
for (EWSMethod.Occurrence occurrence : occurences) { } else {
if (modifiedOccurrencesIterator.hasNext()) { content = getItemMethod.getMimeContent();
VObject modifiedOccurrence = modifiedOccurrencesIterator.next(); if (content == null) {
// fix uid, should be the same as main VEVENT throw new IOException("empty event body");
if (calendaruid != null) { }
modifiedOccurrence.setPropertyValue("UID", calendaruid); if (!"CalendarItem".equals(type)) {
} content = getICS(new SharedByteArrayInputStream(content));
VProperty recurrenceId = modifiedOccurrence.getProperty("RECURRENCE-ID"); }
if (recurrenceId != null) { VCalendar localVCalendar = new VCalendar(content, email, getVTimezone());
recurrenceId.removeParam("TZID"); // remove additional reminder
recurrenceId.getValues().set(0, convertDateFromExchange(occurrence.originalStart)); if (!"true".equals(getItemMethod.getResponseItem().get(Field.get("reminderset").getResponseName()))) {
localVCalendar.removeVAlarm();
}
String calendaruid = getItemMethod.getResponseItem().get(Field.get("calendaruid").getResponseName());
if (calendaruid != null) {
localVCalendar.setFirstVeventPropertyValue("UID", calendaruid);
}
List<EWSMethod.Attendee> attendees = getItemMethod.getResponseItem().getAttendees();
if (attendees != null) {
for (EWSMethod.Attendee attendee : attendees) {
VProperty attendeeProperty = new VProperty("ATTENDEE", "mailto:" + attendee.email);
attendeeProperty.addParam("CN", attendee.name);
attendeeProperty.addParam("PARTSTAT", attendee.partstat);
//attendeeProperty.addParam("RSVP", "TRUE");
attendeeProperty.addParam("ROLE", attendee.role);
localVCalendar.addFirstVeventProperty(attendeeProperty);
}
}
// fix UID and RECURRENCE-ID, broken at least on Exchange 2007
List<EWSMethod.Occurrence> occurences = getItemMethod.getResponseItem().getOccurrences();
if (occurences != null) {
Iterator<VObject> modifiedOccurrencesIterator = localVCalendar.getModifiedOccurrences().iterator();
for (EWSMethod.Occurrence occurrence : occurences) {
if (modifiedOccurrencesIterator.hasNext()) {
VObject modifiedOccurrence = modifiedOccurrencesIterator.next();
// fix uid, should be the same as main VEVENT
if (calendaruid != null) {
modifiedOccurrence.setPropertyValue("UID", calendaruid);
}
VProperty recurrenceId = modifiedOccurrence.getProperty("RECURRENCE-ID");
if (recurrenceId != null) {
recurrenceId.removeParam("TZID");
recurrenceId.getValues().set(0, convertDateFromExchange(occurrence.originalStart));
}
} }
} }
} }
// restore mozilla invitations option
localVCalendar.setFirstVeventPropertyValue("X-MOZ-SEND-INVITATIONS",
getItemMethod.getResponseItem().get(Field.get("xmozsendinvitations").getResponseName()));
// restore mozilla alarm status
localVCalendar.setFirstVeventPropertyValue("X-MOZ-LASTACK",
getItemMethod.getResponseItem().get(Field.get("xmozlastack").getResponseName()));
localVCalendar.setFirstVeventPropertyValue("X-MOZ-SNOOZE-TIME",
getItemMethod.getResponseItem().get(Field.get("xmozsnoozetime").getResponseName()));
// overwrite method
// localVCalendar.setPropertyValue("METHOD", "REQUEST");
content = localVCalendar.toString().getBytes("UTF-8");
} }
// restore mozilla invitations option
localVCalendar.setFirstVeventPropertyValue("X-MOZ-SEND-INVITATIONS",
getItemMethod.getResponseItem().get(Field.get("xmozsendinvitations").getResponseName()));
// restore mozilla alarm status
localVCalendar.setFirstVeventPropertyValue("X-MOZ-LASTACK",
getItemMethod.getResponseItem().get(Field.get("xmozlastack").getResponseName()));
localVCalendar.setFirstVeventPropertyValue("X-MOZ-SNOOZE-TIME",
getItemMethod.getResponseItem().get(Field.get("xmozsnoozetime").getResponseName()));
// overwrite method
// localVCalendar.setPropertyValue("METHOD", "REQUEST");
content = localVCalendar.toString().getBytes("UTF-8");
} catch (IOException e) { } catch (IOException e) {
throw buildHttpException(e); throw buildHttpException(e);
} catch (MessagingException e) { } catch (MessagingException e) {
@ -1428,6 +1481,7 @@ public class EwsExchangeSession extends ExchangeSession {
for (EWSMethod.Item response : responses) { for (EWSMethod.Item response : responses) {
Event event = new Event(response); Event event = new Event(response);
if ("Message".equals(event.type)) { if ("Message".equals(event.type)) {
// TODO: just exclude
// need to check body // need to check body
try { try {
event.getEventContent(); event.getEventContent();
@ -1435,7 +1489,7 @@ public class EwsExchangeSession extends ExchangeSession {
} catch (HttpException e) { } catch (HttpException e) {
LOGGER.warn("Ignore invalid event " + event.getHref()); LOGGER.warn("Ignore invalid event " + event.getHref());
} }
// exclude exceptions // exclude exceptions
} else if (event.isException) { } else if (event.isException) {
LOGGER.debug("Exclude recurrence exception " + event.getHref()); LOGGER.debug("Exclude recurrence exception " + event.getHref());
} else { } else {
@ -1489,6 +1543,11 @@ public class EwsExchangeSession extends ExchangeSession {
@Override @Override
public Item getItem(String folderPath, String itemName) throws IOException { public Item getItem(String folderPath, String itemName) throws IOException {
EWSMethod.Item item = getEwsItem(folderPath, itemName); EWSMethod.Item item = getEwsItem(folderPath, itemName);
if (item == null && isMainCalendar(folderPath)) {
// look for item in task folder
item = getEwsItem("tasks", itemName);
}
if (item == null) { if (item == null) {
throw new HttpNotFoundException(itemName + " not found in " + folderPath); throw new HttpNotFoundException(itemName + " not found in " + folderPath);
} }
@ -1509,6 +1568,7 @@ public class EwsExchangeSession extends ExchangeSession {
return new Contact(item); return new Contact(item);
} else if ("CalendarItem".equals(itemType) } else if ("CalendarItem".equals(itemType)
|| "MeetingRequest".equals(itemType) || "MeetingRequest".equals(itemType)
|| "Task".equals(itemType)
// VTODOs appear as Messages // VTODOs appear as Messages
|| "Message".equals(itemType)) { || "Message".equals(itemType)) {
return new Event(item); return new Event(item);
@ -1600,6 +1660,11 @@ public class EwsExchangeSession extends ExchangeSession {
return folderPath.startsWith("/") && !folderPath.toLowerCase().startsWith(currentMailboxPath); return folderPath.startsWith("/") && !folderPath.toLowerCase().startsWith(currentMailboxPath);
} }
@Override
public boolean isMainCalendar(String folderPath) {
return "calendar".equals(folderPath) || (currentMailboxPath + "/calendar").equals(folderPath);
}
@Override @Override
protected String getFreeBusyData(String attendee, String start, String end, int interval) throws IOException { protected String getFreeBusyData(String attendee, String start, String end, int interval) throws IOException {
GetUserAvailabilityMethod getUserAvailabilityMethod = new GetUserAvailabilityMethod(attendee, start, end, interval); GetUserAvailabilityMethod getUserAvailabilityMethod = new GetUserAvailabilityMethod(attendee, start, end, interval);
@ -1747,6 +1812,9 @@ public class EwsExchangeSession extends ExchangeSession {
} else if (folderPath.startsWith(CALENDAR)) { } else if (folderPath.startsWith(CALENDAR)) {
currentFolderId = DistinguishedFolderId.getInstance(mailbox, DistinguishedFolderId.Name.calendar); currentFolderId = DistinguishedFolderId.getInstance(mailbox, DistinguishedFolderId.Name.calendar);
folderNames = folderPath.substring(CALENDAR.length()).split("/"); folderNames = folderPath.substring(CALENDAR.length()).split("/");
} else if (folderPath.startsWith(TASKS)) {
currentFolderId = DistinguishedFolderId.getInstance(mailbox, DistinguishedFolderId.Name.tasks);
folderNames = folderPath.substring(TASKS.length()).split("/");
} else if (folderPath.startsWith(CONTACTS)) { } else if (folderPath.startsWith(CONTACTS)) {
currentFolderId = DistinguishedFolderId.getInstance(mailbox, DistinguishedFolderId.Name.contacts); currentFolderId = DistinguishedFolderId.getInstance(mailbox, DistinguishedFolderId.Name.contacts);
folderNames = folderPath.substring(CONTACTS.length()).split("/"); folderNames = folderPath.substring(CONTACTS.length()).split("/");

View File

@ -36,6 +36,7 @@ public final class Field {
FIELD_MAP.put("displayname", new ExtendedFieldURI(0x3001, ExtendedFieldURI.PropertyType.String)); FIELD_MAP.put("displayname", new ExtendedFieldURI(0x3001, ExtendedFieldURI.PropertyType.String));
FIELD_MAP.put("urlcompname", new ExtendedFieldURI(0x10f3, ExtendedFieldURI.PropertyType.String)); FIELD_MAP.put("urlcompname", new ExtendedFieldURI(0x10f3, ExtendedFieldURI.PropertyType.String));
FIELD_MAP.put("lastmodified", new ExtendedFieldURI(0x3008, ExtendedFieldURI.PropertyType.SystemTime)); FIELD_MAP.put("lastmodified", new ExtendedFieldURI(0x3008, ExtendedFieldURI.PropertyType.SystemTime));
FIELD_MAP.put("created", new ExtendedFieldURI(0x3007, ExtendedFieldURI.PropertyType.SystemTime));
// folder // folder
FIELD_MAP.put("ctag", new ExtendedFieldURI(0x670a, ExtendedFieldURI.PropertyType.SystemTime)); // PR_LOCAL_COMMIT_TIME_MAX FIELD_MAP.put("ctag", new ExtendedFieldURI(0x670a, ExtendedFieldURI.PropertyType.SystemTime)); // PR_LOCAL_COMMIT_TIME_MAX