EWS: fix 3098008, implement result paging to handle message folders with more than 1000 messages

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1569 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2010-12-08 21:39:55 +00:00
parent 67e4b676ec
commit db3f898ce4
4 changed files with 45 additions and 14 deletions

View File

@ -28,7 +28,7 @@ import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.log4j.Logger;
import org.codehaus.stax2.XMLStreamReader2;
import org.codehaus.stax2.typed.TypedXMLStreamReader;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
@ -55,7 +55,12 @@ public abstract class EWSMethod extends PostMethod {
protected Disposal deleteType;
protected Set<AttributeOption> methodOptions;
protected ElementOption unresolvedEntry;
// paging request
protected int maxCount;
protected int offset;
// paging response
protected boolean includesLastItemInRange;
protected List<FieldUpdate> updates;
@ -368,7 +373,10 @@ public abstract class EWSMethod extends PostMethod {
if (maxCount > 0) {
writer.write("<m:IndexedPageItemView MaxEntriesReturned=\"");
writer.write(String.valueOf(maxCount));
writer.write("\" Offset=\"0\" BasePoint=\"Beginning\"/>");
writer.write("\" Offset=\"");
writer.write(String.valueOf(offset));
writer.write("\" BasePoint=\"Beginning\"/>");
}
}
@ -838,9 +846,9 @@ public abstract class EWSMethod extends PostMethod {
protected void handleMimeContent(XMLStreamReader reader, Item responseItem) throws XMLStreamException {
if (reader instanceof XMLStreamReader2) {
if (reader instanceof TypedXMLStreamReader) {
// Stax2 parser: use enhanced base64 conversion
responseItem.mimeContent = ((XMLStreamReader2) reader).getElementAsBinary();
responseItem.mimeContent = ((TypedXMLStreamReader) reader).getElementAsBinary();
} else {
// failover: slow and memory consuming conversion
byte[] base64MimeContent = reader.getElementText().getBytes();
@ -942,6 +950,8 @@ public abstract class EWSMethod extends PostMethod {
} else {
serverVersion = "Exchange2007_SP1";
}
} else if (XMLStreamUtil.isStartTag(reader, "RootFolder")) {
includesLastItemInRange = "true".equals(reader.getAttributeValue(null, "IncludesLastItemInRange"));
} else if (XMLStreamUtil.isStartTag(reader, responseCollectionName)) {
handleItems(reader);
} else {

View File

@ -50,7 +50,10 @@ import java.util.*;
*/
public class EwsExchangeSession extends ExchangeSession {
protected static final int PAGE_SIZE = 100;
protected static Set<String> MESSAGE_TYPES = new HashSet<String>();
static {
MESSAGE_TYPES.add("Message");
MESSAGE_TYPES.add("CalendarItem");
@ -488,15 +491,26 @@ public class EwsExchangeSession extends ExchangeSession {
}
protected List<EWSMethod.Item> searchItems(String folderPath, Set<String> attributes, Condition condition, FolderQueryTraversal folderQueryTraversal, int maxCount) throws IOException {
FindItemMethod findItemMethod = new FindItemMethod(folderQueryTraversal, BaseShape.ID_ONLY, getFolderId(folderPath), maxCount);
for (String attribute : attributes) {
findItemMethod.addAdditionalProperty(Field.get(attribute));
}
if (condition != null && !condition.isEmpty()) {
findItemMethod.setSearchExpression((SearchExpression) condition);
}
executeMethod(findItemMethod);
return findItemMethod.getResponseItems();
int offset = 0;
List<EWSMethod.Item> results = new ArrayList<EWSMethod.Item>();
FindItemMethod findItemMethod;
do {
int fetchCount = PAGE_SIZE;
if (maxCount > 0) {
fetchCount = Math.min(PAGE_SIZE, maxCount - offset);
}
findItemMethod = new FindItemMethod(folderQueryTraversal, BaseShape.ID_ONLY, getFolderId(folderPath), offset, fetchCount);
for (String attribute : attributes) {
findItemMethod.addAdditionalProperty(Field.get(attribute));
}
if (condition != null && !condition.isEmpty()) {
findItemMethod.setSearchExpression((SearchExpression) condition);
}
executeMethod(findItemMethod);
results.addAll(findItemMethod.getResponseItems());
offset = results.size();
} while (!(findItemMethod.includesLastItemInRange || (maxCount > 0 && offset == maxCount)));
return results;
}
protected static class MultiCondition extends ExchangeSession.MultiCondition implements SearchExpression {

View File

@ -28,13 +28,15 @@ public class FindItemMethod extends EWSMethod {
* @param traversal folder traversal mode
* @param baseShape base item shape
* @param parentFolderId parent folder id
* @param offset start offset
* @param maxCount maximum result count
*/
public FindItemMethod(FolderQueryTraversal traversal, BaseShape baseShape, FolderId parentFolderId, int maxCount) {
public FindItemMethod(FolderQueryTraversal traversal, BaseShape baseShape, FolderId parentFolderId, int offset, int maxCount) {
super("Item", "FindItem");
this.traversal = traversal;
this.baseShape = baseShape;
this.parentFolderId = parentFolderId;
this.offset = offset;
this.maxCount = maxCount;
}
}

View File

@ -42,6 +42,11 @@ public class TestExchangeSessionMessage extends AbstractExchangeSessionTestCase
session.createMessage("testfolder", messageName, properties, mimeMessage);
}
public void testSearchInbox() throws IOException, MessagingException {
ExchangeSession.MessageList messageList = session.searchMessages("INBOX");
assertNotNull(messageList);
}
public void testSearchMessage() throws IOException, MessagingException {
ExchangeSession.MessageList messageList = session.searchMessages("testfolder");
assertNotNull(messageList);