2008-11-01 17:32:06 -04:00
|
|
|
|
2009-12-14 21:50:53 -05:00
|
|
|
package com.fsck.k9.mail;
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2012-03-05 15:04:34 -05:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
2012-12-01 02:02:55 -05:00
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2008-11-01 17:32:06 -04:00
|
|
|
import android.app.Application;
|
2010-11-13 16:40:56 -05:00
|
|
|
import android.content.Context;
|
2010-03-03 23:00:30 -05:00
|
|
|
|
|
|
|
import com.fsck.k9.Account;
|
2009-12-14 21:50:53 -05:00
|
|
|
import com.fsck.k9.mail.store.ImapStore;
|
|
|
|
import com.fsck.k9.mail.store.LocalStore;
|
|
|
|
import com.fsck.k9.mail.store.Pop3Store;
|
2010-11-13 16:40:56 -05:00
|
|
|
import com.fsck.k9.mail.store.StorageManager.StorageProvider;
|
2012-03-05 15:04:34 -05:00
|
|
|
import com.fsck.k9.mail.store.UnavailableStorageException;
|
|
|
|
import com.fsck.k9.mail.store.WebDavStore;
|
2009-12-09 22:16:42 -05:00
|
|
|
|
2008-11-01 17:32:06 -04:00
|
|
|
/**
|
|
|
|
* Store is the access point for an email message store. It's location can be
|
|
|
|
* local or remote and no specific protocol is defined. Store is intended to
|
|
|
|
* loosely model in combination the JavaMail classes javax.mail.Store and
|
|
|
|
* javax.mail.Folder along with some additional functionality to improve
|
|
|
|
* performance on mobile devices. Implementations of this class should focus on
|
|
|
|
* making as few network connections as possible.
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public abstract class Store {
|
2010-04-05 22:54:48 -04:00
|
|
|
protected static final int SOCKET_CONNECT_TIMEOUT = 30000;
|
2008-11-01 17:32:06 -04:00
|
|
|
protected static final int SOCKET_READ_TIMEOUT = 60000;
|
|
|
|
|
2010-11-13 16:40:56 -05:00
|
|
|
/**
|
|
|
|
* Remote stores indexed by Uri.
|
|
|
|
*/
|
2011-06-06 15:10:14 -04:00
|
|
|
private static HashMap<String, Store> sStores = new HashMap<String, Store>();
|
|
|
|
|
2010-11-13 16:40:56 -05:00
|
|
|
/**
|
2012-12-01 02:02:55 -05:00
|
|
|
* Local stores indexed by UUID because the Uri may change due to migration to/from SD-card.
|
2010-11-13 16:40:56 -05:00
|
|
|
*/
|
2012-12-01 02:02:55 -05:00
|
|
|
private static ConcurrentHashMap<String, Store> sLocalStores = new ConcurrentHashMap<String, Store>();
|
2010-03-03 23:00:30 -05:00
|
|
|
|
2012-12-01 02:02:55 -05:00
|
|
|
/**
|
|
|
|
* Lock objects indexed by account UUID.
|
|
|
|
*
|
|
|
|
* @see #getLocalInstance(Account, Application)
|
|
|
|
*/
|
|
|
|
private static ConcurrentHashMap<String, Object> sAccountLocks = new ConcurrentHashMap<String, Object>();
|
2010-03-03 23:00:30 -05:00
|
|
|
|
2008-11-01 17:32:06 -04:00
|
|
|
/**
|
2010-03-03 23:00:30 -05:00
|
|
|
* Get an instance of a remote mail store.
|
2008-11-01 17:32:06 -04:00
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public synchronized static Store getRemoteInstance(Account account) throws MessagingException {
|
2010-03-03 23:00:30 -05:00
|
|
|
String uri = account.getStoreUri();
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (uri.startsWith("local")) {
|
2010-03-03 23:00:30 -05:00
|
|
|
throw new RuntimeException("Asked to get non-local Store object but given LocalStore URI");
|
|
|
|
}
|
|
|
|
|
2011-06-06 15:10:14 -04:00
|
|
|
Store store = sStores.get(uri);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (store == null) {
|
|
|
|
if (uri.startsWith("imap")) {
|
2010-03-03 23:00:30 -05:00
|
|
|
store = new ImapStore(account);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else if (uri.startsWith("pop3")) {
|
2010-03-03 23:00:30 -05:00
|
|
|
store = new Pop3Store(account);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else if (uri.startsWith("webdav")) {
|
2010-03-03 23:00:30 -05:00
|
|
|
store = new WebDavStore(account);
|
2009-11-24 19:40:29 -05:00
|
|
|
}
|
2010-03-03 23:00:30 -05:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (store != null) {
|
2011-06-06 15:10:14 -04:00
|
|
|
sStores.put(uri, store);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
2010-03-03 23:00:30 -05:00
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (store == null) {
|
2010-03-03 23:00:30 -05:00
|
|
|
throw new MessagingException("Unable to locate an applicable Store for " + uri);
|
|
|
|
}
|
|
|
|
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an instance of a local mail store.
|
2012-12-01 02:02:55 -05:00
|
|
|
*
|
|
|
|
* @throws UnavailableStorageException
|
|
|
|
* if not {@link StorageProvider#isReady(Context)}
|
2010-03-03 23:00:30 -05:00
|
|
|
*/
|
2012-12-01 02:02:55 -05:00
|
|
|
public static LocalStore getLocalInstance(Account account, Application application)
|
|
|
|
throws MessagingException {
|
|
|
|
|
|
|
|
String accountUuid = account.getUuid();
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2012-12-01 02:02:55 -05:00
|
|
|
// 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;
|
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
2011-06-06 18:08:43 -04:00
|
|
|
/**
|
2011-06-07 10:09:15 -04:00
|
|
|
* Decodes the contents of store-specific URIs and puts them into a {@link ServerSettings}
|
2011-06-06 18:08:43 -04:00
|
|
|
* object.
|
|
|
|
*
|
|
|
|
* @param uri
|
|
|
|
* the store-specific URI to decode
|
|
|
|
*
|
2011-06-07 10:09:15 -04:00
|
|
|
* @return A {@link ServerSettings} object holding the settings contained in the URI.
|
2011-06-06 18:08:43 -04:00
|
|
|
*
|
|
|
|
* @see ImapStore#decodeUri(String)
|
|
|
|
* @see Pop3Store#decodeUri(String)
|
|
|
|
* @see WebDavStore#decodeUri(String)
|
|
|
|
*/
|
2011-06-07 10:09:15 -04:00
|
|
|
public static ServerSettings decodeStoreUri(String uri) {
|
2011-06-06 18:08:43 -04:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-08 23:50:43 -04:00
|
|
|
/**
|
|
|
|
* 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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-06 15:10:14 -04:00
|
|
|
protected final Account mAccount;
|
|
|
|
|
|
|
|
|
|
|
|
protected Store(Account account) {
|
|
|
|
mAccount = account;
|
|
|
|
}
|
|
|
|
|
2010-11-30 22:02:13 -05:00
|
|
|
public abstract Folder getFolder(String name);
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public abstract List <? extends Folder > getPersonalNamespaces(boolean forceListAll) throws MessagingException;
|
2008-11-01 17:32:06 -04:00
|
|
|
|
|
|
|
public abstract void checkSettings() throws MessagingException;
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean isCopyCapable() {
|
2009-11-24 19:40:29 -05:00
|
|
|
return false;
|
2009-03-05 02:32:45 -05:00
|
|
|
}
|
2011-06-06 15:10:14 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean isMoveCapable() {
|
2009-11-24 19:40:29 -05:00
|
|
|
return false;
|
2009-03-05 02:32:45 -05:00
|
|
|
}
|
2011-06-06 15:10:14 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean isPushCapable() {
|
2009-10-21 20:41:06 -04:00
|
|
|
return false;
|
|
|
|
}
|
2011-06-06 15:10:14 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean isSendCapable() {
|
2009-10-24 22:58:26 -04:00
|
|
|
return false;
|
|
|
|
}
|
2011-06-06 15:10:14 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean isExpungeCapable() {
|
Implementation of complete IMAP two-phase "delete/expunge" behavior.
On each IMAP account, the expunge behavior can be set to expunge
messages in a folder as soon as a move or delete is performed on the
folder ("immediately"), each time the folder is polled, or only when
executed manually.
In the Message List, there is now an Expunge action in the option
menu.
In the Folder List, there is now an Expunge action in the context
menu (long-press on the folder).
For IMAP accounts, it is also possible to disable the copying of deleted messages to the
Trash folder, by setting the Trash folder to -NONE-.
Fixes Issue 536.
Separately, in WebDAV accounts, the user can now choose the
server-side equivalents of the special folders, just like for IMAP.
2009-12-20 18:13:49 -05:00
|
|
|
return false;
|
|
|
|
}
|
2010-01-02 20:50:51 -05:00
|
|
|
|
2013-03-13 01:34:14 -04:00
|
|
|
public boolean isSeenFlagSupported() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void sendMessages(Message[] messages) throws MessagingException {
|
2009-10-24 22:58:26 -04:00
|
|
|
}
|
2009-10-21 20:41:06 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public Pusher getPusher(PushReceiver receiver) {
|
2009-10-21 20:41:06 -04:00
|
|
|
return null;
|
|
|
|
}
|
2009-03-05 02:32:45 -05:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public Account getAccount() {
|
2010-03-03 23:00:30 -05:00
|
|
|
return mAccount;
|
|
|
|
}
|
2012-03-05 15:04:34 -05:00
|
|
|
|
2013-07-23 02:08:20 -04:00
|
|
|
public void resetRemoteStore(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);
|
|
|
|
}
|
2012-09-25 17:34:59 -04:00
|
|
|
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|