Coverage Report - org.mule.transport.email.AbstractMailConnector
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractMailConnector
0%
0/82
0%
0/32
0
 
 1  
 /*
 2  
  * $Id: AbstractMailConnector.java 20072 2010-11-04 18:12:14Z mike.schilling $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.transport.email;
 12  
 
 13  
 import org.mule.api.MuleContext;
 14  
 import org.mule.api.MuleException;
 15  
 import org.mule.api.endpoint.EndpointURI;
 16  
 import org.mule.api.endpoint.ImmutableEndpoint;
 17  
 import org.mule.api.lifecycle.InitialisationException;
 18  
 import org.mule.transport.AbstractConnector;
 19  
 import org.mule.util.PropertiesUtils;
 20  
 import org.mule.util.StringUtils;
 21  
 
 22  
 import java.io.UnsupportedEncodingException;
 23  
 import java.net.URLDecoder;
 24  
 import java.util.Enumeration;
 25  
 import java.util.HashMap;
 26  
 import java.util.Map;
 27  
 import java.util.Properties;
 28  
 
 29  
 import javax.mail.Authenticator;
 30  
 import javax.mail.Session;
 31  
 import javax.mail.URLName;
 32  
 
 33  
 /**
 34  
  * Abstract superclass for mail connectors. Provides Mule with an Authenticator
 35  
  * object and other shared functionality like e.g. MuleSession creation.
 36  
  */
 37  
 public abstract class AbstractMailConnector extends AbstractConnector
 38  
 {
 39  
     public static final String ATTACHMENT_HEADERS_PROPERTY_POSTFIX = "Headers";
 40  
     public static final String MAILBOX = "INBOX";
 41  
 
 42  0
     private Map<ImmutableEndpoint, SessionDetails> sessions = new HashMap<ImmutableEndpoint, SessionDetails>();
 43  
     private String mailboxFolder;
 44  
     private int defaultPort;
 45  
 
 46  
     /**
 47  
      * A custom authenticator to be used on any mail sessions created with this
 48  
      * connector. This will only be used if user name credendials are set on the
 49  
      * endpoint.
 50  
      */
 51  0
     private Authenticator authenticator = null;
 52  
 
 53  
     public AbstractMailConnector(int defaultPort, String mailboxFolder, MuleContext context)
 54  
     {
 55  0
         super(context);
 56  0
         this.defaultPort = defaultPort;
 57  0
         this.mailboxFolder = mailboxFolder;
 58  0
     }
 59  
 
 60  
     public int getDefaultPort()
 61  
     {
 62  0
         return defaultPort;
 63  
     }
 64  
 
 65  
     public Authenticator getAuthenticator()
 66  
     {
 67  0
         return authenticator;
 68  
     }
 69  
 
 70  
     public void setAuthenticator(Authenticator authenticator)
 71  
     {
 72  0
         this.authenticator = authenticator;
 73  0
     }
 74  
     
 75  
     public String getMailboxFolder()
 76  
     {
 77  0
         return mailboxFolder;
 78  
     }
 79  
 
 80  
     public void setMailboxFolder(String mailboxFolder)
 81  
     {
 82  0
         this.mailboxFolder = mailboxFolder;
 83  0
     }
 84  
 
 85  
     public SessionDetails getSessionDetails(ImmutableEndpoint endpoint) throws UnsupportedEncodingException
 86  
     {
 87  
         // do not use this connector's implicit mutex by making this method synchronized. This
 88  
         // may interfere with other methods using the same mutex for different purposes.
 89  0
         synchronized (sessions)
 90  
         {
 91  0
             SessionDetails sessionDetails = sessions.get(endpoint);
 92  0
             if (null == sessionDetails)
 93  
             {
 94  0
                 sessionDetails = newSession(endpoint);
 95  0
                 sessions.put(endpoint, sessionDetails);
 96  
             }
 97  0
             return sessionDetails;
 98  0
         }
 99  
     }
 100  
     
 101  
     public URLName urlFromEndpoint(ImmutableEndpoint endpoint) throws UnsupportedEncodingException
 102  
     {
 103  0
         String inbox = endpoint.getEndpointURI().getPath();
 104  0
         if (inbox.length() == 0)
 105  
         {
 106  0
             inbox = getMailboxFolder();
 107  
         }
 108  
         else
 109  
         {
 110  0
             inbox = inbox.substring(1);
 111  
         }
 112  
 
 113  0
         EndpointURI uri = endpoint.getEndpointURI();
 114  0
         String user = uri.getUser();
 115  0
         if (user != null)
 116  
         {
 117  0
             user = URLDecoder.decode(user, endpoint.getEncoding());
 118  
         }
 119  0
         String pass = uri.getPassword();
 120  0
         if (pass != null)
 121  
         {
 122  0
             pass = URLDecoder.decode(pass, endpoint.getEncoding());
 123  
         }
 124  
 
 125  0
         return new URLName(uri.getScheme(), uri.getHost(), uri.getPort(), inbox, user, pass);
 126  
     }
 127  
     
 128  
     /**
 129  
      * Some protocols (eg secure extensions) extend a "base" protocol.
 130  
      * Subclasses for such protocols should override this method.
 131  
      * 
 132  
      * @return the underlying (eg non-secure) protocol
 133  
      */
 134  
     protected String getBaseProtocol()
 135  
     {
 136  0
         return getProtocol();
 137  
     }
 138  
     
 139  
     /**
 140  
      * Subclasses should extend this to add further properties.  
 141  
      * Synchronization is managed outside this call (so no need to synchronize further on properties)
 142  
      * 
 143  
      * @param global system properties 
 144  
      * @param local local properties (specific to one session)
 145  
      * @param url the endpoint url
 146  
      */
 147  
     protected void extendPropertiesForSession(Properties global, Properties local, URLName url)
 148  
     {
 149  0
         int port = url.getPort();
 150  0
         if (port == -1)
 151  
         {
 152  0
             port = this.getDefaultPort();
 153  
         }
 154  0
         local.setProperty("mail." + getBaseProtocol() + ".socketFactory.port", Integer.toString(port));
 155  
 
 156  0
         if (StringUtils.isNotBlank(url.getPassword()))
 157  
         {
 158  0
             local.setProperty("mail." + getBaseProtocol() + ".auth", "true");
 159  0
             if (getAuthenticator() == null)
 160  
             {
 161  0
                 setAuthenticator(new DefaultAuthenticator(url.getUsername(), url.getPassword()));
 162  0
                 if (logger.isDebugEnabled())
 163  
                 {
 164  0
                     logger.debug("No Authenticator set on connector: " + getName() + "; using default.");
 165  
                 }
 166  
             }
 167  
         }
 168  
         else
 169  
         {
 170  0
             local.setProperty("mail." + getBaseProtocol() + ".auth", "false");
 171  
         }
 172  
         
 173  
         // TODO - i'm not at all certain that these properties (especially the ones
 174  
         // using the base protocol) are needed.  they are inherited from old, gnarly
 175  
         // code.
 176  
 
 177  0
         if (StringUtils.isNotBlank(url.getHost())) {
 178  0
             local.setProperty("mail." + getBaseProtocol() + ".host", url.getHost());
 179  
         }
 180  0
         local.setProperty("mail." + getBaseProtocol() + ".rsetbeforequit", "true");
 181  0
     }
 182  
 
 183  
     protected SessionDetails newSession(ImmutableEndpoint endpoint) throws UnsupportedEncodingException
 184  
     {
 185  0
         URLName url = urlFromEndpoint(endpoint);
 186  
 
 187  0
         Properties global = System.getProperties();
 188  0
         Properties local = new Properties();
 189  
         //Allow properties to be set on the endpoint
 190  0
         PropertiesUtils.getPropertiesWithPrefix(endpoint.getProperties(), "mail.", local);
 191  
         Session session;
 192  
 
 193  
         // make sure we do not mess with authentication set via system properties
 194  0
         synchronized (global)
 195  
         {
 196  0
             extendPropertiesForSession(global, local, url);
 197  0
             session = Session.getInstance(local, getAuthenticator());
 198  0
         }
 199  
 
 200  0
         if (logger.isDebugEnabled())
 201  
         {
 202  0
             local.setProperty("mail.debug", "true");
 203  
             
 204  0
             dumpProperties("MuleSession local properties", local, true);
 205  0
             dumpProperties("System global properties", global, true);
 206  0
             logger.debug("Creating mail session: host = " + url.getHost() + ", port = " + url.getPort()
 207  
                 + ", user = " + url.getUsername() + ", pass = " + url.getPassword());
 208  
         }
 209  
 
 210  0
         return new SessionDetails(session, url);
 211  
     }
 212  
     
 213  
     protected void dumpProperties(String title, Properties properties, boolean filter)
 214  
     {
 215  0
         int skipped = 0;
 216  0
         logger.debug(title + " =============");
 217  0
         Enumeration keys = properties.keys();
 218  0
         while (keys.hasMoreElements())
 219  
         {
 220  0
             String key = (String) keys.nextElement();
 221  0
             if (!filter || key.startsWith("mule.") || key.startsWith("mail.") || key.startsWith("javax."))
 222  
             {
 223  0
                 String value = properties.getProperty(key);
 224  0
                 logger.debug(key + ": " + value);
 225  0
             }
 226  
             else 
 227  
             {
 228  0
                 ++skipped;
 229  
             }
 230  0
         }
 231  0
         if (filter)
 232  
         {
 233  0
             logger.debug("skipped " + skipped);
 234  
         }
 235  0
     }
 236  
     
 237  
     // supply these here because sub-classes are very simple
 238  
 
 239  
     @Override
 240  
     protected void doInitialise() throws InitialisationException
 241  
     {
 242  
         // template method, nothing to do
 243  0
     }
 244  
 
 245  
     @Override
 246  
     protected void doDispose()
 247  
     {
 248  
         // template method, nothing to do
 249  0
     }
 250  
 
 251  
     @Override
 252  
     protected void doConnect() throws Exception
 253  
     {
 254  
         // template method, nothing to do
 255  0
     }
 256  
 
 257  
     @Override
 258  
     protected void doDisconnect() throws Exception
 259  
     {
 260  
         // template method, nothing to do
 261  0
     }
 262  
 
 263  
     @Override
 264  
     protected void doStart() throws MuleException
 265  
     {
 266  
         // template method, nothing to do
 267  0
     }
 268  
 
 269  
     @Override
 270  
     protected void doStop() throws MuleException
 271  
     {
 272  
         // template method, nothing to do
 273  0
     }
 274  
 
 275  
 }