From b55a273921d1e2391a80e45caced268bcb5a274c Mon Sep 17 00:00:00 2001 From: mguessan Date: Tue, 14 May 2013 20:35:29 +0000 Subject: [PATCH] POP: load big messages in a separate thread git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@2118 3d1905a2-6b24-0410-a738-b14d5a86fcbd --- .../davmail/exchange/MessageLoadThread.java | 73 +++++++++++++++++++ src/java/davmail/imap/ImapConnection.java | 51 +------------ src/java/davmail/pop/PopConnection.java | 7 ++ 3 files changed, 82 insertions(+), 49 deletions(-) create mode 100644 src/java/davmail/exchange/MessageLoadThread.java diff --git a/src/java/davmail/exchange/MessageLoadThread.java b/src/java/davmail/exchange/MessageLoadThread.java new file mode 100644 index 00000000..9a629ab4 --- /dev/null +++ b/src/java/davmail/exchange/MessageLoadThread.java @@ -0,0 +1,73 @@ +package davmail.exchange; + +import org.apache.log4j.Logger; + +import javax.mail.MessagingException; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Message load thread. + * Used to avoid timeouts over POP and IMAP + */ +public class MessageLoadThread extends Thread { + private static final Logger LOGGER = Logger.getLogger(MessageLoadThread.class); + + protected boolean isComplete = false; + protected ExchangeSession.Message message; + protected IOException ioException; + protected MessagingException messagingException; + + protected MessageLoadThread(String threadName, ExchangeSession.Message message) { + super(threadName + "-LoadMessage"); + setDaemon(true); + this.message = message; + } + + public void run() { + try { + message.loadMimeMessage(); + } catch (IOException e) { + ioException = e; + } catch (MessagingException e) { + messagingException = e; + } finally { + isComplete = true; + } + } + + /** + * Load mime message in a separate thread if over 1MB. + * Send a space character every ten seconds to avoid client timeouts + * + * @param message message + * @param outputStream output stream + * @throws IOException on error + * @throws MessagingException on error + */ + public static void loadMimeMessage(ExchangeSession.Message message, OutputStream outputStream) throws IOException, MessagingException { + if (message.size < 1024 * 1024) { + message.loadMimeMessage(); + } else { + LOGGER.debug("Load large message " + (message.size / 1024) + "KB uid " + message.getUid() + " imapUid " + message.getImapUid() + " in a separate thread"); + try { + MessageLoadThread messageLoadThread = new MessageLoadThread(currentThread().getName(), message); + messageLoadThread.start(); + while (!messageLoadThread.isComplete) { + messageLoadThread.join(10000); + LOGGER.debug("Still loading uid " + message.getUid() + " imapUid " + message.getImapUid()); + outputStream.write(' '); + outputStream.flush(); + } + if (messageLoadThread.ioException != null) { + throw messageLoadThread.ioException; + } + if (messageLoadThread.messagingException != null) { + throw messageLoadThread.messagingException; + } + } catch (InterruptedException e) { + throw new IOException(e + " " + e.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/src/java/davmail/imap/ImapConnection.java b/src/java/davmail/imap/ImapConnection.java index 3524e9ed..24e6ac39 100644 --- a/src/java/davmail/imap/ImapConnection.java +++ b/src/java/davmail/imap/ImapConnection.java @@ -30,6 +30,7 @@ import davmail.exception.HttpNotFoundException; import davmail.exception.InsufficientStorageException; import davmail.exchange.ExchangeSession; import davmail.exchange.ExchangeSessionFactory; +import davmail.exchange.MessageLoadThread; import davmail.ui.tray.DavGatewayTray; import davmail.util.IOUtil; import davmail.util.StringUtil; @@ -755,31 +756,6 @@ public class ImapConnection extends AbstractConnection { sendClient("* " + currentFolder.recent + " RECENT"); } - class MessageLoadThread extends Thread { - boolean isComplete = false; - ExchangeSession.Message message; - IOException ioException; - MessagingException messagingException; - - MessageLoadThread(String threadName, ExchangeSession.Message message) { - super(threadName + "-LoadMessage"); - setDaemon(true); - this.message = message; - } - - public void run() { - try { - message.loadMimeMessage(); - } catch (IOException e) { - ioException = e; - } catch (MessagingException e) { - messagingException = e; - } finally { - isComplete = true; - } - } - } - class MessageWrapper { protected OutputStream os; protected StringBuilder buffer; @@ -808,30 +784,7 @@ public class ImapConnection extends AbstractConnection { // flush current buffer os.write(buffer.toString().getBytes()); buffer.setLength(0); - if (message.size < 1024 * 1024) { - message.loadMimeMessage(); - } else { - LOGGER.debug("Load large message " +(message.size / 1024)+"KB uid "+ message.imapUid + " in a separate thread"); - try { - MessageLoadThread messageLoadThread = new MessageLoadThread(currentThread().getName(), message); - messageLoadThread.start(); - while (!messageLoadThread.isComplete) { - messageLoadThread.join(10000); - LOGGER.debug("Still loading " + message.imapUid); - os.write(' '); - os.flush(); - } - if (messageLoadThread.ioException != null) { - throw messageLoadThread.ioException; - } - if (messageLoadThread.messagingException != null) { - throw messageLoadThread.messagingException; - } - } catch (InterruptedException e) { - throw new IOException(e + " " + e.getMessage()); - } - } - + MessageLoadThread.loadMimeMessage(message, os); } } diff --git a/src/java/davmail/pop/PopConnection.java b/src/java/davmail/pop/PopConnection.java index 27926940..e89bf720 100644 --- a/src/java/davmail/pop/PopConnection.java +++ b/src/java/davmail/pop/PopConnection.java @@ -25,6 +25,7 @@ import davmail.Settings; import davmail.exchange.DoubleDotOutputStream; import davmail.exchange.ExchangeSession; import davmail.exchange.ExchangeSessionFactory; +import davmail.exchange.MessageLoadThread; import davmail.ui.tray.DavGatewayTray; import davmail.util.IOUtil; import org.apache.log4j.Logger; @@ -204,6 +205,12 @@ public class PopConnection extends AbstractConnection { sendOK(""); DoubleDotOutputStream doubleDotOutputStream = new DoubleDotOutputStream(os); ExchangeSession.Message message = messages.get(messageNumber); + + // load big messages in a separate thread + os.write("+OK ".getBytes()); + MessageLoadThread.loadMimeMessage(message, os); + sendClient(""); + IOUtil.write(message.getRawInputStream(), doubleDotOutputStream); doubleDotOutputStream.close(); if (Settings.getBooleanProperty("davmail.popMarkReadOnRetr")) {