Carddav: refactor folder handling code to prepart CardDav support

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@984 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2010-04-01 09:12:44 +00:00
parent 28c02c9a3a
commit 67e10a2ba8
2 changed files with 65 additions and 23 deletions

View File

@ -208,10 +208,10 @@ public class CaldavConnection extends AbstractConnection {
if (request.isPropFind() && request.isPathLength(3)) { if (request.isPropFind() && request.isPathLength(3)) {
sendUserRoot(request); sendUserRoot(request);
} else { } else {
handleCalendar(request); handleFolder(request);
} }
} else if (request.isPath(1, "public")) { } else if (request.isPath(1, "public")) {
handleCalendar(request); handleFolder(request);
} else { } else {
sendUnsupported(request); sendUnsupported(request);
} }
@ -238,7 +238,7 @@ public class CaldavConnection extends AbstractConnection {
} }
} }
protected void handleCalendar(CaldavRequest request) throws IOException { protected void handleFolder(CaldavRequest request) throws IOException {
String lastPath = xmlDecodeName(request.getLastPath()); String lastPath = xmlDecodeName(request.getLastPath());
// folder requests // folder requests
if (request.isPropFind() && "inbox".equals(lastPath)) { if (request.isPropFind() && "inbox".equals(lastPath)) {
@ -254,7 +254,7 @@ public class CaldavConnection extends AbstractConnection {
sendHttpResponse(status); sendHttpResponse(status);
} }
} else if (request.isPropFind()) { } else if (request.isPropFind()) {
sendCalendar(request); sendFolder(request);
} else if (request.isPropPatch()) { } else if (request.isPropPatch()) {
patchCalendar(request); patchCalendar(request);
} else if (request.isReport()) { } else if (request.isReport()) {
@ -359,20 +359,29 @@ public class CaldavConnection extends AbstractConnection {
} }
/** /**
* Append calendar object to Caldav response. * Append folder object to Caldav response.
* *
* @param response Caldav response * @param response Caldav response
* @param request Caldav request * @param request Caldav request
* @param subFolder calendar folder path relative to request path * @param subFolder calendar folder path relative to request path
* @throws IOException on error * @throws IOException on error
*/ */
public void appendCalendar(CaldavResponse response, CaldavRequest request, String subFolder) throws IOException { public void appendFolder(CaldavResponse response, CaldavRequest request, String subFolder) throws IOException {
ExchangeSession.Folder folder = session.getFolder(request.getExchangeFolderPath(subFolder));
response.startResponse(URIUtil.encodePath(request.getPath(subFolder))); response.startResponse(URIUtil.encodePath(request.getPath(subFolder)));
response.startPropstat(); response.startPropstat();
if (request.hasProperty("resourcetype")) { if (request.hasProperty("resourcetype")) {
response.appendProperty("D:resourcetype", "<D:collection/>" + if (folder.isContact()) {
"<C:calendar/>"); response.appendProperty("D:resourcetype", "CD=\"urn:ietf:params:xml:ns:carddav\"", "<D:collection/>" +
"<CD:addressbook/>");
} else if (folder.isCalendar()) {
response.appendProperty("D:resourcetype", "<D:collection/>" + "<C:calendar/>");
} else {
response.appendProperty("D:resourcetype", "<D:collection/>");
}
} }
if (request.hasProperty("owner")) { if (request.hasProperty("owner")) {
if ("users".equals(request.getPathElement(1))) { if ("users".equals(request.getPathElement(1))) {
@ -382,14 +391,18 @@ public class CaldavConnection extends AbstractConnection {
} }
} }
if (request.hasProperty("getcontenttype")) { if (request.hasProperty("getcontenttype")) {
response.appendProperty("D:getcontenttype", "text/calendar; component=vevent"); if (folder.isContact()) {
response.appendProperty("D:getcontenttype", "text/x-vcard");
} else if (folder.isCalendar()) {
response.appendProperty("D:getcontenttype", "text/calendar; component=vevent");
}
} }
if (request.hasProperty("getetag")) { if (request.hasProperty("getetag")) {
response.appendProperty("D:getetag", session.getFolderResourceTag(request.getExchangeFolderPath(subFolder))); response.appendProperty("D:getetag", folder.etag);
} }
if (request.hasProperty("getctag")) { if (request.hasProperty("getctag")) {
response.appendProperty("CS:getctag", "CS=\"http://calendarserver.org/ns/\"", response.appendProperty("CS:getctag", "CS=\"http://calendarserver.org/ns/\"",
base64Encode(session.getFolderCtag(request.getExchangeFolderPath(subFolder)))); base64Encode(folder.ctag));
} }
if (request.hasProperty("displayname")) { if (request.hasProperty("displayname")) {
if (subFolder == null || subFolder.length() == 0) { if (subFolder == null || subFolder.length() == 0) {
@ -401,7 +414,7 @@ public class CaldavConnection extends AbstractConnection {
if (request.hasProperty("calendar-description")) { if (request.hasProperty("calendar-description")) {
response.appendProperty("C:calendar-description", ""); response.appendProperty("C:calendar-description", "");
} }
if (request.hasProperty("supported-calendar-component-set")) { if (request.hasProperty("supported-calendar-component-set") && folder.isCalendar()) {
response.appendProperty("C:supported-calendar-component-set", "<C:comp name=\"VEVENT\"/>"); response.appendProperty("C:supported-calendar-component-set", "<C:comp name=\"VEVENT\"/>");
} }
@ -507,7 +520,7 @@ public class CaldavConnection extends AbstractConnection {
CaldavResponse response = new CaldavResponse(HttpStatus.SC_MULTI_STATUS); CaldavResponse response = new CaldavResponse(HttpStatus.SC_MULTI_STATUS);
response.startMultistatus(); response.startMultistatus();
appendInbox(response, request, null); appendInbox(response, request, null);
// do not try to access inbox on shared calendar // do not try to access inbox on shared calendar
if (!session.isSharedFolder(request.getExchangeFolderPath(null)) && request.getDepth() == 1 && !Settings.getBooleanProperty("davmail.caldavDisableInbox")) { if (!session.isSharedFolder(request.getExchangeFolderPath(null)) && request.getDepth() == 1 && !Settings.getBooleanProperty("davmail.caldavDisableInbox")) {
try { try {
DavGatewayTray.debug(new BundleMessage("LOG_SEARCHING_CALENDAR_MESSAGES")); DavGatewayTray.debug(new BundleMessage("LOG_SEARCHING_CALENDAR_MESSAGES"));
@ -543,11 +556,11 @@ public class CaldavConnection extends AbstractConnection {
* @param request Caldav request * @param request Caldav request
* @throws IOException on error * @throws IOException on error
*/ */
public void sendCalendar(CaldavRequest request) throws IOException { public void sendFolder(CaldavRequest request) throws IOException {
String folderPath = request.getExchangeFolderPath(); String folderPath = request.getExchangeFolderPath();
CaldavResponse response = new CaldavResponse(HttpStatus.SC_MULTI_STATUS); CaldavResponse response = new CaldavResponse(HttpStatus.SC_MULTI_STATUS);
response.startMultistatus(); response.startMultistatus();
appendCalendar(response, request, null); appendFolder(response, request, null);
if (request.getDepth() == 1) { if (request.getDepth() == 1) {
DavGatewayTray.debug(new BundleMessage("LOG_SEARCHING_CALENDAR_EVENTS", folderPath)); DavGatewayTray.debug(new BundleMessage("LOG_SEARCHING_CALENDAR_EVENTS", folderPath));
List<ExchangeSession.Event> events = session.getAllEvents(folderPath); List<ExchangeSession.Event> events = session.getAllEvents(folderPath);
@ -557,7 +570,7 @@ public class CaldavConnection extends AbstractConnection {
if (!folderPath.startsWith("/public")) { if (!folderPath.startsWith("/public")) {
List<ExchangeSession.Folder> folderList = session.getSubCalendarFolders(folderPath, false); List<ExchangeSession.Folder> folderList = session.getSubCalendarFolders(folderPath, false);
for (ExchangeSession.Folder folder : folderList) { for (ExchangeSession.Folder folder : folderList) {
appendCalendar(response, request, folder.folderPath.substring(folder.folderPath.indexOf('/') + 1)); appendFolder(response, request, folder.folderPath.substring(folder.folderPath.indexOf('/') + 1));
} }
} }
} }
@ -670,7 +683,7 @@ public class CaldavConnection extends AbstractConnection {
if (request.getDepth() == 1) { if (request.getDepth() == 1) {
appendInbox(response, request, "inbox"); appendInbox(response, request, "inbox");
appendOutbox(response, request, "outbox"); appendOutbox(response, request, "outbox");
appendCalendar(response, request, "calendar"); appendFolder(response, request, "calendar");
} }
response.endResponse(); response.endResponse();
response.endMultistatus(); response.endMultistatus();
@ -1003,7 +1016,7 @@ public class CaldavConnection extends AbstractConnection {
if (status != HttpStatus.SC_UNAUTHORIZED) { if (status != HttpStatus.SC_UNAUTHORIZED) {
String version = DavGateway.getCurrentVersion(); String version = DavGateway.getCurrentVersion();
sendClient("Server: DavMail Gateway " + (version == null ? "" : version)); sendClient("Server: DavMail Gateway " + (version == null ? "" : version));
sendClient("DAV: 1, calendar-access, calendar-schedule, calendarserver-private-events"); sendClient("DAV: 1, calendar-access, calendar-schedule, calendarserver-private-events, addressbook");
SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH); SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
// force GMT timezone // force GMT timezone
formatter.setTimeZone(ExchangeSession.GMT_TIMEZONE); formatter.setTimeZone(ExchangeSession.GMT_TIMEZONE);

View File

@ -133,10 +133,12 @@ public class ExchangeSession {
protected static final DavPropertyNameSet FOLDER_PROPERTIES = new DavPropertyNameSet(); protected static final DavPropertyNameSet FOLDER_PROPERTIES = new DavPropertyNameSet();
static { static {
FOLDER_PROPERTIES.add(DavPropertyName.create("contentclass", Namespace.getNamespace("DAV:")));
FOLDER_PROPERTIES.add(DavPropertyName.create("hassubs")); FOLDER_PROPERTIES.add(DavPropertyName.create("hassubs"));
FOLDER_PROPERTIES.add(DavPropertyName.create("nosubs")); FOLDER_PROPERTIES.add(DavPropertyName.create("nosubs"));
FOLDER_PROPERTIES.add(DavPropertyName.create("unreadcount", URN_SCHEMAS_HTTPMAIL)); FOLDER_PROPERTIES.add(DavPropertyName.create("unreadcount", URN_SCHEMAS_HTTPMAIL));
FOLDER_PROPERTIES.add(DavPropertyName.create("contenttag", Namespace.getNamespace("http://schemas.microsoft.com/repl/"))); FOLDER_PROPERTIES.add(DavPropertyName.create("contenttag", Namespace.getNamespace("http://schemas.microsoft.com/repl/")));
FOLDER_PROPERTIES.add(DavPropertyName.create("resourcetag", Namespace.getNamespace("http://schemas.microsoft.com/repl/")));
} }
protected static final DavPropertyNameSet CONTENT_TAG = new DavPropertyNameSet(); protected static final DavPropertyNameSet CONTENT_TAG = new DavPropertyNameSet();
@ -969,10 +971,12 @@ public class ExchangeSession {
String href = URIUtil.decode(entity.getHref()); String href = URIUtil.decode(entity.getHref());
Folder folder = new Folder(); Folder folder = new Folder();
DavPropertySet properties = entity.getProperties(HttpStatus.SC_OK); DavPropertySet properties = entity.getProperties(HttpStatus.SC_OK);
folder.contentClass = getPropertyIfExists(properties, "contentclass", Namespace.getNamespace("DAV:"));
folder.hasChildren = "1".equals(getPropertyIfExists(properties, "hassubs", Namespace.getNamespace("DAV:"))); folder.hasChildren = "1".equals(getPropertyIfExists(properties, "hassubs", Namespace.getNamespace("DAV:")));
folder.noInferiors = "1".equals(getPropertyIfExists(properties, "nosubs", Namespace.getNamespace("DAV:"))); folder.noInferiors = "1".equals(getPropertyIfExists(properties, "nosubs", Namespace.getNamespace("DAV:")));
folder.unreadCount = getIntPropertyIfExists(properties, "unreadcount", URN_SCHEMAS_HTTPMAIL); folder.unreadCount = getIntPropertyIfExists(properties, "unreadcount", URN_SCHEMAS_HTTPMAIL);
folder.contenttag = getPropertyIfExists(properties, "contenttag", Namespace.getNamespace("http://schemas.microsoft.com/repl/")); folder.ctag = getPropertyIfExists(properties, "contenttag", Namespace.getNamespace("http://schemas.microsoft.com/repl/"));
folder.etag = getPropertyIfExists(properties, "resourcetag", Namespace.getNamespace("http://schemas.microsoft.com/repl/"));
// replace well known folder names // replace well known folder names
if (href.startsWith(inboxUrl)) { if (href.startsWith(inboxUrl)) {
@ -1178,15 +1182,15 @@ public class ExchangeSession {
*/ */
public boolean refreshFolder(Folder currentFolder) throws IOException { public boolean refreshFolder(Folder currentFolder) throws IOException {
Folder newFolder = getFolder(currentFolder.folderName); Folder newFolder = getFolder(currentFolder.folderName);
if (currentFolder.contenttag == null || !currentFolder.contenttag.equals(newFolder.contenttag)) { if (currentFolder.ctag == null || !currentFolder.ctag.equals(newFolder.ctag)) {
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Contenttag changed on " + currentFolder.folderName + ' ' LOGGER.debug("Contenttag changed on " + currentFolder.folderName + ' '
+ currentFolder.contenttag + " => " + newFolder.contenttag + ", reloading messages"); + currentFolder.ctag + " => " + newFolder.ctag + ", reloading messages");
} }
currentFolder.hasChildren = newFolder.hasChildren; currentFolder.hasChildren = newFolder.hasChildren;
currentFolder.noInferiors = newFolder.noInferiors; currentFolder.noInferiors = newFolder.noInferiors;
currentFolder.unreadCount = newFolder.unreadCount; currentFolder.unreadCount = newFolder.unreadCount;
currentFolder.contenttag = newFolder.contenttag; currentFolder.ctag = newFolder.ctag;
currentFolder.loadMessages(); currentFolder.loadMessages();
return true; return true;
} else { } else {
@ -1322,6 +1326,11 @@ public class ExchangeSession {
* Logical (IMAP) folder path. * Logical (IMAP) folder path.
*/ */
public String folderPath; public String folderPath;
/**
* Folder content class.
*/
public String contentClass;
/** /**
* Folder unread message count. * Folder unread message count.
*/ */
@ -1341,7 +1350,11 @@ public class ExchangeSession {
/** /**
* Folder content tag (to detect folder content changes). * Folder content tag (to detect folder content changes).
*/ */
public String contenttag; public String ctag;
/**
* Folder etag (to detect folder object changes).
*/
public String etag;
/** /**
* Folder message list, empty before loadMessages call. * Folder message list, empty before loadMessages call.
*/ */
@ -1441,6 +1454,22 @@ public class ExchangeSession {
public Message get(int index) { public Message get(int index) {
return messages.get(index); return messages.get(index);
} }
/**
* Calendar folder flag.
* @return true if this is a calendar folder
*/
public boolean isCalendar() {
return "urn:content-classes:calendarfolder".equals(contentClass);
}
/**
* Contact folder flag.
* @return true if this is a calendar folder
*/
public boolean isContact() {
return "urn:content-classes:contactfolder".equals(contentClass);
}
} }
/** /**