Coverage Report - org.mule.providers.email.RetrieveMessageReceiver
 
Classes in this File Line Coverage Branch Coverage Complexity
RetrieveMessageReceiver
58%
70/120
37%
19/52
3.429
 
 1  
 /*
 2  
  * $Id: RetrieveMessageReceiver.java 10330 2008-01-15 15:32:02Z holger $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.providers.email;
 12  
 
 13  
 import org.mule.MuleManager;
 14  
 import org.mule.impl.MuleMessage;
 15  
 import org.mule.providers.AbstractPollingMessageReceiver;
 16  
 import org.mule.providers.email.i18n.EmailMessages;
 17  
 import org.mule.umo.UMOComponent;
 18  
 import org.mule.umo.UMOException;
 19  
 import org.mule.umo.UMOMessage;
 20  
 import org.mule.umo.endpoint.UMOEndpoint;
 21  
 import org.mule.umo.lifecycle.InitialisationException;
 22  
 import org.mule.umo.lifecycle.Startable;
 23  
 import org.mule.umo.lifecycle.Stoppable;
 24  
 import org.mule.umo.provider.ReceiveException;
 25  
 import org.mule.umo.provider.UMOConnector;
 26  
 import org.mule.umo.routing.RoutingException;
 27  
 import org.mule.util.FileUtils;
 28  
 import org.mule.util.StringUtils;
 29  
 import org.mule.util.UUID;
 30  
 
 31  
 import java.io.File;
 32  
 import java.io.FileOutputStream;
 33  
 import java.io.IOException;
 34  
 
 35  
 import javax.mail.Address;
 36  
 import javax.mail.Flags;
 37  
 import javax.mail.Folder;
 38  
 import javax.mail.Message;
 39  
 import javax.mail.MessagingException;
 40  
 import javax.mail.Store;
 41  
 import javax.mail.event.MessageCountEvent;
 42  
 import javax.mail.event.MessageCountListener;
 43  
 import javax.mail.internet.InternetAddress;
 44  
 import javax.mail.internet.MimeMessage;
 45  
 
 46  
 /**
 47  
  * Poll a mailbox for messages, remove the messages and route them as events into Mule.
 48  
  *
 49  
  * This contains a reference to a mail folder (and also the endpoint and connector, via superclasses)
 50  
  */
 51  
 
 52  
 public class RetrieveMessageReceiver extends AbstractPollingMessageReceiver
 53  
     implements MessageCountListener, Startable, Stoppable
 54  
 {
 55  26
     private Folder folder = null;
 56  
     private boolean backupEnabled;
 57  26
     private String backupFolder = null;
 58  
 
 59  
     public RetrieveMessageReceiver(UMOConnector connector,
 60  
                                    UMOComponent component,
 61  
                                    UMOEndpoint endpoint,
 62  
                                    long checkFrequency,
 63  
                                    boolean backupEnabled,
 64  
                                    String backupFolder)
 65  
     throws InitialisationException
 66  
     {
 67  26
         super(connector, component, endpoint);
 68  26
         this.backupFolder = backupFolder;
 69  26
         this.backupEnabled = backupEnabled;
 70  26
         this.setFrequency(checkFrequency);
 71  26
     }
 72  
 
 73  
     private AbstractRetrieveMailConnector castConnector()
 74  
     {
 75  56
         return (AbstractRetrieveMailConnector) getConnector();
 76  
     }
 77  
 
 78  
     protected void doConnect() throws Exception
 79  
     {
 80  14
         SessionDetails session = castConnector().getSessionDetails(endpoint);
 81  
 
 82  14
         Store store = session.newStore();
 83  14
         store.connect();
 84  14
         folder = store.getFolder(castConnector().getMailboxFolder());
 85  
 
 86  
         // set default value if empty/null
 87  14
         if (StringUtils.isEmpty(backupFolder))
 88  
         {
 89  14
             this.backupFolder = 
 90  
                 MuleManager.getConfiguration().getWorkingDirectory() + "/mail/" + folder.getName();
 91  
         }
 92  
 
 93  14
         if (backupFolder != null && !this.backupFolder.endsWith(File.separator))
 94  
         {
 95  14
             this.backupFolder += File.separator;
 96  
         }
 97  14
     }
 98  
 
 99  
     protected void doDisconnect() throws Exception
 100  
     {
 101  
         // nothing to do here
 102  14
     }
 103  
 
 104  
     protected void doStop()
 105  
     {
 106  14
         if (folder != null)
 107  
         {
 108  14
             folder.removeMessageCountListener(this);
 109  
         }
 110  14
     }
 111  
 
 112  
     protected void doStart() throws UMOException
 113  
     {
 114  14
         super.doStart();
 115  14
         folder.addMessageCountListener(this);
 116  14
     }
 117  
 
 118  
     public void messagesAdded(MessageCountEvent event)
 119  
     {
 120  14
         Message messages[] = event.getMessages();
 121  14
         if (messages != null)
 122  
         {
 123  14
             UMOMessage message = null;
 124  28
             for (int i = 0; i < messages.length; i++)
 125  
             {
 126  
                 try
 127  
                 {
 128  14
                     if (!messages[i].getFlags().contains(Flags.Flag.DELETED))
 129  
                     {
 130  14
                         MimeMessage mimeMessage = new MimeMessage((MimeMessage) messages[i]);
 131  14
                         storeMessage(mimeMessage);
 132  14
                         message = new MuleMessage(castConnector().getMessageAdapter(mimeMessage));
 133  
 
 134  14
                         if (castConnector().isDeleteReadMessages())
 135  
                         {
 136  
                             // Mark as deleted
 137  14
                             messages[i].setFlag(Flags.Flag.DELETED, true);
 138  
                         }
 139  
                         else
 140  
                         {
 141  0
                             messages[i].setFlag(Flags.Flag.SEEN, true);
 142  
                         }
 143  14
                         routeMessage(message, endpoint.isSynchronous());
 144  
                     }
 145  
                 }
 146  0
                 catch (UMOException e)
 147  
                 {
 148  0
                     handleException(e);
 149  
                 }
 150  0
                 catch (Exception e)
 151  
                 {
 152  
                     Exception forwarded;
 153  
 
 154  0
                     if (message != null)
 155  
                     {
 156  0
                         forwarded = new RoutingException(EmailMessages.routingError(), message, endpoint, e);
 157  
                     }
 158  
                     else
 159  
                     {
 160  0
                         forwarded = new ReceiveException(endpoint, -1, e);
 161  
                     }
 162  
 
 163  0
                     handleException(forwarded);
 164  14
                 }
 165  
             }
 166  
         }
 167  14
     }
 168  
 
 169  
     // @Override
 170  
     protected UMOMessage handleUnacceptedFilter(UMOMessage message)
 171  
     {
 172  0
         super.handleUnacceptedFilter(message);
 173  0
         if (message.getPayload() instanceof Message)
 174  
         {
 175  0
             Message msg = (Message) message.getPayload();
 176  
             try
 177  
             {
 178  0
                 msg.setFlag(Flags.Flag.DELETED, endpoint.isDeleteUnacceptedMessages());
 179  
             }
 180  0
             catch (MessagingException e)
 181  
             {
 182  0
                 logger.error("failed to set message deleted: " + e.getMessage(), e);
 183  0
             }
 184  
         }
 185  0
         return message;
 186  
     }
 187  
 
 188  
     public void messagesRemoved(MessageCountEvent event)
 189  
     {
 190  0
         if (logger.isDebugEnabled())
 191  
         {
 192  0
             Message messages[] = event.getMessages();
 193  0
             for (int i = 0; i < messages.length; i++)
 194  
             {
 195  
                 try
 196  
                 {
 197  0
                     logger.debug("Message removed: " + messages[i].getSubject());
 198  
                 }
 199  0
                 catch (MessagingException ignore)
 200  
                 {
 201  0
                     logger.debug("ignoring exception: " + ignore.getMessage());
 202  0
                 }
 203  
             }
 204  
         }
 205  0
     }
 206  
 
 207  
     /**
 208  
      * @return the current Mail folder
 209  
      */
 210  
     public Folder getFolder()
 211  
     {
 212  0
         return folder;
 213  
     }
 214  
 
 215  
     /**
 216  
      * @param folder
 217  
      */
 218  
     public synchronized void setFolder(Folder folder)
 219  
     {
 220  0
         if (folder == null)
 221  
         {
 222  0
             throw new IllegalArgumentException("Mail folder cannot be null");
 223  
         }
 224  0
         this.folder = folder;
 225  0
         synchronized (this.folder)
 226  
         {
 227  0
             if (!this.folder.isOpen())
 228  
             {
 229  
                 try
 230  
                 {
 231  0
                     this.folder.open(Folder.READ_WRITE);
 232  
                 }
 233  0
                 catch (MessagingException e)
 234  
                 {
 235  0
                     logger.warn("Failed to open folder: " + folder.getFullName(), e);
 236  0
                 }
 237  
             }
 238  0
         }
 239  0
     }
 240  
 
 241  
     /**
 242  
      * Helper method for testing which stores a copy of the message locally as the
 243  
      * POP3 <p/> message will be deleted from the server
 244  
      * 
 245  
      * @param msg the message to store
 246  
      * @throws IOException If a failure happens writing the message
 247  
      * @throws MessagingException If a failure happens reading the message
 248  
      */
 249  
     protected void storeMessage(Message msg) throws IOException, MessagingException
 250  
     {
 251  14
         if (backupEnabled)
 252  
         {
 253  2
             String filename = msg.getFileName();
 254  2
             if (filename == null)
 255  
             {
 256  2
                 Address[] from = msg.getFrom();
 257  2
                 if (from != null && from.length > 0)
 258  
                 {
 259  0
                     filename = from[0] instanceof InternetAddress
 260  
                     ? ((InternetAddress) from[0]).getAddress()
 261  
                     : from[0].toString();
 262  
                 }
 263  
                 else
 264  
                 {
 265  2
                     filename = "(no from address)";
 266  
                 }
 267  2
                 filename += "[" + UUID.getUUID() + "]";
 268  
             }
 269  2
             filename = FileUtils.prepareWinFilename(filename);
 270  2
             filename = backupFolder + filename + ".msg";
 271  2
             if (logger.isDebugEnabled())
 272  
             {
 273  0
                 logger.debug("Writing message to: " + filename);
 274  
             }
 275  2
             File f = FileUtils.createFile(filename);
 276  2
             FileOutputStream fos = new FileOutputStream(f);
 277  2
             msg.writeTo(fos);
 278  
         }
 279  14
     }
 280  
 
 281  
     public synchronized void poll()
 282  
     {
 283  
         try
 284  
         {
 285  
             try
 286  
             {
 287  14
                 if (!folder.isOpen())
 288  
                 {
 289  14
                     folder.open(Folder.READ_WRITE);
 290  
                 }
 291  
             }
 292  0
             catch (Exception e)
 293  
             {
 294  0
                 if (logger.isDebugEnabled())
 295  
                 {
 296  0
                     logger.debug("ignoring exception: " + e.getMessage());
 297  
                 }
 298  14
             }
 299  
 
 300  14
             int count = folder.getMessageCount();
 301  14
             if (count > 0)
 302  
             {
 303  14
                 Message[] messages = folder.getMessages();
 304  14
                 MessageCountEvent event = new MessageCountEvent(folder, MessageCountEvent.ADDED, true,
 305  
                     messages);
 306  14
                 messagesAdded(event);
 307  14
             }
 308  0
             else if (count == -1)
 309  
             {
 310  0
                 throw new MessagingException("Cannot monitor folder: " + folder.getFullName()
 311  
                     + " as folder is closed");
 312  
             }
 313  
         }
 314  0
         catch (MessagingException e)
 315  
         {
 316  0
             handleException(e);
 317  
         }
 318  
         finally
 319  
         {
 320  0
             try
 321  
             {
 322  14
                 folder.close(true); // close and expunge deleted messages
 323  
             }
 324  5
             catch (Exception e)
 325  
             {
 326  5
                 logger.error("Failed to close pop3  inbox: " + e.getMessage());
 327  9
             }
 328  5
         }
 329  14
     }
 330  
 
 331  
     protected void doDispose()
 332  
     {
 333  26
         if (null != folder)
 334  
         {
 335  14
             folder.removeMessageCountListener(this);
 336  14
             if (folder.isOpen())
 337  
             {
 338  
                 try
 339  
                 {
 340  
 
 341  0
                     folder.close(true);
 342  
                 }
 343  0
                 catch (Exception e)
 344  
                 {
 345  0
                     logger.debug("ignoring exception: " + e.getMessage(), e);
 346  0
                 }
 347  
             }
 348  
         }
 349  26
     }
 350  
 
 351  
 }