messageview: use memory-backed body for decrpyted parts which are small and not attachments

This commit is contained in:
Vincent Breitmoser 2016-05-13 08:51:33 +02:00 committed by Vincent Breitmoser
parent a55db0f3cf
commit 6ceec725cb
2 changed files with 74 additions and 10 deletions

View file

@ -1,6 +1,7 @@
package com.fsck.k9.mailstore;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@ -8,13 +9,23 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.support.annotation.Nullable;
import android.util.Log;
import com.fsck.k9.K9;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.internet.SizeAware;
import org.apache.commons.io.output.DeferredFileOutputStream;
public class DecryptedTempFileBody extends BinaryAttachmentBody implements SizeAware {
public static final int MEMORY_BACKED_THRESHOLD = 1024 * 8;
private final File tempDirectory;
@Nullable
private File file;
@Nullable
private byte[] data;
public DecryptedTempFileBody(File tempDirectory, String transferEncoding) {
@ -27,14 +38,33 @@ public class DecryptedTempFileBody extends BinaryAttachmentBody implements SizeA
}
public OutputStream getOutputStream() throws IOException {
file = File.createTempFile("decrypted", null, tempDirectory);
return new FileOutputStream(file);
return new DeferredFileOutputStream(MEMORY_BACKED_THRESHOLD, "decrypted", null, tempDirectory) {
@Override
public void close() throws IOException {
super.close();
if (isThresholdExceeded()) {
file = getFile();
} else {
data = getData();
}
}
};
}
@Override
public InputStream getInputStream() throws MessagingException {
try {
return new FileInputStream(file);
if (file != null) {
Log.d(K9.LOG_TAG, "Decrypted data is file-backed.");
return new FileInputStream(file);
}
if (data != null) {
Log.d(K9.LOG_TAG, "Decrypted data is memory-backed.");
return new ByteArrayInputStream(data);
}
throw new IllegalStateException("Data must be fully written before it can be read!");
} catch (IOException ioe) {
throw new MessagingException("Unable to open body", ioe);
}
@ -42,10 +72,39 @@ public class DecryptedTempFileBody extends BinaryAttachmentBody implements SizeA
@Override
public long getSize() {
return file.length();
if (file != null) {
return file.length();
}
if (data != null) {
return data.length;
}
throw new IllegalStateException("Data must be fully written before it can be read!");
}
public File getFile() {
public File getFile() throws IOException {
if (file == null) {
writeMemoryToFile();
}
return file;
}
private void writeMemoryToFile() throws IOException {
if (file != null) {
throw new IllegalStateException("Body is already file-backed!");
}
if (data == null) {
throw new IllegalStateException("Data must be fully written before it can be read!");
}
Log.d(K9.LOG_TAG, "Writing body to file for attachment access");
file = File.createTempFile("decrypted", null, tempDirectory);
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);
fos.close();
data = null;
}
}

View file

@ -2,6 +2,7 @@ package com.fsck.k9.message.extractors;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -45,14 +46,18 @@ public class AttachmentInfoExtractor {
Body body = part.getBody();
if (body instanceof DecryptedTempFileBody) {
DecryptedTempFileBody decryptedTempFileBody = (DecryptedTempFileBody) body;
size = decryptedTempFileBody.getSize();
try {
size = decryptedTempFileBody.getSize();
File file = decryptedTempFileBody.getFile();
uri = K9FileProvider.getUriForFile(context, file, part.getMimeType());
File file = decryptedTempFileBody.getFile();
uri = K9FileProvider.getUriForFile(context, file, part.getMimeType());
} catch (IOException e) {
throw new MessagingException("Error preparing decrypted data as attachment", e);
}
return extractAttachmentInfo(part, uri, size);
} else {
throw new RuntimeException("Not supported");
throw new UnsupportedOperationException();
}
}