From 843125b98a8130069fb4cdca92029fed3e189e7b Mon Sep 17 00:00:00 2001 From: Andy Stadler Date: Tue, 5 May 2009 10:26:55 -0700 Subject: [PATCH] AI 148300: Reduce memory waste in getTextFromPart(), and improve error handling. Fix NPE's in loadMessageForViewBodyAvailable(). BUG=1831272 Automated import of CL 148300 --- .../android/email/activity/MessageView.java | 28 ++++++------ .../email/mail/internet/MimeUtility.java | 43 +++++++++++-------- .../email/activity/MessageViewTests.java | 6 ++- 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/com/android/email/activity/MessageView.java b/src/com/android/email/activity/MessageView.java index 132c37180..a0523790a 100644 --- a/src/com/android/email/activity/MessageView.java +++ b/src/com/android/email/activity/MessageView.java @@ -727,8 +727,8 @@ public class MessageView extends Activity */ /* package */ String resolveInlineImage(String text, Part part, int depth) throws MessagingException { - // avoid too deep recursive call. - if (depth >= 10) { + // avoid too deep recursive call or null text + if (depth >= 10 || text == null) { return text; } String contentType = MimeUtility.unfoldAndDecode(part.getContentType()); @@ -945,20 +945,22 @@ public class MessageView extends Activity * Linkify the plain text and convert it to HTML by replacing * \r?\n with
and adding a html/body wrapper. */ - Matcher m = Regex.WEB_URL_PATTERN.matcher(text); - StringBuffer sb = new StringBuffer(); - while (m.find()) { - int start = m.start(); - if (start != 0 && text.charAt(start - 1) != '@') { - m.appendReplacement(sb, "$0"); - } - else { - m.appendReplacement(sb, "$0"); + StringBuffer sb = new StringBuffer(""); + if (text != null) { + Matcher m = Regex.WEB_URL_PATTERN.matcher(text); + while (m.find()) { + int start = m.start(); + if (start != 0 && text.charAt(start - 1) != '@') { + m.appendReplacement(sb, "$0"); + } + else { + m.appendReplacement(sb, "$0"); + } } + m.appendTail(sb); } - m.appendTail(sb); + sb.append(""); text = sb.toString().replaceAll("\r?\n", "
"); - text = "" + text + ""; } /* diff --git a/src/com/android/email/mail/internet/MimeUtility.java b/src/com/android/email/mail/internet/MimeUtility.java index 008b60adf..1b0cb9f60 100644 --- a/src/com/android/email/mail/internet/MimeUtility.java +++ b/src/com/android/email/mail/internet/MimeUtility.java @@ -245,9 +245,9 @@ public class MimeUtility { /** * Reads the Part's body and returns a String based on any charset conversion that needed * to be done. - * @param part - * @return - * @throws IOException + * @param part The part containing a body + * @return a String containing the converted text in the body, or null if there was no text + * or an error during conversion. */ public static String getTextFromPart(Part part) { try { @@ -261,43 +261,48 @@ public class MimeUtility { */ ByteArrayOutputStream out = new ByteArrayOutputStream(); IOUtils.copy(in, out); - - byte[] bytes = out.toByteArray(); in.close(); - out.close(); + in = null; // we want all of our memory back, and close might not release - String charset = getHeaderParameter(part.getContentType(), "charset"); /* * We've got a text part, so let's see if it needs to be processed further. */ + String charset = getHeaderParameter(part.getContentType(), "charset"); if (charset != null) { /* * See if there is conversion from the MIME charset to the Java one. */ charset = CharsetUtil.toJavaCharset(charset); } - if (charset != null) { - /* - * We've got a charset encoding, so decode using it. - */ - return new String(bytes, 0, bytes.length, charset); - } - else { - /* - * No encoding, so use us-ascii, which is the standard. - */ - return new String(bytes, 0, bytes.length, "ASCII"); + /* + * No encoding, so use us-ascii, which is the standard. + */ + if (charset == null) { + charset = "ASCII"; } + /* + * Convert and return as new String + */ + String result = out.toString(charset); + out.close(); + return result; } } } + catch (OutOfMemoryError oom) { + /* + * If we are not able to process the body there's nothing we can do about it. Return + * null and let the upper layers handle the missing content. + */ + Log.e(Email.LOG_TAG, "Unable to getTextFromPart " + oom.toString()); + } catch (Exception e) { /* * If we are not able to process the body there's nothing we can do about it. Return * null and let the upper layers handle the missing content. */ - Log.e(Email.LOG_TAG, "Unable to getTextFromPart", e); + Log.e(Email.LOG_TAG, "Unable to getTextFromPart " + e.toString()); } return null; } diff --git a/tests/src/com/android/email/activity/MessageViewTests.java b/tests/src/com/android/email/activity/MessageViewTests.java index 8fad155cc..fd576ddbe 100644 --- a/tests/src/com/android/email/activity/MessageViewTests.java +++ b/tests/src/com/android/email/activity/MessageViewTests.java @@ -176,7 +176,7 @@ public class MessageViewTests final String actual1 = a.resolveInlineImage(text1, msg1, 0); assertEquals("one content id reference is not resolved", expected1, actual1); - + // Exceed recursive limit. final String actual0 = a.resolveInlineImage(text1, msg1, 10); assertEquals("recursive call limit may exceeded", @@ -231,6 +231,10 @@ public class MessageViewTests final String actual4 = a.resolveInlineImage(text2 + text1, msg4, 0); assertEquals("two content ids in deep multipart level are resolved", expected2 + expected1, actual4); + + // No crash on null text + final String actual5 = a.resolveInlineImage(null, msg4, 0); + assertNull(actual5); }