mirror of
https://github.com/moparisthebest/davmail
synced 2025-03-03 18:59:53 -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:
parent
6ce33f23b9
commit
7036f3fd51
@ -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() {
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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).
|
||||||
*
|
*
|
||||||
|
@ -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("/");
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user