COPYUID implementation now in place and working, restructured appendMessages, copyMessages and moveMessages globally to return a Map of srcUids -> destUids rather than returning nothing. This is now used to bring local and remote UIDs upto speed without the need for additional requests.

This commit is contained in:
Apoorv Khatreja 2011-06-28 16:50:48 +05:30
parent 0ba7f20622
commit bc9b7030d7
6 changed files with 163 additions and 69 deletions

View File

@ -2088,9 +2088,32 @@ public class MessagingController implements Runnable {
command.arguments[0] = srcFolder; command.arguments[0] = srcFolder;
command.arguments[1] = destFolder; command.arguments[1] = destFolder;
command.arguments[2] = Boolean.toString(isCopy); command.arguments[2] = Boolean.toString(isCopy);
System.arraycopy(uids, 0, command.arguments, 3, uids.length); command.arguments[3] = Boolean.toString(false);
System.arraycopy(uids, 0, command.arguments, 4, uids.length);
queuePendingCommand(account, command); queuePendingCommand(account, command);
} }
private void queueMoveOrCopy(Account account, String srcFolder, String destFolder, boolean isCopy, String uids[], Map<String, String> uidMap) {
if (uidMap == null || uidMap.isEmpty()) {
queueMoveOrCopy(account, srcFolder, destFolder, isCopy, uids);
} else {
if (account.getErrorFolderName().equals(srcFolder)) {
return;
}
PendingCommand command = new PendingCommand();
command.command = PENDING_COMMAND_MOVE_OR_COPY_BULK;
int length = 4 + uidMap.keySet().size() + uidMap.values().size();
command.arguments = new String[length];
command.arguments[0] = srcFolder;
command.arguments[1] = destFolder;
command.arguments[2] = Boolean.toString(isCopy);
command.arguments[3] = Boolean.toString(true);
System.arraycopy(uidMap.keySet().toArray(), 0, command.arguments, 4, uidMap.keySet().size());
System.arraycopy(uidMap.values().toArray(), 0, command.arguments, 4 + uidMap.keySet().size(), uidMap.values().size());
queuePendingCommand(account, command);
}
}
/** /**
* Process a pending trash message command. * Process a pending trash message command.
* *
@ -2102,6 +2125,7 @@ public class MessagingController implements Runnable {
throws MessagingException { throws MessagingException {
Folder remoteSrcFolder = null; Folder remoteSrcFolder = null;
Folder remoteDestFolder = null; Folder remoteDestFolder = null;
Folder localDestFolder = null;
try { try {
String srcFolder = command.arguments[0]; String srcFolder = command.arguments[0];
if (account.getErrorFolderName().equals(srcFolder)) { if (account.getErrorFolderName().equals(srcFolder)) {
@ -2109,14 +2133,42 @@ public class MessagingController implements Runnable {
} }
String destFolder = command.arguments[1]; String destFolder = command.arguments[1];
String isCopyS = command.arguments[2]; String isCopyS = command.arguments[2];
String hasNewUidsS = command.arguments[3];
boolean hasNewUids = false;
if (hasNewUidsS != null) {
hasNewUids = Boolean.parseBoolean(hasNewUidsS);
}
Store remoteStore = account.getRemoteStore(); Store remoteStore = account.getRemoteStore();
remoteSrcFolder = remoteStore.getFolder(srcFolder); remoteSrcFolder = remoteStore.getFolder(srcFolder);
Store localStore = account.getLocalStore();
localDestFolder = localStore.getFolder(destFolder);
List<Message> messages = new ArrayList<Message>(); List<Message> messages = new ArrayList<Message>();
for (int i = 3; i < command.arguments.length; i++) {
String uid = command.arguments[i]; /*
if (!uid.startsWith(K9.LOCAL_UID_PREFIX)) { * We split up the localUidMap into two parts while sending the command, here we assemble it back.
messages.add(remoteSrcFolder.getMessage(uid)); */
Map<String, String> localUidMap = new HashMap<String, String>();
if (hasNewUids) {
int offset = (command.arguments.length - 4) / 2;
for (int i = 4; i < 4 + offset; i++) {
localUidMap.put(command.arguments[i], command.arguments[i + offset]);
String uid = command.arguments[i];
if (!uid.startsWith(K9.LOCAL_UID_PREFIX)) {
messages.add(remoteSrcFolder.getMessage(uid));
}
}
} else {
for (int i = 4; i < command.arguments.length; i++) {
String uid = command.arguments[i];
if (!uid.startsWith(K9.LOCAL_UID_PREFIX)) {
messages.add(remoteSrcFolder.getMessage(uid));
}
} }
} }
@ -2137,6 +2189,8 @@ public class MessagingController implements Runnable {
Log.d(K9.LOG_TAG, "processingPendingMoveOrCopy: source folder = " + srcFolder Log.d(K9.LOG_TAG, "processingPendingMoveOrCopy: source folder = " + srcFolder
+ ", " + messages.size() + " messages, destination folder = " + destFolder + ", isCopy = " + isCopy); + ", " + messages.size() + " messages, destination folder = " + destFolder + ", isCopy = " + isCopy);
Map <String, String> remoteUidMap = new HashMap<String, String>();
if (!isCopy && destFolder.equals(account.getTrashFolderName())) { if (!isCopy && destFolder.equals(account.getTrashFolderName())) {
if (K9.DEBUG) if (K9.DEBUG)
Log.d(K9.LOG_TAG, "processingPendingMoveOrCopy doing special case for deleting message"); Log.d(K9.LOG_TAG, "processingPendingMoveOrCopy doing special case for deleting message");
@ -2150,9 +2204,9 @@ public class MessagingController implements Runnable {
remoteDestFolder = remoteStore.getFolder(destFolder); remoteDestFolder = remoteStore.getFolder(destFolder);
if (isCopy) { if (isCopy) {
remoteSrcFolder.copyMessages(messages.toArray(EMPTY_MESSAGE_ARRAY), remoteDestFolder); remoteUidMap = remoteSrcFolder.copyMessages(messages.toArray(EMPTY_MESSAGE_ARRAY), remoteDestFolder);
} else { } else {
remoteSrcFolder.moveMessages(messages.toArray(EMPTY_MESSAGE_ARRAY), remoteDestFolder); remoteUidMap = remoteSrcFolder.moveMessages(messages.toArray(EMPTY_MESSAGE_ARRAY), remoteDestFolder);
} }
} }
if (!isCopy && Account.EXPUNGE_IMMEDIATELY.equals(account.getExpungePolicy())) { if (!isCopy && Account.EXPUNGE_IMMEDIATELY.equals(account.getExpungePolicy())) {
@ -2161,12 +2215,27 @@ public class MessagingController implements Runnable {
remoteSrcFolder.expunge(); remoteSrcFolder.expunge();
} }
/*
* This next part is used to bring the local UIDs of the local destination folder
* upto speed with the remote UIDs of remote destionation folder.
*/
if (!localUidMap.isEmpty() && !remoteUidMap.isEmpty()) {
Set<String> remoteSrcUids = remoteUidMap.keySet();
Iterator<String> remoteSrcUidsIterator = remoteSrcUids.iterator();
while (remoteSrcUidsIterator.hasNext()) {
String remoteSrcUid = remoteSrcUidsIterator.next();
String localDestUid = localUidMap.get(remoteSrcUid);
Message localDestMessage = localDestFolder.getMessage(localDestUid);
localDestMessage.setUid(remoteUidMap.get(remoteSrcUid));
}
}
} finally { } finally {
closeFolder(remoteSrcFolder); closeFolder(remoteSrcFolder);
closeFolder(remoteDestFolder); closeFolder(remoteDestFolder);
} }
} }
private void queueSetFlag(final Account account, final String folderName, final String newState, final String flag, final String[] uids) { private void queueSetFlag(final Account account, final String folderName, final String newState, final String flag, final String[] uids) {
@ -3248,6 +3317,7 @@ public class MessagingController implements Runnable {
private void moveOrCopyMessageSynchronous(final Account account, final String srcFolder, final Message[] inMessages, private void moveOrCopyMessageSynchronous(final Account account, final String srcFolder, final Message[] inMessages,
final String destFolder, final boolean isCopy, MessagingListener listener) { final String destFolder, final boolean isCopy, MessagingListener listener) {
try { try {
Map<String, String> uidMap = new HashMap<String, String>();
Store localStore = account.getLocalStore(); Store localStore = account.getLocalStore();
Store remoteStore = account.getRemoteStore(); Store remoteStore = account.getRemoteStore();
if (!isCopy && (!remoteStore.isMoveCapable() || !localStore.isMoveCapable())) { if (!isCopy && (!remoteStore.isMoveCapable() || !localStore.isMoveCapable())) {
@ -3285,9 +3355,9 @@ public class MessagingController implements Runnable {
fp.add(FetchProfile.Item.ENVELOPE); fp.add(FetchProfile.Item.ENVELOPE);
fp.add(FetchProfile.Item.BODY); fp.add(FetchProfile.Item.BODY);
localSrcFolder.fetch(messages, fp, null); localSrcFolder.fetch(messages, fp, null);
localSrcFolder.copyMessages(messages, localDestFolder); uidMap = localSrcFolder.copyMessages(messages, localDestFolder);
} else { } else {
localSrcFolder.moveMessages(messages, localDestFolder); uidMap = localSrcFolder.moveMessages(messages, localDestFolder);
for (String origUid : origUidMap.keySet()) { for (String origUid : origUidMap.keySet()) {
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.messageUidChanged(account, srcFolder, origUid, origUidMap.get(origUid).getUid()); l.messageUidChanged(account, srcFolder, origUid, origUidMap.get(origUid).getUid());
@ -3296,7 +3366,7 @@ public class MessagingController implements Runnable {
} }
} }
queueMoveOrCopy(account, srcFolder, destFolder, isCopy, origUidMap.keySet().toArray(EMPTY_STRING_ARRAY)); queueMoveOrCopy(account, srcFolder, destFolder, isCopy, origUidMap.keySet().toArray(EMPTY_STRING_ARRAY), uidMap);
} }
processPendingCommands(account); processPendingCommands(account);

View File

@ -1,6 +1,7 @@
package com.fsck.k9.mail; package com.fsck.k9.mail;
import java.util.Date; import java.util.Date;
import java.util.Map;
import android.util.Log; import android.util.Log;
import com.fsck.k9.Account; import com.fsck.k9.Account;
@ -102,11 +103,15 @@ public abstract class Folder {
public abstract Message[] getMessages(String[] uids, MessageRetrievalListener listener) public abstract Message[] getMessages(String[] uids, MessageRetrievalListener listener)
throws MessagingException; throws MessagingException;
public abstract void appendMessages(Message[] messages) throws MessagingException; public abstract Map<String, String> appendMessages(Message[] messages) throws MessagingException;
public void copyMessages(Message[] msgs, Folder folder) throws MessagingException {} public Map<String, String> copyMessages(Message[] msgs, Folder folder) throws MessagingException {
return null;
}
public void moveMessages(Message[] msgs, Folder folder) throws MessagingException {} public Map<String, String> moveMessages(Message[] msgs, Folder folder) throws MessagingException {
return null;
}
public void delete(Message[] msgs, String trashFolderName) throws MessagingException { public void delete(Message[] msgs, String trashFolderName) throws MessagingException {
for (Message message : msgs) { for (Message message : msgs) {

View File

@ -29,7 +29,6 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -40,9 +39,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -806,32 +803,19 @@ public class ImapStore extends Store {
} }
@Override @Override
public void copyMessages(Message[] messages, Folder folder) throws MessagingException { public Map<String, String> copyMessages(Message[] messages, Folder folder) throws MessagingException {
if (!(folder instanceof ImapFolder)) { if (!(folder instanceof ImapFolder)) {
throw new MessagingException("ImapFolder.copyMessages passed non-ImapFolder"); throw new MessagingException("ImapFolder.copyMessages passed non-ImapFolder");
} }
if (messages.length == 0) if (messages.length == 0)
return; return null;
ImapFolder iFolder = (ImapFolder)folder; ImapFolder iFolder = (ImapFolder)folder;
checkOpen(); checkOpen();
SortedSet<Message> messageSet = new TreeSet<Message>(new Comparator<Message>() {
public int compare(Message m1, Message m2) {
int uid1 = Integer.parseInt(m1.getUid()), uid2 = Integer.parseInt(m2.getUid());
if (uid1 < uid2) {
return -1;
} else if (uid1 == uid2) {
return 0;
} else {
return 1;
}
}
});
String[] uids = new String[messages.length]; String[] uids = new String[messages.length];
for (int i = 0, count = messages.length; i < count; i++) { for (int i = 0, count = messages.length; i < count; i++) {
messageSet.add(messages[i]);
// Not bothering to sort the UIDs in ascending order while sending the command for convenience, and because it does not make a difference. // Not bothering to sort the UIDs in ascending order while sending the command for convenience, and because it does not make a difference.
uids[i] = messages[i].getUid(); uids[i] = messages[i].getUid();
@ -875,31 +859,36 @@ public class ImapStore extends Store {
Object responseList = response.get(1); Object responseList = response.get(1);
Map<String, String> uidMap = null;
if (responseList instanceof ImapList) { if (responseList instanceof ImapList) {
final ImapList copyList = (ImapList) responseList; final ImapList copyList = (ImapList) responseList;
if ((copyList.size() >= 4) && copyList.getString(0).equals("COPYUID")) { if ((copyList.size() >= 4) && copyList.getString(0).equals("COPYUID")) {
List<String> oldUids = parseSequenceSet(copyList.getString(2)); List<String> srcUids = parseSequenceSet(copyList.getString(2));
List<String> newUids = parseSequenceSet(copyList.getString(3)); List<String> destUids = parseSequenceSet(copyList.getString(3));
if (oldUids.size() == newUids.size()) { if (srcUids.size() == destUids.size()) {
Iterator<Message> messageIterator = messageSet.iterator(); Iterator<String> srcUidsIterator = srcUids.iterator();
for (int i = 0; i < messages.length && messageIterator.hasNext(); i++) { Iterator<String> destUidsIterator = destUids.iterator();
Message nextMessage = messageIterator.next(); uidMap = new HashMap<String, String>();
if (oldUids.get(i).equals(nextMessage.getUid())) { while (srcUidsIterator.hasNext() && destUidsIterator.hasNext()) {
/* uidMap.put(srcUidsIterator.next(), destUidsIterator.next());
* Here, we need to *create* new messages in the localstore, same as the older messages, the only changes are that old UIDs need to be swapped with new UIDs,
* and old folder swapped with new folder.
*/
// nextMessage.setUid(newUids.get(i));
}
} }
} }
} }
} }
return uidMap;
} catch (IOException ioe) { } catch (IOException ioe) {
throw ioExceptionHandler(mConnection, ioe); throw ioExceptionHandler(mConnection, ioe);
} }
} }
/**
* Can be used to parse sequence sets or UID sets appearing is responses such as COPYUID.
* e.g. [COPYUID 38505 304,319:320 3956:3958]
*
* @param set
* @return List<String> sequenceSet
*/
private List<String> parseSequenceSet(String set) { private List<String> parseSequenceSet(String set) {
int index = 0; int index = 0;
List<String> sequenceList = new ArrayList<String>(); List<String> sequenceList = new ArrayList<String>();
@ -947,11 +936,12 @@ public class ImapStore extends Store {
} }
@Override @Override
public void moveMessages(Message[] messages, Folder folder) throws MessagingException { public Map<String, String> moveMessages(Message[] messages, Folder folder) throws MessagingException {
if (messages.length == 0) if (messages.length == 0)
return; return null;
copyMessages(messages, folder); Map<String, String> uidMap = copyMessages(messages, folder);
setFlags(messages, new Flag[] { Flag.DELETED }, true); setFlags(messages, new Flag[] { Flag.DELETED }, true);
return uidMap;
} }
@Override @Override
@ -1698,9 +1688,10 @@ public class ImapStore extends Store {
* new server UID. * new server UID.
*/ */
@Override @Override
public void appendMessages(Message[] messages) throws MessagingException { public Map<String, String> appendMessages(Message[] messages) throws MessagingException {
checkOpen(); checkOpen();
try { try {
Map<String, String> uidMap = null;
for (Message message : messages) { for (Message message : messages) {
mConnection.sendCommand( mConnection.sendCommand(
String.format("APPEND %s (%s) {%d}", String.format("APPEND %s (%s) {%d}",
@ -1734,9 +1725,18 @@ public class ImapStore extends Store {
if (responseList instanceof ImapList) { if (responseList instanceof ImapList) {
final ImapList appendList = (ImapList) responseList; final ImapList appendList = (ImapList) responseList;
if ((appendList.size() >= 3) && appendList.getString(0).equals("APPENDUID")) { if ((appendList.size() >= 3) && appendList.getString(0).equals("APPENDUID")) {
String serverUid = appendList.getString(2); String newUid = appendList.getString(2);
if (!TextUtils.isEmpty(serverUid)) {
message.setUid(serverUid); /*
* We need uidMap to be null initially to maintain consistency with the behavior of other similar methods (copyMessages, moveMessages) which
* return null if new UIDs are not available. Therefore, we initialize uidMap over here.
*/
if (uidMap == null) {
uidMap = new HashMap<String, String>();
}
uidMap.put(message.getUid(), newUid);
if (!TextUtils.isEmpty(newUid)) {
message.setUid(newUid);
continue; continue;
} }
} }
@ -1751,11 +1751,14 @@ public class ImapStore extends Store {
Log.d(K9.LOG_TAG, "Got UID " + newUid + " for message for " + getLogId()); Log.d(K9.LOG_TAG, "Got UID " + newUid + " for message for " + getLogId());
if (newUid != null) { if (newUid != null) {
if (uidMap == null) {
uidMap = new HashMap<String, String>();
}
uidMap.put(message.getUid(), newUid);
message.setUid(newUid); message.setUid(newUid);
} }
} }
return uidMap;
} catch (IOException ioe) { } catch (IOException ioe) {
throw ioExceptionHandler(mConnection, ioe); throw ioExceptionHandler(mConnection, ioe);
} }

View File

@ -1885,21 +1885,23 @@ public class LocalStore extends Store implements Serializable {
} }
@Override @Override
public void copyMessages(Message[] msgs, Folder folder) throws MessagingException { public Map<String, String> copyMessages(Message[] msgs, Folder folder) throws MessagingException {
if (!(folder instanceof LocalFolder)) { if (!(folder instanceof LocalFolder)) {
throw new MessagingException("copyMessages called with incorrect Folder"); throw new MessagingException("copyMessages called with incorrect Folder");
} }
((LocalFolder) folder).appendMessages(msgs, true); return ((LocalFolder) folder).appendMessages(msgs, true);
} }
@Override @Override
public void moveMessages(final Message[] msgs, final Folder destFolder) throws MessagingException { public Map<String, String> moveMessages(final Message[] msgs, final Folder destFolder) throws MessagingException {
if (!(destFolder instanceof LocalFolder)) { if (!(destFolder instanceof LocalFolder)) {
throw new MessagingException("moveMessages called with non-LocalFolder"); throw new MessagingException("moveMessages called with non-LocalFolder");
} }
final LocalFolder lDestFolder = (LocalFolder)destFolder; final LocalFolder lDestFolder = (LocalFolder)destFolder;
final Map<String, String> uidMap = new HashMap<String, String>();
try { try {
database.execute(false, new DbCallback<Void>() { database.execute(false, new DbCallback<Void>() {
@Override @Override
@ -1936,7 +1938,7 @@ public class LocalStore extends Store implements Serializable {
LocalMessage placeHolder = new LocalMessage(oldUID, LocalFolder.this); LocalMessage placeHolder = new LocalMessage(oldUID, LocalFolder.this);
placeHolder.setFlagInternal(Flag.DELETED, true); placeHolder.setFlagInternal(Flag.DELETED, true);
placeHolder.setFlagInternal(Flag.SEEN, true); placeHolder.setFlagInternal(Flag.SEEN, true);
appendMessages(new Message[] { placeHolder }); uidMap.putAll(appendMessages(new Message[] { placeHolder }));
} }
} catch (MessagingException e) { } catch (MessagingException e) {
throw new WrappedException(e); throw new WrappedException(e);
@ -1944,6 +1946,7 @@ public class LocalStore extends Store implements Serializable {
return null; return null;
} }
}); });
return uidMap;
} catch (WrappedException e) { } catch (WrappedException e) {
throw(MessagingException) e.getCause(); throw(MessagingException) e.getCause();
} }
@ -1989,8 +1992,8 @@ public class LocalStore extends Store implements Serializable {
* message, retrieve the appropriate local message instance first (if it already exists). * message, retrieve the appropriate local message instance first (if it already exists).
*/ */
@Override @Override
public void appendMessages(Message[] messages) throws MessagingException { public Map<String, String> appendMessages(Message[] messages) throws MessagingException {
appendMessages(messages, false); return appendMessages(messages, false);
} }
public void destroyMessages(final Message[] messages) throws MessagingException { public void destroyMessages(final Message[] messages) throws MessagingException {
@ -2026,10 +2029,12 @@ public class LocalStore extends Store implements Serializable {
* message, retrieve the appropriate local message instance first (if it already exists). * message, retrieve the appropriate local message instance first (if it already exists).
* @param messages * @param messages
* @param copy * @param copy
* @return Map<String, String> uidMap of srcUids -> destUids
*/ */
private void appendMessages(final Message[] messages, final boolean copy) throws MessagingException { private Map<String, String> appendMessages(final Message[] messages, final boolean copy) throws MessagingException {
open(OpenMode.READ_WRITE); open(OpenMode.READ_WRITE);
try { try {
final Map<String, String> uidMap = new HashMap<String, String>();
database.execute(true, new DbCallback<Void>() { database.execute(true, new DbCallback<Void>() {
@Override @Override
public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException { public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
@ -2040,11 +2045,15 @@ public class LocalStore extends Store implements Serializable {
} }
String uid = message.getUid(); String uid = message.getUid();
if (uid == null || copy) { if (uid == null && !copy) {
uid = K9.LOCAL_UID_PREFIX + UUID.randomUUID().toString(); uid = K9.LOCAL_UID_PREFIX + UUID.randomUUID().toString();
if (!copy) { message.setUid(uid);
message.setUid(uid); } else if (copy) {
String temp = K9.LOCAL_UID_PREFIX + UUID.randomUUID().toString();
if (uid != null) {
uidMap.put(uid, temp);
} }
uid = temp;
} else { } else {
Message oldMessage = getMessage(uid); Message oldMessage = getMessage(uid);
if (oldMessage != null && !oldMessage.isSet(Flag.SEEN)) { if (oldMessage != null && !oldMessage.isSet(Flag.SEEN)) {
@ -2150,6 +2159,7 @@ public class LocalStore extends Store implements Serializable {
return null; return null;
} }
}); });
return uidMap;
} catch (WrappedException e) { } catch (WrappedException e) {
throw(MessagingException) e.getCause(); throw(MessagingException) e.getCause();
} }

View File

@ -24,6 +24,7 @@ import java.util.LinkedList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
public class Pop3Store extends Store { public class Pop3Store extends Store {
public static final int CONNECTION_SECURITY_NONE = 0; public static final int CONNECTION_SECURITY_NONE = 0;
@ -736,7 +737,8 @@ public class Pop3Store extends Store {
} }
@Override @Override
public void appendMessages(Message[] messages) throws MessagingException { public Map<String, String> appendMessages(Message[] messages) throws MessagingException {
return null;
} }
@Override @Override

View File

@ -51,6 +51,7 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.Stack; import java.util.Stack;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@ -1161,13 +1162,15 @@ public class WebDavStore extends Store {
} }
@Override @Override
public void copyMessages(Message[] messages, Folder folder) throws MessagingException { public Map<String, String> copyMessages(Message[] messages, Folder folder) throws MessagingException {
moveOrCopyMessages(messages, folder.getName(), false); moveOrCopyMessages(messages, folder.getName(), false);
return null;
} }
@Override @Override
public void moveMessages(Message[] messages, Folder folder) throws MessagingException { public Map<String, String> moveMessages(Message[] messages, Folder folder) throws MessagingException {
moveOrCopyMessages(messages, folder.getName(), true); moveOrCopyMessages(messages, folder.getName(), true);
return null;
} }
@Override @Override
@ -1728,8 +1731,9 @@ public class WebDavStore extends Store {
} }
@Override @Override
public void appendMessages(Message[] messages) throws MessagingException { public Map<String, String> appendMessages(Message[] messages) throws MessagingException {
appendWebDavMessages(messages); appendWebDavMessages(messages);
return null;
} }
public Message[] appendWebDavMessages(Message[] messages) throws MessagingException { public Message[] appendWebDavMessages(Message[] messages) throws MessagingException {