EWS: implement more contact and event methods

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1146 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2010-07-07 09:20:42 +00:00
parent 9371f57285
commit be39c055bb
4 changed files with 251 additions and 51 deletions

View File

@ -1593,7 +1593,7 @@ public abstract class ExchangeSession {
public abstract static class Item extends HashMap<String, String> {
protected String folderPath;
protected String itemName;
public String permanentUrl;
protected String permanentUrl;
/**
* Display name.
*/
@ -1602,12 +1602,7 @@ public abstract class ExchangeSession {
* item etag
*/
public String etag;
protected String contentClass;
protected String noneMatch;
/**
* ICS content
*/
protected String itemBody;
/**
* Build item instance.
@ -1654,6 +1649,10 @@ public abstract class ExchangeSession {
return itemName;
}
public String getPermanentUrl() {
return permanentUrl;
}
/**
* Get event etag (last change tag).
*
@ -1833,6 +1832,40 @@ public abstract class ExchangeSession {
return "text/calendar;charset=UTF-8";
}
/**
* Load ICS content from MIME message input stream
*
* @param mimeInputStream mime message input stream
* @return mime message ics attachment body
* @throws IOException on error
* @throws MessagingException on error
*/
protected String getICS(InputStream mimeInputStream) throws IOException, MessagingException {
String result;
MimeMessage mimeMessage = new MimeMessage(null, mimeInputStream);
Object mimeBody = mimeMessage.getContent();
MimePart bodyPart = null;
if (mimeBody instanceof MimeMultipart) {
bodyPart = getCalendarMimePart((MimeMultipart) mimeBody);
} else if (isCalendarContentType(mimeMessage.getContentType())) {
// no multipart, single body
bodyPart = mimeMessage;
}
if (bodyPart != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bodyPart.getDataHandler().writeTo(baos);
baos.close();
result = fixICS(new String(baos.toByteArray(), "UTF-8"), true);
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mimeMessage.writeTo(baos);
baos.close();
throw new DavMailException("EXCEPTION_INVALID_MESSAGE_CONTENT", new String(baos.toByteArray(), "UTF-8"));
}
return result;
}
protected static final String TEXT_CALENDAR = "text/calendar";
protected static final String APPLICATION_ICS = "application/ics";

View File

@ -48,7 +48,6 @@ import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.NoRouteToHostException;
@ -690,41 +689,6 @@ public class DavExchangeSession extends ExchangeSession {
super(folderPath, itemName, contentClass, itemBody, etag, noneMatch);
}
/**
* Load ICS content from MIME message input stream
*
* @param mimeInputStream mime message input stream
* @return mime message ics attachment body
* @throws IOException on error
* @throws MessagingException on error
*/
protected String getICS(InputStream mimeInputStream) throws IOException, MessagingException {
String result;
MimeMessage mimeMessage = new MimeMessage(null, mimeInputStream);
Object mimeBody = mimeMessage.getContent();
MimePart bodyPart = null;
if (mimeBody instanceof MimeMultipart) {
bodyPart = getCalendarMimePart((MimeMultipart) mimeBody);
} else if (isCalendarContentType(mimeMessage.getContentType())) {
// no multipart, single body
bodyPart = mimeMessage;
}
if (bodyPart != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bodyPart.getDataHandler().writeTo(baos);
baos.close();
result = fixICS(new String(baos.toByteArray(), "UTF-8"), true);
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mimeMessage.writeTo(baos);
baos.close();
throw new DavMailException("EXCEPTION_INVALID_MESSAGE_CONTENT", new String(baos.toByteArray(), "UTF-8"));
}
return result;
}
protected String getICSFromInternetContentProperty() throws IOException, DavException, MessagingException {
String result = null;
// PropFind PR_INTERNET_CONTENT
@ -1187,7 +1151,7 @@ public class DavExchangeSession extends ExchangeSession {
@Override
public ExchangeSession.ContactPhoto getContactPhoto(ExchangeSession.Contact contact) throws IOException {
ContactPhoto contactPhoto;
final GetMethod method = new GetMethod(URIUtil.encodePath(contact.permanentUrl));
final GetMethod method = new GetMethod(URIUtil.encodePath(contact.getPermanentUrl()));
method.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
method.setRequestHeader("Translate", "f");
method.setRequestHeader("Accept-Encoding", "gzip");

View File

@ -24,17 +24,21 @@ import davmail.exchange.ExchangeSession;
import davmail.http.DavGatewayHttpClientFacade;
import davmail.util.StringUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.HeadMethod;
import javax.mail.MessagingException;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.NoRouteToHostException;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.*;
/**
@ -163,6 +167,7 @@ public class EwsExchangeSession extends ExchangeSession {
item.mimeContent = Base64.encodeBase64(messageBody.getBytes());
String bcc = properties.get("bcc");
// Exchange 2007 is unable to handle bcc field on create
//noinspection VariableNotUsedInsideIf
if (bcc != null) {
properties.remove("bcc");
}
@ -227,7 +232,14 @@ public class EwsExchangeSession extends ExchangeSession {
*/
@Override
protected byte[] getContent(ExchangeSession.Message message) throws IOException {
GetItemMethod getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, ((EwsExchangeSession.Message) message).itemId, true);
return getContent(((EwsExchangeSession.Message) message).itemId);
}
/**
* Get item MIME content.
*/
protected byte[] getContent(ItemId itemId) throws IOException {
GetItemMethod getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, itemId, true);
executeMethod(getItemMethod);
return getItemMethod.getMimeContent();
}
@ -629,17 +641,172 @@ public class EwsExchangeSession extends ExchangeSession {
*/
@Override
protected void moveToTrash(ExchangeSession.Message message) throws IOException {
throw new UnsupportedOperationException();
MoveItemMethod moveItemMethod = new MoveItemMethod(((EwsExchangeSession.Message) message).itemId, getFolderId(TRASH));
executeMethod(moveItemMethod);
}
protected class Contact extends ExchangeSession.Contact {
// item id
ItemId itemId;
protected Contact(EWSMethod.Item response) throws URIException {
itemId = new ItemId(response.get("ItemId"), response.get("ChangeKey"));
permanentUrl = response.get(Field.get("permanenturl").getResponseName());
etag = response.get(Field.get("etag").getResponseName());
displayName = response.get(Field.get("displayname").getResponseName());
for (String attributeName : CONTACT_ATTRIBUTES) {
String value = response.get(Field.get("attributeName").getResponseName());
if (value != null) {
if ("bday".equals(attributeName) || "lastmodified".equals(attributeName)) {
try {
value = ExchangeSession.getZuluDateFormat().format(ExchangeSession.getExchangeZuluDateFormatMillisecond().parse(value));
} catch (ParseException e) {
LOGGER.warn("Invalid date: " + value);
}
}
put(attributeName, value);
}
}
}
/**
* @inheritDoc
*/
public Contact(String folderPath, String itemName, Map<String, String> properties, String etag, String noneMatch) {
super(folderPath, itemName, properties, etag, noneMatch);
}
protected Set<FieldUpdate> buildProperties() throws IOException {
HashSet<FieldUpdate> list = new HashSet<FieldUpdate>();
for (Map.Entry<String, String> entry : entrySet()) {
list.add(Field.createFieldUpdate(entry.getKey(), entry.getValue()));
}
return list;
}
/**
* Create or update contact
*
* @return action result
* @throws IOException on error
*/
public ItemResult createOrUpdate() throws IOException {
EWSMethod.Item item = new EWSMethod.Item();
item.type = "Contact";
item.setFieldUpdates(buildProperties());
// TODO: handle etag and noneMatch
CreateItemMethod createItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, getFolderId(folderPath), item);
executeMethod(createItemMethod);
// TODO: detect create/update
int status = createItemMethod.getStatusCode();
if (status == HttpURLConnection.HTTP_OK) {
if (etag != null) {
LOGGER.debug("Updated event " + getHref());
} else {
LOGGER.warn("Overwritten event " + getHref());
}
}
ItemResult itemResult = new ItemResult();
itemResult.status = status;
// TODO: get etag
// itemResult.etag = ???
return itemResult;
}
}
protected class Event extends ExchangeSession.Event {
// item id
ItemId itemId;
protected Event(EWSMethod.Item response) throws URIException {
itemId = new ItemId(response.get("ItemId"), response.get("ChangeKey"));
permanentUrl = response.get(Field.get("permanenturl").getResponseName());
etag = response.get(Field.get("etag").getResponseName());
displayName = response.get(Field.get("displayname").getResponseName());
}
/**
* @inheritDoc
*/
public Event(String folderPath, String itemName, String contentClass, String itemBody, String etag, String noneMatch) {
super(folderPath, itemName, contentClass, itemBody, etag, noneMatch);
}
@Override
protected ItemResult createOrUpdate(byte[] content) throws IOException {
EWSMethod.Item item = new EWSMethod.Item();
item.type = "Message";
item.mimeContent = Base64.encodeBase64(content);
// TODO: handle etag and noneMatch
CreateItemMethod createItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, getFolderId(folderPath), item);
executeMethod(createItemMethod);
// TODO: detect create/update
int status = createItemMethod.getStatusCode();
if (status == HttpURLConnection.HTTP_OK) {
if (etag != null) {
LOGGER.debug("Updated event " + getHref());
} else {
LOGGER.warn("Overwritten event " + getHref());
}
}
ItemResult itemResult = new ItemResult();
itemResult.status = status;
// TODO: get etag
// itemResult.etag = ???
return itemResult;
}
@Override
public String getBody() throws HttpException {
String result;
LOGGER.debug("Get event: " + permanentUrl);
try {
byte[] content = getContent(itemId);
result = getICS(new ByteArrayInputStream(content));
} catch (IOException e) {
throw buildHttpException(e);
} catch (MessagingException e) {
throw buildHttpException(e);
}
return result;
}
}
@Override
public List<Contact> searchContacts(String folderName, Set<String> attributes, Condition condition) throws IOException {
throw new UnsupportedOperationException();
public List<ExchangeSession.Contact> searchContacts(String folderPath, Set<String> attributes, Condition condition) throws IOException {
List<ExchangeSession.Contact> contacts = new ArrayList<ExchangeSession.Contact>();
List<EWSMethod.Item> responses = searchItems(folderPath, attributes,
and(equals("outlookmessageclass", "IPM.Contact"), condition),
FolderQueryTraversal.SHALLOW);
for (EWSMethod.Item response : responses) {
contacts.add(new Contact(response));
}
return contacts;
}
@Override
protected List<Event> searchEvents(String folderPath, Set<String> attributes, Condition condition) throws IOException {
throw new UnsupportedOperationException();
protected List<ExchangeSession.Event> searchEvents(String folderPath, Set<String> attributes, Condition condition) throws IOException {
List<ExchangeSession.Event> events = new ArrayList<ExchangeSession.Event>();
List<EWSMethod.Item> responses = searchItems(folderPath, attributes,
condition,
FolderQueryTraversal.SHALLOW);
for (EWSMethod.Item response : responses) {
events.add(new Event(response));
}
return events;
}
@Override
@ -647,6 +814,11 @@ public class EwsExchangeSession extends ExchangeSession {
throw new UnsupportedOperationException();
}
@Override
public ContactPhoto getContactPhoto(ExchangeSession.Contact contact) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int deleteItem(String folderPath, String itemName) throws IOException {
throw new UnsupportedOperationException();
@ -659,12 +831,12 @@ public class EwsExchangeSession extends ExchangeSession {
@Override
protected ItemResult internalCreateOrUpdateContact(String folderPath, String itemName, Map<String, String> properties, String etag, String noneMatch) throws IOException {
throw new UnsupportedOperationException();
return new Contact(folderPath, itemName, properties, etag, noneMatch).createOrUpdate();
}
@Override
protected ItemResult internalCreateOrUpdateEvent(String folderPath, String itemName, String contentClass, String icsBody, String etag, String noneMatch) throws IOException {
throw new UnsupportedOperationException();
return new Event(folderPath, itemName, contentClass, icsBody, etag, noneMatch).createOrUpdate();
}
@Override
@ -761,3 +933,4 @@ public class EwsExchangeSession extends ExchangeSession {
}
}

View File

@ -0,0 +1,30 @@
/*
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
* Copyright (C) 2010 Mickael Guessant
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package davmail.exchange.ews;
/**
* Move Item method.
*/
public class MoveItemMethod extends EWSMethod {
public MoveItemMethod(ItemId itemId, FolderId toFolderId) {
super("Item", "MoveItem");
this.itemId = itemId;
this.toFolderId = toFolderId;
}
}