View Javadoc
1   package davmail.exchange;
2   
3   import davmail.Settings;
4   import org.apache.log4j.Logger;
5   
6   import javax.mail.MessagingException;
7   import java.io.IOException;
8   import java.io.OutputStream;
9   import java.net.SocketException;
10  
11  /**
12   * Message load thread.
13   * Used to avoid timeouts over POP and IMAP
14   */
15  public class MessageLoadThread extends Thread {
16      private static final Logger LOGGER = Logger.getLogger(MessageLoadThread.class);
17  
18      protected volatile boolean isComplete = false;
19      protected ExchangeSession.Message message;
20      protected IOException ioException;
21      protected MessagingException messagingException;
22  
23      protected MessageLoadThread(String threadName, ExchangeSession.Message message) {
24          super(threadName + "-LoadMessage");
25          setDaemon(true);
26          this.message = message;
27      }
28  
29      public void run() {
30          try {
31              message.loadMimeMessage();
32          } catch (IOException e) {
33              ioException = e;
34          } catch (MessagingException e) {
35              messagingException = e;
36          } finally {
37              isComplete = true;
38          }
39      }
40  
41      /**
42       * Load mime message in a separate thread if over 1MB.
43       * Send a space character every ten seconds to avoid client timeouts
44       *
45       * @param message      message
46       * @param outputStream output stream
47       * @throws IOException        on error
48       * @throws MessagingException on error
49       */
50      public static void loadMimeMessage(ExchangeSession.Message message, OutputStream outputStream) throws IOException, MessagingException {
51          if (message.size < 1024 * 1024) {
52              message.loadMimeMessage();
53          } else {
54              LOGGER.debug("Load large message " + (message.size / 1024) + "KB uid " + message.getUid() + " imapUid " + message.getImapUid() + " in a separate thread");
55              MessageLoadThread messageLoadThread = new MessageLoadThread(currentThread().getName(), message);
56              messageLoadThread.start();
57              while (!messageLoadThread.isComplete) {
58                  try {
59                      messageLoadThread.join(10000);
60                  } catch (InterruptedException e) {
61                      LOGGER.warn("Thread interrupted", e);
62                      Thread.currentThread().interrupt();
63                  }
64                  if (!messageLoadThread.isComplete) {
65                      LOGGER.debug("Still loading uid " + message.getUid() + " imapUid " + message.getImapUid());
66                      if (Settings.getBooleanProperty("davmail.enableKeepAlive", false)) {
67                          try {
68                              outputStream.write(' ');
69                              outputStream.flush();
70                          } catch (SocketException e) {
71                              // client closed connection, stop thread
72                              messageLoadThread.interrupt();
73                              try {
74                                  messageLoadThread.join(1000);
75                              } catch (InterruptedException ie) {
76                                  Thread.currentThread().interrupt();
77                              }
78                              message.dropMimeMessage();
79                              throw e;
80                          }
81                      }
82                  }
83              }
84              if (messageLoadThread.ioException != null) {
85                  throw messageLoadThread.ioException;
86              }
87              if (messageLoadThread.messagingException != null) {
88                  throw messageLoadThread.messagingException;
89              }
90          }
91      }
92  }