diff --git a/src/java/davmail/exchange/ExchangeSession.java b/src/java/davmail/exchange/ExchangeSession.java index 68531b0c..3614001d 100644 --- a/src/java/davmail/exchange/ExchangeSession.java +++ b/src/java/davmail/exchange/ExchangeSession.java @@ -846,67 +846,7 @@ public abstract class ExchangeSession { * @return list of folders * @throws IOException on error */ - public List getSubFolders(String folderName, String filter, boolean recursive) throws IOException { - String mode = recursive ? "DEEP" : "SHALLOW"; - List folders = new ArrayList(); - StringBuilder searchRequest = new StringBuilder(); - searchRequest.append("Select \"DAV:nosubs\", \"DAV:hassubs\", \"DAV:hassubs\"," + - "\"urn:schemas:httpmail:unreadcount\" FROM Scope('").append(mode).append(" TRAVERSAL OF \"").append(getFolderPath(folderName)).append("\"')\n" + - " WHERE \"DAV:ishidden\" = False AND \"DAV:isfolder\" = True \n"); - if (filter != null && filter.length() > 0) { - searchRequest.append(" AND ").append(filter); - } - MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executeSearchMethod( - httpClient, URIUtil.encodePath(getFolderPath(folderName)), searchRequest.toString()); - - for (MultiStatusResponse response : responses) { - folders.add(buildFolder(response)); - } - return folders; - } - - protected Folder buildFolder(MultiStatusResponse entity) throws IOException { - String href = URIUtil.decode(entity.getHref()); - Folder folder = new Folder(); - DavPropertySet properties = entity.getProperties(HttpStatus.SC_OK); - folder.contentClass = getPropertyIfExists(properties, "contentclass", DAV); - folder.hasChildren = "1".equals(getPropertyIfExists(properties, "hassubs", DAV)); - folder.noInferiors = "1".equals(getPropertyIfExists(properties, "nosubs", DAV)); - folder.unreadCount = getIntPropertyIfExists(properties, "unreadcount", URN_SCHEMAS_HTTPMAIL); - 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 - if (href.startsWith(inboxUrl)) { - folder.folderPath = href.replaceFirst(inboxUrl, "INBOX"); - } else if (href.startsWith(sentitemsUrl)) { - folder.folderPath = href.replaceFirst(sentitemsUrl, "Sent"); - } else if (href.startsWith(draftsUrl)) { - folder.folderPath = href.replaceFirst(draftsUrl, "Drafts"); - } else if (href.startsWith(deleteditemsUrl)) { - folder.folderPath = href.replaceFirst(deleteditemsUrl, "Trash"); - } else { - int index = href.indexOf(mailPath.substring(0, mailPath.length() - 1)); - if (index >= 0) { - if (index + mailPath.length() > href.length()) { - folder.folderPath = ""; - } else { - folder.folderPath = href.substring(index + mailPath.length()); - } - } else { - try { - URI folderURI = new URI(href, false); - folder.folderPath = folderURI.getPath(); - } catch (URIException e) { - throw new DavMailException("EXCEPTION_INVALID_FOLDER_URL", href); - } - } - } - if (folder.folderPath.endsWith("/")) { - folder.folderPath = folder.folderPath.substring(0, folder.folderPath.length() - 1); - } - return folder; - } + public abstract List getSubFolders(String folderName, String filter, boolean recursive) throws IOException; /** * Delete oldest messages in trash. @@ -1062,16 +1002,7 @@ public abstract class ExchangeSession { * @return Folder object * @throws IOException on error */ - public Folder getFolder(String folderName) throws IOException { - MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executePropFindMethod( - httpClient, URIUtil.encodePath(getFolderPath(folderName)), 0, FOLDER_PROPERTIES); - Folder folder = null; - if (responses.length > 0) { - folder = buildFolder(responses[0]); - folder.folderName = folderName; - } - return folder; - } + public abstract Folder getFolder(String folderName) throws IOException; /** * Check folder ctag and reload messages as needed. @@ -2412,7 +2343,7 @@ public abstract class ExchangeSession { line = "TZID:" + validTimezoneId; } else if ("BEGIN:VEVENT".equals(line)) { currentAllDayState = allDayStates.get(count++); - // remove calendarserver access + // remove calendarserver access } else if (line.startsWith("X-CALENDARSERVER-ACCESS:")) { continue; } else if (line.startsWith("EXDATE;TZID=") || line.startsWith("EXDATE:")) { diff --git a/src/java/davmail/exchange/dav/DavExchangeSession.java b/src/java/davmail/exchange/dav/DavExchangeSession.java index 3df1ccc4..c2d4bc31 100644 --- a/src/java/davmail/exchange/dav/DavExchangeSession.java +++ b/src/java/davmail/exchange/dav/DavExchangeSession.java @@ -25,15 +25,19 @@ import davmail.http.DavGatewayHttpClientFacade; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.URI; +import org.apache.commons.httpclient.URIException; import org.apache.commons.httpclient.util.URIUtil; import org.apache.jackrabbit.webdav.MultiStatusResponse; import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.xml.Namespace; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; +import java.util.ArrayList; +import java.util.List; /** * Webdav Exchange adapter. @@ -164,4 +168,85 @@ public class DavExchangeSession extends ExchangeSession { } } + protected Folder buildFolder(MultiStatusResponse entity) throws IOException { + String href = URIUtil.decode(entity.getHref()); + Folder folder = new Folder(); + DavPropertySet properties = entity.getProperties(HttpStatus.SC_OK); + folder.contentClass = getPropertyIfExists(properties, "contentclass", DAV); + folder.hasChildren = "1".equals(getPropertyIfExists(properties, "hassubs", DAV)); + folder.noInferiors = "1".equals(getPropertyIfExists(properties, "nosubs", DAV)); + folder.unreadCount = getIntPropertyIfExists(properties, "unreadcount", URN_SCHEMAS_HTTPMAIL); + 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 + if (href.startsWith(inboxUrl)) { + folder.folderPath = href.replaceFirst(inboxUrl, "INBOX"); + } else if (href.startsWith(sentitemsUrl)) { + folder.folderPath = href.replaceFirst(sentitemsUrl, "Sent"); + } else if (href.startsWith(draftsUrl)) { + folder.folderPath = href.replaceFirst(draftsUrl, "Drafts"); + } else if (href.startsWith(deleteditemsUrl)) { + folder.folderPath = href.replaceFirst(deleteditemsUrl, "Trash"); + } else { + int index = href.indexOf(mailPath.substring(0, mailPath.length() - 1)); + if (index >= 0) { + if (index + mailPath.length() > href.length()) { + folder.folderPath = ""; + } else { + folder.folderPath = href.substring(index + mailPath.length()); + } + } else { + try { + URI folderURI = new URI(href, false); + folder.folderPath = folderURI.getPath(); + } catch (URIException e) { + throw new DavMailException("EXCEPTION_INVALID_FOLDER_URL", href); + } + } + } + if (folder.folderPath.endsWith("/")) { + folder.folderPath = folder.folderPath.substring(0, folder.folderPath.length() - 1); + } + return folder; + } + + /** + * @inheritDoc + */ + @Override + public Folder getFolder(String folderName) throws IOException { + MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executePropFindMethod( + httpClient, URIUtil.encodePath(getFolderPath(folderName)), 0, FOLDER_PROPERTIES); + Folder folder = null; + if (responses.length > 0) { + folder = buildFolder(responses[0]); + folder.folderName = folderName; + } + return folder; + } + + /** + * @inheritDoc + */ + @Override + public List getSubFolders(String folderName, String filter, boolean recursive) throws IOException { + String mode = recursive ? "DEEP" : "SHALLOW"; + List folders = new ArrayList(); + StringBuilder searchRequest = new StringBuilder(); + searchRequest.append("Select \"DAV:nosubs\", \"DAV:hassubs\"," + + "\"urn:schemas:httpmail:unreadcount\" FROM Scope('").append(mode).append(" TRAVERSAL OF \"").append(getFolderPath(folderName)).append("\"')\n" + + " WHERE \"DAV:ishidden\" = False AND \"DAV:isfolder\" = True \n"); + if (filter != null && filter.length() > 0) { + searchRequest.append(" AND ").append(filter); + } + MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executeSearchMethod( + httpClient, URIUtil.encodePath(getFolderPath(folderName)), searchRequest.toString()); + + for (MultiStatusResponse response : responses) { + folders.add(buildFolder(response)); + } + return folders; + } + } diff --git a/src/java/davmail/exchange/ews/EwsExchangeSession.java b/src/java/davmail/exchange/ews/EwsExchangeSession.java index b76b3cb7..cbaa44ba 100644 --- a/src/java/davmail/exchange/ews/EwsExchangeSession.java +++ b/src/java/davmail/exchange/ews/EwsExchangeSession.java @@ -23,6 +23,7 @@ import davmail.exchange.ExchangeSession; import org.apache.commons.httpclient.HttpMethod; import java.io.IOException; +import java.util.List; /** * EWS Exchange adapter. @@ -30,6 +31,10 @@ import java.io.IOException; */ public class EwsExchangeSession extends ExchangeSession { + protected class EwsFolder extends Folder { + public FolderId folderId; + } + /** * @inheritDoc */ @@ -42,4 +47,72 @@ public class EwsExchangeSession extends ExchangeSession { // nothing to do, mailPath not used in EWS mode } + /** + * @inheritDoc + */ + @Override + public List getSubFolders(String folderName, String filter, boolean recursive) throws IOException { + // TODO + throw new UnsupportedOperationException(); + } + + /** + * @inheritDoc + */ + @Override + public Folder getFolder(String folderPath) throws IOException { + GetFolderMethod getFolderMethod = new GetFolderMethod(BaseShape.ALL_PROPERTIES, getFolderId(folderPath)); + getFolderMethod.addAdditionalProperty(ExtendedFieldURI.PR_URL_COMP_NAME); + getFolderMethod.addAdditionalProperty(ExtendedFieldURI.PR_LAST_MODIFICATION_TIME); + //getFolderMethod.addAdditionalProperty(new ExtendedFieldURI("0x65E2", ExtendedFieldURI.PropertyType.Binary)); + //getFolderMethod.addAdditionalProperty(new ExtendedFieldURI("00062040-0000-0000-C000-000000000046", 0x8A23, ExtendedFieldURI.PropertyType.SystemTime)); + + httpClient.executeMethod(getFolderMethod); + EWSMethod.Item item = getFolderMethod.getResponseItem(); + EwsFolder folder = null; + if (item != null) { + folder = new EwsFolder(); + folder.folderId = new FolderId(item.get("FolderId")); + folder.folderName = folderPath; + folder.etag = item.get(ExtendedFieldURI.PR_LAST_MODIFICATION_TIME.getPropertyTag()); + // TODO: implement ctag + folder.ctag = String.valueOf(System.currentTimeMillis()); + // TODO: implement contentClass, unreadCount, hasChildren, noInferiors + } + return folder; + } + + + private FolderId getFolderId(String folderPath) throws IOException { + FolderId currentFolderId = DistinguishedFolderId.MSGFOLDERROOT; + String[] folderNames = folderPath.split("/"); + for (String folderName : folderNames) { + if ("INBOX".equals(folderName)) { + currentFolderId = DistinguishedFolderId.INBOX; + } else if ("Sent".equals(folderName)) { + currentFolderId = DistinguishedFolderId.SENTITEMS; + } else if ("Drafts".equals(folderName)) { + currentFolderId = DistinguishedFolderId.DRAFTS; + } else if ("Trash".equals(folderName)) { + currentFolderId = DistinguishedFolderId.DELETEDITEMS; + } else { + currentFolderId = getSubFolderByName(currentFolderId, folderName); + } + } + return currentFolderId; + } + + protected FolderId getSubFolderByName(FolderId parentFolderId, String folderName) throws IOException { + FindFolderMethod findFolderMethod = new FindFolderMethod( + FolderQueryTraversal.SHALLOW, + BaseShape.ID_ONLY, + parentFolderId, + new TwoOperandExpression(TwoOperandExpression.Operator.IsEqualTo, + ExtendedFieldURI.PR_URL_COMP_NAME, folderName) + ); + httpClient.executeMethod(findFolderMethod); + EWSMethod.Item item = findFolderMethod.getResponseItem(); + return new FolderId(item.get("Id")); + } + } diff --git a/src/java/davmail/exchange/ews/FindFolderMethod.java b/src/java/davmail/exchange/ews/FindFolderMethod.java index 3c72563d..cf1a2a14 100644 --- a/src/java/davmail/exchange/ews/FindFolderMethod.java +++ b/src/java/davmail/exchange/ews/FindFolderMethod.java @@ -23,11 +23,31 @@ package davmail.exchange.ews; */ public class FindFolderMethod extends EWSMethod { + /** + * Find Exchange Folder. + * + * @param traversal traversal type + * @param baseShape base shape + * @param parentFolderId parent folder id + */ public FindFolderMethod(FolderQueryTraversal traversal, BaseShape baseShape, FolderId parentFolderId) { super("Folder", "FindFolder"); this.traversal = traversal; this.baseShape = baseShape; this.parentFolderId = parentFolderId; } - + + /** + * Find Exchange Folder. + * + * @param traversal traversal type + * @param baseShape base shape + * @param parentFolderId parent folder id + * @param searchExpression search expression + */ + public FindFolderMethod(FolderQueryTraversal traversal, BaseShape baseShape, FolderId parentFolderId, + SearchExpression searchExpression) { + this(traversal, baseShape, parentFolderId); + this.searchExpression = searchExpression; + } }