diff --git a/src/com/android/email/MessagingController.java b/src/com/android/email/MessagingController.java index ebee84eb9..1811064ad 100644 --- a/src/com/android/email/MessagingController.java +++ b/src/com/android/email/MessagingController.java @@ -1874,7 +1874,22 @@ public class MessagingController implements Runnable } } } - + private void queueMoveOrCopy(Account account, String srcFolder, String destFolder, boolean isCopy, String uids[]) + { + PendingCommand command = new PendingCommand(); + command.command = PENDING_COMMAND_MOVE_OR_COPY; + + int length = 3 + uids.length; + command.arguments = new String[length]; + command.arguments[0] = srcFolder; + command.arguments[1] = destFolder; + command.arguments[2] = Boolean.toString(isCopy); + for (int i = 0; i < uids.length; i++) + { + command.arguments[3 + i] = uids[i]; + } + queuePendingCommand(account, command); + } /** * Process a pending trash message command. * @@ -1885,79 +1900,88 @@ public class MessagingController implements Runnable private void processPendingMoveOrCopy(PendingCommand command, Account account) throws MessagingException { - String srcFolder = command.arguments[0]; - String uid = command.arguments[1]; - String destFolder = command.arguments[2]; - String isCopyS = command.arguments[3]; - - boolean isCopy = false; - if (isCopyS != null) - { - isCopy = Boolean.parseBoolean(isCopyS); - } - - if (account.getErrorFolderName().equals(srcFolder)) - { - return; - } - - Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication); - Folder remoteSrcFolder = remoteStore.getFolder(srcFolder); - Folder remoteDestFolder = remoteStore.getFolder(destFolder); - - if (!remoteSrcFolder.exists()) - { - throw new MessagingException("processingPendingMoveOrCopy: remoteFolder " + srcFolder + " does not exist", true); - } - remoteSrcFolder.open(OpenMode.READ_WRITE); - if (remoteSrcFolder.getMode() != OpenMode.READ_WRITE) - { - throw new MessagingException("processingPendingMoveOrCopy: could not open remoteSrcFolder " + srcFolder + " read/write", true); - } - - Message remoteMessage = null; - if (!uid.startsWith(Email.LOCAL_UID_PREFIX)) - { - remoteMessage = remoteSrcFolder.getMessage(uid); - } - if (remoteMessage == null) - { - throw new MessagingException("processingPendingMoveOrCopy: remoteMessage " + uid + " does not exist", true); - } - - if (Email.DEBUG) - { - Log.d(Email.LOG_TAG, "processingPendingMoveOrCopy: source folder = " + srcFolder - + ", uid = " + uid + ", destination folder = " + destFolder + ", isCopy = " + isCopy); - } - if (isCopy == false && destFolder.equals(account.getTrashFolderName())) + Folder remoteSrcFolder = null; + Folder remoteDestFolder = null; + try { + String srcFolder = command.arguments[0]; + String destFolder = command.arguments[1]; + String isCopyS = command.arguments[2]; + Store remoteStore = Store.getInstance(account.getStoreUri(), mApplication); + remoteSrcFolder = remoteStore.getFolder(srcFolder); + + List messages = new ArrayList(); + for (int i = 3; i < command.arguments.length; i++) + { + String uid = command.arguments[i]; + if (!uid.startsWith(Email.LOCAL_UID_PREFIX)) + { + messages.add(remoteSrcFolder.getMessage(uid)); + } + } + + boolean isCopy = false; + if (isCopyS != null) + { + isCopy = Boolean.parseBoolean(isCopyS); + } + + if (!remoteSrcFolder.exists()) + { + throw new MessagingException("processingPendingMoveOrCopy: remoteFolder " + srcFolder + " does not exist", true); + } + remoteSrcFolder.open(OpenMode.READ_WRITE); + if (remoteSrcFolder.getMode() != OpenMode.READ_WRITE) + { + throw new MessagingException("processingPendingMoveOrCopy: could not open remoteSrcFolder " + srcFolder + " read/write", true); + } + if (Email.DEBUG) { - Log.d(Email.LOG_TAG, "processingPendingMoveOrCopy doing special case for deleting message"); + Log.d(Email.LOG_TAG, "processingPendingMoveOrCopy: source folder = " + srcFolder + + ", " + messages.size() + " messages, destination folder = " + destFolder + ", isCopy = " + isCopy); } - remoteMessage.delete(account.getTrashFolderName()); - remoteSrcFolder.close(true); - return; + if (isCopy == false && destFolder.equals(account.getTrashFolderName())) + { + if (Email.DEBUG) + { + Log.d(Email.LOG_TAG, "processingPendingMoveOrCopy doing special case for deleting message"); + } + remoteSrcFolder.delete(messages.toArray(new Message[0]), account.getTrashFolderName()); + } + else + { + remoteDestFolder = remoteStore.getFolder(destFolder); + + remoteDestFolder.open(OpenMode.READ_WRITE); + if (remoteDestFolder.getMode() != OpenMode.READ_WRITE) + { + throw new MessagingException("processingPendingMoveOrCopy: could not open remoteDestFolder " + srcFolder + " read/write", true); + } + + if (isCopy) + { + remoteSrcFolder.copyMessages(messages.toArray(new Message[0]), remoteDestFolder); + } + else + { + remoteSrcFolder.moveMessages(messages.toArray(new Message[0]), remoteDestFolder); + } + } + remoteSrcFolder.expunge(); } - - remoteDestFolder.open(OpenMode.READ_WRITE); - if (remoteDestFolder.getMode() != OpenMode.READ_WRITE) + finally { - throw new MessagingException("processingPendingMoveOrCopy: could not open remoteDestFolder " + srcFolder + " read/write", true); + if (remoteSrcFolder != null) + { + remoteSrcFolder.close(false); + } + if (remoteDestFolder != null) + { + remoteDestFolder.close(false); + } } - if (isCopy) - { - remoteSrcFolder.copyMessages(new Message[] { remoteMessage }, remoteDestFolder); - } - else - { - remoteSrcFolder.moveMessages(new Message[] { remoteMessage }, remoteDestFolder); - } - remoteSrcFolder.close(true); - remoteDestFolder.close(true); - } @@ -3192,10 +3216,8 @@ public class MessagingController implements Runnable unsuppressMessage(account, srcFolder, origUid); } } - PendingCommand command = new PendingCommand(); - command.command = PENDING_COMMAND_MOVE_OR_COPY; - command.arguments = new String[] { srcFolder, origUid, destFolder, Boolean.toString(isCopy) }; - queuePendingCommand(account, command); + queueMoveOrCopy(account, srcFolder, destFolder, isCopy, new String[] { origUid }); + processPendingCommands(account); } catch (MessagingException me) @@ -3206,85 +3228,68 @@ public class MessagingController implements Runnable } } - public void deleteMessageList(final Account account, final String folder, final List messageList, + public void deleteMessages(final Account account, final String folder, final Message[] messages, final MessagingListener listener) { - for (Message message : messageList) + for (Message message : messages) { suppressMessage(account, folder, message); } - - put("deleteMessageList", null, new Runnable() + + put("deleteMessages", null, new Runnable() { public void run() { - for (Message message : messageList) - { - deleteMessageSynchronous(account, folder, message, listener); - } + deleteMessagesSynchronous(account, folder, messages, listener); } }); } - public void deleteMessage(final Account account, final String folder, final Message message, - final MessagingListener listener) - { - suppressMessage(account, folder, message); - - put("deleteMessage", null, new Runnable() - { - public void run() - { - deleteMessageSynchronous(account, folder, message, listener); - } - }); - } - - private void deleteMessageSynchronous(final Account account, final String folder, final Message message, + private void deleteMessagesSynchronous(final Account account, final String folder, final Message[] messages, MessagingListener listener) { - + Folder localFolder = null; + Folder localTrashFolder = null; + String[] uids = getUidsFromMessages(messages); try { Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication); - Folder localFolder = localStore.getFolder(folder); - Message lMessage = localFolder.getMessage(message.getUid()); - String origUid = message.getUid(); - if (lMessage != null) + localFolder = localStore.getFolder(folder); + if (folder.equals(account.getTrashFolderName())) { - if (folder.equals(account.getTrashFolderName())) + if (Email.DEBUG) + { + Log.d(Email.LOG_TAG, "Deleting messages in trash folder, not copying"); + } + localFolder.setFlags(messages, new Flag[] { Flag.DELETED }, true); + } + else + { + localTrashFolder = localStore.getFolder(account.getTrashFolderName()); + if (localTrashFolder.exists() == false) + { + localTrashFolder.create(Folder.FolderType.HOLDS_MESSAGES); + } + if (localTrashFolder.exists() == true) { if (Email.DEBUG) { - Log.d(Email.LOG_TAG, "Deleting message in trash folder, not copying"); + Log.d(Email.LOG_TAG, "Deleting messages in normal folder, moving"); } - lMessage.setFlag(Flag.DELETED, true); - } - else - { - Folder localTrashFolder = localStore.getFolder(account.getTrashFolderName()); - if (localTrashFolder.exists() == false) - { - localTrashFolder.create(Folder.FolderType.HOLDS_MESSAGES); - } - if (localTrashFolder.exists() == true) - { - if (Email.DEBUG) - { - Log.d(Email.LOG_TAG, "Deleting message in normal folder, moving"); - } - localFolder.moveMessages(new Message[] { message }, localTrashFolder); + localFolder.moveMessages(messages, localTrashFolder); - } } } - localFolder.close(false); - unsuppressMessage(account, folder, message); - if (listener != null) + for (Message message : messages) { - listener.messageDeleted(account, folder, message); + unsuppressMessage(account, folder, message); + if (listener != null) + { + listener.messageDeleted(account, folder, message); + } } + for (MessagingListener l : getListeners()) { l.folderStatusChanged(account, account.getTrashFolderName()); @@ -3296,35 +3301,35 @@ public class MessagingController implements Runnable } if (folder.equals(account.getOutboxFolderName())) { - // If the message was in the Outbox, then it has been copied to local Trash, and has - // to be copied to remote trash - PendingCommand command = new PendingCommand(); - command.command = PENDING_COMMAND_APPEND; - command.arguments = - new String[] + for (Message message : messages) { - account.getTrashFolderName(), - message.getUid() - }; - queuePendingCommand(account, command); + // If the message was in the Outbox, then it has been copied to local Trash, and has + // to be copied to remote trash + PendingCommand command = new PendingCommand(); + command.command = PENDING_COMMAND_APPEND; + command.arguments = + new String[] + { + account.getTrashFolderName(), + message.getUid() + }; + queuePendingCommand(account, command); + } processPendingCommands(account); } else if (folder.equals(account.getTrashFolderName()) && account.getDeletePolicy() == Account.DELETE_POLICY_ON_DELETE) { - queueSetFlag(account, folder, Boolean.toString(true), Flag.DELETED.toString(), new String[] { origUid }); + queueSetFlag(account, folder, Boolean.toString(true), Flag.DELETED.toString(), uids); processPendingCommands(account); } else if (account.getDeletePolicy() == Account.DELETE_POLICY_ON_DELETE) { - PendingCommand command = new PendingCommand(); - command.command = PENDING_COMMAND_MOVE_OR_COPY; - command.arguments = new String[] { folder, origUid, account.getTrashFolderName(), "false" }; - queuePendingCommand(account, command); + queueMoveOrCopy(account, folder, account.getTrashFolderName(), false, uids); processPendingCommands(account); } else if (account.getDeletePolicy() == Account.DELETE_POLICY_MARK_AS_READ) { - queueSetFlag(account, folder, Boolean.toString(true), Flag.SEEN.toString(), new String[] { origUid }); + queueSetFlag(account, folder, Boolean.toString(true), Flag.SEEN.toString(), uids); processPendingCommands(account); } else @@ -3341,6 +3346,27 @@ public class MessagingController implements Runnable throw new RuntimeException("Error deleting message from local store.", me); } + finally + { + if (localFolder != null) + { + localFolder.close(false); + } + if (localTrashFolder != null) + { + localTrashFolder.close(false); + } + } + } + + private String[] getUidsFromMessages(Message[] messages) + { + String[] uids = new String[messages.length]; + for (int i = 0; i < messages.length; i++) + { + uids[i] = messages[i].getUid(); + } + return uids; } private void processPendingEmptyTrash(PendingCommand command, Account account) throws MessagingException diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java index 79af03080..cf294a9af 100644 --- a/src/com/android/email/activity/MessageCompose.java +++ b/src/com/android/email/activity/MessageCompose.java @@ -857,7 +857,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc /* * We're sending a previously saved draft, so delete the old draft first. */ - MessagingController.getInstance(getApplication()).deleteMessage(mAccount, mFolder, mSourceMessage, null); + MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mFolder, new Message[] { mSourceMessage }, null); } if (mDraftUid != null) { @@ -866,7 +866,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc */ Message draftMessage = new MimeMessage(); draftMessage.setUid(mDraftUid); - MessagingController.getInstance(getApplication()).deleteMessage(mAccount, mAccount.getDraftsFolderName(), draftMessage, null); + MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mAccount.getDraftsFolderName(), new Message[] { draftMessage }, null); } MessagingController.getInstance(getApplication()).sendMessage(mAccount, message, null); } @@ -901,13 +901,13 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc { if (ACTION_EDIT_DRAFT.equals(getIntent().getAction()) && mSourceMessageUid != null) { - MessagingController.getInstance(getApplication()).deleteMessage(mAccount, mFolder, mSourceMessage, null); + MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mFolder, new Message[] { mSourceMessage }, null); } } if (mDraftUid != null) { Message draftMessage = new MimeMessage(); - MessagingController.getInstance(getApplication()).deleteMessage(mAccount, mAccount.getDraftsFolderName(), draftMessage, null); + MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mAccount.getDraftsFolderName(), new Message[] { draftMessage }, null); } mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT); mDraftNeedsSaving = false; diff --git a/src/com/android/email/activity/MessageList.java b/src/com/android/email/activity/MessageList.java index 43f9c4105..2c3063a7c 100644 --- a/src/com/android/email/activity/MessageList.java +++ b/src/com/android/email/activity/MessageList.java @@ -882,7 +882,7 @@ public class MessageList private void onDelete(MessageInfoHolder holder, int position) { mAdapter.removeMessage(holder); - MessagingController.getInstance(getApplication()).deleteMessage(mAccount, holder.message.getFolder().getName(), holder.message, null); + MessagingController.getInstance(getApplication()).deleteMessages(mAccount, holder.message.getFolder().getName(), new Message[] { holder.message }, null); mListView.setSelection(position); } @@ -2257,7 +2257,7 @@ public class MessageList { if (mBatchDeleteButton == v) { - MessagingController.getInstance(getApplication()).deleteMessageList(mAccount, mCurrentFolder.name, messageList, null); + MessagingController.getInstance(getApplication()).deleteMessages(mAccount, mCurrentFolder.name, messageList.toArray(new Message[0]), null); mSelectedCount = 0; configureBatchButtons(); } diff --git a/src/com/android/email/activity/MessageView.java b/src/com/android/email/activity/MessageView.java index 80d8a346f..1bb08a718 100644 --- a/src/com/android/email/activity/MessageView.java +++ b/src/com/android/email/activity/MessageView.java @@ -758,10 +758,10 @@ public class MessageView extends K9Activity // Remove this message's Uid locally mMessageUids.remove(messageToDelete.getUid()); - MessagingController.getInstance(getApplication()).deleteMessage( + MessagingController.getInstance(getApplication()).deleteMessages( accountForDelete, folderForDelete, - messageToDelete, + new Message[] { messageToDelete }, null); if (mNextMessageUid != null) { diff --git a/src/com/android/email/mail/Folder.java b/src/com/android/email/mail/Folder.java index c59c628f6..1c3bf59ff 100644 --- a/src/com/android/email/mail/Folder.java +++ b/src/com/android/email/mail/Folder.java @@ -102,6 +102,15 @@ public abstract class Folder public void copyMessages(Message[] msgs, Folder folder) throws MessagingException {} ; public void moveMessages(Message[] msgs, Folder folder) throws MessagingException {} ; + + public void delete(Message[] msgs, String trashFolderName) throws MessagingException + { + for (Message message : msgs) + { + Message myMessage = getMessage(message.getUid()); + myMessage.delete(trashFolderName); + } + } public abstract void setFlags(Message[] messages, Flag[] flags, boolean value) throws MessagingException; diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java index 664e861dd..7862e2708 100644 --- a/src/com/android/email/mail/store/ImapStore.java +++ b/src/com/android/email/mail/store/ImapStore.java @@ -768,6 +768,47 @@ public class ImapStore extends Store copyMessages(messages, folder); setFlags(messages, new Flag[] { Flag.DELETED }, true); } + + public void delete(Message[] messages, String trashFolderName) throws MessagingException + { + if (getName().equals(trashFolderName)) + { + setFlags(messages, new Flag[] { Flag.DELETED }, true); + expunge(); + } + else + { + ImapFolder remoteTrashFolder = (ImapFolder)getStore().getFolder(trashFolderName); + /* + * Attempt to copy the remote message to the remote trash folder. + */ + remoteTrashFolder.mExists = false; // Force redetection of Trash folder; some desktops delete it + if (!remoteTrashFolder.exists()) + { + /* + * If the remote trash folder doesn't exist we try to create it. + */ + Log.i(Email.LOG_TAG, "IMAPMessage.delete: attempting to create remote '" + trashFolderName + "' folder for " + getLogId()); + remoteTrashFolder.create(FolderType.HOLDS_MESSAGES); + } + + if (remoteTrashFolder.exists()) + { + if (Email.DEBUG) + { + Log.d(Email.LOG_TAG, "IMAPMessage.delete: copying remote " + messages.length + " messages to '" + trashFolderName + "' for " + getLogId()); + } + moveMessages(messages, remoteTrashFolder); + expunge(); + } + else + { + throw new MessagingException("IMAPMessage.delete: remote Trash folder " + trashFolderName + " does not exist and could not be created for " + getLogId() + , true); + } + } + } + @Override public int getMessageCount() @@ -2256,46 +2297,8 @@ public class ImapStore extends Store @Override public void delete(String trashFolderName) throws MessagingException { - ImapFolder iFolder = (ImapFolder)getFolder(); - if (iFolder.getName().equals(trashFolderName)) - { - setFlag(Flag.DELETED, true); - iFolder.expunge(); - } - else - { - ImapFolder remoteTrashFolder = (ImapFolder)iFolder.getStore().getFolder(trashFolderName); - /* - * Attempt to copy the remote message to the remote trash folder. - */ - remoteTrashFolder.mExists = false; // Force redetection of Trash folder; some desktops delete it - if (!remoteTrashFolder.exists()) - { - /* - * If the remote trash folder doesn't exist we try to create it. - */ - Log.i(Email.LOG_TAG, "IMAPMessage.delete: attempting to create remote '" + trashFolderName + "' folder for " + iFolder.getLogId()); - remoteTrashFolder.create(FolderType.HOLDS_MESSAGES); - } - - if (remoteTrashFolder.exists()) - { - if (Email.DEBUG) - { - Log.d(Email.LOG_TAG, "IMAPMessage.delete: copying remote message to '" + trashFolderName + "' for " + iFolder.getLogId()); - } - iFolder.copyMessages(new Message[] { this }, remoteTrashFolder); - setFlag(Flag.DELETED, true); - iFolder.expunge(); - } - else - { - throw new MessagingException("IMAPMessage.delete: remote Trash folder " + trashFolderName + " does not exist and could not be created for " + iFolder.getLogId() - , true); - } - } + getFolder().delete(new Message[] { this }, trashFolderName); } - } class ImapBodyPart extends MimeBodyPart