k-9/src/com/fsck/k9/provider/MessageProvider.java

388 lines
11 KiB
Java
Raw Normal View History

package com.fsck.k9.provider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import android.app.Application;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.util.Log;
import com.fsck.k9.Account;
import com.fsck.k9.AccountStats;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.SearchAccount;
import com.fsck.k9.activity.MessageInfoHolder;
import com.fsck.k9.activity.MessageList;
import com.fsck.k9.controller.MessagingController;
import com.fsck.k9.controller.MessagingListener;
import com.fsck.k9.mail.Folder;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.store.LocalStore;
public class MessageProvider extends ContentProvider
{
protected class MesssageInfoHolderRetrieverListener extends MessagingListener
{
private final BlockingQueue<List<MessageInfoHolder>> queue;
private List<MessageInfoHolder> holders = new ArrayList<MessageInfoHolder>();
private MesssageInfoHolderRetrieverListener(BlockingQueue<List<MessageInfoHolder>> queue)
{
this.queue = queue;
}
@Override
public void listLocalMessagesAddMessages(Account account,
String folder, List<Message> messages)
{
for (final Message message : messages)
{
holders.add(new MessageInfoHolder(context, message));
}
}
@Override
public void searchStats(AccountStats stats)
{
try
{
queue.put(holders);
}
catch (InterruptedException e)
{
Log.e(K9.LOG_TAG, "Unable to return message list back to caller", e);
}
}
}
public static final String AUTHORITY = "com.fsck.k9.messageprovider";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int URI_INBOX_MESSAGES = 0;
private static final int URI_DELETE_MESSAGE = 1;
private static final int URI_ACCOUNTS = 2;
private static final int URI_ACCOUNT_UNREAD = 3;
private static Context context = null;
private static boolean mIsListenerRegister = false;
private static Application mApp;
static
{
URI_MATCHER.addURI(AUTHORITY, "inbox_messages/", URI_INBOX_MESSAGES);
URI_MATCHER.addURI(AUTHORITY, "delete_message/", URI_DELETE_MESSAGE);
URI_MATCHER.addURI(AUTHORITY, "accounts", URI_ACCOUNTS);
URI_MATCHER.addURI(AUTHORITY, "account_unread/#", URI_ACCOUNT_UNREAD);
}
static String[] messages_projection = new String[]
{
"id",
"date",
"sender",
"subject",
"preview",
"account",
"uri",
"delUri"
};
MessagingListener mListener = new MessagingListener()
{
public void searchStats(AccountStats stats)
{
notifyDatabaseModification();
}
};
public Cursor getAllAccounts()
{
String[] projection = new String[] { "accountNumber", "accountName" };
MatrixCursor ret = new MatrixCursor(projection);
for (Account account : Preferences.getPreferences(getContext()).getAccounts())
{
Object[] values = new Object[2];
values[0] = account.getAccountNumber();
values[1] = account.getDescription();
ret.addRow(values);
}
return ret;
}
public Cursor getAccountUnread(int accountNumber)
{
String[] projection = new String[] { "accountName", "unread" };
MatrixCursor ret = new MatrixCursor(projection);
Account myAccount;
AccountStats myAccountStats = null;
Object[] values = new Object[2];
for (Account account : Preferences.getPreferences(getContext()).getAccounts())
{
if (account.getAccountNumber()==accountNumber)
{
myAccount = account;
try
{
myAccountStats = account.getStats(getContext());
values[0] = myAccount.getDescription();
values[1] = myAccountStats.unreadMessageCount;
ret.addRow(values);
}
catch (MessagingException e)
{
Log.e(K9.LOG_TAG, e.getMessage());
values[0] = "Unknown";
values[1] = 0;
}
}
}
return ret;
}
public void setApplication(Application app)
{
2010-08-29 12:57:13 -04:00
if (context == null)
{
context = app.getApplicationContext();
}
if (app != null)
{
mApp = app;
MessagingController msgController = MessagingController.getInstance(mApp);
if ((msgController != null) && (!mIsListenerRegister))
{
msgController.addListener(mListener);
mIsListenerRegister = true;
}
}
}
@Override
public boolean onCreate()
{
context = getContext();
if (mApp != null)
{
MessagingController msgController = MessagingController.getInstance(mApp);
if ((msgController != null) && (!mIsListenerRegister))
{
msgController.addListener(mListener);
mIsListenerRegister = true;
}
}
return false;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs)
{
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "delete");
if (mApp == null)
{
Log.d(K9.LOG_TAG, "K9 not ready");
return 0;
}
// Nota : can only delete a message
List<String> segments = null;
int accountId = -1;
String folderName = null;
String msgUid = null;
segments = uri.getPathSegments();
accountId = Integer.parseInt(segments.get(1));
folderName = segments.get(2);
msgUid = segments.get(3);
// get account
Account myAccount = null;
for (Account account : Preferences.getPreferences(getContext()).getAccounts())
{
if (account.getAccountNumber() == accountId)
{
myAccount = account;
}
}
// get localstore parameter
Message msg = null;
try
{
Folder lf = LocalStore.getLocalInstance(myAccount, mApp).getFolder(folderName);
int msgCount = lf.getMessageCount();
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "folder msg count = " + msgCount);
msg = lf.getMessage(msgUid);
}
catch (MessagingException e)
{
Log.e(K9.LOG_TAG, e.getMessage());
}
// launch command to delete the message
if ((myAccount != null) && (msg != null))
{
MessagingController.getInstance(mApp).deleteMessages(new Message[] { msg }, mListener);
}
return 0;
}
@Override
public String getType(Uri uri)
{
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values)
{
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
{
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "query");
if (mApp == null)
{
Log.d(K9.LOG_TAG, "K9 not ready");
return null;
}
Cursor cursor;
switch (URI_MATCHER.match(uri))
{
case URI_INBOX_MESSAGES:
{
final MatrixCursor mCursor = new MatrixCursor(messages_projection);
final BlockingQueue<List<MessageInfoHolder>> queue = new SynchronousQueue<List<MessageInfoHolder>>();
// new code for integrated inbox, only execute this once as it will be processed afterwards via the listener
SearchAccount integratedInboxAccount = new SearchAccount(getContext(), true, null, null);
MessagingController msgController = MessagingController.getInstance(mApp);
msgController.searchLocalMessages(integratedInboxAccount, null,
new MesssageInfoHolderRetrieverListener(queue));
List<MessageInfoHolder> holders;
try
{
holders = queue.take();
}
catch (InterruptedException e)
{
Log.e(K9.LOG_TAG, "Unable to retrieve message list", e);
return null;
}
Collections.sort(holders, new MessageList.ReverseComparator<MessageInfoHolder>(new MessageList.DateComparator()));
int id = -1;
for (final MessageInfoHolder holder : holders)
{
final Message message = holder.message;
id++;
mCursor.addRow(new Object[]
{
id,
holder.fullDate,
holder.sender,
holder.subject,
holder.preview,
holder.account,
holder.uri,
CONTENT_URI + "/delete_message/"
+ message.getFolder().getAccount().getAccountNumber() + "/"
+ message.getFolder().getName() + "/" + message.getUid() });
}
cursor = mCursor;
break;
}
case URI_ACCOUNTS:
cursor = getAllAccounts();
break;
case URI_ACCOUNT_UNREAD:
List<String> segments = null;
int accountId = -1;
segments = uri.getPathSegments();
accountId = Integer.parseInt(segments.get(1));
cursor = getAccountUnread(accountId);
break;
default:
throw new IllegalStateException("Unrecognized URI:" + uri);
}
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
{
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "update");
//TBD
return 0;
}
public static void notifyDatabaseModification()
{
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "notifyDatabaseModification -> UPDATE");
Intent intent = new Intent(K9.Intents.EmailReceived.ACTION_REFRESH_OBSERVER, null);
context.sendBroadcast(intent);
context.getContentResolver().notifyChange(CONTENT_URI, null);
}
}