More Store cleanup
Change-Id: I8f542175b4468c7a320322a57bfdaf19a7320165
This commit is contained in:
parent
aa46bc3919
commit
0b8e04c84d
|
@ -254,6 +254,18 @@ public class Mailbox extends EmailContent implements SyncColumns, MailboxColumns
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Mailbox} for the given path. If the path is not in the database, a new
|
||||
* mailbox will be created.
|
||||
*/
|
||||
public static Mailbox getMailboxForPath(Context context, long accountId, String path) {
|
||||
Mailbox mailbox = restoreMailboxForPath(context, accountId, path);
|
||||
if (mailbox == null) {
|
||||
mailbox = new Mailbox();
|
||||
}
|
||||
return mailbox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restore(Cursor cursor) {
|
||||
mBaseUri = CONTENT_URI;
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!--
|
||||
This file contains configuration data for commonly-used email store.
|
||||
|
||||
==== CONTENT GUIDELINES ====
|
||||
|
||||
This file should only be used for email store that are considered "universal"
|
||||
and are appropriate for *all* android platform devices. These entries must be accessible
|
||||
from all networks. It should be reasonable for any user to obtain an account on these
|
||||
networks, and test accounts must be easily obtainable. No entries should be added
|
||||
that are device, product, or carrier-specific.
|
||||
|
||||
Entries that are device, product or carrier-specific should be added as overlays
|
||||
in the appropriate stores_product.xml file.
|
||||
-->
|
||||
|
||||
<stores>
|
||||
<store scheme="local" class="com.android.email.mail.store.LocalStore" />
|
||||
<store scheme="pop3" class="com.android.email.mail.store.Pop3Store" />
|
||||
<store scheme="imap" class="com.android.email.mail.store.ImapStore" />
|
||||
<store scheme="eas" class="com.android.email.mail.store.ExchangeStore"
|
||||
push="true" visibleLimitDefault="-1" visibleLimitIncrement="-1" />
|
||||
</stores>
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Email stores that are considered "universal" and are appropriate for *all* android
|
||||
platform devices should be defined in stores.xml.
|
||||
|
||||
Entries that are device, product or carrier-specific should be added as overlays
|
||||
in the appropriate stores_product.xml file.
|
||||
|
||||
Because overlays must correspond to an existing platform resource, this empty placeholder
|
||||
is included in the platform build.
|
||||
-->
|
||||
|
||||
<stores_product>
|
||||
|
||||
<!-- THIS SECTION MUST REMAIN EMPTY -->
|
||||
<!-- Actual entries should be in the overlay files found elsewhere -->
|
||||
|
||||
</stores_product>
|
|
@ -31,7 +31,6 @@ import android.os.RemoteCallbackList;
|
|||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.email.mail.Store;
|
||||
import com.android.email.mail.store.Pop3Store.Pop3Message;
|
||||
import com.android.email.provider.AccountBackupRestore;
|
||||
import com.android.email.service.EmailServiceUtils;
|
||||
|
@ -1096,16 +1095,6 @@ public class Controller {
|
|||
return; // Already deleted?
|
||||
}
|
||||
|
||||
try {
|
||||
// Remove the store instance from cache
|
||||
Store oldStore = Store.removeInstance(account, context);
|
||||
if (oldStore != null) {
|
||||
oldStore.delete(); // If the store was removed, delete it
|
||||
}
|
||||
} catch (MessagingException e) {
|
||||
Log.w(Logging.LOG_TAG, "Failed to delete store", e);
|
||||
}
|
||||
|
||||
Uri uri = ContentUris.withAppendedId(
|
||||
Account.CONTENT_URI, accountId);
|
||||
context.getContentResolver().delete(uri, null, null);
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
package com.android.email.mail;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.email.Email;
|
||||
import com.android.email.R;
|
||||
import com.android.email.mail.store.ExchangeStore;
|
||||
import com.android.email.mail.store.ImapStore;
|
||||
import com.android.email.mail.store.Pop3Store;
|
||||
import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.mail.Folder;
|
||||
import com.android.emailcommon.mail.MessagingException;
|
||||
|
@ -32,21 +33,13 @@ import com.android.emailcommon.provider.HostAuth;
|
|||
import com.android.emailcommon.provider.Mailbox;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Store is the legacy equivalent of the Account class
|
||||
*/
|
||||
public abstract class Store {
|
||||
|
||||
/**
|
||||
* A global suggestion to Store implementors on how much of the body
|
||||
* should be returned on FetchProfile.Item.BODY_SANE requests.
|
||||
|
@ -55,13 +48,21 @@ public abstract class Store {
|
|||
|
||||
@VisibleForTesting
|
||||
static final HashMap<HostAuth, Store> sStores = new HashMap<HostAuth, Store>();
|
||||
|
||||
protected Context mContext;
|
||||
protected Account mAccount;
|
||||
protected Transport mTransport;
|
||||
protected String mUsername;
|
||||
protected String mPassword;
|
||||
|
||||
static final HashMap<String, Class<? extends Store>> sStoreClasses =
|
||||
new HashMap<String, Class<? extends Store>>();
|
||||
|
||||
{
|
||||
sStoreClasses.put(HostAuth.SCHEME_EAS, ExchangeStore.class);
|
||||
sStoreClasses.put(HostAuth.SCHEME_IMAP, ImapStore.class);
|
||||
sStoreClasses.put(HostAuth.SCHEME_POP3, Pop3Store.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static named constructor. It should be overrode by extending class.
|
||||
* Because this method will be called through reflection, it can not be protected.
|
||||
|
@ -71,83 +72,6 @@ public abstract class Store {
|
|||
+ account.mDisplayName);
|
||||
}
|
||||
|
||||
private static Store instantiateStore(String className, Account account, Context context)
|
||||
throws MessagingException {
|
||||
Object o = null;
|
||||
try {
|
||||
Class<?> c = Class.forName(className);
|
||||
// and invoke "newInstance" class method and instantiate store object.
|
||||
java.lang.reflect.Method m =
|
||||
c.getMethod("newInstance", Account.class, Context.class);
|
||||
// TODO Do the stores _really need a context? Is there a way to not pass it along?
|
||||
o = m.invoke(null, account, context);
|
||||
} catch (Exception e) {
|
||||
Log.d(Logging.LOG_TAG, String.format(
|
||||
"exception %s invoking method %s#newInstance(Account, Context) for %s",
|
||||
e.toString(), className, account.mDisplayName));
|
||||
throw new MessagingException("can not instantiate Store for " + account.mDisplayName);
|
||||
}
|
||||
if (!(o instanceof Store)) {
|
||||
throw new MessagingException(
|
||||
account.mDisplayName + ": " + className + " create incompatible object");
|
||||
}
|
||||
return (Store) o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up descriptive information about a particular type of store.
|
||||
*/
|
||||
public static class StoreInfo {
|
||||
public String mScheme;
|
||||
public String mClassName;
|
||||
public boolean mPushSupported = false;
|
||||
public int mVisibleLimitDefault;
|
||||
public int mVisibleLimitIncrement;
|
||||
public int mAccountInstanceLimit;
|
||||
|
||||
// TODO cache result for performance - silly to keep reading the XML
|
||||
public static StoreInfo getStoreInfo(String scheme, Context context) {
|
||||
StoreInfo result = getStoreInfo(R.xml.stores_product, scheme, context);
|
||||
if (result == null) {
|
||||
result = getStoreInfo(R.xml.stores, scheme, context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static StoreInfo getStoreInfo(int resourceId, String scheme, Context context) {
|
||||
try {
|
||||
XmlResourceParser xml = context.getResources().getXml(resourceId);
|
||||
int xmlEventType;
|
||||
// walk through stores.xml file.
|
||||
while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) {
|
||||
if (xmlEventType == XmlResourceParser.START_TAG &&
|
||||
"store".equals(xml.getName())) {
|
||||
String xmlScheme = xml.getAttributeValue(null, "scheme");
|
||||
if (scheme != null && scheme.startsWith(xmlScheme)) {
|
||||
StoreInfo result = new StoreInfo();
|
||||
result.mScheme = xmlScheme;
|
||||
result.mClassName = xml.getAttributeValue(null, "class");
|
||||
result.mPushSupported = xml.getAttributeBooleanValue(
|
||||
null, "push", false);
|
||||
result.mVisibleLimitDefault = xml.getAttributeIntValue(
|
||||
null, "visibleLimitDefault", Email.VISIBLE_LIMIT_DEFAULT);
|
||||
result.mVisibleLimitIncrement = xml.getAttributeIntValue(
|
||||
null, "visibleLimitIncrement", Email.VISIBLE_LIMIT_INCREMENT);
|
||||
result.mAccountInstanceLimit = xml.getAttributeIntValue(
|
||||
null, "accountInstanceLimit", -1);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (XmlPullParserException e) {
|
||||
// ignore
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of a mail store for the given account. The account must be valid (i.e. has
|
||||
* at least an incoming server name).
|
||||
|
@ -167,20 +91,22 @@ public abstract class Store {
|
|||
Store store = sStores.get(hostAuth);
|
||||
if (store == null) {
|
||||
Context appContext = context.getApplicationContext();
|
||||
StoreInfo info = StoreInfo.getStoreInfo(hostAuth.mProtocol, context);
|
||||
if (info != null) {
|
||||
store = instantiateStore(info.mClassName, account, appContext);
|
||||
Class<? extends Store> klass = sStoreClasses.get(hostAuth.mProtocol);
|
||||
try {
|
||||
// invoke "newInstance" class method
|
||||
Method m = klass.getMethod("newInstance", Account.class, Context.class);
|
||||
store = (Store)m.invoke(null, account, appContext);
|
||||
} catch (Exception e) {
|
||||
Log.d(Logging.LOG_TAG, String.format(
|
||||
"exception %s invoking method %s#newInstance(Account, Context) for %s",
|
||||
e.toString(), klass.getName(), account.mDisplayName));
|
||||
throw new MessagingException("Can't instantiate Store for " + account.mDisplayName);
|
||||
}
|
||||
// Don't cache this unless it's we've got a saved HostAUth
|
||||
if (store != null && (hostAuth.mId != EmailContent.NOT_SAVED)) {
|
||||
// Don't cache this unless it's we've got a saved HostAuth
|
||||
if (hostAuth.mId != EmailContent.NOT_SAVED) {
|
||||
sStores.put(hostAuth, store);
|
||||
}
|
||||
}
|
||||
|
||||
if (store == null) {
|
||||
throw new MessagingException("Cannot find store for account " + account.mDisplayName);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
|
@ -235,13 +161,6 @@ public abstract class Store {
|
|||
|
||||
public abstract Bundle checkSettings() throws MessagingException;
|
||||
|
||||
/**
|
||||
* Delete Store and its corresponding resources.
|
||||
* @throws MessagingException
|
||||
*/
|
||||
public void delete() throws MessagingException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle discovery of account settings using only the user's email address and password
|
||||
* @param context the context of the caller
|
||||
|
@ -255,18 +174,6 @@ public abstract class Store {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Mailbox} for the given path. If the path is not in the database, a new
|
||||
* mailbox will be created.
|
||||
*/
|
||||
protected static Mailbox getMailboxForPath(Context context, long accountId, String path) {
|
||||
Mailbox mailbox = Mailbox.restoreMailboxForPath(context, accountId, path);
|
||||
if (mailbox == null) {
|
||||
mailbox = new Mailbox();
|
||||
}
|
||||
return mailbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the fields within the given mailbox. Only the fields that are important to
|
||||
* non-EAS accounts are modified.
|
||||
|
|
|
@ -353,7 +353,7 @@ public class ImapStore extends Store {
|
|||
private ImapFolder addMailbox(Context context, long accountId, String mailboxPath,
|
||||
char delimiter, boolean selectable) {
|
||||
ImapFolder folder = (ImapFolder) getFolder(mailboxPath);
|
||||
Mailbox mailbox = getMailboxForPath(context, accountId, mailboxPath);
|
||||
Mailbox mailbox = Mailbox.getMailboxForPath(context, accountId, mailboxPath);
|
||||
if (mailbox.isSaved()) {
|
||||
// existing mailbox
|
||||
// mailbox retrieved from database; save hash _before_ updating fields
|
||||
|
|
|
@ -151,7 +151,7 @@ public class Pop3Store extends Store {
|
|||
|
||||
@Override
|
||||
public Folder[] updateFolders() {
|
||||
Mailbox mailbox = getMailboxForPath(mContext, mAccount.mId, POP3_MAILBOX_NAME);
|
||||
Mailbox mailbox = Mailbox.getMailboxForPath(mContext, mAccount.mId, POP3_MAILBOX_NAME);
|
||||
updateMailbox(mailbox, mAccount.mId, POP3_MAILBOX_NAME, '\0', true, Mailbox.TYPE_INBOX);
|
||||
// Force the parent key to be "no mailbox" for the mail POP3 mailbox
|
||||
mailbox.mParentKey = Mailbox.NO_MAILBOX;
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
|
||||
package com.android.email.activity.setup;
|
||||
|
||||
import com.android.email.mail.Store;
|
||||
import com.android.emailcommon.provider.Account;
|
||||
import com.android.emailcommon.provider.HostAuth;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -29,6 +25,9 @@ import android.preference.PreferenceFragment;
|
|||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
|
||||
import com.android.emailcommon.provider.Account;
|
||||
import com.android.emailcommon.provider.HostAuth;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +37,7 @@ import java.net.URISyntaxException;
|
|||
* TODO: These cannot run in the single-pane mode, and need to be refactored into single-pane
|
||||
* and multi-pane versions. Until then, they are all disabled.
|
||||
*
|
||||
* To execute: runtest -c com.android.email.activity.setup.AccountSettingsXLTests email
|
||||
* To execute: runtest -c com.android.email.activity.setup.AccountSettingsTests email
|
||||
*/
|
||||
@MediumTest
|
||||
public class AccountSettingsTests extends ActivityInstrumentationTestCase2<AccountSettings> {
|
||||
|
@ -111,12 +110,6 @@ public class AccountSettingsTests extends ActivityInstrumentationTestCase2<Accou
|
|||
* Test that EAS accounts are displayed with a push option
|
||||
*/
|
||||
public void disable_testPushOptionEAS() throws Throwable {
|
||||
// This test should only be run if EAS is supported
|
||||
if (Store.StoreInfo.getStoreInfo("eas", getInstrumentation().getTargetContext())
|
||||
== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent i = getTestIntent("Name", "eas://user:password@server.com",
|
||||
"eas://user:password@server.com");
|
||||
setActivityIntent(i);
|
||||
|
|
|
@ -16,11 +16,6 @@
|
|||
|
||||
package com.android.email.activity.setup;
|
||||
|
||||
import com.android.email.R;
|
||||
import com.android.email.mail.Store;
|
||||
import com.android.emailcommon.provider.Account;
|
||||
import com.android.emailcommon.provider.HostAuth;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
|
@ -30,6 +25,10 @@ import android.widget.CheckBox;
|
|||
import android.widget.Spinner;
|
||||
import android.widget.SpinnerAdapter;
|
||||
|
||||
import com.android.email.R;
|
||||
import com.android.emailcommon.provider.Account;
|
||||
import com.android.emailcommon.provider.HostAuth;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
|
@ -82,12 +81,6 @@ public class AccountSetupOptionsTests
|
|||
*/
|
||||
public void testPushOptionEAS()
|
||||
throws URISyntaxException {
|
||||
// This test should only be run if EAS is supported
|
||||
if (Store.StoreInfo.getStoreInfo("eas", this.getInstrumentation().getTargetContext())
|
||||
== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent i = getTestIntent("Name", "eas://user:password@server.com");
|
||||
this.setActivityIntent(i);
|
||||
|
||||
|
@ -118,11 +111,6 @@ public class AccountSetupOptionsTests
|
|||
*/
|
||||
public void testBackgroundAttachmentsEas()
|
||||
throws URISyntaxException {
|
||||
// This test should only be run if EAS is supported
|
||||
if (Store.StoreInfo.getStoreInfo("eas", this.getInstrumentation().getTargetContext())
|
||||
== null) {
|
||||
return;
|
||||
}
|
||||
checkBackgroundAttachments("eas://user:password@server.com", true);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@ import android.content.Context;
|
|||
import android.test.ProviderTestCase2;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
|
||||
import com.android.email.Email;
|
||||
import com.android.email.mail.Store.StoreInfo;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.provider.ProviderTestUtils;
|
||||
import com.android.emailcommon.mail.MessagingException;
|
||||
|
@ -54,32 +52,6 @@ public class StoreTests extends ProviderTestCase2<EmailProvider> {
|
|||
super(EmailProvider.class, EmailContent.AUTHORITY);
|
||||
}
|
||||
|
||||
public void testGetStoreInfo() {
|
||||
StoreInfo testInfo;
|
||||
|
||||
// POP3
|
||||
testInfo = Store.StoreInfo.getStoreInfo("pop3", mContext);
|
||||
assertNotNull(testInfo);
|
||||
assertNotNull(testInfo.mScheme);
|
||||
assertNotNull(testInfo.mClassName);
|
||||
assertFalse(testInfo.mPushSupported);
|
||||
assertEquals(Email.VISIBLE_LIMIT_DEFAULT, testInfo.mVisibleLimitDefault);
|
||||
assertEquals(Email.VISIBLE_LIMIT_INCREMENT, testInfo.mVisibleLimitIncrement);
|
||||
|
||||
// IMAP
|
||||
testInfo = Store.StoreInfo.getStoreInfo("imap", mContext);
|
||||
assertNotNull(testInfo);
|
||||
assertNotNull(testInfo.mScheme);
|
||||
assertNotNull(testInfo.mClassName);
|
||||
assertFalse(testInfo.mPushSupported);
|
||||
assertEquals(Email.VISIBLE_LIMIT_DEFAULT, testInfo.mVisibleLimitDefault);
|
||||
assertEquals(Email.VISIBLE_LIMIT_INCREMENT, testInfo.mVisibleLimitIncrement);
|
||||
|
||||
// Unknown
|
||||
testInfo = Store.StoreInfo.getStoreInfo("unknownscheme", mContext);
|
||||
assertNull(testInfo);
|
||||
}
|
||||
|
||||
public void testGetInstance() throws MessagingException {
|
||||
Store testStore;
|
||||
|
||||
|
|
Loading…
Reference in New Issue