196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/* 2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Copyright (C) 2008 The Android Open Source Project 396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * you may not use this file except in compliance with the License. 696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * You may obtain a copy of the License at 796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * See the License for the specific language governing permissions and 1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * limitations under the License. 1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 1796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpackage com.android.email.mail; 1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 1985e4c101b014857fe40f87c3837b82564cfc5b6cMarc Blankimport android.content.Context; 2085e4c101b014857fe40f87c3837b82564cfc5b6cMarc Blankimport android.os.Bundle; 2185e4c101b014857fe40f87c3837b82564cfc5b6cMarc Blankimport android.util.Log; 2285e4c101b014857fe40f87c3837b82564cfc5b6cMarc Blank 23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.Email; 24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.mail.store.ExchangeStore; 255c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.email.mail.store.ImapStore; 260b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blankimport com.android.email.mail.store.Pop3Store; 2731d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.Logging; 282193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Folder; 292193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessagingException; 30f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport com.android.emailcommon.provider.Account; 3185e4c101b014857fe40f87c3837b82564cfc5b6cMarc Blankimport com.android.emailcommon.provider.EmailContent; 3212b82d9374947c9268217f45befe8a74bd9b60d7Ben Komaloimport com.android.emailcommon.provider.HostAuth; 3353ea83ebf91f820692e8fa8e781f5cc982dd94dbBen Komaloimport com.android.emailcommon.provider.Mailbox; 34a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedyimport com.google.common.annotations.VisibleForTesting; 3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 360b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blankimport java.lang.reflect.Method; 37e46ac1a61f32bd762a879457b1850087a1ad3a8cMakoto Onukiimport java.util.HashMap; 3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/** 400b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank * Store is the legacy equivalent of the Account class 4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 4296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpublic abstract class Store { 4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 4496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * A global suggestion to Store implementors on how much of the body 45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * should be returned on FetchProfile.Item.BODY_SANE requests. 4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final int FETCH_BODY_SANE_SUGGESTED_SIZE = (50 * 1024); 48581e3c2333deec3d57d9a18a2ed6da26ae71c8a2Todd Kennedy 49a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy @VisibleForTesting 50f65bdbdaf5960951452b148f801c51feca864bfeMarc Blank static final HashMap<HostAuth, Store> sStores = new HashMap<HostAuth, Store>(); 51171c3f2273223652b9999977d530a715420c0f64Todd Kennedy protected Context mContext; 52171c3f2273223652b9999977d530a715420c0f64Todd Kennedy protected Account mAccount; 53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook protected Transport mTransport; 54171c3f2273223652b9999977d530a715420c0f64Todd Kennedy protected String mUsername; 55171c3f2273223652b9999977d530a715420c0f64Todd Kennedy protected String mPassword; 56171c3f2273223652b9999977d530a715420c0f64Todd Kennedy 570b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank static final HashMap<String, Class<? extends Store>> sStoreClasses = 580b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank new HashMap<String, Class<? extends Store>>(); 590b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank 60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook static { 61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook sStoreClasses.put(HostAuth.SCHEME_EAS, ExchangeStore.class); 62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook sStoreClasses.put(HostAuth.SCHEME_IMAP, ImapStore.class); 63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook sStoreClasses.put(HostAuth.SCHEME_POP3, Pop3Store.class); 64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 66ae8ca3fbd1545c3a94011d7d70bcadac99e7779fAndy Stadler /** 67ae8ca3fbd1545c3a94011d7d70bcadac99e7779fAndy Stadler * Static named constructor. It should be overrode by extending class. 68968be441b4c253668c4ee1c7a3f8e4b0eb12cf24Makoto Onuki * Because this method will be called through reflection, it can not be protected. 69ae8ca3fbd1545c3a94011d7d70bcadac99e7779fAndy Stadler */ 7035b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blank static Store newInstance(Account account, Context context) throws MessagingException { 71a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy throw new MessagingException("Store#newInstance: Unknown scheme in " 72a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy + account.mDisplayName); 73ae8ca3fbd1545c3a94011d7d70bcadac99e7779fAndy Stadler } 74ae8ca3fbd1545c3a94011d7d70bcadac99e7779fAndy Stadler 75a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy /** 76a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy * Get an instance of a mail store for the given account. The account must be valid (i.e. has 77a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy * at least an incoming server name). 78968be441b4c253668c4ee1c7a3f8e4b0eb12cf24Makoto Onuki * 79f65bdbdaf5960951452b148f801c51feca864bfeMarc Blank * NOTE: The internal algorithm used to find a cached store depends upon the account's 80f65bdbdaf5960951452b148f801c51feca864bfeMarc Blank * HostAuth row. If this ever changes (e.g. such as the user updating the 81581e3c2333deec3d57d9a18a2ed6da26ae71c8a2Todd Kennedy * host name or port), we will leak entries. This should not be typical, so, it is not 82581e3c2333deec3d57d9a18a2ed6da26ae71c8a2Todd Kennedy * a critical problem. However, it is something we should consider fixing. 8396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 84a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy * @param account The account of the store. 8596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @return an initialized store of the appropriate class 86a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy * @throws MessagingException If the store cannot be obtained or if the account is invalid. 8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 8835b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blank public synchronized static Store getInstance(Account account, Context context) 8935b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blank throws MessagingException { 90f65bdbdaf5960951452b148f801c51feca864bfeMarc Blank HostAuth hostAuth = account.getOrCreateHostAuthRecv(context); 913285fb3cfdb209257ed5fb8f36a4d98c67b0d53eMarc Blank // An existing account might have been deleted 923285fb3cfdb209257ed5fb8f36a4d98c67b0d53eMarc Blank if (hostAuth == null) return null; 93f65bdbdaf5960951452b148f801c51feca864bfeMarc Blank Store store = sStores.get(hostAuth); 9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (store == null) { 95a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy Context appContext = context.getApplicationContext(); 960b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank Class<? extends Store> klass = sStoreClasses.get(hostAuth.mProtocol); 970b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank try { 980b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank // invoke "newInstance" class method 990b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank Method m = klass.getMethod("newInstance", Account.class, Context.class); 1000b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank store = (Store)m.invoke(null, account, appContext); 1010b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank } catch (Exception e) { 1020b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank Log.d(Logging.LOG_TAG, String.format( 1030b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank "exception %s invoking method %s#newInstance(Account, Context) for %s", 1040b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank e.toString(), klass.getName(), account.mDisplayName)); 1050b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank throw new MessagingException("Can't instantiate Store for " + account.mDisplayName); 10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 1070b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank // Don't cache this unless it's we've got a saved HostAuth 1080b8e04c84def3a06ef45126b48efc485fa0a7628Marc Blank if (hostAuth.mId != EmailContent.NOT_SAVED) { 109f65bdbdaf5960951452b148f801c51feca864bfeMarc Blank sStores.put(hostAuth, store); 11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return store; 11396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 114968be441b4c253668c4ee1c7a3f8e4b0eb12cf24Makoto Onuki 1153b7a93e8bbeda13e49ef17b45ba7b46fe8284deeAndy Stadler /** 116a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy * Delete the mail store associated with the given account. The account must be valid (i.e. has 117a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy * at least an incoming server name). 118968be441b4c253668c4ee1c7a3f8e4b0eb12cf24Makoto Onuki * 1193b7a93e8bbeda13e49ef17b45ba7b46fe8284deeAndy Stadler * The store should have been notified already by calling delete(), and the caller should 1203b7a93e8bbeda13e49ef17b45ba7b46fe8284deeAndy Stadler * also take responsibility for deleting the matching LocalStore, etc. 121a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy * 122a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy * @throws MessagingException If the store cannot be removed or if the account is invalid. 1233b7a93e8bbeda13e49ef17b45ba7b46fe8284deeAndy Stadler */ 124581e3c2333deec3d57d9a18a2ed6da26ae71c8a2Todd Kennedy public synchronized static Store removeInstance(Account account, Context context) 125a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy throws MessagingException { 126f65bdbdaf5960951452b148f801c51feca864bfeMarc Blank return sStores.remove(HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv)); 1273b7a93e8bbeda13e49ef17b45ba7b46fe8284deeAndy Stadler } 12896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 129ae8ca3fbd1545c3a94011d7d70bcadac99e7779fAndy Stadler /** 130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Get class of SettingActivity for this Store class. 131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return Activity class that has class method actionEditIncomingSettings(). 132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public Class<? extends android.app.Activity> getSettingActivityClass() { 134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook // default SettingActivity class 135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return com.android.email.activity.setup.AccountSetupIncoming.class; 136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 139c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler * Some protocols require that a sent message be copied (uploaded) into the Sent folder 140c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler * while others can take care of it automatically (ideally, on the server). This function 141c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler * allows a given store to indicate which mode(s) it supports. 142c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler * @return true if the store requires an upload into "sent", false if this happens automatically 143c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler * for any sent message. 144c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler */ 145c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler public boolean requireCopyMessageToSentFolder() { 146c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler return true; 147c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler } 148968be441b4c253668c4ee1c7a3f8e4b0eb12cf24Makoto Onuki 14966a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank public Folder getFolder(String name) throws MessagingException { 15066a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank return null; 15166a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank } 15296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 153200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy /** 154200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy * Updates the local list of mailboxes according to what is located on the remote server. 155200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy * <em>Note: This does not perform folder synchronization and it will not remove mailboxes 156200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy * that are stored locally but not remotely.</em> 157200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy * @return The set of remote folders 158200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy * @throws MessagingException If there was a problem connecting to the remote server 159200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy */ 16066a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank public Folder[] updateFolders() throws MessagingException { 16166a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank return null; 16266a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank } 163968be441b4c253668c4ee1c7a3f8e4b0eb12cf24Makoto Onuki 164d6d874f8c6ce2580ef9ec2406fe411af45b2d92dMarc Blank public abstract Bundle checkSettings() throws MessagingException; 165968be441b4c253668c4ee1c7a3f8e4b0eb12cf24Makoto Onuki 166ae8ca3fbd1545c3a94011d7d70bcadac99e7779fAndy Stadler /** 16717da1767e396b873723d53b2aef93da8aca2c00eMarc Blank * Handle discovery of account settings using only the user's email address and password 16817da1767e396b873723d53b2aef93da8aca2c00eMarc Blank * @param context the context of the caller 16917da1767e396b873723d53b2aef93da8aca2c00eMarc Blank * @param emailAddress the email address of the exchange user 17017da1767e396b873723d53b2aef93da8aca2c00eMarc Blank * @param password the password of the exchange user 17117da1767e396b873723d53b2aef93da8aca2c00eMarc Blank * @return a Bundle containing an error code and a HostAuth (if successful) 17217da1767e396b873723d53b2aef93da8aca2c00eMarc Blank * @throws MessagingException 17317da1767e396b873723d53b2aef93da8aca2c00eMarc Blank */ 17417da1767e396b873723d53b2aef93da8aca2c00eMarc Blank public Bundle autoDiscover(Context context, String emailAddress, String password) 17517da1767e396b873723d53b2aef93da8aca2c00eMarc Blank throws MessagingException { 17617da1767e396b873723d53b2aef93da8aca2c00eMarc Blank return null; 17717da1767e396b873723d53b2aef93da8aca2c00eMarc Blank } 178200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy 179200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy /** 18022208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy * Updates the fields within the given mailbox. Only the fields that are important to 18122208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy * non-EAS accounts are modified. 182200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy */ 18322208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy protected static void updateMailbox(Mailbox mailbox, long accountId, String mailboxPath, 184019341af98ffe2dcd484bd0468c9858d9e7cd7a3Todd Kennedy char delimiter, boolean selectable, int type) { 185200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy mailbox.mAccountKey = accountId; 18622208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy mailbox.mDelimiter = delimiter; 18722208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy String displayPath = mailboxPath; 18822208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy int pathIndex = mailboxPath.lastIndexOf(delimiter); 18922208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy if (pathIndex > 0) { 19022208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy displayPath = mailboxPath.substring(pathIndex + 1); 19122208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy } 19222208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy mailbox.mDisplayName = displayPath; 193019341af98ffe2dcd484bd0468c9858d9e7cd7a3Todd Kennedy if (selectable) { 194019341af98ffe2dcd484bd0468c9858d9e7cd7a3Todd Kennedy mailbox.mFlags = Mailbox.FLAG_HOLDS_MAIL | Mailbox.FLAG_ACCEPTS_MOVED_MAIL; 195019341af98ffe2dcd484bd0468c9858d9e7cd7a3Todd Kennedy } 196200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy mailbox.mFlagVisible = true; 197200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy //mailbox.mParentKey; 198200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy //mailbox.mParentServerId; 199200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy mailbox.mServerId = mailboxPath; 200200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy //mailbox.mServerId; 201200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy //mailbox.mSyncFrequency; 202200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy //mailbox.mSyncKey; 203200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy //mailbox.mSyncLookback; 204200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy //mailbox.mSyncTime; 20522208771b7b39c5d131372ba6bc45ab23cc22232Todd Kennedy mailbox.mType = type; 206200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy //box.mUnreadCount; 207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook mailbox.mVisibleLimit = Email.VISIBLE_LIMIT_DEFAULT; 208200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy } 20996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project} 210