From 9fd722d7cd98b0af2fe5898f09080b317c26fd8e Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Fri, 12 Dec 2014 03:23:32 +0000 Subject: [PATCH] Split message code into Local/Remote The remote network code does not need to be aware of concepts like Accounts etc. --- src/com/fsck/k9/Account.java | 8 +- src/com/fsck/k9/Preferences.java | 3 +- src/com/fsck/k9/activity/Accounts.java | 10 +- src/com/fsck/k9/activity/MessageCompose.java | 30 ++- .../fsck/k9/activity/MessageInfoHolder.java | 5 +- src/com/fsck/k9/activity/MessageList.java | 12 +- .../fsck/k9/activity/MessageReference.java | 8 +- .../k9/activity/setup/AccountSetupBasics.java | 4 +- .../activity/setup/AccountSetupIncoming.java | 5 +- src/com/fsck/k9/cache/EmailProviderCache.java | 10 +- .../controller/MessageRetrievalListener.java | 4 +- .../k9/controller/MessagingController.java | 86 ++++--- .../fsck/k9/controller/MessagingListener.java | 25 +-- .../fsck/k9/fragment/MessageListFragment.java | 163 +++++++------- .../fsck/k9/fragment/MessageViewFragment.java | 11 +- src/com/fsck/k9/helper/MessageHelper.java | 16 +- src/com/fsck/k9/mail/Folder.java | 30 +-- src/com/fsck/k9/mail/Message.java | 13 +- src/com/fsck/k9/mail/Store.java | 209 +----------------- .../k9/mail/store/ImapResponseParser.java | 2 +- src/com/fsck/k9/mail/store/ImapStore.java | 74 +++---- src/com/fsck/k9/mail/store/Pop3Store.java | 40 ++-- src/com/fsck/k9/mail/store/RemoteStore.java | 122 ++++++++++ src/com/fsck/k9/mail/store/StoreConfig.java | 32 +++ src/com/fsck/k9/mail/store/WebDavStore.java | 41 ++-- .../fsck/k9/mail/store/local/LocalFolder.java | 67 ++++-- .../k9/mail/store/local/LocalMessage.java | 43 +++- .../fsck/k9/mail/store/local/LocalStore.java | 82 ++++++- .../fsck/k9/mail/transport/SmtpTransport.java | 3 +- .../k9/mail/transport/WebDavTransport.java | 10 +- .../fsck/k9/preferences/SettingsExporter.java | 4 +- .../fsck/k9/preferences/SettingsImporter.java | 4 +- .../fsck/k9/provider/AttachmentProvider.java | 4 +- src/com/fsck/k9/provider/MessageProvider.java | 21 +- .../k9/service/NotificationActionService.java | 8 +- .../fsck/k9/mail/store/ImapStoreUriTest.java | 21 +- 36 files changed, 641 insertions(+), 589 deletions(-) create mode 100644 src/com/fsck/k9/mail/store/RemoteStore.java create mode 100644 src/com/fsck/k9/mail/store/StoreConfig.java diff --git a/src/com/fsck/k9/Account.java b/src/com/fsck/k9/Account.java index 54a04197a..d7413b6d1 100644 --- a/src/com/fsck/k9/Account.java +++ b/src/com/fsck/k9/Account.java @@ -29,6 +29,8 @@ import com.fsck.k9.mail.Address; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.Store; import com.fsck.k9.mail.Folder.FolderClass; +import com.fsck.k9.mail.store.RemoteStore; +import com.fsck.k9.mail.store.StoreConfig; import com.fsck.k9.mail.store.StorageManager; import com.fsck.k9.mail.store.StorageManager.StorageProvider; import com.fsck.k9.mail.store.local.LocalStore; @@ -48,7 +50,7 @@ import com.larswerkman.colorpicker.ColorPicker; * Account stores all of the settings for a single account defined by the user. It is able to save * and delete itself given a Preferences to work with. Each account is defined by a UUID. */ -public class Account implements BaseAccount { +public class Account implements BaseAccount, StoreConfig { /** * Default value for the inbox folder (never changes for POP3 and IMAP) */ @@ -1289,11 +1291,11 @@ public class Account implements BaseAccount { } public LocalStore getLocalStore() throws MessagingException { - return Store.getLocalInstance(this, K9.app); + return LocalStore.getInstance(this, K9.app); } public Store getRemoteStore() throws MessagingException { - return Store.getRemoteInstance(this); + return RemoteStore.getInstance(this); } // It'd be great if this actually went into the store implementation diff --git a/src/com/fsck/k9/Preferences.java b/src/com/fsck/k9/Preferences.java index 5fd4929a3..6504626a2 100644 --- a/src/com/fsck/k9/Preferences.java +++ b/src/com/fsck/k9/Preferences.java @@ -14,6 +14,7 @@ import android.content.SharedPreferences; import android.util.Log; import com.fsck.k9.mail.Store; +import com.fsck.k9.mail.store.local.LocalStore; import com.fsck.k9.preferences.Editor; import com.fsck.k9.preferences.Storage; @@ -121,7 +122,7 @@ public class Preferences { accountsInOrder.remove(account); } - Store.removeAccount(account); + LocalStore.removeAccount(account); account.deleteCertificates(); account.delete(this); diff --git a/src/com/fsck/k9/activity/Accounts.java b/src/com/fsck/k9/activity/Accounts.java index 738ee32a3..5b7a757ae 100644 --- a/src/com/fsck/k9/activity/Accounts.java +++ b/src/com/fsck/k9/activity/Accounts.java @@ -5,7 +5,6 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.EnumSet; import java.util.HashSet; @@ -76,12 +75,11 @@ import com.fsck.k9.activity.setup.Prefs; import com.fsck.k9.activity.setup.WelcomeMessage; import com.fsck.k9.controller.MessagingController; import com.fsck.k9.helper.SizeFormatter; -import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.AuthType; import com.fsck.k9.mail.ServerSettings; -import com.fsck.k9.mail.Store; import com.fsck.k9.mail.Transport; import com.fsck.k9.mail.internet.MimeUtility; +import com.fsck.k9.mail.store.RemoteStore; import com.fsck.k9.mail.store.StorageManager; import com.fsck.k9.mail.store.WebDavStore; import com.fsck.k9.preferences.SettingsExporter; @@ -771,7 +769,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener { } private void show(final Accounts activity, boolean restore) { - ServerSettings incoming = Store.decodeStoreUri(mAccount.getStoreUri()); + ServerSettings incoming = RemoteStore.decodeStoreUri(mAccount.getStoreUri()); ServerSettings outgoing = Transport.decodeTransportUri(mAccount.getTransportUri()); /* @@ -992,9 +990,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener { if (mIncomingPassword != null) { // Set incoming server password String storeUri = mAccount.getStoreUri(); - ServerSettings incoming = Store.decodeStoreUri(storeUri); + ServerSettings incoming = RemoteStore.decodeStoreUri(storeUri); ServerSettings newIncoming = incoming.newPassword(mIncomingPassword); - String newStoreUri = Store.createStoreUri(newIncoming); + String newStoreUri = RemoteStore.createStoreUri(newIncoming); mAccount.setStoreUri(newStoreUri); } diff --git a/src/com/fsck/k9/activity/MessageCompose.java b/src/com/fsck/k9/activity/MessageCompose.java index 141399bcc..2e6bacf99 100644 --- a/src/com/fsck/k9/activity/MessageCompose.java +++ b/src/com/fsck/k9/activity/MessageCompose.java @@ -108,6 +108,7 @@ import com.fsck.k9.mail.internet.MimeUtility; import com.fsck.k9.mail.internet.TextBody; import com.fsck.k9.mail.internet.TextBodyBuilder; import com.fsck.k9.mail.store.local.LocalAttachmentBody; +import com.fsck.k9.mail.store.local.LocalMessage; import com.fsck.k9.mail.store.local.TempFileBody; import com.fsck.k9.mail.store.local.TempFileMessageBody; import com.fsck.k9.view.MessageWebView; @@ -435,17 +436,15 @@ public class MessageCompose extends K9Activity implements OnClickListener, * Get intent for composing a new message as a reply to the given message. If replyAll is true * the function is reply all instead of simply reply. * @param context - * @param account * @param message * @param replyAll * @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message */ public static Intent getActionReplyIntent( - Context context, - Account account, - Message message, - boolean replyAll, - String messageBody) { + Context context, + Message message, + boolean replyAll, + String messageBody) { Intent i = new Intent(context, MessageCompose.class); i.putExtra(EXTRA_MESSAGE_BODY, messageBody); i.putExtra(EXTRA_MESSAGE_REFERENCE, message.makeMessageReference()); @@ -468,25 +467,22 @@ public class MessageCompose extends K9Activity implements OnClickListener, */ public static void actionReply( Context context, - Account account, Message message, boolean replyAll, String messageBody) { - context.startActivity(getActionReplyIntent(context, account, message, replyAll, messageBody)); + context.startActivity(getActionReplyIntent(context, message, replyAll, messageBody)); } /** * Compose a new message as a forward of the given message. * @param context - * @param account * @param message * @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message */ public static void actionForward( - Context context, - Account account, - Message message, - String messageBody) { + Context context, + Message message, + String messageBody) { Intent i = new Intent(context, MessageCompose.class); i.putExtra(EXTRA_MESSAGE_BODY, messageBody); i.putExtra(EXTRA_MESSAGE_REFERENCE, message.makeMessageReference()); @@ -2646,7 +2642,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, * @param message * The source message used to populate the various text fields. */ - private void processSourceMessage(Message message) { + private void processSourceMessage(LocalMessage message) { try { switch (mAction) { case REPLY: @@ -2800,7 +2796,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, } } - private void processDraftMessage(Message message) throws MessagingException { + private void processDraftMessage(LocalMessage message) throws MessagingException { String showQuotedTextMode = "NONE"; mDraftId = MessagingController.getInstance(getApplication()).getId(message); @@ -2852,7 +2848,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, newIdentity.setSignature(k9identity.get(IdentityField.SIGNATURE)); mSignatureChanged = true; } else { - newIdentity.setSignatureUse(message.getFolder().getAccount().getSignatureUse()); + newIdentity.setSignatureUse(message.getFolder().getSignatureUse()); newIdentity.setSignature(mIdentity.getSignature()); } @@ -3437,7 +3433,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, } updateMessageFormat(); } else { - processSourceMessage(message); + processSourceMessage((LocalMessage) message); mSourceProcessed = true; } } diff --git a/src/com/fsck/k9/activity/MessageInfoHolder.java b/src/com/fsck/k9/activity/MessageInfoHolder.java index eecf4f80d..e217a0f78 100644 --- a/src/com/fsck/k9/activity/MessageInfoHolder.java +++ b/src/com/fsck/k9/activity/MessageInfoHolder.java @@ -2,6 +2,7 @@ package com.fsck.k9.activity; import java.util.Date; import com.fsck.k9.mail.Message; +import com.fsck.k9.mail.store.local.LocalMessage; public class MessageInfoHolder { public String date; @@ -18,7 +19,7 @@ public class MessageInfoHolder { public boolean forwarded; public boolean flagged; public boolean dirty; - public Message message; + public LocalMessage message; public FolderInfoHolder folder; public boolean selected; public String account; @@ -31,7 +32,7 @@ public class MessageInfoHolder { @Override public boolean equals(Object o) { - if (o instanceof MessageInfoHolder == false) { + if (!(o instanceof MessageInfoHolder)) { return false; } MessageInfoHolder other = (MessageInfoHolder)o; diff --git a/src/com/fsck/k9/activity/MessageList.java b/src/com/fsck/k9/activity/MessageList.java index 25306140f..765d03673 100644 --- a/src/com/fsck/k9/activity/MessageList.java +++ b/src/com/fsck/k9/activity/MessageList.java @@ -1199,17 +1199,17 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme @Override public void onForward(Message message) { - MessageCompose.actionForward(this, message.getFolder().getAccount(), message, null); + MessageCompose.actionForward(this, message, null); } @Override public void onReply(Message message) { - MessageCompose.actionReply(this, message.getFolder().getAccount(), message, false, null); + MessageCompose.actionReply(this, message, false, null); } @Override public void onReplyAll(Message message) { - MessageCompose.actionReply(this, message.getFolder().getAccount(), message, true, null); + MessageCompose.actionReply(this, message, true, null); } @Override @@ -1400,17 +1400,17 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme @Override public void onReply(Message message, PgpData pgpData) { - MessageCompose.actionReply(this, mAccount, message, false, pgpData.getDecryptedData()); + MessageCompose.actionReply(this, message, false, pgpData.getDecryptedData()); } @Override public void onReplyAll(Message message, PgpData pgpData) { - MessageCompose.actionReply(this, mAccount, message, true, pgpData.getDecryptedData()); + MessageCompose.actionReply(this, message, true, pgpData.getDecryptedData()); } @Override public void onForward(Message mMessage, PgpData mPgpData) { - MessageCompose.actionForward(this, mAccount, mMessage, mPgpData.getDecryptedData()); + MessageCompose.actionForward(this, mMessage, mPgpData.getDecryptedData()); } @Override diff --git a/src/com/fsck/k9/activity/MessageReference.java b/src/com/fsck/k9/activity/MessageReference.java index 990d99774..bb2d6264d 100644 --- a/src/com/fsck/k9/activity/MessageReference.java +++ b/src/com/fsck/k9/activity/MessageReference.java @@ -13,6 +13,8 @@ import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.Message; import com.fsck.k9.mail.MessagingException; +import com.fsck.k9.mail.store.local.LocalFolder; +import com.fsck.k9.mail.store.local.LocalMessage; import java.util.StringTokenizer; @@ -128,13 +130,13 @@ public class MessageReference implements Parcelable { '}'; } - public Message restoreToLocalMessage(Context context) { + public LocalMessage restoreToLocalMessage(Context context) { try { Account account = Preferences.getPreferences(context).getAccount(accountUuid); if (account != null) { - Folder folder = account.getLocalStore().getFolder(folderName); + LocalFolder folder = account.getLocalStore().getFolder(folderName); if (folder != null) { - Message message = folder.getMessage(uid); + LocalMessage message = folder.getMessage(uid); if (message != null) { return message; } else { diff --git a/src/com/fsck/k9/activity/setup/AccountSetupBasics.java b/src/com/fsck/k9/activity/setup/AccountSetupBasics.java index 56d409743..eab3db5fd 100644 --- a/src/com/fsck/k9/activity/setup/AccountSetupBasics.java +++ b/src/com/fsck/k9/activity/setup/AccountSetupBasics.java @@ -38,9 +38,9 @@ import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.AuthType; import com.fsck.k9.mail.ConnectionSecurity; import com.fsck.k9.mail.ServerSettings; -import com.fsck.k9.mail.Store; import com.fsck.k9.mail.Transport; import com.fsck.k9.mail.store.ImapStore; +import com.fsck.k9.mail.store.RemoteStore; import com.fsck.k9.mail.transport.SmtpTransport; import com.fsck.k9.view.ClientCertificateSpinner; import com.fsck.k9.view.ClientCertificateSpinner.OnClientCertificateChangedListener; @@ -421,7 +421,7 @@ public class AccountSetupBasics extends K9Activity ConnectionSecurity.SSL_TLS_REQUIRED, authenticationType, user, password, clientCertificateAlias); ServerSettings transportServer = new ServerSettings(SmtpTransport.TRANSPORT_TYPE, "mail." + domain, -1, ConnectionSecurity.SSL_TLS_REQUIRED, authenticationType, user, password, clientCertificateAlias); - String storeUri = Store.createStoreUri(storeServer); + String storeUri = RemoteStore.createStoreUri(storeServer); String transportUri = Transport.createTransportUri(transportServer); mAccount.setStoreUri(storeUri); mAccount.setTransportUri(transportUri); diff --git a/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java b/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java index ff4cd531b..5d417309f 100644 --- a/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java +++ b/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java @@ -27,6 +27,7 @@ import com.fsck.k9.mail.Store; import com.fsck.k9.mail.Transport; import com.fsck.k9.mail.store.ImapStore; import com.fsck.k9.mail.store.Pop3Store; +import com.fsck.k9.mail.store.RemoteStore; import com.fsck.k9.mail.store.WebDavStore; import com.fsck.k9.mail.store.ImapStore.ImapStoreSettings; import com.fsck.k9.mail.store.WebDavStore.WebDavStoreSettings; @@ -163,7 +164,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener } try { - ServerSettings settings = Store.decodeStoreUri(mAccount.getStoreUri()); + ServerSettings settings = RemoteStore.decodeStoreUri(mAccount.getStoreUri()); if (savedInstanceState == null) { // The first item is selected if settings.authenticationType is null or is not in mAuthTypeAdapter @@ -610,7 +611,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener ServerSettings settings = new ServerSettings(mStoreType, host, port, connectionSecurity, authType, username, password, clientCertificateAlias, extra); - mAccount.setStoreUri(Store.createStoreUri(settings)); + mAccount.setStoreUri(RemoteStore.createStoreUri(settings)); mAccount.setCompression(Account.TYPE_MOBILE, mCompressionMobile.isChecked()); mAccount.setCompression(Account.TYPE_WIFI, mCompressionWifi.isChecked()); diff --git a/src/com/fsck/k9/cache/EmailProviderCache.java b/src/com/fsck/k9/cache/EmailProviderCache.java index 9b3e7d5e0..ccd712d12 100644 --- a/src/com/fsck/k9/cache/EmailProviderCache.java +++ b/src/com/fsck/k9/cache/EmailProviderCache.java @@ -123,13 +123,11 @@ public class EmailProviderCache { } } - public void hideMessages(List messages) { + public void hideMessages(List messages) { synchronized (mHiddenMessageCache) { - for (Message message : messages) { - LocalMessage localMessage = (LocalMessage) message; - long messageId = localMessage.getId(); - long folderId = ((LocalFolder) localMessage.getFolder()).getId(); - mHiddenMessageCache.put(messageId, folderId); + for (LocalMessage message : messages) { + long messageId = message.getId(); + mHiddenMessageCache.put(messageId, message.getFolder().getId()); } } diff --git a/src/com/fsck/k9/controller/MessageRetrievalListener.java b/src/com/fsck/k9/controller/MessageRetrievalListener.java index 24ecb52e2..6af8714af 100644 --- a/src/com/fsck/k9/controller/MessageRetrievalListener.java +++ b/src/com/fsck/k9/controller/MessageRetrievalListener.java @@ -3,10 +3,10 @@ package com.fsck.k9.controller; import com.fsck.k9.mail.Message; -public interface MessageRetrievalListener { +public interface MessageRetrievalListener { public void messageStarted(String uid, int number, int ofTotal); - public void messageFinished(Message message, int number, int ofTotal); + public void messageFinished(T message, int number, int ofTotal); /** * FIXME this method is almost never invoked by various Stores! Don't rely on it unless fixed!! diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 7f889650b..d776c5fb3 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -312,7 +312,7 @@ public class MessagingController implements Runnable { private static final Set SYNC_FLAGS = EnumSet.of(Flag.SEEN, Flag.FLAGGED, Flag.ANSWERED, Flag.FORWARDED); - private void suppressMessages(Account account, List messages) { + private void suppressMessages(Account account, List messages) { EmailProviderCache cache = EmailProviderCache.getCache(account.getUuid(), mApplication.getApplicationContext()); cache.hideMessages(messages); @@ -324,13 +324,11 @@ public class MessagingController implements Runnable { cache.unhideMessages(messages); } - private boolean isMessageSuppressed(Account account, Message message) { - LocalMessage localMessage = (LocalMessage) message; - String accountUuid = account.getUuid(); - long messageId = localMessage.getId(); - long folderId = ((LocalFolder) localMessage.getFolder()).getId(); + private boolean isMessageSuppressed(LocalMessage message) { + long messageId = message.getId(); + long folderId = message.getFolder().getId(); - EmailProviderCache cache = EmailProviderCache.getCache(accountUuid, + EmailProviderCache cache = EmailProviderCache.getCache(message.getFolder().getUuid(), mApplication.getApplicationContext()); return cache.isMessageHidden(messageId, folderId); } @@ -690,15 +688,15 @@ public class MessagingController implements Runnable { } // Collecting statistics of the search result - MessageRetrievalListener retrievalListener = new MessageRetrievalListener() { + MessageRetrievalListener retrievalListener = new MessageRetrievalListener() { @Override public void messageStarted(String message, int number, int ofTotal) {} @Override public void messagesFinished(int number) {} @Override - public void messageFinished(Message message, int number, int ofTotal) { - if (!isMessageSuppressed(message.getFolder().getAccount(), message)) { - List messages = new ArrayList(); + public void messageFinished(LocalMessage message, int number, int ofTotal) { + if (!isMessageSuppressed(message)) { + List messages = new ArrayList(); messages.add(message); stats.unreadMessageCount += (!message.isSet(Flag.SEEN)) ? 1 : 0; @@ -762,7 +760,7 @@ public class MessagingController implements Runnable { final Account acct = Preferences.getPreferences(mApplication.getApplicationContext()).getAccount(acctUuid); if (listener != null) { - listener.remoteSearchStarted(acct, folderName); + listener.remoteSearchStarted(folderName); } List extraResults = new ArrayList(); @@ -791,7 +789,7 @@ public class MessagingController implements Runnable { messages.clear(); if (listener != null) { - listener.remoteSearchServerQueryComplete(acct, folderName, remoteMessages.size()); + listener.remoteSearchServerQueryComplete(folderName, remoteMessages.size(), acct.getRemoteSearchNumResults()); } Collections.sort(remoteMessages, new UidReverseComparator()); @@ -811,13 +809,13 @@ public class MessagingController implements Runnable { } else { Log.e(K9.LOG_TAG, "Could not complete remote search", e); if (listener != null) { - listener.remoteSearchFailed(acct, null, e.getMessage()); + listener.remoteSearchFailed(null, e.getMessage()); } addErrorMessage(acct, null, e); } } finally { if (listener != null) { - listener.remoteSearchFinished(acct, folderName, 0, extraResults); + listener.remoteSearchFinished(folderName, 0, acct.getRemoteSearchNumResults(), extraResults); } } @@ -878,7 +876,7 @@ public class MessagingController implements Runnable { } if (listener != null) { - listener.remoteSearchAddMessage(remoteFolder.getAccount(), remoteFolder.getName(), localMsg, i, messages.size()); + listener.remoteSearchAddMessage(remoteFolder.getName(), localMsg, i, messages.size()); } } } @@ -1455,7 +1453,7 @@ public class MessagingController implements Runnable { } } - private void fetchUnsyncedMessages(final Account account, final Folder remoteFolder, + private void fetchUnsyncedMessages(final Account account, final Folder remoteFolder, final LocalFolder localFolder, List unsyncedMessages, final List smallMessages, @@ -1473,9 +1471,9 @@ public class MessagingController implements Runnable { final List chunk = new ArrayList(UNSYNC_CHUNK_SIZE); remoteFolder.fetch(unsyncedMessages, fp, - new MessageRetrievalListener() { + new MessageRetrievalListener() { @Override - public void messageFinished(Message message, int number, int ofTotal) { + public void messageFinished(T message, int number, int ofTotal) { try { String newPushState = remoteFolder.getNewPushState(localFolder.getPushState(), message); if (newPushState != null) { @@ -1564,7 +1562,7 @@ public class MessagingController implements Runnable { localFolder.appendMessages(messages); for (final Message message : messages) { - final Message localMessage = localFolder.getMessage(message.getUid()); + final LocalMessage localMessage = localFolder.getMessage(message.getUid()); syncFlags(localMessage, message); if (K9.DEBUG) Log.v(K9.LOG_TAG, "About to notify listeners that we got a new unsynced message " @@ -1592,9 +1590,9 @@ public class MessagingController implements Runnable { return true; } - private void downloadSmallMessages(final Account account, final Folder remoteFolder, + private void downloadSmallMessages(final Account account, final Folder remoteFolder, final LocalFolder localFolder, - List smallMessages, + List smallMessages, final AtomicInteger progress, final int unreadBeforeStart, final AtomicInteger newMessages, @@ -1608,9 +1606,9 @@ public class MessagingController implements Runnable { Log.d(K9.LOG_TAG, "SYNC: Fetching small messages for folder " + folder); remoteFolder.fetch(smallMessages, - fp, new MessageRetrievalListener() { + fp, new MessageRetrievalListener() { @Override - public void messageFinished(final Message message, int number, int ofTotal) { + public void messageFinished(final T message, int number, int ofTotal) { try { if (!shouldImportMessage(account, folder, message, progress, earliestDate)) { @@ -1671,9 +1669,9 @@ public class MessagingController implements Runnable { - private void downloadLargeMessages(final Account account, final Folder remoteFolder, + private void downloadLargeMessages(final Account account, final Folder remoteFolder, final LocalFolder localFolder, - List largeMessages, + List largeMessages, final AtomicInteger progress, final int unreadBeforeStart, final AtomicInteger newMessages, @@ -1821,11 +1819,11 @@ public class MessagingController implements Runnable { remoteFolder.fetch(undeletedMessages, fp, null); for (Message remoteMessage : syncFlagMessages) { - Message localMessage = localFolder.getMessage(remoteMessage.getUid()); + LocalMessage localMessage = localFolder.getMessage(remoteMessage.getUid()); boolean messageChanged = syncFlags(localMessage, remoteMessage); if (messageChanged) { boolean shouldBeNotifiedOf = false; - if (localMessage.isSet(Flag.DELETED) || isMessageSuppressed(account, localMessage)) { + if (localMessage.isSet(Flag.DELETED) || isMessageSuppressed(localMessage)) { for (MessagingListener l : getListeners()) { l.synchronizeMailboxRemovedMessage(account, folder, localMessage); } @@ -1859,13 +1857,13 @@ public class MessagingController implements Runnable { } } - private boolean syncFlags(Message localMessage, Message remoteMessage) throws MessagingException { + private boolean syncFlags(LocalMessage localMessage, Message remoteMessage) throws MessagingException { boolean messageChanged = false; if (localMessage == null || localMessage.isSet(Flag.DELETED)) { return false; } if (remoteMessage.isSet(Flag.DELETED)) { - if (localMessage.getFolder().getAccount().syncRemoteDeletions()) { + if (localMessage.getFolder().syncRemoteDeletions()) { localMessage.setFlag(Flag.DELETED, true); messageChanged = true; } @@ -2857,7 +2855,7 @@ public class MessagingController implements Runnable { * @param newState * {@code true}, if the flag should be set. {@code false} if it should be removed. */ - public void setFlag(Account account, String folderName, List messages, Flag flag, + public void setFlag(Account account, String folderName, List messages, Flag flag, boolean newState) { // TODO: Put this into the background, but right now some callers depend on the message // objects being modified right after this method returns. @@ -3775,7 +3773,7 @@ public class MessagingController implements Runnable { } } public void moveMessages(final Account account, final String srcFolder, - final List messages, final String destFolder, + final List messages, final String destFolder, final MessagingListener listener) { suppressMessages(account, messages); @@ -3790,7 +3788,7 @@ public class MessagingController implements Runnable { } public void moveMessagesInThread(final Account account, final String srcFolder, - final List messages, final String destFolder) { + final List messages, final String destFolder) { suppressMessages(account, messages); @@ -3808,14 +3806,14 @@ public class MessagingController implements Runnable { }); } - public void moveMessage(final Account account, final String srcFolder, final Message message, + public void moveMessage(final Account account, final String srcFolder, final LocalMessage message, final String destFolder, final MessagingListener listener) { moveMessages(account, srcFolder, Collections.singletonList(message), destFolder, listener); } public void copyMessages(final Account account, final String srcFolder, - final List messages, final String destFolder, + final List messages, final String destFolder, final MessagingListener listener) { putBackground("copyMessages", null, new Runnable() { @@ -3828,7 +3826,7 @@ public class MessagingController implements Runnable { } public void copyMessagesInThread(final Account account, final String srcFolder, - final List messages, final String destFolder) { + final List messages, final String destFolder) { putBackground("copyMessagesInThread", null, new Runnable() { @Override @@ -3851,7 +3849,7 @@ public class MessagingController implements Runnable { } private void moveOrCopyMessageSynchronous(final Account account, final String srcFolder, - final List inMessages, final String destFolder, final boolean isCopy, + final List inMessages, final String destFolder, final boolean isCopy, MessagingListener listener) { try { @@ -3962,7 +3960,7 @@ public class MessagingController implements Runnable { localFolder.open(Folder.OPEN_MODE_RW); String uid = localFolder.getMessageUidById(id); if (uid != null) { - Message message = localFolder.getMessage(uid); + LocalMessage message = localFolder.getMessage(uid); if (message != null) { deleteMessages(Collections.singletonList(message), null); } @@ -3974,7 +3972,7 @@ public class MessagingController implements Runnable { } } - public void deleteThreads(final List messages) { + public void deleteThreads(final List messages) { actOnMessages(messages, new MessageActor() { @Override @@ -4006,7 +4004,7 @@ public class MessagingController implements Runnable { } } - public List collectMessagesInThreads(Account account, List messages) + public List collectMessagesInThreads(Account account, List messages) throws MessagingException { LocalStore localStore = account.getLocalStore(); @@ -4025,7 +4023,7 @@ public class MessagingController implements Runnable { return messagesInThreads; } - public void deleteMessages(final List messages, final MessagingListener listener) { + public void deleteMessages(final List messages, final MessagingListener listener) { actOnMessages(messages, new MessageActor() { @Override @@ -5685,15 +5683,15 @@ public class MessagingController implements Runnable { } - private void actOnMessages(List messages, MessageActor actor) { + private void actOnMessages(List messages, MessageActor actor) { Map>> accountMap = new HashMap>>(); - for (Message message : messages) { + for (LocalMessage message : messages) { if ( message == null) { continue; } Folder folder = message.getFolder(); - Account account = folder.getAccount(); + Account account = message.getAccount(); Map> folderMap = accountMap.get(account); if (folderMap == null) { diff --git a/src/com/fsck/k9/controller/MessagingListener.java b/src/com/fsck/k9/controller/MessagingListener.java index 5c5a66f50..470cc6387 100644 --- a/src/com/fsck/k9/controller/MessagingListener.java +++ b/src/com/fsck/k9/controller/MessagingListener.java @@ -11,6 +11,7 @@ import com.fsck.k9.BaseAccount; import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.Message; import com.fsck.k9.mail.Part; +import com.fsck.k9.mail.store.local.LocalMessage; /** * Defines the interface that {@link MessagingController} will use to callback to requesters. @@ -42,10 +43,8 @@ public class MessagingListener { public void listLocalMessagesStarted(Account account, String folder) {} - public void listLocalMessages(Account account, String folder, Message[] messages) {} - public void listLocalMessagesAddMessages(Account account, String folder, - List messages) {} + List messages) {} public void listLocalMessagesUpdateMessage(Account account, String folder, Message message) {} @@ -156,10 +155,9 @@ public class MessagingListener { /** * Called when a remote search is started * - * @param acct * @param folder */ - public void remoteSearchStarted(Account acct, String folder) {} + public void remoteSearchStarted(String folder) {} /** @@ -167,35 +165,30 @@ public class MessagingListener { * * @param numResults */ - public void remoteSearchServerQueryComplete(Account account, String folderName, int numResults) { } + public void remoteSearchServerQueryComplete(String folderName, int numResults, int maxResults) { } /** * Called when a new result message is available for a remote search * Can assume headers have been downloaded, but potentially not body. - * @param account * @param folder * @param message */ - public void remoteSearchAddMessage(Account account, String folder, Message message, int numDone, int numTotal) { } + public void remoteSearchAddMessage(String folder, Message message, int numDone, int numTotal) { } /** * Called when Remote Search is fully complete - * - * @param acct - * @param folder + * @param folder * @param numResults */ - public void remoteSearchFinished(Account acct, String folder, int numResults, List extraResults) {} + public void remoteSearchFinished(String folder, int numResults, int maxResults, List extraResults) {} /** * Called when there was a problem with a remote search operation. - * - * @param acct - * @param folder + * @param folder * @param err */ - public void remoteSearchFailed(Account acct, String folder, String err) { } + public void remoteSearchFailed(String folder, String err) { } /** * General notification messages subclasses can override to be notified that the controller diff --git a/src/com/fsck/k9/fragment/MessageListFragment.java b/src/com/fsck/k9/fragment/MessageListFragment.java index 80b19b33a..48e5b6190 100644 --- a/src/com/fsck/k9/fragment/MessageListFragment.java +++ b/src/com/fsck/k9/fragment/MessageListFragment.java @@ -89,6 +89,7 @@ import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.Message; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.store.local.LocalFolder; +import com.fsck.k9.mail.store.local.LocalMessage; import com.fsck.k9.mail.store.local.LocalStore; import com.fsck.k9.provider.EmailProvider; import com.fsck.k9.provider.EmailProvider.MessageColumns; @@ -427,7 +428,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * Relevant messages for the current context when we have to remember the chosen messages * between user interactions (e.g. selecting a folder for move operation). */ - private List mActiveMessages; + private List mActiveMessages; /* package visibility for faster inner class access */ MessageHelper mMessageHelper; @@ -1035,7 +1036,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener return null; } - private Folder getFolderById(Account account, long folderId) { + private LocalFolder getFolderById(Account account, long folderId) { try { LocalStore localStore = account.getLocalStore(); LocalFolder localFolder = localStore.getFolderById(folderId); @@ -1309,11 +1310,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener changeSort(sorts[curIndex]); } - private void onDelete(Message message) { + private void onDelete(LocalMessage message) { onDelete(Collections.singletonList(message)); } - private void onDelete(List messages) { + private void onDelete(List messages) { if (K9.confirmDelete()) { // remember the message selection for #onCreateDialog(int) mActiveMessages = messages; @@ -1323,7 +1324,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } } - private void onDeleteConfirmed(List messages) { + private void onDeleteConfirmed(List messages) { if (mThreadedList) { mController.deleteThreads(messages); } else { @@ -1345,15 +1346,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } final String destFolderName = data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER); - final List messages = mActiveMessages; + final List messages = mActiveMessages; if (destFolderName != null) { mActiveMessages = null; // don't need it any more if (messages.size() > 0) { - Account account = messages.get(0).getFolder().getAccount(); - account.setLastSelectedFolderName(destFolderName); + messages.get(0).getFolder().setLastSelectedFolderName(destFolderName); } switch (requestCode) { @@ -1539,7 +1539,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener break; } case R.id.delete: { - Message message = getMessageAtPosition(adapterPosition); + LocalMessage message = getMessageAtPosition(adapterPosition); onDelete(message); break; } @@ -1562,23 +1562,19 @@ public class MessageListFragment extends Fragment implements OnItemClickListener // only if the account supports this case R.id.archive: { - Message message = getMessageAtPosition(adapterPosition); - onArchive(message); + onArchive(getMessageAtPosition(adapterPosition)); break; } case R.id.spam: { - Message message = getMessageAtPosition(adapterPosition); - onSpam(message); + onSpam(getMessageAtPosition(adapterPosition)); break; } case R.id.move: { - Message message = getMessageAtPosition(adapterPosition); - onMove(message); + onMove(getMessageAtPosition(adapterPosition)); break; } case R.id.copy: { - Message message = getMessageAtPosition(adapterPosition); - onCopy(message); + onCopy(getMessageAtPosition(adapterPosition)); break; } } @@ -1711,7 +1707,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener class MessageListActivityListener extends ActivityListener { @Override - public void remoteSearchFailed(Account acct, String folder, final String err) { + public void remoteSearchFailed(String folder, final String err) { mHandler.post(new Runnable() { @Override public void run() { @@ -1725,7 +1721,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } @Override - public void remoteSearchStarted(Account acct, String folder) { + public void remoteSearchStarted(String folder) { mHandler.progress(true); mHandler.updateFooter(mContext.getString(R.string.remote_search_sending_query)); } @@ -1736,12 +1732,12 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } @Override - public void remoteSearchFinished(Account acct, String folder, int numResults, List extraResults) { + public void remoteSearchFinished(String folder, int numResults, int maxResults, List extraResults) { mHandler.progress(false); mHandler.remoteSearchFinished(); mExtraSearchResults = extraResults; if (extraResults != null && extraResults.size() > 0) { - mHandler.updateFooter(String.format(mContext.getString(R.string.load_more_messages_fmt), acct.getRemoteSearchNumResults())); + mHandler.updateFooter(String.format(mContext.getString(R.string.load_more_messages_fmt), maxResults)); } else { mHandler.updateFooter(""); } @@ -1750,11 +1746,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } @Override - public void remoteSearchServerQueryComplete(Account account, String folderName, int numResults) { + public void remoteSearchServerQueryComplete(String folderName, int numResults, int maxResults) { mHandler.progress(true); - if (account != null && account.getRemoteSearchNumResults() != 0 && numResults > account.getRemoteSearchNumResults()) { + if (maxResults != 0 && numResults > maxResults) { mHandler.updateFooter(mContext.getString(R.string.remote_search_downloading_limited, - account.getRemoteSearchNumResults(), numResults)); + maxResults, numResults)); } else { mHandler.updateFooter(mContext.getString(R.string.remote_search_downloading, numResults)); } @@ -2416,7 +2412,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener computeBatchDirection(); } - private void onMove(Message message) { + private void onMove(LocalMessage message) { onMove(Collections.singletonList(message)); } @@ -2426,7 +2422,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * @param messages * Never {@code null}. */ - private void onMove(List messages) { + private void onMove(List messages) { if (!checkCopyOrMovePossible(messages, FolderOperation.MOVE)) { return; } @@ -2440,12 +2436,13 @@ public class MessageListFragment extends Fragment implements OnItemClickListener folder = null; } - Account account = messages.get(0).getFolder().getAccount(); - displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_MOVE, account, folder, messages); + displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_MOVE, folder, + messages.get(0).getFolder().getUuid(), null, + messages); } - private void onCopy(Message message) { + private void onCopy(LocalMessage message) { onCopy(Collections.singletonList(message)); } @@ -2455,7 +2452,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * @param messages * Never {@code null}. */ - private void onCopy(List messages) { + private void onCopy(List messages) { if (!checkCopyOrMovePossible(messages, FolderOperation.COPY)) { return; } @@ -2469,7 +2466,10 @@ public class MessageListFragment extends Fragment implements OnItemClickListener folder = null; } - displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_COPY, mAccount, folder, messages); + displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_COPY, folder, + messages.get(0).getFolder().getUuid(), + null, + messages); } /** @@ -2486,12 +2486,13 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * * @see #startActivityForResult(Intent, int) */ - private void displayFolderChoice(int requestCode, Account account, Folder folder, - List messages) { + private void displayFolderChoice(int requestCode, Folder folder, + String accountId, String lastSelectedFolderName, + List messages) { Intent intent = new Intent(getActivity(), ChooseFolder.class); - intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, account.getUuid()); - intent.putExtra(ChooseFolder.EXTRA_SEL_FOLDER, account.getLastSelectedFolderName()); + intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, accountId); + intent.putExtra(ChooseFolder.EXTRA_SEL_FOLDER, lastSelectedFolderName); if (folder == null) { intent.putExtra(ChooseFolder.EXTRA_SHOW_CURRENT, "yes"); @@ -2504,14 +2505,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener startActivityForResult(intent, requestCode); } - private void onArchive(final Message message) { + private void onArchive(final LocalMessage message) { onArchive(Collections.singletonList(message)); } - private void onArchive(final List messages) { - Map> messagesByAccount = groupMessagesByAccount(messages); + private void onArchive(final List messages) { + Map> messagesByAccount = groupMessagesByAccount(messages); - for (Entry> entry : messagesByAccount.entrySet()) { + for (Entry> entry : messagesByAccount.entrySet()) { Account account = entry.getKey(); String archiveFolder = account.getArchiveFolderName(); @@ -2521,14 +2522,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } } - private Map> groupMessagesByAccount(final List messages) { - Map> messagesByAccount = new HashMap>(); - for (Message message : messages) { - Account account = message.getFolder().getAccount(); + private Map> groupMessagesByAccount(final List messages) { + Map> messagesByAccount = new HashMap>(); + for (LocalMessage message : messages) { + Account account = message.getAccount(); - List msgList = messagesByAccount.get(account); + List msgList = messagesByAccount.get(account); if (msgList == null) { - msgList = new ArrayList(); + msgList = new ArrayList(); messagesByAccount.put(account, msgList); } @@ -2537,7 +2538,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener return messagesByAccount; } - private void onSpam(Message message) { + private void onSpam(LocalMessage message) { onSpam(Collections.singletonList(message)); } @@ -2547,7 +2548,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * @param messages * The messages to move to the spam folder. Never {@code null}. */ - private void onSpam(List messages) { + private void onSpam(List messages) { if (K9.confirmSpam()) { // remember the message selection for #onCreateDialog(int) mActiveMessages = messages; @@ -2557,10 +2558,10 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } } - private void onSpamConfirmed(List messages) { - Map> messagesByAccount = groupMessagesByAccount(messages); + private void onSpamConfirmed(List messages) { + Map> messagesByAccount = groupMessagesByAccount(messages); - for (Entry> entry : messagesByAccount.entrySet()) { + for (Entry> entry : messagesByAccount.entrySet()) { Account account = entry.getKey(); String spamFolder = account.getSpamFolderName(); @@ -2584,7 +2585,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * * @return {@code true}, if operation is possible. */ - private boolean checkCopyOrMovePossible(final List messages, + private boolean checkCopyOrMovePossible(final List messages, final FolderOperation operation) { if (messages.isEmpty()) { @@ -2592,11 +2593,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } boolean first = true; - for (final Message message : messages) { + for (final LocalMessage message : messages) { if (first) { first = false; // account check - final Account account = message.getFolder().getAccount(); + final Account account = message.getAccount(); if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(account)) || (operation == FolderOperation.COPY && !mController.isCopyCapable(account))) { return false; @@ -2622,7 +2623,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * @param destination * The name of the destination folder. Never {@code null}. */ - private void copy(List messages, final String destination) { + private void copy(List messages, final String destination) { copyOrMove(messages, destination, FolderOperation.COPY); } @@ -2634,7 +2635,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * @param destination * The name of the destination folder. Never {@code null}. */ - private void move(List messages, final String destination) { + private void move(List messages, final String destination) { copyOrMove(messages, destination, FolderOperation.MOVE); } @@ -2650,12 +2651,12 @@ public class MessageListFragment extends Fragment implements OnItemClickListener * @param operation * Specifies what operation to perform. Never {@code null}. */ - private void copyOrMove(List messages, final String destination, + private void copyOrMove(List messages, final String destination, final FolderOperation operation) { - Map> folderMap = new HashMap>(); + Map> folderMap = new HashMap>(); - for (Message message : messages) { + for (LocalMessage message : messages) { if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(message)) || (operation == FolderOperation.COPY && !mController.isCopyCapable(message))) { @@ -2674,19 +2675,19 @@ public class MessageListFragment extends Fragment implements OnItemClickListener continue; } - List outMessages = folderMap.get(folderName); + List outMessages = folderMap.get(folderName); if (outMessages == null) { - outMessages = new ArrayList(); + outMessages = new ArrayList(); folderMap.put(folderName, outMessages); } outMessages.add(message); } - for (Map.Entry> entry : folderMap.entrySet()) { + for (Map.Entry> entry : folderMap.entrySet()) { String folderName = entry.getKey(); - List outMessages = entry.getValue(); - Account account = outMessages.get(0).getFolder().getAccount(); + List outMessages = entry.getValue(); + Account account = outMessages.get(0).getAccount(); if (operation == FolderOperation.MOVE) { if (mThreadedList) { @@ -2859,7 +2860,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener */ switch (item.getItemId()) { case R.id.delete: { - List messages = getCheckedMessages(); + List messages = getCheckedMessages(); onDelete(messages); mSelectedCount = 0; break; @@ -2887,26 +2888,22 @@ public class MessageListFragment extends Fragment implements OnItemClickListener // only if the account supports this case R.id.archive: { - List messages = getCheckedMessages(); - onArchive(messages); + onArchive(getCheckedMessages()); mSelectedCount = 0; break; } case R.id.spam: { - List messages = getCheckedMessages(); - onSpam(messages); + onSpam(getCheckedMessages()); mSelectedCount = 0; break; } case R.id.move: { - List messages = getCheckedMessages(); - onMove(messages); + onMove(getCheckedMessages()); mSelectedCount = 0; break; } case R.id.copy: { - List messages = getCheckedMessages(); - onCopy(messages); + onCopy(getCheckedMessages()); mSelectedCount = 0; break; } @@ -2987,7 +2984,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener final Folder remoteFolder = mCurrentFolder.folder; remoteFolder.close(); // Send a remoteSearchFinished() message for good measure. - mListener.remoteSearchFinished(searchAccount, mCurrentFolder.name, 0, null); + mListener.remoteSearchFinished(mCurrentFolder.name, 0, searchAccount.getRemoteSearchNumResults(), null); } catch (Exception e) { // Since the user is going back, log and squash any exceptions. Log.e(K9.LOG_TAG, "Could not abort remote search before going back", e); @@ -3135,7 +3132,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener changeSort(mSortType); } - private Message getSelectedMessage() { + private LocalMessage getSelectedMessage() { int listViewPosition = mListView.getSelectedItemPosition(); int adapterPosition = listViewToAdapterPosition(listViewPosition); @@ -3158,7 +3155,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener return AdapterView.INVALID_POSITION; } - private Message getMessageAtPosition(int adapterPosition) { + private LocalMessage getMessageAtPosition(int adapterPosition) { if (adapterPosition == AdapterView.INVALID_POSITION) { return null; } @@ -3168,7 +3165,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener Account account = getAccountFromCursor(cursor); long folderId = cursor.getLong(FOLDER_ID_COLUMN); - Folder folder = getFolderById(account, folderId); + LocalFolder folder = getFolderById(account, folderId); try { return folder.getMessage(uid); @@ -3179,14 +3176,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener return null; } - private List getCheckedMessages() { - List messages = new ArrayList(mSelected.size()); + private List getCheckedMessages() { + List messages = new ArrayList(mSelected.size()); for (int position = 0, end = mAdapter.getCount(); position < end; position++) { Cursor cursor = (Cursor) mAdapter.getItem(position); long uniqueId = cursor.getLong(mUniqueIdColumn); if (mSelected.contains(uniqueId)) { - Message message = getMessageAtPosition(position); + LocalMessage message = getMessageAtPosition(position); if (message != null) { messages.add(message); } @@ -3197,7 +3194,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } public void onDelete() { - Message message = getSelectedMessage(); + LocalMessage message = getSelectedMessage(); if (message != null) { onDelete(Collections.singletonList(message)); } @@ -3227,21 +3224,21 @@ public class MessageListFragment extends Fragment implements OnItemClickListener } public void onMove() { - Message message = getSelectedMessage(); + LocalMessage message = getSelectedMessage(); if (message != null) { onMove(message); } } public void onArchive() { - Message message = getSelectedMessage(); + LocalMessage message = getSelectedMessage(); if (message != null) { onArchive(message); } } public void onCopy() { - Message message = getSelectedMessage(); + LocalMessage message = getSelectedMessage(); if (message != null) { onCopy(message); } diff --git a/src/com/fsck/k9/fragment/MessageViewFragment.java b/src/com/fsck/k9/fragment/MessageViewFragment.java index 3a8bb4ddd..c8cfea928 100644 --- a/src/com/fsck/k9/fragment/MessageViewFragment.java +++ b/src/com/fsck/k9/fragment/MessageViewFragment.java @@ -75,7 +75,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener, private PgpData mPgpData; private Account mAccount; private MessageReference mMessageReference; - private Message mMessage; + private LocalMessage mMessage; private MessagingController mController; private Listener mListener = new Listener(); private MessageViewHandler mHandler = new MessageViewHandler(); @@ -311,7 +311,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener, // Disable the delete button after it's tapped (to try to prevent // accidental clicks) mFragmentListener.disableDeleteAction(); - Message messageToDelete = mMessage; + LocalMessage messageToDelete = mMessage; mFragmentListener.showNextMessageOrReturn(); mController.deleteMessages(Collections.singletonList(messageToDelete), null); } @@ -341,7 +341,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener, private void refileMessage(String dstFolder) { String srcFolder = mMessageReference.folderName; - Message messageToMove = mMessage; + LocalMessage messageToMove = mMessage; mFragmentListener.showNextMessageOrReturn(); mController.moveMessage(mAccount, srcFolder, messageToMove, dstFolder, null); } @@ -576,7 +576,8 @@ public class MessageViewFragment extends Fragment implements OnClickListener, @Override public void loadMessageForViewBodyAvailable(final Account account, String folder, String uid, final Message message) { - if (!mMessageReference.uid.equals(uid) || + if (!(message instanceof LocalMessage) || + !mMessageReference.uid.equals(uid) || !mMessageReference.folderName.equals(folder) || !mMessageReference.accountUuid.equals(account.getUuid())) { return; @@ -586,7 +587,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener, @Override public void run() { try { - mMessage = message; + mMessage = (LocalMessage) message; mMessageView.setMessage(account, (LocalMessage) message, mPgpData, mController, mListener); mFragmentListener.updateMenu(); diff --git a/src/com/fsck/k9/helper/MessageHelper.java b/src/com/fsck/k9/helper/MessageHelper.java index 26430b9e8..5df0161b8 100644 --- a/src/com/fsck/k9/helper/MessageHelper.java +++ b/src/com/fsck/k9/helper/MessageHelper.java @@ -14,6 +14,7 @@ import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Message; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.Message.RecipientType; +import com.fsck.k9.mail.store.local.LocalMessage; public class MessageHelper { @@ -32,8 +33,10 @@ public class MessageHelper { mContext = context; } - public void populate(final MessageInfoHolder target, final Message message, - final FolderInfoHolder folder, final Account account) { + public void populate(final MessageInfoHolder target, + final LocalMessage message, + final FolderInfoHolder folder, + Account account) { final Contacts contactHelper = K9.showContactName() ? Contacts.getInstance(mContext) : null; try { target.message = message; @@ -68,14 +71,9 @@ public class MessageHelper { target.senderAddress = target.compareCounterparty; } - - - target.uid = message.getUid(); - - target.account = account.getUuid(); - target.uri = "email://messages/" + account.getAccountNumber() + "/" + message.getFolder().getName() + "/" + message.getUid(); - + target.account = message.getFolder().getUuid(); + target.uri = message.getUri(); } catch (MessagingException me) { Log.w(K9.LOG_TAG, "Unable to load message info", me); } diff --git a/src/com/fsck/k9/mail/Folder.java b/src/com/fsck/k9/mail/Folder.java index 88af1a31a..5669e9794 100644 --- a/src/com/fsck/k9/mail/Folder.java +++ b/src/com/fsck/k9/mail/Folder.java @@ -1,21 +1,17 @@ package com.fsck.k9.mail; -import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import android.util.Log; -import com.fsck.k9.Account; + import com.fsck.k9.K9; import com.fsck.k9.Preferences; import com.fsck.k9.controller.MessageRetrievalListener; - -public abstract class Folder { - protected final Account mAccount; - +public abstract class Folder { private String status = null; private long lastChecked = 0; private long lastPush = 0; @@ -32,10 +28,6 @@ public abstract class Folder { HOLDS_FOLDERS, HOLDS_MESSAGES, } - protected Folder(Account account) { - mAccount = account; - } - /** * Forces an open of the MailProvider. If the provider is already open this * function returns without doing anything. @@ -83,7 +75,7 @@ public abstract class Folder { public abstract int getUnreadMessageCount() throws MessagingException; public abstract int getFlaggedMessageCount() throws MessagingException; - public abstract Message getMessage(String uid) throws MessagingException; + public abstract T getMessage(String uid) throws MessagingException; /** * Fetch the shells of messages between a range of UIDs and after a given date. @@ -94,7 +86,7 @@ public abstract class Folder { * @return List of messages * @throws MessagingException */ - public abstract List getMessages(int start, int end, Date earliestDate, MessageRetrievalListener listener) throws MessagingException; + public abstract List getMessages(int start, int end, Date earliestDate, MessageRetrievalListener listener) throws MessagingException; /** * Fetches the given list of messages. The specified listener is notified as @@ -104,13 +96,13 @@ public abstract class Folder { * @param listener Listener to notify as we download messages. * @return List of messages */ - public abstract List getMessages(MessageRetrievalListener listener) throws MessagingException; + public abstract List getMessages(MessageRetrievalListener listener) throws MessagingException; - public List getMessages(MessageRetrievalListener listener, boolean includeDeleted) throws MessagingException { + public List getMessages(MessageRetrievalListener listener, boolean includeDeleted) throws MessagingException { return getMessages(listener); } - public abstract List getMessages(String[] uids, MessageRetrievalListener listener) + public abstract List getMessages(String[] uids, MessageRetrievalListener listener) throws MessagingException; public abstract Map appendMessages(List messages) throws MessagingException; @@ -149,10 +141,10 @@ public abstract class Folder { * @throws MessagingException */ public abstract void fetch(List messages, FetchProfile fp, - MessageRetrievalListener listener) throws MessagingException; + MessageRetrievalListener listener) throws MessagingException; public void fetchPart(Message message, Part part, - MessageRetrievalListener listener) throws MessagingException { + MessageRetrievalListener listener) throws MessagingException { // This is causing trouble. Disabled for now. See issue 1733 //throw new RuntimeException("fetchPart() not implemented."); @@ -241,10 +233,6 @@ public abstract class Folder { this.status = status; } - public Account getAccount() { - return mAccount; - } - public List search(String queryString, final Set requiredFlags, final Set forbiddenFlags) throws MessagingException { throw new MessagingException("K-9 does not support searches on this folder type"); diff --git a/src/com/fsck/k9/mail/Message.java b/src/com/fsck/k9/mail/Message.java index 5a4d7a34a..452d312df 100644 --- a/src/com/fsck/k9/mail/Message.java +++ b/src/com/fsck/k9/mail/Message.java @@ -19,8 +19,8 @@ import com.fsck.k9.mail.store.UnavailableStorageException; public abstract class Message implements Part, CompositeBody { + protected MessageReference mReference; - private MessageReference mReference = null; public enum RecipientType { TO, CC, BCC, @@ -55,8 +55,7 @@ public abstract class Message implements Part, CompositeBody { } Message other = (Message)o; return (mUid.equals(other.getUid()) - && mFolder.getName().equals(other.getFolder().getName()) - && mFolder.getAccount().getUuid().equals(other.getFolder().getAccount().getUuid())); + && mFolder.getName().equals(other.getFolder().getName())); } @Override @@ -65,7 +64,6 @@ public abstract class Message implements Part, CompositeBody { int result = 1; result = MULTIPLIER * result + mFolder.getName().hashCode(); - result = MULTIPLIER * result + mFolder.getAccount().getUuid().hashCode(); result = MULTIPLIER * result + mUid.hashCode(); return result; } @@ -75,7 +73,7 @@ public abstract class Message implements Part, CompositeBody { } public void setUid(String uid) { - mReference = null; + this.mReference = null; this.mUid = uid; } @@ -249,15 +247,14 @@ public abstract class Message implements Part, CompositeBody { public void destroy() throws MessagingException {} @Override - public abstract void setEncoding(String encoding) throws UnavailableStorageException, MessagingException; + public abstract void setEncoding(String encoding) throws MessagingException; public abstract void setCharset(String charset) throws MessagingException; public MessageReference makeMessageReference() { if (mReference == null) { mReference = new MessageReference(); - mReference.accountUuid = getFolder().getAccount().getUuid(); - mReference.folderName = getFolder().getName(); + mReference.folderName = getFolder().getName(); mReference.uid = mUid; } return mReference; diff --git a/src/com/fsck/k9/mail/Store.java b/src/com/fsck/k9/mail/Store.java index 7dbfade7e..424b6bca1 100644 --- a/src/com/fsck/k9/mail/Store.java +++ b/src/com/fsck/k9/mail/Store.java @@ -1,24 +1,7 @@ package com.fsck.k9.mail; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import android.app.Application; -import android.content.Context; -import android.util.Log; - -import com.fsck.k9.Account; -import com.fsck.k9.K9; -import com.fsck.k9.mail.store.ImapStore; -import com.fsck.k9.mail.store.Pop3Store; -import com.fsck.k9.mail.store.StorageManager.StorageProvider; -import com.fsck.k9.mail.store.local.LocalStore; -import com.fsck.k9.mail.store.UnavailableStorageException; -import com.fsck.k9.mail.store.WebDavStore; /** * Store is the access point for an email message store. It's location can be @@ -29,191 +12,6 @@ import com.fsck.k9.mail.store.WebDavStore; * making as few network connections as possible. */ public abstract class Store { - protected static final int SOCKET_CONNECT_TIMEOUT = 30000; - protected static final int SOCKET_READ_TIMEOUT = 60000; - - /** - * Remote stores indexed by Uri. - */ - private static Map sStores = new HashMap(); - - /** - * Local stores indexed by UUID because the Uri may change due to migration to/from SD-card. - */ - private static ConcurrentMap sLocalStores = new ConcurrentHashMap(); - - /** - * Lock objects indexed by account UUID. - * - * @see #getLocalInstance(Account, Application) - */ - private static ConcurrentMap sAccountLocks = new ConcurrentHashMap(); - - /** - * Get an instance of a remote mail store. - */ - public synchronized static Store getRemoteInstance(Account account) throws MessagingException { - String uri = account.getStoreUri(); - - if (uri.startsWith("local")) { - throw new RuntimeException("Asked to get non-local Store object but given LocalStore URI"); - } - - Store store = sStores.get(uri); - if (store == null) { - if (uri.startsWith("imap")) { - store = new ImapStore(account); - } else if (uri.startsWith("pop3")) { - store = new Pop3Store(account); - } else if (uri.startsWith("webdav")) { - store = new WebDavStore(account); - } - - if (store != null) { - sStores.put(uri, store); - } - } - - if (store == null) { - throw new MessagingException("Unable to locate an applicable Store for " + uri); - } - - return store; - } - - /** - * Get an instance of a local mail store. - * - * @throws UnavailableStorageException - * if not {@link StorageProvider#isReady(Context)} - */ - public static LocalStore getLocalInstance(Account account, Application application) - throws MessagingException { - - String accountUuid = account.getUuid(); - - // Create new per-account lock object if necessary - sAccountLocks.putIfAbsent(accountUuid, new Object()); - - // Get the account's lock object - Object lock = sAccountLocks.get(accountUuid); - - // Use per-account locks so DatabaseUpgradeService always knows which account database is - // currently upgraded. - synchronized (lock) { - Store store = sLocalStores.get(accountUuid); - - if (store == null) { - // Creating a LocalStore instance will create or upgrade the database if - // necessary. This could take some time. - store = new LocalStore(account, application); - - sLocalStores.put(accountUuid, store); - } - - return (LocalStore) store; - } - } - - public static void removeAccount(Account account) { - try { - removeRemoteInstance(account); - } catch (Exception e) { - Log.e(K9.LOG_TAG, "Failed to reset remote store for account " + account.getUuid(), e); - } - - try { - removeLocalInstance(account); - } catch (Exception e) { - Log.e(K9.LOG_TAG, "Failed to reset local store for account " + account.getUuid(), e); - } - } - - /** - * Release reference to a local mail store instance. - * - * @param account - * {@link Account} instance that is used to get the local mail store instance. - */ - private static void removeLocalInstance(Account account) { - String accountUuid = account.getUuid(); - sLocalStores.remove(accountUuid); - } - - /** - * Release reference to a remote mail store instance. - * - * @param account - * {@link Account} instance that is used to get the remote mail store instance. - */ - private synchronized static void removeRemoteInstance(Account account) { - String uri = account.getStoreUri(); - - if (uri.startsWith("local")) { - throw new RuntimeException("Asked to get non-local Store object but given " + - "LocalStore URI"); - } - - sStores.remove(uri); - } - - /** - * Decodes the contents of store-specific URIs and puts them into a {@link ServerSettings} - * object. - * - * @param uri - * the store-specific URI to decode - * - * @return A {@link ServerSettings} object holding the settings contained in the URI. - * - * @see ImapStore#decodeUri(String) - * @see Pop3Store#decodeUri(String) - * @see WebDavStore#decodeUri(String) - */ - public static ServerSettings decodeStoreUri(String uri) { - if (uri.startsWith("imap")) { - return ImapStore.decodeUri(uri); - } else if (uri.startsWith("pop3")) { - return Pop3Store.decodeUri(uri); - } else if (uri.startsWith("webdav")) { - return WebDavStore.decodeUri(uri); - } else { - throw new IllegalArgumentException("Not a valid store URI"); - } - } - - /** - * Creates a store URI from the information supplied in the {@link ServerSettings} object. - * - * @param server - * The {@link ServerSettings} object that holds the server settings. - * - * @return A store URI that holds the same information as the {@code server} parameter. - * - * @see ImapStore#createUri(ServerSettings) - * @see Pop3Store#createUri(ServerSettings) - * @see WebDavStore#createUri(ServerSettings) - */ - public static String createStoreUri(ServerSettings server) { - if (ImapStore.STORE_TYPE.equals(server.type)) { - return ImapStore.createUri(server); - } else if (Pop3Store.STORE_TYPE.equals(server.type)) { - return Pop3Store.createUri(server); - } else if (WebDavStore.STORE_TYPE.equals(server.type)) { - return WebDavStore.createUri(server); - } else { - throw new IllegalArgumentException("Not a valid store URI"); - } - } - - - protected final Account mAccount; - - - protected Store(Account account) { - mAccount = account; - } - public abstract Folder getFolder(String name); public abstract List getPersonalNamespaces(boolean forceListAll) throws MessagingException; @@ -244,14 +42,9 @@ public abstract class Store { return true; } - public void sendMessages(List messages) throws MessagingException { - } + public void sendMessages(List messages) throws MessagingException { } public Pusher getPusher(PushReceiver receiver) { return null; } - - public Account getAccount() { - return mAccount; - } } diff --git a/src/com/fsck/k9/mail/store/ImapResponseParser.java b/src/com/fsck/k9/mail/store/ImapResponseParser.java index 4a8c8cc2e..541ff2376 100644 --- a/src/com/fsck/k9/mail/store/ImapResponseParser.java +++ b/src/com/fsck/k9/mail/store/ImapResponseParser.java @@ -11,7 +11,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.Locale; -public class ImapResponseParser { +class ImapResponseParser { private static final SimpleDateFormat mDateTimeFormat = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z", Locale.US); private static final SimpleDateFormat badDateTimeFormat = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z", Locale.US); private static final SimpleDateFormat badDateTimeFormat2 = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z", Locale.US); diff --git a/src/com/fsck/k9/mail/store/ImapStore.java b/src/com/fsck/k9/mail/store/ImapStore.java index afd4384fd..98c3a6833 100644 --- a/src/com/fsck/k9/mail/store/ImapStore.java +++ b/src/com/fsck/k9/mail/store/ImapStore.java @@ -55,7 +55,6 @@ import android.os.PowerManager; import android.text.TextUtils; import android.util.Log; -import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.R; import com.fsck.k9.controller.MessageRetrievalListener; @@ -78,7 +77,6 @@ import com.fsck.k9.mail.Part; import com.fsck.k9.mail.PushReceiver; import com.fsck.k9.mail.Pusher; import com.fsck.k9.mail.ServerSettings; -import com.fsck.k9.mail.Store; import com.fsck.k9.mail.filter.Base64; import com.fsck.k9.mail.filter.EOLConvertingOutputStream; import com.fsck.k9.mail.filter.FixedLengthInputStream; @@ -105,7 +103,7 @@ import org.apache.commons.io.IOUtils; * TODO Need a default response handler for things like folder updates * */ -public class ImapStore extends Store { +public class ImapStore extends RemoteStore { public static final String STORE_TYPE = "IMAP"; private static final int IDLE_READ_TIMEOUT_INCREMENT = 5 * 60 * 1000; @@ -113,7 +111,7 @@ public class ImapStore extends Store { private static int MAX_DELAY_TIME = 5 * 60 * 1000; // 5 minutes private static int NORMAL_DELAY_TIME = 5000; - private static int FETCH_WINDOW_SIZE = 100; + private static final int FETCH_WINDOW_SIZE = 100; private Set mPermanentFlagsIndex = EnumSet.noneOf(Flag.class); @@ -387,7 +385,7 @@ public class ImapStore extends Store { @Override public boolean useCompression(final int type) { - return mAccount.useCompression(type); + return mStoreConfig.useCompression(type); } @Override @@ -439,12 +437,12 @@ public class ImapStore extends Store { */ private final Map mFolderCache = new HashMap(); - public ImapStore(Account account) throws MessagingException { - super(account); + public ImapStore(StoreConfig storeConfig) throws MessagingException { + super(storeConfig); ImapStoreSettings settings; try { - settings = decodeUri(mAccount.getStoreUri()); + settings = decodeUri(storeConfig.getStoreUri()); } catch (IllegalArgumentException e) { throw new MessagingException("Error while decoding store URI", e); } @@ -502,7 +500,7 @@ public class ImapStore extends Store { ImapConnection connection = getConnection(); try { List allFolders = listFolders(connection, false); - if (forceListAll || !mAccount.subscribedFoldersOnly()) { + if (forceListAll || !mStoreConfig.subscribedFoldersOnly()) { return allFolders; } else { List resultFolders = new LinkedList(); @@ -570,9 +568,9 @@ public class ImapStore extends Store { mCombinedPrefix = null; } - if (folder.equalsIgnoreCase(mAccount.getInboxFolderName())) { + if (folder.equalsIgnoreCase(mStoreConfig.getInboxFolderName())) { continue; - } else if (folder.equals(mAccount.getOutboxFolderName())) { + } else if (folder.equals(mStoreConfig.getOutboxFolderName())) { /* * There is a folder on the server with the same name as our local * outbox. Until we have a good plan to deal with this situation @@ -604,7 +602,7 @@ public class ImapStore extends Store { } } } - folders.add(getFolder(mAccount.getInboxFolderName())); + folders.add(getFolder(mStoreConfig.getInboxFolderName())); return folders; } @@ -661,17 +659,17 @@ public class ImapStore extends Store { for (int i = 0, count = attributes.size(); i < count; i++) { String attribute = attributes.getString(i); if (attribute.equals("\\Drafts")) { - mAccount.setDraftsFolderName(decodedFolderName); + mStoreConfig.setDraftsFolderName(decodedFolderName); if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration detected draft folder: " + decodedFolderName); } else if (attribute.equals("\\Sent")) { - mAccount.setSentFolderName(decodedFolderName); + mStoreConfig.setSentFolderName(decodedFolderName); if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration detected sent folder: " + decodedFolderName); } else if (attribute.equals("\\Spam") || attribute.equals("\\Junk")) { //rfc6154 just mentions \Junk - mAccount.setSpamFolderName(decodedFolderName); + mStoreConfig.setSpamFolderName(decodedFolderName); if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration detected spam folder: " + decodedFolderName); } else if (attribute.equals("\\Trash")) { - mAccount.setTrashFolderName(decodedFolderName); + mStoreConfig.setTrashFolderName(decodedFolderName); if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration detected trash folder: " + decodedFolderName); } } @@ -777,7 +775,7 @@ public class ImapStore extends Store { } - class ImapFolder extends Folder { + class ImapFolder extends Folder { private String mName; protected volatile int mMessageCount = -1; protected volatile long uidNext = -1L; @@ -789,14 +787,14 @@ public class ImapStore extends Store { private boolean mInSearch = false; public ImapFolder(ImapStore nStore, String name) { - super(nStore.getAccount()); + super(); store = nStore; this.mName = name; } public String getPrefixedName() throws MessagingException { String prefixedName = ""; - if (!mAccount.getInboxFolderName().equalsIgnoreCase(mName)) { + if (!mStoreConfig.getInboxFolderName().equalsIgnoreCase(mName)) { ImapConnection connection = null; synchronized (this) { if (mConnection == null) { @@ -1293,7 +1291,7 @@ public class ImapStore extends Store { } @Override - public Message getMessage(String uid) throws MessagingException { + public ImapMessage getMessage(String uid) throws MessagingException { return new ImapMessage(uid, this); } @@ -1351,7 +1349,7 @@ public class ImapStore extends Store { return search(searcher, listener); } - private List search(ImapSearcher searcher, MessageRetrievalListener listener) throws MessagingException { + private List search(ImapSearcher searcher, MessageRetrievalListener listener) throws MessagingException { checkOpen(); //only need READ access List messages = new ArrayList(); @@ -1432,7 +1430,7 @@ public class ImapStore extends Store { } @Override - public void fetch(List messages, FetchProfile fp, MessageRetrievalListener listener) + public void fetch(List messages, FetchProfile fp, MessageRetrievalListener listener) throws MessagingException { if (messages == null || messages.isEmpty()) { return; @@ -1468,8 +1466,8 @@ public class ImapStore extends Store { } if (fp.contains(FetchProfile.Item.BODY_SANE)) { // If the user wants to download unlimited-size messages, don't go only for the truncated body - if (mAccount.getMaximumAutoDownloadMessageSize() > 0) { - fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", mAccount.getMaximumAutoDownloadMessageSize())); + if (mStoreConfig.getMaximumAutoDownloadMessageSize() > 0) { + fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", mStoreConfig.getMaximumAutoDownloadMessageSize())); } else { fetchFields.add("BODY.PEEK[]"); } @@ -1544,7 +1542,7 @@ public class ImapStore extends Store { } if (listener != null) { - listener.messageFinished(message, messageNumber, messageMap.size()); + listener.messageFinished(imapMessage, messageNumber, messageMap.size()); } } else { handleUntaggedResponse(response); @@ -1572,7 +1570,7 @@ public class ImapStore extends Store { String partId = parts[0]; if ("TEXT".equalsIgnoreCase(partId)) { fetch = String.format(Locale.US, "BODY.PEEK[TEXT]<0.%d>", - mAccount.getMaximumAutoDownloadMessageSize()); + mStoreConfig.getMaximumAutoDownloadMessageSize()); } else { fetch = String.format("BODY.PEEK[%s]", partId); } @@ -2194,7 +2192,7 @@ public class ImapStore extends Store { } protected String getLogId() { - String id = getAccount().getDescription() + ":" + getName() + "/" + Thread.currentThread().getName(); + String id = mStoreConfig.toString() + ":" + getName() + "/" + Thread.currentThread().getName(); if (mConnection != null) { id += "/" + mConnection.getLogId(); } @@ -2213,7 +2211,7 @@ public class ImapStore extends Store { public List search(final String queryString, final Set requiredFlags, final Set forbiddenFlags) throws MessagingException { - if (!mAccount.allowRemoteSearch()) { + if (!mStoreConfig.allowRemoteSearch()) { throw new MessagingException("Your settings do not allow remote searching of this account"); } @@ -2287,7 +2285,7 @@ public class ImapStore extends Store { } } final String encodedQry = encodeString(queryString); - if (mAccount.isRemoteSearchFullText()) { + if (mStoreConfig.isRemoteSearchFullText()) { imapQuery += "TEXT " + encodedQry; } else { imapQuery += "OR SUBJECT " + encodedQry + " FROM " + encodedQry; @@ -2424,7 +2422,7 @@ public class ImapStore extends Store { } } - setReadTimeout(Store.SOCKET_READ_TIMEOUT); + setReadTimeout(SOCKET_READ_TIMEOUT); mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(), 1024)); @@ -2458,7 +2456,7 @@ public class ImapStore extends Store { mSocket = TrustedSocketFactory.createSocket(mSocket, mSettings.getHost(), mSettings.getPort(), mSettings.getClientCertificateAlias()); - mSocket.setSoTimeout(Store.SOCKET_READ_TIMEOUT); + mSocket.setSoTimeout(SOCKET_READ_TIMEOUT); mIn = new PeekableInputStream(new BufferedInputStream(mSocket .getInputStream(), 1024)); mParser = new ImapResponseParser(mIn); @@ -2953,7 +2951,7 @@ public class ImapStore extends Store { super(store, name); receiver = nReceiver; TracingPowerManager pm = TracingPowerManager.getPowerManager(receiver.getContext()); - wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ImapFolderPusher " + store.getAccount().getDescription() + ":" + getName()); + wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ImapFolderPusher " + mStoreConfig.toString() + ":" + getName()); wakeLock.setReferenceCounted(false); } @@ -2968,7 +2966,7 @@ public class ImapStore extends Store { if (doneSent.compareAndSet(false, true)) { ImapConnection conn = mConnection; if (conn != null) { - conn.setReadTimeout(Store.SOCKET_READ_TIMEOUT); + conn.setReadTimeout(SOCKET_READ_TIMEOUT); sendContinuation("DONE"); } @@ -3030,7 +3028,7 @@ public class ImapStore extends Store { throw new MessagingException("IMAP server is not IDLE capable:" + conn.toString()); } - if (!stop.get() && mAccount.isPushPollOnConnect() && (conn != oldConnection || needsPoll.getAndSet(false))) { + if (!stop.get() && mStoreConfig.isPushPollOnConnect() && (conn != oldConnection || needsPoll.getAndSet(false))) { List untaggedResponses = new ArrayList(storedUntaggedResponses); storedUntaggedResponses.clear(); processUntaggedResponses(untaggedResponses); @@ -3061,8 +3059,8 @@ public class ImapStore extends Store { } } - if (startUid < newUidNext - mAccount.getDisplayCount()) { - startUid = newUidNext - mAccount.getDisplayCount(); + if (startUid < newUidNext - mStoreConfig.getDisplayCount()) { + startUid = newUidNext - mStoreConfig.getDisplayCount(); } if (startUid < 1) { startUid = 1; @@ -3099,7 +3097,7 @@ public class ImapStore extends Store { idling.set(true); doneSent.set(false); - conn.setReadTimeout((getAccount().getIdleRefreshMinutes() * 60 * 1000) + IDLE_READ_TIMEOUT_INCREMENT); + conn.setReadTimeout((mStoreConfig.getIdleRefreshMinutes() * 60 * 1000) + IDLE_READ_TIMEOUT_INCREMENT); untaggedResponses = executeSimpleCommand(COMMAND_IDLE, false, ImapFolderPusher.this); idling.set(false); delayTime.set(NORMAL_DELAY_TIME); @@ -3495,7 +3493,7 @@ public class ImapStore extends Store { @Override public int getRefreshInterval() { - return (getAccount().getIdleRefreshMinutes() * 60 * 1000); + return (mStoreConfig.getIdleRefreshMinutes() * 60 * 1000); } @Override diff --git a/src/com/fsck/k9/mail/store/Pop3Store.java b/src/com/fsck/k9/mail/store/Pop3Store.java index 5e2ee632a..593191a14 100644 --- a/src/com/fsck/k9/mail/store/Pop3Store.java +++ b/src/com/fsck/k9/mail/store/Pop3Store.java @@ -3,7 +3,6 @@ package com.fsck.k9.mail.store; import android.util.Log; -import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.R; import com.fsck.k9.controller.MessageRetrievalListener; @@ -24,7 +23,6 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.LinkedList; @@ -35,7 +33,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -public class Pop3Store extends Store { +public class Pop3Store extends RemoteStore { public static final String STORE_TYPE = "POP3"; private static final String STLS_COMMAND = "STLS"; @@ -209,12 +207,12 @@ public class Pop3Store extends Store { private boolean mTopNotSupported; - public Pop3Store(Account account) throws MessagingException { - super(account); + public Pop3Store(StoreConfig storeConfig) throws MessagingException { + super(storeConfig); ServerSettings settings; try { - settings = decodeUri(mAccount.getStoreUri()); + settings = decodeUri(storeConfig.getStoreUri()); } catch (IllegalArgumentException e) { throw new MessagingException("Error while decoding store URI", e); } @@ -243,13 +241,13 @@ public class Pop3Store extends Store { @Override public List getPersonalNamespaces(boolean forceListAll) throws MessagingException { List folders = new LinkedList(); - folders.add(getFolder(mAccount.getInboxFolderName())); + folders.add(getFolder(mStoreConfig.getInboxFolderName())); return folders; } @Override public void checkSettings() throws MessagingException { - Pop3Folder folder = new Pop3Folder(mAccount.getInboxFolderName()); + Pop3Folder folder = new Pop3Folder(mStoreConfig.getInboxFolderName()); folder.open(Folder.OPEN_MODE_RW); if (!mCapabilities.uidl) { /* @@ -272,7 +270,7 @@ public class Pop3Store extends Store { return false; } - class Pop3Folder extends Folder { + class Pop3Folder extends Folder { private Socket mSocket; private InputStream mIn; private OutputStream mOut; @@ -283,11 +281,11 @@ public class Pop3Store extends Store { private int mMessageCount; public Pop3Folder(String name) { - super(Pop3Store.this.mAccount); + super(); this.mName = name; - if (mName.equalsIgnoreCase(mAccount.getInboxFolderName())) { - mName = mAccount.getInboxFolderName(); + if (mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName())) { + mName = mStoreConfig.getInboxFolderName(); } } @@ -297,7 +295,7 @@ public class Pop3Store extends Store { return; } - if (!mName.equalsIgnoreCase(mAccount.getInboxFolderName())) { + if (!mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName())) { throw new MessagingException("Folder does not exist"); } @@ -313,7 +311,7 @@ public class Pop3Store extends Store { mIn = new BufferedInputStream(mSocket.getInputStream(), 1024); mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512); - mSocket.setSoTimeout(Store.SOCKET_READ_TIMEOUT); + mSocket.setSoTimeout(SOCKET_READ_TIMEOUT); if (!isOpen()) { throw new MessagingException("Unable to connect socket"); } @@ -328,7 +326,7 @@ public class Pop3Store extends Store { mSocket = TrustedSocketFactory.createSocket(mSocket, mHost, mPort, mClientCertificateAlias); - mSocket.setSoTimeout(Store.SOCKET_READ_TIMEOUT); + mSocket.setSoTimeout(SOCKET_READ_TIMEOUT); mIn = new BufferedInputStream(mSocket.getInputStream(), 1024); mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512); if (!isOpen()) { @@ -541,7 +539,7 @@ public class Pop3Store extends Store { @Override public boolean exists() throws MessagingException { - return mName.equalsIgnoreCase(mAccount.getInboxFolderName()); + return mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName()); } @Override @@ -559,7 +557,7 @@ public class Pop3Store extends Store { } @Override - public Message getMessage(String uid) throws MessagingException { + public Pop3Message getMessage(String uid) throws MessagingException { Pop3Message message = mUidToMsgMap.get(uid); if (message == null) { message = new Pop3Message(uid, this); @@ -761,7 +759,7 @@ public class Pop3Store extends Store { * @throws MessagingException */ @Override - public void fetch(List messages, FetchProfile fp, MessageRetrievalListener listener) + public void fetch(List messages, FetchProfile fp, MessageRetrievalListener listener) throws MessagingException { if (messages == null || messages.isEmpty()) { return; @@ -805,9 +803,9 @@ public class Pop3Store extends Store { * To convert the suggested download size we take the size * divided by the maximum line size (76). */ - if (mAccount.getMaximumAutoDownloadMessageSize() > 0) { + if (mStoreConfig.getMaximumAutoDownloadMessageSize() > 0) { fetchBody(pop3Message, - (mAccount.getMaximumAutoDownloadMessageSize() / 76)); + (mStoreConfig.getMaximumAutoDownloadMessageSize() / 76)); } else { fetchBody(pop3Message, -1); } @@ -819,7 +817,7 @@ public class Pop3Store extends Store { pop3Message.setBody(null); } if (listener != null && !(fp.contains(FetchProfile.Item.ENVELOPE) && fp.size() == 1)) { - listener.messageFinished(message, i, count); + listener.messageFinished(pop3Message, i, count); } } catch (IOException ioe) { throw new MessagingException("Unable to fetch message", ioe); diff --git a/src/com/fsck/k9/mail/store/RemoteStore.java b/src/com/fsck/k9/mail/store/RemoteStore.java new file mode 100644 index 000000000..9cad2aac2 --- /dev/null +++ b/src/com/fsck/k9/mail/store/RemoteStore.java @@ -0,0 +1,122 @@ +package com.fsck.k9.mail.store; + +import com.fsck.k9.mail.MessagingException; +import com.fsck.k9.mail.ServerSettings; +import com.fsck.k9.mail.Store; + +import java.util.HashMap; +import java.util.Map; + +public abstract class RemoteStore extends Store { + protected static final int SOCKET_CONNECT_TIMEOUT = 30000; + protected static final int SOCKET_READ_TIMEOUT = 60000; + + protected StoreConfig mStoreConfig; + + /** + * Remote stores indexed by Uri. + */ + private static Map sStores = new HashMap(); + + + public RemoteStore(StoreConfig storeConfig) { + mStoreConfig = storeConfig; + } + + /** + * Get an instance of a remote mail store. + */ + public synchronized static Store getInstance(StoreConfig storeConfig) throws MessagingException { + String uri = storeConfig.getStoreUri(); + + if (uri.startsWith("local")) { + throw new RuntimeException("Asked to get non-local Store object but given LocalStore URI"); + } + + Store store = sStores.get(uri); + if (store == null) { + if (uri.startsWith("imap")) { + store = new ImapStore(storeConfig); + } else if (uri.startsWith("pop3")) { + store = new Pop3Store(storeConfig); + } else if (uri.startsWith("webdav")) { + store = new WebDavStore(storeConfig); + } + + if (store != null) { + sStores.put(uri, store); + } + } + + if (store == null) { + throw new MessagingException("Unable to locate an applicable Store for " + uri); + } + + return store; + } + + /** + * Release reference to a remote mail store instance. + * + * @param storeConfig {@link com.fsck.k9.mail.store.StoreConfig} instance that is used to get the remote mail store instance. + */ + public static void removeInstance(StoreConfig storeConfig) { + String uri = storeConfig.getStoreUri(); + + if (uri.startsWith("local")) { + throw new RuntimeException("Asked to get non-local Store object but given " + + "LocalStore URI"); + } + + sStores.remove(uri); + } + + /** + * Decodes the contents of store-specific URIs and puts them into a {@link com.fsck.k9.mail.ServerSettings} + * object. + * + * @param uri + * the store-specific URI to decode + * + * @return A {@link com.fsck.k9.mail.ServerSettings} object holding the settings contained in the URI. + * + * @see com.fsck.k9.mail.store.ImapStore#decodeUri(String) + * @see com.fsck.k9.mail.store.Pop3Store#decodeUri(String) + * @see com.fsck.k9.mail.store.WebDavStore#decodeUri(String) + */ + public static ServerSettings decodeStoreUri(String uri) { + if (uri.startsWith("imap")) { + return ImapStore.decodeUri(uri); + } else if (uri.startsWith("pop3")) { + return Pop3Store.decodeUri(uri); + } else if (uri.startsWith("webdav")) { + return WebDavStore.decodeUri(uri); + } else { + throw new IllegalArgumentException("Not a valid store URI"); + } + } + + /** + * Creates a store URI from the information supplied in the {@link com.fsck.k9.mail.ServerSettings} object. + * + * @param server + * The {@link com.fsck.k9.mail.ServerSettings} object that holds the server settings. + * + * @return A store URI that holds the same information as the {@code server} parameter. + * + * @see com.fsck.k9.mail.store.ImapStore#createUri(com.fsck.k9.mail.ServerSettings) + * @see com.fsck.k9.mail.store.Pop3Store#createUri(com.fsck.k9.mail.ServerSettings) + * @see com.fsck.k9.mail.store.WebDavStore#createUri(com.fsck.k9.mail.ServerSettings) + */ + public static String createStoreUri(ServerSettings server) { + if (ImapStore.STORE_TYPE.equals(server.type)) { + return ImapStore.createUri(server); + } else if (Pop3Store.STORE_TYPE.equals(server.type)) { + return Pop3Store.createUri(server); + } else if (WebDavStore.STORE_TYPE.equals(server.type)) { + return WebDavStore.createUri(server); + } else { + throw new IllegalArgumentException("Not a valid store URI"); + } + } +} diff --git a/src/com/fsck/k9/mail/store/StoreConfig.java b/src/com/fsck/k9/mail/store/StoreConfig.java new file mode 100644 index 000000000..ba83ba201 --- /dev/null +++ b/src/com/fsck/k9/mail/store/StoreConfig.java @@ -0,0 +1,32 @@ +package com.fsck.k9.mail.store; + +public interface StoreConfig { + String getUuid(); + String getStoreUri(); + String getTransportUri(); + + boolean subscribedFoldersOnly(); + boolean useCompression(int type); + + String getInboxFolderName(); + String getOutboxFolderName(); + String getDraftsFolderName(); + + void setInboxFolderName(String folderName); + void setDraftsFolderName(String decodedFolderName); + void setTrashFolderName(String decodedFolderName); + void setSpamFolderName(String decodedFolderName); + void setSentFolderName(String decodedFolderName); + void setAutoExpandFolderName(String folderName); + + int getMaximumAutoDownloadMessageSize(); + + boolean allowRemoteSearch(); + boolean isRemoteSearchFullText(); + + boolean isPushPollOnConnect(); + + int getDisplayCount(); + + int getIdleRefreshMinutes(); +} diff --git a/src/com/fsck/k9/mail/store/WebDavStore.java b/src/com/fsck/k9/mail/store/WebDavStore.java index 27d0c7ccb..61dba1088 100644 --- a/src/com/fsck/k9/mail/store/WebDavStore.java +++ b/src/com/fsck/k9/mail/store/WebDavStore.java @@ -2,7 +2,6 @@ package com.fsck.k9.mail.store; import android.util.Log; -import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.controller.MessageRetrievalListener; @@ -55,7 +54,7 @@ import java.util.zip.GZIPInputStream; * and email information. * */ -public class WebDavStore extends Store { +public class WebDavStore extends RemoteStore { public static final String STORE_TYPE = "WebDAV"; // Authentication types @@ -294,12 +293,12 @@ public class WebDavStore extends Store { private Map mFolderList = new HashMap(); - public WebDavStore(Account account) throws MessagingException { - super(account); + public WebDavStore(StoreConfig storeConfig) throws MessagingException { + super(storeConfig); WebDavStoreSettings settings; try { - settings = decodeUri(mAccount.getStoreUri()); + settings = decodeUri(storeConfig.getStoreUri()); } catch (IllegalArgumentException e) { throw new MessagingException("Error while decoding store URI", e); } @@ -380,21 +379,21 @@ public class WebDavStore extends Store { Map specialFoldersMap = dataset.getSpecialFolderToUrl(); String folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_INBOX_FOLDER)); if (folderName != null) { - mAccount.setAutoExpandFolderName(folderName); - mAccount.setInboxFolderName(folderName); + mStoreConfig.setAutoExpandFolderName(folderName); + mStoreConfig.setInboxFolderName(folderName); } folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_DRAFTS_FOLDER)); if (folderName != null) - mAccount.setDraftsFolderName(folderName); + mStoreConfig.setDraftsFolderName(folderName); folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_TRASH_FOLDER)); if (folderName != null) - mAccount.setTrashFolderName(folderName); + mStoreConfig.setTrashFolderName(folderName); folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_SPAM_FOLDER)); if (folderName != null) - mAccount.setSpamFolderName(folderName); + mStoreConfig.setSpamFolderName(folderName); // K-9 Mail's outbox is a special local folder and different from Exchange/WebDAV's outbox. /* @@ -405,7 +404,7 @@ public class WebDavStore extends Store { folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_SENT_FOLDER)); if (folderName != null) - mAccount.setSentFolderName(folderName); + mStoreConfig.setSentFolderName(folderName); /** * Next we get all the folders (including "special" ones) @@ -1196,7 +1195,7 @@ public class WebDavStore extends Store { @Override public void sendMessages(List messages) throws MessagingException { - WebDavFolder tmpFolder = (WebDavStore.WebDavFolder) getFolder(mAccount.getDraftsFolderName()); + WebDavFolder tmpFolder = (WebDavStore.WebDavFolder) getFolder(mStoreConfig.getDraftsFolderName()); try { tmpFolder.open(Folder.OPEN_MODE_RW); List retMessages = tmpFolder.appendWebDavMessages(messages); @@ -1216,7 +1215,7 @@ public class WebDavStore extends Store { /** * A WebDav Folder */ - class WebDavFolder extends Folder { + class WebDavFolder extends Folder { private String mName; private String mFolderUrl; private boolean mIsOpen = false; @@ -1229,7 +1228,7 @@ public class WebDavStore extends Store { } public WebDavFolder(WebDavStore nStore, String name) { - super(nStore.getAccount()); + super(); store = nStore; this.mName = name; @@ -1397,7 +1396,7 @@ public class WebDavStore extends Store { } @Override - public Message getMessage(String uid) throws MessagingException { + public WebDavMessage getMessage(String uid) throws MessagingException { return new WebDavMessage(uid, this); } @@ -1498,7 +1497,7 @@ public class WebDavStore extends Store { } @Override - public void fetch(List messages, FetchProfile fp, MessageRetrievalListener listener) + public void fetch(List messages, FetchProfile fp, MessageRetrievalListener listener) throws MessagingException { if (messages == null || messages.isEmpty()) { @@ -1519,8 +1518,8 @@ public class WebDavStore extends Store { } if (fp.contains(FetchProfile.Item.BODY_SANE)) { - if (mAccount.getMaximumAutoDownloadMessageSize() > 0) { - fetchMessages(messages, listener, (mAccount.getMaximumAutoDownloadMessageSize() / 76)); + if (mStoreConfig.getMaximumAutoDownloadMessageSize() > 0) { + fetchMessages(messages, listener, (mStoreConfig.getMaximumAutoDownloadMessageSize() / 76)); } else { fetchMessages(messages, listener, -1); } @@ -1533,7 +1532,7 @@ public class WebDavStore extends Store { /** * Fetches the full messages or up to lines lines and passes them to the message parser. */ - private void fetchMessages(List messages, MessageRetrievalListener listener, int lines) + private void fetchMessages(List messages, MessageRetrievalListener listener, int lines) throws MessagingException { WebDavHttpClient httpclient; httpclient = getHttpClient(); @@ -1594,8 +1593,8 @@ public class WebDavStore extends Store { if (entity != null) { InputStream istream = null; StringBuilder buffer = new StringBuilder(); - String tempText = ""; - String resultText = ""; + String tempText; + String resultText; BufferedReader reader = null; int currentLines = 0; diff --git a/src/com/fsck/k9/mail/store/local/LocalFolder.java b/src/com/fsck/k9/mail/store/local/LocalFolder.java index 56e2558e4..22c3674ee 100644 --- a/src/com/fsck/k9/mail/store/local/LocalFolder.java +++ b/src/com/fsck/k9/mail/store/local/LocalFolder.java @@ -28,6 +28,7 @@ import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log; +import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.Account.MessageFormat; import com.fsck.k9.activity.Search; @@ -58,7 +59,7 @@ import com.fsck.k9.mail.store.local.LockableDatabase.DbCallback; import com.fsck.k9.mail.store.local.LockableDatabase.WrappedException; import com.fsck.k9.provider.AttachmentProvider; -public class LocalFolder extends Folder implements Serializable { +public class LocalFolder extends Folder implements Serializable { private static final long serialVersionUID = -1973296520918624767L; @@ -80,22 +81,19 @@ public class LocalFolder extends Folder implements Serializable { private Integer mLastUid = null; public LocalFolder(LocalStore localStore, String name) { - super(localStore.getAccount()); + super(); this.localStore = localStore; this.mName = name; - if (this.localStore.getAccount().getInboxFolderName().equals(getName())) { - + if (getAccount().getInboxFolderName().equals(getName())) { mSyncClass = FolderClass.FIRST_CLASS; mPushClass = FolderClass.FIRST_CLASS; mInTopGroup = true; } - - } public LocalFolder(LocalStore localStore, long id) { - super(localStore.getAccount()); + super(); this.localStore = localStore; this.mFolderId = id; } @@ -104,6 +102,25 @@ public class LocalFolder extends Folder implements Serializable { return mFolderId; } + public String getUuid() + { + return getAccount().getUuid(); + } + + public boolean getSignatureUse() { + return getAccount().getSignatureUse(); + } + + public void setLastSelectedFolderName(String destFolderName) { + getAccount().setLastSelectedFolderName(destFolderName); + } + + public boolean syncRemoteDeletions() { + return getAccount().syncRemoteDeletions(); + } + + + @Override public void open(final int mode) throws MessagingException { @@ -216,7 +233,7 @@ public class LocalFolder extends Folder implements Serializable { @Override public boolean create(FolderType type) throws MessagingException { - return create(type, mAccount.getDisplayCount()); + return create(type, getAccount().getDisplayCount()); } @Override @@ -517,25 +534,25 @@ public class LocalFolder extends Folder implements Serializable { String id = getPrefId(); // there can be a lot of folders. For the defaults, let's not save prefs, saving space, except for INBOX - if (mDisplayClass == FolderClass.NO_CLASS && !mAccount.getInboxFolderName().equals(getName())) { + if (mDisplayClass == FolderClass.NO_CLASS && !getAccount().getInboxFolderName().equals(getName())) { editor.remove(id + ".displayMode"); } else { editor.putString(id + ".displayMode", mDisplayClass.name()); } - if (mSyncClass == FolderClass.INHERITED && !mAccount.getInboxFolderName().equals(getName())) { + if (mSyncClass == FolderClass.INHERITED && !getAccount().getInboxFolderName().equals(getName())) { editor.remove(id + ".syncMode"); } else { editor.putString(id + ".syncMode", mSyncClass.name()); } - if (mNotifyClass == FolderClass.INHERITED && !mAccount.getInboxFolderName().equals(getName())) { + if (mNotifyClass == FolderClass.INHERITED && !getAccount().getInboxFolderName().equals(getName())) { editor.remove(id + ".notifyMode"); } else { editor.putString(id + ".notifyMode", mNotifyClass.name()); } - if (mPushClass == FolderClass.SECOND_CLASS && !mAccount.getInboxFolderName().equals(getName())) { + if (mPushClass == FolderClass.SECOND_CLASS && !getAccount().getInboxFolderName().equals(getName())) { editor.remove(id + ".pushMode"); } else { editor.putString(id + ".pushMode", mPushClass.name()); @@ -597,7 +614,7 @@ public class LocalFolder extends Folder implements Serializable { } @Override - public void fetch(final List messages, final FetchProfile fp, final MessageRetrievalListener listener) + public void fetch(final List messages, final FetchProfile fp, final MessageRetrievalListener listener) throws MessagingException { try { this.localStore.database.execute(false, new DbCallback() { @@ -614,7 +631,7 @@ public class LocalFolder extends Folder implements Serializable { try { cursor = db.rawQuery("SELECT html_content, text_content, mime_type FROM messages " + "WHERE id = ?", - new String[] { Long.toString(localMessage.mId) }); + new String[] { Long.toString(localMessage.getId()) }); cursor.moveToNext(); String htmlContent = cursor.getString(0); String textContent = cursor.getString(1); @@ -629,7 +646,7 @@ public class LocalFolder extends Folder implements Serializable { mp.addBodyPart(bp); } - if (mAccount.getMessageFormat() != MessageFormat.TEXT) { + if (getAccount().getMessageFormat() != MessageFormat.TEXT) { if (htmlContent != null) { TextBody body = new TextBody(htmlContent); MimeBodyPart bp = new MimeBodyPart(body, "text/html"); @@ -700,7 +717,7 @@ public class LocalFolder extends Folder implements Serializable { "content_disposition" }, "message_id = ?", - new String[] { Long.toString(localMessage.mId) }, + new String[] { Long.toString(localMessage.getId()) }, null, null, null); @@ -1439,12 +1456,12 @@ public class LocalFolder extends Folder implements Serializable { message.isSet(Flag.FLAGGED) ? 1 : 0, message.isSet(Flag.ANSWERED) ? 1 : 0, message.isSet(Flag.FORWARDED) ? 1 : 0, - message.mId + message.getId() }); for (int i = 0, count = attachments.size(); i < count; i++) { Part attachment = attachments.get(i); - saveAttachment(message.mId, attachment, false); + saveAttachment(message.getId(), attachment, false); } saveHeaders(message.getId(), message); } catch (Exception e) { @@ -1637,7 +1654,7 @@ public class LocalFolder extends Folder implements Serializable { File attachmentFile = new File(attachmentDirectory, Long.toString(attachmentId)); tempAttachmentFile.renameTo(attachmentFile); contentUri = AttachmentProvider.getAttachmentUri( - mAccount, + getAccount(), attachmentId); if (MimeUtil.isMessage(attachment.getMimeType())) { attachment.setBody(new LocalAttachmentMessageBody( @@ -1712,7 +1729,7 @@ public class LocalFolder extends Folder implements Serializable { @Override public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException { db.update("messages", cv, "id = ?", new String[] - { Long.toString(message.mId) }); + { Long.toString(message.getId()) }); return null; } }); @@ -1829,7 +1846,7 @@ public class LocalFolder extends Folder implements Serializable { setPushState(null); setLastPush(0); setLastChecked(0); - setVisibleLimit(mAccount.getDisplayCount()); + setVisibleLimit(getAccount().getDisplayCount()); } @Override @@ -1878,7 +1895,7 @@ public class LocalFolder extends Folder implements Serializable { public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException { Cursor attachmentsCursor = null; try { - String accountUuid = mAccount.getUuid(); + String accountUuid = getUuid(); Context context = LocalFolder.this.localStore.mApplication; // Get attachment IDs @@ -2039,7 +2056,7 @@ public class LocalFolder extends Folder implements Serializable { // Append the first message ID from the "In-Reply-To" header line String[] inReplyToArray = message.getHeader("In-Reply-To"); - String inReplyTo = null; + String inReplyTo; if (inReplyToArray != null && inReplyToArray.length > 0) { inReplyTo = Utility.extractMessageId(inReplyToArray[0]); if (inReplyTo != null) { @@ -2194,4 +2211,8 @@ public class LocalFolder extends Folder implements Serializable { throw(MessagingException) e.getCause(); } } + + private Account getAccount() { + return localStore.getAccount(); + } } diff --git a/src/com/fsck/k9/mail/store/local/LocalMessage.java b/src/com/fsck/k9/mail/store/local/LocalMessage.java index 56e20ea8d..6dd164f14 100644 --- a/src/com/fsck/k9/mail/store/local/LocalMessage.java +++ b/src/com/fsck/k9/mail/store/local/LocalMessage.java @@ -12,7 +12,9 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.util.Log; +import com.fsck.k9.Account; import com.fsck.k9.K9; +import com.fsck.k9.activity.MessageReference; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Folder; @@ -28,7 +30,7 @@ public class LocalMessage extends MimeMessage { private final LocalStore localStore; - long mId; + private long mId; private int mAttachmentCount; private String mSubject; @@ -557,4 +559,43 @@ public class LocalMessage extends MimeMessage { public long getRootId() { return mRootId; } + + public Account getAccount() { + return localStore.getAccount(); + } + + @Override + public MessageReference makeMessageReference() { + if (mReference == null) { + mReference = super.makeMessageReference(); + mReference.accountUuid = getFolder().getUuid(); + } + return mReference; + } + + @Override + public LocalFolder getFolder() { + return (LocalFolder) super.getFolder(); + } + + public String getUri() { + return "email://messages/" + getAccount().getAccountNumber() + "/" + getFolder().getName() + "/" + getUid(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + + LocalMessage that = (LocalMessage) o; + return !(getUid() != null ? !getUid().equals(that.getUid()) : that.getUid() != null); + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (getUid() != null ? getUid().hashCode() : 0); + return result; + } } \ No newline at end of file diff --git a/src/com/fsck/k9/mail/store/local/LocalStore.java b/src/com/fsck/k9/mail/store/local/LocalStore.java index 02002c125..f4c82743a 100644 --- a/src/com/fsck/k9/mail/store/local/LocalStore.java +++ b/src/com/fsck/k9/mail/store/local/LocalStore.java @@ -10,6 +10,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import android.app.Application; import android.content.ContentResolver; @@ -32,6 +34,8 @@ import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.Store; +import com.fsck.k9.mail.store.RemoteStore; +import com.fsck.k9.mail.store.StoreConfig; import com.fsck.k9.mail.store.local.LockableDatabase.DbCallback; import com.fsck.k9.mail.store.local.LockableDatabase.WrappedException; import com.fsck.k9.mail.store.StorageManager; @@ -56,6 +60,18 @@ public class LocalStore extends Store implements Serializable { static final String[] EMPTY_STRING_ARRAY = new String[0]; static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + /** + * Lock objects indexed by account UUID. + * + * @see #getInstance(Account, Application) + */ + private static ConcurrentMap sAccountLocks = new ConcurrentHashMap(); + + /** + * Local stores indexed by UUID because the Uri may change due to migration to/from SD-card. + */ + private static ConcurrentMap sLocalStores = new ConcurrentHashMap(); + /* * a String containing the columns getMessages expects to work with * in the correct order. @@ -138,6 +154,7 @@ public class LocalStore extends Store implements Serializable { LockableDatabase database; private ContentResolver mContentResolver; + private final Account mAccount; /** * local://localhost/path/to/database/uuid.db @@ -147,7 +164,7 @@ public class LocalStore extends Store implements Serializable { * @throws UnavailableStorageException if not {@link StorageProvider#isReady(Context)} */ public LocalStore(final Account account, final Application application) throws MessagingException { - super(account); + mAccount = account; database = new LockableDatabase(application, account.getUuid(), new StoreSchemaDefinition(this)); mApplication = application; @@ -158,10 +175,73 @@ public class LocalStore extends Store implements Serializable { database.open(); } + /** + * Get an instance of a local mail store. + * + * @throws UnavailableStorageException + * if not {@link StorageProvider#isReady(Context)} + */ + public static LocalStore getInstance(Account account, Application application) + throws MessagingException { + + String accountUuid = account.getUuid(); + + // Create new per-account lock object if necessary + sAccountLocks.putIfAbsent(accountUuid, new Object()); + + // Get the account's lock object + Object lock = sAccountLocks.get(accountUuid); + + // Use per-account locks so DatabaseUpgradeService always knows which account database is + // currently upgraded. + synchronized (lock) { + Store store = sLocalStores.get(accountUuid); + + if (store == null) { + // Creating a LocalStore instance will create or upgrade the database if + // necessary. This could take some time. + store = new LocalStore(account, application); + + sLocalStores.put(accountUuid, store); + } + + return (LocalStore) store; + } + } + + public static void removeAccount(StoreConfig storeConfig) { + try { + RemoteStore.removeInstance(storeConfig); + } catch (Exception e) { + Log.e(K9.LOG_TAG, "Failed to reset remote store for account " + storeConfig.getUuid(), e); + } + + try { + removeInstance(storeConfig); + } catch (Exception e) { + Log.e(K9.LOG_TAG, "Failed to reset local store for account " + storeConfig.getUuid(), e); + } + } + + /** + * Release reference to a local mail store instance. + * + * @param account + * {@link Account} instance that is used to get the local mail store instance. + */ + private static void removeInstance(StoreConfig account) { + String accountUuid = account.getUuid(); + sLocalStores.remove(accountUuid); + } + public void switchLocalStorage(final String newStorageProviderId) throws MessagingException { database.switchProvider(newStorageProviderId); } + protected Account getAccount() { + return mAccount; + } + protected SharedPreferences getPreferences() { return Preferences.getPreferences(mApplication).getPreferences(); } diff --git a/src/com/fsck/k9/mail/transport/SmtpTransport.java b/src/com/fsck/k9/mail/transport/SmtpTransport.java index 428c0dce2..a5365a33a 100644 --- a/src/com/fsck/k9/mail/transport/SmtpTransport.java +++ b/src/com/fsck/k9/mail/transport/SmtpTransport.java @@ -15,6 +15,7 @@ import com.fsck.k9.mail.filter.LineWrapOutputStream; import com.fsck.k9.mail.filter.PeekableInputStream; import com.fsck.k9.mail.filter.SmtpDataStuffing; import com.fsck.k9.mail.internet.MimeUtility; +import com.fsck.k9.mail.store.StoreConfig; import com.fsck.k9.mail.store.local.LocalMessage; import com.fsck.k9.net.ssl.TrustedSocketFactory; @@ -183,7 +184,7 @@ public class SmtpTransport extends Transport { private boolean m8bitEncodingAllowed; private int mLargestAcceptableMessage; - public SmtpTransport(Account account) throws MessagingException { + public SmtpTransport(StoreConfig account) throws MessagingException { ServerSettings settings; try { settings = decodeUri(account.getTransportUri()); diff --git a/src/com/fsck/k9/mail/transport/WebDavTransport.java b/src/com/fsck/k9/mail/transport/WebDavTransport.java index 1c94d01d5..40b8b6884 100644 --- a/src/com/fsck/k9/mail/transport/WebDavTransport.java +++ b/src/com/fsck/k9/mail/transport/WebDavTransport.java @@ -3,12 +3,12 @@ package com.fsck.k9.mail.transport; import android.util.Log; -import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.mail.Message; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.ServerSettings; import com.fsck.k9.mail.Transport; +import com.fsck.k9.mail.store.StoreConfig; import com.fsck.k9.mail.store.WebDavStore; import java.util.Collections; @@ -43,12 +43,8 @@ public class WebDavTransport extends Transport { private WebDavStore store; - public WebDavTransport(Account account) throws MessagingException { - if (account.getRemoteStore() instanceof WebDavStore) { - store = (WebDavStore) account.getRemoteStore(); - } else { - store = new WebDavStore(account); - } + public WebDavTransport(StoreConfig configInterface) throws MessagingException { + store = new WebDavStore(configInterface); if (K9.DEBUG) Log.d(K9.LOG_TAG, ">>> New WebDavTransport creation complete"); diff --git a/src/com/fsck/k9/preferences/SettingsExporter.java b/src/com/fsck/k9/preferences/SettingsExporter.java index 6085f3014..f49ec7a20 100644 --- a/src/com/fsck/k9/preferences/SettingsExporter.java +++ b/src/com/fsck/k9/preferences/SettingsExporter.java @@ -25,9 +25,9 @@ import android.util.Xml; import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.Preferences; -import com.fsck.k9.mail.Store; import com.fsck.k9.mail.ServerSettings; import com.fsck.k9.mail.Transport; +import com.fsck.k9.mail.store.RemoteStore; import com.fsck.k9.preferences.Settings.InvalidSettingValueException; import com.fsck.k9.preferences.Settings.SettingsDescription; @@ -223,7 +223,7 @@ public class SettingsExporter { // Write incoming server settings - ServerSettings incoming = Store.decodeStoreUri(account.getStoreUri()); + ServerSettings incoming = RemoteStore.decodeStoreUri(account.getStoreUri()); serializer.startTag(null, INCOMING_SERVER_ELEMENT); serializer.attribute(null, TYPE_ATTRIBUTE, incoming.type); diff --git a/src/com/fsck/k9/preferences/SettingsImporter.java b/src/com/fsck/k9/preferences/SettingsImporter.java index b3143f724..1a7af8d26 100644 --- a/src/com/fsck/k9/preferences/SettingsImporter.java +++ b/src/com/fsck/k9/preferences/SettingsImporter.java @@ -26,8 +26,8 @@ import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.AuthType; import com.fsck.k9.mail.ConnectionSecurity; import com.fsck.k9.mail.ServerSettings; -import com.fsck.k9.mail.Store; import com.fsck.k9.mail.Transport; +import com.fsck.k9.mail.store.RemoteStore; import com.fsck.k9.mail.store.WebDavStore; import com.fsck.k9.preferences.Settings.InvalidSettingValueException; @@ -376,7 +376,7 @@ public class SettingsImporter { // Write incoming server settings (storeUri) ServerSettings incoming = new ImportedServerSettings(account.incoming); - String storeUri = Store.createStoreUri(incoming); + String storeUri = RemoteStore.createStoreUri(incoming); putString(editor, accountKeyPrefix + Account.STORE_URI_KEY, Utility.base64Encode(storeUri)); // Mark account as disabled if the AuthType isn't EXTERNAL and the diff --git a/src/com/fsck/k9/provider/AttachmentProvider.java b/src/com/fsck/k9/provider/AttachmentProvider.java index 6f5bf32ac..bfcdaac9b 100644 --- a/src/com/fsck/k9/provider/AttachmentProvider.java +++ b/src/com/fsck/k9/provider/AttachmentProvider.java @@ -215,7 +215,7 @@ public class AttachmentProvider extends ContentProvider { final AttachmentInfo attachmentInfo; try { final Account account = Preferences.getPreferences(getContext()).getAccount(dbName); - attachmentInfo = LocalStore.getLocalInstance(account, K9.app).getAttachmentInfo(id); + attachmentInfo = LocalStore.getInstance(account, K9.app).getAttachmentInfo(id); } catch (MessagingException e) { Log.e(K9.LOG_TAG, "Unable to retrieve attachment info from local store for ID: " + id, e); return null; @@ -269,7 +269,7 @@ public class AttachmentProvider extends ContentProvider { final Account account = Preferences.getPreferences(getContext()).getAccount(dbName); try { - final LocalStore localStore = LocalStore.getLocalInstance(account, K9.app); + final LocalStore localStore = LocalStore.getInstance(account, K9.app); AttachmentInfo attachmentInfo = localStore.getAttachmentInfo(id); if (FORMAT_VIEW.equals(format) && mimeType != null) { diff --git a/src/com/fsck/k9/provider/MessageProvider.java b/src/com/fsck/k9/provider/MessageProvider.java index 6ce34baf3..c75f017df 100644 --- a/src/com/fsck/k9/provider/MessageProvider.java +++ b/src/com/fsck/k9/provider/MessageProvider.java @@ -32,6 +32,7 @@ import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.Message; import com.fsck.k9.mail.MessagingException; +import com.fsck.k9.mail.store.local.LocalFolder; import com.fsck.k9.mail.store.local.LocalMessage; import com.fsck.k9.mail.store.local.LocalStore; import com.fsck.k9.search.SearchAccount; @@ -200,9 +201,9 @@ public class MessageProvider extends ContentProvider { public static class DeleteUriExtractor implements FieldExtractor { @Override public String getField(final MessageInfoHolder source) { - final Message message = source.message; + final LocalMessage message = source.message; return CONTENT_URI + "/delete_message/" - + message.getFolder().getAccount().getAccountNumber() + "/" + + message.getAccount().getAccountNumber() + "/" + message.getFolder().getName() + "/" + message.getUid(); } } @@ -221,21 +222,21 @@ public class MessageProvider extends ContentProvider { public static class AccountExtractor implements FieldExtractor { @Override public String getField(final MessageInfoHolder source) { - return source.message.getFolder().getAccount().getDescription(); + return source.message.getAccount().getDescription(); } } public static class AccountColorExtractor implements FieldExtractor { @Override public Integer getField(final MessageInfoHolder source) { - return source.message.getFolder().getAccount().getChipColor(); + return source.message.getAccount().getChipColor(); } } public static class AccountNumberExtractor implements FieldExtractor { @Override public Integer getField(final MessageInfoHolder source) { - return source.message.getFolder().getAccount().getAccountNumber(); + return source.message.getAccount().getAccountNumber(); } } @@ -910,18 +911,18 @@ public class MessageProvider extends ContentProvider { @Override public void listLocalMessagesAddMessages(final Account account, - final String folderName, final List messages) { + final String folderName, final List messages) { // cache fields into local variables for faster access on JVM without JIT final MessageHelper helper = mMessageHelper; final List holders = mHolders; final Context context = getContext(); - for (final Message message : messages) { + for (final LocalMessage message : messages) { final MessageInfoHolder messageInfoHolder = new MessageInfoHolder(); final Folder messageFolder = message.getFolder(); - final Account messageAccount = messageFolder.getAccount(); + final Account messageAccount = messageInfoHolder.message.getAccount(); helper.populate(messageInfoHolder, message, new FolderInfoHolder(context, messageFolder, messageAccount), messageAccount); @@ -1038,9 +1039,9 @@ public class MessageProvider extends ContentProvider { } // get localstore parameter - Message msg = null; + LocalMessage msg = null; try { - Folder lf = LocalStore.getLocalInstance(myAccount, K9.app).getFolder(folderName); + LocalFolder lf = LocalStore.getInstance(myAccount, K9.app).getFolder(folderName); int msgCount = lf.getMessageCount(); if (K9.DEBUG) { Log.d(K9.LOG_TAG, "folder msg count = " + msgCount); diff --git a/src/com/fsck/k9/service/NotificationActionService.java b/src/com/fsck/k9/service/NotificationActionService.java index 107bd0f4c..2baef7560 100644 --- a/src/com/fsck/k9/service/NotificationActionService.java +++ b/src/com/fsck/k9/service/NotificationActionService.java @@ -10,9 +10,9 @@ import com.fsck.k9.Preferences; import com.fsck.k9.activity.MessageCompose; import com.fsck.k9.activity.MessageReference; import com.fsck.k9.controller.MessagingController; -import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Message; +import com.fsck.k9.mail.store.local.LocalMessage; import android.app.PendingIntent; import android.content.Context; @@ -89,10 +89,10 @@ public class NotificationActionService extends CoreService { List refs = intent.getParcelableArrayListExtra(EXTRA_MESSAGE_LIST); - List messages = new ArrayList(); + List messages = new ArrayList(); for (MessageReference ref : refs) { - Message m = ref.restoreToLocalMessage(this); + LocalMessage m = ref.restoreToLocalMessage(this); if (m != null) { messages.add(m); } @@ -106,7 +106,7 @@ public class NotificationActionService extends CoreService { MessageReference ref = (MessageReference) intent.getParcelableExtra(EXTRA_MESSAGE); Message message = ref.restoreToLocalMessage(this); if (message != null) { - Intent i = MessageCompose.getActionReplyIntent(this, account, message, false, null); + Intent i = MessageCompose.getActionReplyIntent(this, message, false, null); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); } else { diff --git a/tests/src/com/fsck/k9/mail/store/ImapStoreUriTest.java b/tests/src/com/fsck/k9/mail/store/ImapStoreUriTest.java index 92ef27dda..7badc97e0 100644 --- a/tests/src/com/fsck/k9/mail/store/ImapStoreUriTest.java +++ b/tests/src/com/fsck/k9/mail/store/ImapStoreUriTest.java @@ -6,14 +6,13 @@ import java.util.Map; import com.fsck.k9.mail.AuthType; import com.fsck.k9.mail.ConnectionSecurity; import com.fsck.k9.mail.ServerSettings; -import com.fsck.k9.mail.Store; -import com.fsck.k9.mail.store.ImapStore; + import junit.framework.TestCase; public class ImapStoreUriTest extends TestCase { public void testDecodeStoreUriImapAllExtras() { String uri = "imap://PLAIN:user:pass@server:143/0%7CcustomPathPrefix"; - ServerSettings settings = Store.decodeStoreUri(uri); + ServerSettings settings = RemoteStore.decodeStoreUri(uri); assertEquals(AuthType.PLAIN, settings.authenticationType); assertEquals("user", settings.username); @@ -26,7 +25,7 @@ public class ImapStoreUriTest extends TestCase { public void testDecodeStoreUriImapNoExtras() { String uri = "imap://PLAIN:user:pass@server:143/"; - ServerSettings settings = Store.decodeStoreUri(uri); + ServerSettings settings = RemoteStore.decodeStoreUri(uri); assertEquals(AuthType.PLAIN, settings.authenticationType); assertEquals("user", settings.username); @@ -38,7 +37,7 @@ public class ImapStoreUriTest extends TestCase { public void testDecodeStoreUriImapPrefixOnly() { String uri = "imap://PLAIN:user:pass@server:143/customPathPrefix"; - ServerSettings settings = Store.decodeStoreUri(uri); + ServerSettings settings = RemoteStore.decodeStoreUri(uri); assertEquals(AuthType.PLAIN, settings.authenticationType); assertEquals("user", settings.username); @@ -51,7 +50,7 @@ public class ImapStoreUriTest extends TestCase { public void testDecodeStoreUriImapEmptyPrefix() { String uri = "imap://PLAIN:user:pass@server:143/0%7C"; - ServerSettings settings = Store.decodeStoreUri(uri); + ServerSettings settings = RemoteStore.decodeStoreUri(uri); assertEquals(AuthType.PLAIN, settings.authenticationType); assertEquals("user", settings.username); @@ -64,7 +63,7 @@ public class ImapStoreUriTest extends TestCase { public void testDecodeStoreUriImapAutodetectAndPrefix() { String uri = "imap://PLAIN:user:pass@server:143/1%7CcustomPathPrefix"; - ServerSettings settings = Store.decodeStoreUri(uri); + ServerSettings settings = RemoteStore.decodeStoreUri(uri); assertEquals(AuthType.PLAIN, settings.authenticationType); assertEquals("user", settings.username); @@ -84,7 +83,7 @@ public class ImapStoreUriTest extends TestCase { ServerSettings settings = new ServerSettings(ImapStore.STORE_TYPE, "server", 143, ConnectionSecurity.NONE, AuthType.PLAIN, "user", "pass", null, extra); - String uri = Store.createStoreUri(settings); + String uri = RemoteStore.createStoreUri(settings); assertEquals("imap://PLAIN:user:pass@server:143/0%7CcustomPathPrefix", uri); } @@ -97,7 +96,7 @@ public class ImapStoreUriTest extends TestCase { ServerSettings settings = new ServerSettings(ImapStore.STORE_TYPE, "server", 143, ConnectionSecurity.NONE, AuthType.PLAIN, "user", "pass", null, extra); - String uri = Store.createStoreUri(settings); + String uri = RemoteStore.createStoreUri(settings); assertEquals("imap://PLAIN:user:pass@server:143/0%7C", uri); } @@ -106,7 +105,7 @@ public class ImapStoreUriTest extends TestCase { ServerSettings settings = new ServerSettings(ImapStore.STORE_TYPE, "server", 143, ConnectionSecurity.NONE, AuthType.PLAIN, "user", "pass", null); - String uri = Store.createStoreUri(settings); + String uri = RemoteStore.createStoreUri(settings); assertEquals("imap://PLAIN:user:pass@server:143/1%7C", uri); } @@ -118,7 +117,7 @@ public class ImapStoreUriTest extends TestCase { ServerSettings settings = new ServerSettings(ImapStore.STORE_TYPE, "server", 143, ConnectionSecurity.NONE, AuthType.PLAIN, "user", "pass", null, extra); - String uri = Store.createStoreUri(settings); + String uri = RemoteStore.createStoreUri(settings); assertEquals("imap://PLAIN:user:pass@server:143/1%7C", uri); }