Clean up LegacyConversions

Change-Id: I9cb9bf8a08663004a497af9f52e3ab0647bd2168
This commit is contained in:
Tony Mantler 2014-04-18 13:24:18 -07:00
parent a5ba759443
commit f0db9ce9ab
2 changed files with 70 additions and 91 deletions

View File

@ -76,21 +76,23 @@ public class LegacyConversions {
/** /**
* Copy field-by-field from a "store" message to a "provider" message * Copy field-by-field from a "store" message to a "provider" message
* @param message The message we've just downloaded (must be a MimeMessage) *
* @param message The message we've just downloaded (must be a MimeMessage)
* @param localMessage The message we'd like to write into the DB * @param localMessage The message we'd like to write into the DB
* @return true if dirty (changes were made) * @return true if dirty (changes were made)
*/ */
public static boolean updateMessageFields(EmailContent.Message localMessage, Message message, public static boolean updateMessageFields(final EmailContent.Message localMessage,
long accountId, long mailboxId) throws MessagingException { final Message message, final long accountId, final long mailboxId)
throws MessagingException {
Address[] from = message.getFrom(); final Address[] from = message.getFrom();
Address[] to = message.getRecipients(Message.RecipientType.TO); final Address[] to = message.getRecipients(Message.RecipientType.TO);
Address[] cc = message.getRecipients(Message.RecipientType.CC); final Address[] cc = message.getRecipients(Message.RecipientType.CC);
Address[] bcc = message.getRecipients(Message.RecipientType.BCC); final Address[] bcc = message.getRecipients(Message.RecipientType.BCC);
Address[] replyTo = message.getReplyTo(); final Address[] replyTo = message.getReplyTo();
String subject = message.getSubject(); final String subject = message.getSubject();
Date sentDate = message.getSentDate(); final Date sentDate = message.getSentDate();
Date internalDate = message.getInternalDate(); final Date internalDate = message.getInternalDate();
if (from != null && from.length > 0) { if (from != null && from.length > 0) {
localMessage.mDisplayName = from[0].toFriendly(); localMessage.mDisplayName = from[0].toFriendly();
@ -130,7 +132,7 @@ public class LegacyConversions {
// Only replace the local message-id if a new one was found. This is seen in some ISP's // Only replace the local message-id if a new one was found. This is seen in some ISP's
// which may deliver messages w/o a message-id header. // which may deliver messages w/o a message-id header.
String messageId = message.getMessageId(); final String messageId = message.getMessageId();
if (messageId != null) { if (messageId != null) {
localMessage.mMessageId = messageId; localMessage.mMessageId = messageId;
} }
@ -162,21 +164,22 @@ public class LegacyConversions {
/** /**
* Copy attachments from MimeMessage to provider Message. * Copy attachments from MimeMessage to provider Message.
* *
* @param context a context for file operations * @param context a context for file operations
* @param localMessage the attachments will be built against this message * @param localMessage the attachments will be built against this message
* @param attachments the attachments to add * @param attachments the attachments to add
* @throws IOException
*/ */
public static void updateAttachments(Context context, EmailContent.Message localMessage, public static void updateAttachments(final Context context,
ArrayList<Part> attachments) throws MessagingException, IOException { final EmailContent.Message localMessage, final ArrayList<Part> attachments)
throws MessagingException, IOException {
localMessage.mAttachments = null; localMessage.mAttachments = null;
for (Part attachmentPart : attachments) { for (Part attachmentPart : attachments) {
addOneAttachment(context, localMessage, attachmentPart); addOneAttachment(context, localMessage, attachmentPart);
} }
} }
public static void updateInlineAttachments(Context context, EmailContent.Message localMessage, public static void updateInlineAttachments(final Context context,
ArrayList<Part> inlineAttachments) throws MessagingException, IOException { final EmailContent.Message localMessage, final ArrayList<Part> inlineAttachments)
throws MessagingException, IOException {
for (final Part inlinePart : inlineAttachments) { for (final Part inlinePart : inlineAttachments) {
final String disposition = MimeUtility.getHeaderParameter( final String disposition = MimeUtility.getHeaderParameter(
MimeUtility.unfoldAndDecode(inlinePart.getDisposition()), null); MimeUtility.unfoldAndDecode(inlinePart.getDisposition()), null);
@ -200,27 +203,24 @@ public class LegacyConversions {
* *
* TODO: Take a closer look at encoding and deal with it if necessary. * TODO: Take a closer look at encoding and deal with it if necessary.
* *
* @param context a context for file operations * @param context a context for file operations
* @param localMessage the attachments will be built against this message * @param localMessage the attachments will be built against this message
* @param part a single attachment part from POP or IMAP * @param part a single attachment part from POP or IMAP
* @throws IOException
*/ */
public static void addOneAttachment(Context context, EmailContent.Message localMessage, public static void addOneAttachment(final Context context,
Part part) throws MessagingException, IOException { final EmailContent.Message localMessage, final Part part)
throws MessagingException, IOException {
Attachment localAttachment = new Attachment();
// Transfer fields from mime format to provider format // Transfer fields from mime format to provider format
String contentType = MimeUtility.unfoldAndDecode(part.getContentType()); final String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
String name = MimeUtility.getHeaderParameter(contentType, "name"); String name = MimeUtility.getHeaderParameter(contentType, "name");
if (name == null) { if (name == null) {
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition()); final String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
name = MimeUtility.getHeaderParameter(contentDisposition, "filename"); name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
} }
// Incoming attachment: Try to pull size from disposition (if not downloaded yet) // Incoming attachment: Try to pull size from disposition (if not downloaded yet)
long size = 0; long size = 0;
String disposition = part.getDisposition(); final String disposition = part.getDisposition();
if (disposition != null) { if (disposition != null) {
String s = MimeUtility.getHeaderParameter(disposition, "size"); String s = MimeUtility.getHeaderParameter(disposition, "size");
if (s != null) { if (s != null) {
@ -230,11 +230,12 @@ public class LegacyConversions {
// Get partId for unloaded IMAP attachments (if any) // Get partId for unloaded IMAP attachments (if any)
// This is only provided (and used) when we have structure but not the actual attachment // This is only provided (and used) when we have structure but not the actual attachment
String[] partIds = part.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA); final String[] partIds = part.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA);
String partId = partIds != null ? partIds[0] : null; final String partId = partIds != null ? partIds[0] : null;
// Run the mime type through inferMimeType in case we have something generic and can do // Run the mime type through inferMimeType in case we have something generic and can do
// better using the filename extension // better using the filename extension
final Attachment localAttachment = new Attachment();
localAttachment.mMimeType = AttachmentUtilities.inferMimeType(name, part.getMimeType()); localAttachment.mMimeType = AttachmentUtilities.inferMimeType(name, part.getMimeType());
localAttachment.mFileName = name; localAttachment.mFileName = name;
localAttachment.mSize = size; // May be reset below if file handled localAttachment.mSize = size; // May be reset below if file handled
@ -254,20 +255,22 @@ public class LegacyConversions {
// mFileName, mMimeType, mContentId, mMessageKey, mLocation // mFileName, mMimeType, mContentId, mMessageKey, mLocation
// NOTE: This will false-positive if you attach the exact same file, twice, to a POP3 // NOTE: This will false-positive if you attach the exact same file, twice, to a POP3
// message. We can live with that - you'll get one of the copies. // message. We can live with that - you'll get one of the copies.
Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId); final Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId);
Cursor cursor = context.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, final Cursor cursor = context.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION,
null, null, null); null, null, null);
boolean attachmentFoundInDb = false; boolean attachmentFoundInDb = false;
try { try {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
Attachment dbAttachment = new Attachment(); final Attachment dbAttachment = new Attachment();
dbAttachment.restore(cursor); dbAttachment.restore(cursor);
// We test each of the fields here (instead of in SQL) because they may be // We test each of the fields here (instead of in SQL) because they may be
// null, or may be strings. // null, or may be strings.
if (stringNotEqual(dbAttachment.mFileName, localAttachment.mFileName)) continue; if (!TextUtils.equals(dbAttachment.mFileName, localAttachment.mFileName) ||
if (stringNotEqual(dbAttachment.mMimeType, localAttachment.mMimeType)) continue; !TextUtils.equals(dbAttachment.mMimeType, localAttachment.mMimeType) ||
if (stringNotEqual(dbAttachment.mContentId, localAttachment.mContentId)) continue; !TextUtils.equals(dbAttachment.mContentId, localAttachment.mContentId) ||
if (stringNotEqual(dbAttachment.mLocation, localAttachment.mLocation)) continue; !TextUtils.equals(dbAttachment.mLocation, localAttachment.mLocation)) {
continue;
}
// We found a match, so use the existing attachment id, and stop looking/looping // We found a match, so use the existing attachment id, and stop looking/looping
attachmentFoundInDb = true; attachmentFoundInDb = true;
localAttachment.mId = dbAttachment.mId; localAttachment.mId = dbAttachment.mId;
@ -295,22 +298,12 @@ public class LegacyConversions {
localMessage.mFlagAttachment = true; localMessage.mFlagAttachment = true;
} }
/**
* Helper for addOneAttachment that compares two strings, deals with nulls, and treats
* nulls and empty strings as equal.
*/
/* package */ static boolean stringNotEqual(String a, String b) {
if (a == null && b == null) return false; // fast exit for two null strings
if (a == null) a = "";
if (b == null) b = "";
return !a.equals(b);
}
/** /**
* Save the body part of a single attachment, to a file in the attachments directory. * Save the body part of a single attachment, to a file in the attachments directory.
*/ */
public static void saveAttachmentBody(Context context, Part part, Attachment localAttachment, public static void saveAttachmentBody(final Context context, final Part part,
long accountId) throws MessagingException, IOException { final Attachment localAttachment, long accountId)
throws MessagingException, IOException {
if (part.getBody() != null) { if (part.getBody() != null) {
final long attachmentId = localAttachment.mId; final long attachmentId = localAttachment.mId;
@ -359,13 +352,14 @@ public class LegacyConversions {
* Read a complete Provider message into a legacy message (for IMAP upload). This * Read a complete Provider message into a legacy message (for IMAP upload). This
* is basically the equivalent of LocalFolder.getMessages() + LocalFolder.fetch(). * is basically the equivalent of LocalFolder.getMessages() + LocalFolder.fetch().
*/ */
public static Message makeMessage(Context context, EmailContent.Message localMessage) public static Message makeMessage(final Context context,
final EmailContent.Message localMessage)
throws MessagingException { throws MessagingException {
MimeMessage message = new MimeMessage(); final MimeMessage message = new MimeMessage();
// LocalFolder.getMessages() equivalent: Copy message fields // LocalFolder.getMessages() equivalent: Copy message fields
message.setSubject(localMessage.mSubject == null ? "" : localMessage.mSubject); message.setSubject(localMessage.mSubject == null ? "" : localMessage.mSubject);
Address[] from = Address.fromHeader(localMessage.mFrom); final Address[] from = Address.fromHeader(localMessage.mFrom);
if (from.length > 0) { if (from.length > 0) {
message.setFrom(from[0]); message.setFrom(from[0]);
} }
@ -385,28 +379,29 @@ public class LegacyConversions {
// LocalFolder.fetch() equivalent: build body parts // LocalFolder.fetch() equivalent: build body parts
message.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "multipart/mixed"); message.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "multipart/mixed");
MimeMultipart mp = new MimeMultipart(); final MimeMultipart mp = new MimeMultipart();
mp.setSubType("mixed"); mp.setSubType("mixed");
message.setBody(mp); message.setBody(mp);
try { try {
addTextBodyPart(mp, "text/html", null, addTextBodyPart(mp, "text/html",
EmailContent.Body.restoreBodyHtmlWithMessageId(context, localMessage.mId)); EmailContent.Body.restoreBodyHtmlWithMessageId(context, localMessage.mId));
} catch (RuntimeException rte) { } catch (RuntimeException rte) {
LogUtils.d(Logging.LOG_TAG, "Exception while reading html body " + rte.toString()); LogUtils.d(Logging.LOG_TAG, "Exception while reading html body " + rte.toString());
} }
try { try {
addTextBodyPart(mp, "text/plain", null, addTextBodyPart(mp, "text/plain",
EmailContent.Body.restoreBodyTextWithMessageId(context, localMessage.mId)); EmailContent.Body.restoreBodyTextWithMessageId(context, localMessage.mId));
} catch (RuntimeException rte) { } catch (RuntimeException rte) {
LogUtils.d(Logging.LOG_TAG, "Exception while reading text body " + rte.toString()); LogUtils.d(Logging.LOG_TAG, "Exception while reading text body " + rte.toString());
} }
// Attachments // Attachments
Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId); final Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId);
Cursor attachments = context.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, final Cursor attachments =
null, null, null); context.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION,
null, null, null);
try { try {
while (attachments != null && attachments.moveToNext()) { while (attachments != null && attachments.moveToNext()) {
@ -456,34 +451,30 @@ public class LegacyConversions {
/** /**
* Helper method to add a body part for a given type of text, if found * Helper method to add a body part for a given type of text, if found
* *
* @param mp The text body part will be added to this multipart * @param mp The text body part will be added to this multipart
* @param contentType The content-type of the text being added * @param contentType The content-type of the text being added
* @param quotedPartTag If non-null, HEADER_ANDROID_BODY_QUOTED_PART will be set to this value * @param partText The text to add. If null, nothing happens
* @param partText The text to add. If null, nothing happens
*/ */
private static void addTextBodyPart(MimeMultipart mp, String contentType, String quotedPartTag, private static void addTextBodyPart(final MimeMultipart mp, final String contentType,
String partText) throws MessagingException { final String partText)
throws MessagingException {
if (partText == null) { if (partText == null) {
return; return;
} }
TextBody body = new TextBody(partText); final TextBody body = new TextBody(partText);
MimeBodyPart bp = new MimeBodyPart(body, contentType); final MimeBodyPart bp = new MimeBodyPart(body, contentType);
if (quotedPartTag != null) {
bp.addHeader(MimeHeader.HEADER_ANDROID_BODY_QUOTED_PART, quotedPartTag);
}
mp.addBodyPart(bp); mp.addBodyPart(bp);
} }
/** /**
* Helper method to add an attachment part * Helper method to add an attachment part
* *
* @param mp Multipart message to append attachment part to * @param mp Multipart message to append attachment part to
* @param contentType Mime type * @param contentType Mime type
* @param contentSize Attachment metadata: unencoded file size * @param contentSize Attachment metadata: unencoded file size
* @param filename Attachment metadata: file name * @param filename Attachment metadata: file name
* @param contentId as referenced from cid: uris in the message body (if applicable) * @param contentId as referenced from cid: uris in the message body (if applicable)
* @param content unencoded bytes * @param content unencoded bytes
* @throws MessagingException
*/ */
private static void addAttachmentPart(final Multipart mp, final String contentType, private static void addAttachmentPart(final Multipart mp, final String contentType,
final Long contentSize, final String filename, final String contentId, final Long contentSize, final String filename, final String contentId,
@ -502,7 +493,10 @@ public class LegacyConversions {
/** /**
* Infer mailbox type from mailbox name. Used by MessagingController (for live folder sync). * Infer mailbox type from mailbox name. Used by MessagingController (for live folder sync).
*
* Deprecation: this should be configured in the UI, in conjunction with RF6154 support
*/ */
@Deprecated
public static synchronized int inferMailboxTypeFromName(Context context, String mailboxName) { public static synchronized int inferMailboxTypeFromName(Context context, String mailboxName) {
if (sServerMailboxNames.size() == 0) { if (sServerMailboxNames.size() == 0) {
// preload the hashmap, one time only // preload the hashmap, one time only

View File

@ -172,19 +172,4 @@ public class LegacyConversionsTest extends AndroidTestCase {
final BodyFieldData data = ConversionUtilities.parseBodyFields(viewables); final BodyFieldData data = ConversionUtilities.parseBodyFields(viewables);
assertNull(data.textContent); assertNull(data.textContent);
} }
public void testStringNotEqual() {
// Pairs that are "equal"
assertFalse(LegacyConversions.stringNotEqual(null, null));
assertFalse(LegacyConversions.stringNotEqual(null, ""));
assertFalse(LegacyConversions.stringNotEqual("", null));
assertFalse(LegacyConversions.stringNotEqual("", ""));
assertFalse(LegacyConversions.stringNotEqual("string-equal", "string-equal"));
// Pairs that are "inequal"
assertTrue(LegacyConversions.stringNotEqual(null, "string-inequal"));
assertTrue(LegacyConversions.stringNotEqual("", "string-inequal"));
assertTrue(LegacyConversions.stringNotEqual("string-inequal", null));
assertTrue(LegacyConversions.stringNotEqual("string-inequal", ""));
assertTrue(LegacyConversions.stringNotEqual("string-inequal-a", "string-inequal-b"));
}
} }