mirror of
https://github.com/moparisthebest/davmail
synced 2025-01-13 06:28:19 -05:00
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:
parent
9371f57285
commit
be39c055bb
@ -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";
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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 {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
30
src/java/davmail/exchange/ews/MoveItemMethod.java
Normal file
30
src/java/davmail/exchange/ews/MoveItemMethod.java
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user