Caldav: improve Exchange 2007 EWS meeting support

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1937 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2012-03-22 14:54:48 +00:00
parent 4a116b8fb9
commit a15f954419
4 changed files with 93 additions and 21 deletions

View File

@ -491,6 +491,7 @@ public abstract class EWSMethod extends PostMethod {
protected List<Attendee> attendees;
protected final List<String> fieldNames = new ArrayList<String>();
protected List<Occurrence> occurrences;
protected ItemId referenceItemId;
@Override
public String toString() {
@ -524,6 +525,9 @@ public abstract class EWSMethod extends PostMethod {
writer.write(new String(mimeContent));
writer.write("</t:MimeContent>");
}
if (referenceItemId != null) {
referenceItemId.write(writer);
}
// write ordered fields
for (String key : fieldNames) {
if ("MeetingTimeZone".equals(key)) {
@ -726,7 +730,7 @@ public abstract class EWSMethod extends PostMethod {
*/
public Item getResponseItem() throws EWSException {
checkSuccess();
if (responseItems != null && responseItems.size() == 1) {
if (responseItems != null && responseItems.size() > 0) {
return responseItems.get(0);
} else {
return null;
@ -871,6 +875,18 @@ public abstract class EWSMethod extends PostMethod {
}
}
}
public static String responseTypeToPartstat(String responseType) {
if ("Accept".equals(responseType)) {
return "ACCEPTED";
} else if ("Tentative".equals(responseType)) {
return "TENTATIVE";
} else if ("Decline".equals(responseType)) {
return "DECLINED";
} else {
return "NEEDS-ACTION";
}
}
protected void handleAttendee(XMLStreamReader reader, Item item, String attendeeType) throws XMLStreamException {
Attendee attendee = new Attendee();
@ -889,15 +905,7 @@ public abstract class EWSMethod extends PostMethod {
attendee.name = XMLStreamUtil.getElementText(reader);
} else if ("ResponseType".equals(tagLocalName)) {
String responseType = XMLStreamUtil.getElementText(reader);
if ("Accept".equals(responseType)) {
attendee.partstat = "ACCEPTED";
} else if ("Tentative".equals(responseType)) {
attendee.partstat = "TENTATIVE";
} else if ("Decline".equals(responseType)) {
attendee.partstat = "DECLINED";
} else {
attendee.partstat = "NEEDS-ACTION";
}
attendee.partstat = responseTypeToPartstat(responseType);
}
}
}

View File

@ -38,6 +38,7 @@ import org.apache.commons.httpclient.params.HttpClientParams;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.util.SharedByteArrayInputStream;
import java.io.BufferedReader;
@ -1292,6 +1293,8 @@ public class EwsExchangeSession extends ExchangeSession {
// first try to load existing event
String currentEtag = null;
ItemId currentItemId = null;
String ownerResponseReply = null;
EWSMethod.Item currentItem = getEwsItem(folderPath, itemName);
if (currentItem != null) {
currentItemId = new ItemId(currentItem);
@ -1381,8 +1384,12 @@ public class EwsExchangeSession extends ExchangeSession {
//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"));
if (vCalendar.isMeeting()) {
if (vCalendar.isMeetingOrganizer()) {
updates.add(Field.createFieldUpdate("apptstateflags", "1"));
} else {
updates.add(Field.createFieldUpdate("apptstateflags", "3"));
}
} else {
updates.add(Field.createFieldUpdate("apptstateflags", "0"));
}
@ -1409,16 +1416,24 @@ public class EwsExchangeSession extends ExchangeSession {
for (VProperty property : attendeeProperties) {
String attendeeEmail = vCalendar.getEmailValue(property);
if (attendeeEmail != null && attendeeEmail.indexOf('@') >= 0) {
EWSMethod.Attendee attendee = new EWSMethod.Attendee();
attendee.email = attendeeEmail;
attendee.name = property.getParamValue("CN");
if (email.equals(attendeeEmail)) {
String ownerPartStat = property.getParamValue("PARTSTAT");
if ("ACCEPTED".equals(ownerPartStat)) {
ownerResponseReply = "AcceptItem";
// do not send DeclineItem to avoid deleting target event
//} else if ("DECLINED".equals(ownerPartStat)) {
// ownerResponseReply = "DeclineItem";
} else if ("TENTATIVE".equals(ownerPartStat)) {
ownerResponseReply = "TentativelyAcceptItem";
}
}
InternetAddress internetAddress = new InternetAddress(attendeeEmail, property.getParamValue("CN"));
String attendeeRole = property.getParamValue("ROLE");
if ("REQ-PARTICIPANT".equals(attendeeRole)) {
requiredAttendees.add(attendeeEmail);
requiredAttendees.add(internetAddress.toString());
} else {
optionalAttendees.add(attendeeEmail);
optionalAttendees.add(internetAddress.toString());
}
newItem.addAttendee(attendee);
}
}
}
@ -1474,6 +1489,25 @@ public class EwsExchangeSession extends ExchangeSession {
}
}
// force responsetype on Exchange 2007
if (ownerResponseReply != null) {
EWSMethod.Item responseTypeItem = new EWSMethod.Item();
responseTypeItem.referenceItemId = new ItemId("ReferenceItemId", createOrUpdateItemMethod.getResponseItem());
responseTypeItem.type = ownerResponseReply;
createOrUpdateItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, null, responseTypeItem);
executeMethod(createOrUpdateItemMethod);
// force urlcompname again
ArrayList<FieldUpdate> updates = new ArrayList<FieldUpdate>();
updates.add(Field.createFieldUpdate("urlcompname", convertItemNameToEML(itemName)));
createOrUpdateItemMethod = new UpdateItemMethod(MessageDisposition.SaveOnly,
ConflictResolution.AlwaysOverwrite,
SendMeetingInvitationsOrCancellations.SendToNone,
new ItemId(createOrUpdateItemMethod.getResponseItem()),
updates);
executeMethod(createOrUpdateItemMethod);
}
ItemId newItemId = new ItemId(createOrUpdateItemMethod.getResponseItem());
GetItemMethod getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, newItemId, false);
getItemMethod.addAdditionalProperty(Field.get("etag"));
@ -1510,6 +1544,7 @@ public class EwsExchangeSession extends ExchangeSession {
getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, itemId, true);
getItemMethod.addAdditionalProperty(Field.get("reminderset"));
getItemMethod.addAdditionalProperty(Field.get("calendaruid"));
getItemMethod.addAdditionalProperty(Field.get("myresponsetype"));
getItemMethod.addAdditionalProperty(Field.get("requiredattendees"));
getItemMethod.addAdditionalProperty(Field.get("optionalattendees"));
getItemMethod.addAdditionalProperty(Field.get("modifiedoccurrences"));
@ -1570,7 +1605,12 @@ public class EwsExchangeSession extends ExchangeSession {
for (EWSMethod.Attendee attendee : attendees) {
VProperty attendeeProperty = new VProperty("ATTENDEE", "mailto:" + attendee.email);
attendeeProperty.addParam("CN", attendee.name);
attendeeProperty.addParam("PARTSTAT", attendee.partstat);
String myResponseType = getItemMethod.getResponseItem().get(Field.get("myresponsetype").getResponseName());
if ("Exchange2007_SP1".equals(serverVersion) && email.equalsIgnoreCase(attendee.email) && myResponseType != null) {
attendeeProperty.addParam("PARTSTAT", EWSMethod.responseTypeToPartstat(myResponseType));
} else {
attendeeProperty.addParam("PARTSTAT", attendee.partstat);
}
//attendeeProperty.addParam("RSVP", "TRUE");
attendeeProperty.addParam("ROLE", attendee.role);
localVCalendar.addFirstVeventProperty(attendeeProperty);

View File

@ -196,6 +196,7 @@ public final class Field {
FIELD_MAP.put("ismeeting", new UnindexedFieldURI("item:IsMeeting"));
FIELD_MAP.put("apptstateflags", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Appointment, 0x8217, ExtendedFieldURI.PropertyType.Integer)); // PidLidAppointmentStateFlags 1: Meeting, 2: Received, 4: Cancelled
FIELD_MAP.put("appointmentstate", new UnindexedFieldURI("calendar:AppointmentState"));
FIELD_MAP.put("myresponsetype", new UnindexedFieldURI("calendar:MyResponseType"));
FIELD_MAP.put("calendaruid", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.PublicStrings, "urn:schemas:calendar:uid", ExtendedFieldURI.PropertyType.String));
FIELD_MAP.put("meetingtimezone", new UnindexedFieldURI("calendar:MeetingTimeZone"));

View File

@ -25,6 +25,7 @@ import java.io.Writer;
* Item id.
*/
public class ItemId {
protected final String name;
protected final String id;
protected final String changeKey;
@ -34,6 +35,25 @@ public class ItemId {
* @param item response item
*/
public ItemId(EWSMethod.Item item) {
this("ItemId", item);
}
/**
* Build Item id object from item id.
*
* @param itemId item id
*/
public ItemId(String itemId) {
this("ItemId", itemId);
}
/**
* Build Item id from response item.
*
* @param item response item
*/
public ItemId(String name, EWSMethod.Item item) {
this.name = name;
this.id = item.get("ItemId");
this.changeKey = item.get("ChangeKey");
}
@ -43,7 +63,8 @@ public class ItemId {
*
* @param itemId item id
*/
public ItemId(String itemId) {
public ItemId(String name, String itemId) {
this.name = name;
this.id = itemId;
this.changeKey = null;
}
@ -55,7 +76,9 @@ public class ItemId {
* @throws IOException on error
*/
public void write(Writer writer) throws IOException {
writer.write("<t:ItemId Id=\"");
writer.write("<t:");
writer.write(name);
writer.write(" Id=\"");
writer.write(id);
if (changeKey != null) {
writer.write("\" ChangeKey=\"");