Clover coverage report - Maven Clover report
Coverage timestamp: Sun Aug 20 2006 04:01:04 PDT
file stats: LOC: 204   Methods: 6
NCLOC: 101   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Transport.java 0% 1.9% 16.7% 2.3%
coverage coverage
 1    /**
 2    *
 3    * Copyright 2003-2004 The Apache Software Foundation
 4    *
 5    * Licensed under the Apache License, Version 2.0 (the "License");
 6    * you may not use this file except in compliance with the License.
 7    * You may obtain a copy of the License at
 8    *
 9    * http://www.apache.org/licenses/LICENSE-2.0
 10    *
 11    * Unless required by applicable law or agreed to in writing, software
 12    * distributed under the License is distributed on an "AS IS" BASIS,
 13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14    * See the License for the specific language governing permissions and
 15    * limitations under the License.
 16    */
 17   
 18    package javax.mail;
 19   
 20    import java.util.ArrayList;
 21    import java.util.HashMap;
 22    import java.util.Iterator;
 23    import java.util.List;
 24    import java.util.Map;
 25    import java.util.Vector;
 26    import javax.mail.event.TransportEvent;
 27    import javax.mail.event.TransportListener;
 28   
 29    /**
 30    * Abstract class modeling a message transport.
 31    *
 32    * @version $Rev: 382388 $ $Date: 2006-03-02 06:20:38 -0800 (Thu, 02 Mar 2006) $
 33    */
 34    public abstract class Transport extends Service {
 35    /**
 36    * Send a message to all recipient addresses it contains (as returned by {@link Message#getAllRecipients()})
 37    * using message transports appropriate for each address. Message addresses are checked during submission,
 38    * but there is no guarantee that the ultimate address is valid or that the message will ever be delivered.
 39    * <p/>
 40    * {@link Message#saveChanges()} will be called before the message is actually sent.
 41    *
 42    * @param message the message to send
 43    * @throws MessagingException if there was a problem sending the message
 44    */
 45  0 public static void send(Message message) throws MessagingException {
 46  0 send(message, message.getAllRecipients());
 47    }
 48   
 49    /**
 50    * Send a message to all addresses provided irrespective of any recipients contained in the message itself
 51    * using message transports appropriate for each address. Message addresses are checked during submission,
 52    * but there is no guarantee that the ultimate address is valid or that the message will ever be delivered.
 53    * <p/>
 54    * {@link Message#saveChanges()} will be called before the message is actually sent.
 55    *
 56    * @param message the message to send
 57    * @param addresses the addesses to send to
 58    * @throws MessagingException if there was a problem sending the message
 59    */
 60  0 public static void send(Message message, Address[] addresses) throws MessagingException {
 61  0 Session session = message.session;
 62  0 Map msgsByTransport = new HashMap();
 63  0 for (int i = 0; i < addresses.length; i++) {
 64  0 Address address = addresses[i];
 65  0 Transport transport = session.getTransport(address);
 66  0 List addrs = (List) msgsByTransport.get(transport);
 67  0 if (addrs == null) {
 68  0 addrs = new ArrayList();
 69  0 msgsByTransport.put(transport, addrs);
 70    }
 71  0 addrs.add(address);
 72    }
 73   
 74  0 message.saveChanges();
 75   
 76    // Since we might be sending to multiple protocols, we need to catch and process each exception
 77    // when we send and then throw a new SendFailedException when everything is done. Unfortunately, this
 78    // also means unwrapping the information in any SendFailedExceptions we receive and building
 79    // composite failed list.
 80  0 MessagingException chainedException = null;
 81  0 ArrayList sentAddresses = new ArrayList();
 82  0 ArrayList unsentAddresses = new ArrayList();
 83  0 ArrayList invalidAddresses = new ArrayList();
 84   
 85   
 86  0 for (Iterator i = msgsByTransport.entrySet().iterator(); i.hasNext();) {
 87  0 Map.Entry entry = (Map.Entry) i.next();
 88  0 Transport transport = (Transport) entry.getKey();
 89  0 List addrs = (List) entry.getValue();
 90  0 try {
 91    // we MUST connect to the transport before attempting to send.
 92  0 transport.connect();
 93  0 transport.sendMessage(message, (Address[]) addrs.toArray(new Address[addrs.size()]));
 94    // if we have to throw an exception because of another failure, these addresses need to
 95    // be in the valid list. Since we succeeded here, we can add these now.
 96  0 sentAddresses.addAll(addrs);
 97    } catch (SendFailedException e) {
 98    // a true send failure. The exception contains a wealth of information about
 99    // the failures, including a potential chain of exceptions explaining what went wrong. We're
 100    // going to send a new one of these, so we need to merge the information.
 101   
 102    // add this to our exception chain
 103  0 if (chainedException == null) {
 104  0 chainedException = e;
 105    }
 106    else {
 107  0 chainedException.setNextException(e);
 108    }
 109   
 110    // now extract each of the address categories from
 111  0 Address[] exAddrs = e.getValidSentAddresses();
 112  0 if (exAddrs != null) {
 113  0 for (int j = 0; j < exAddrs.length; j++) {
 114  0 sentAddresses.add(exAddrs[j]);
 115    }
 116    }
 117   
 118  0 exAddrs = e.getValidUnsentAddresses();
 119  0 if (exAddrs != null) {
 120  0 for (int j = 0; j < exAddrs.length; j++) {
 121  0 unsentAddresses.add(exAddrs[j]);
 122    }
 123    }
 124   
 125  0 exAddrs = e.getInvalidAddresses();
 126  0 if (exAddrs != null) {
 127  0 for (int j = 0; j < exAddrs.length; j++) {
 128  0 invalidAddresses.add(exAddrs[j]);
 129    }
 130    }
 131   
 132    } catch (MessagingException e) {
 133    // add this to our exception chain
 134  0 if (chainedException == null) {
 135  0 chainedException = e;
 136    }
 137    else {
 138  0 chainedException.setNextException(e);
 139    }
 140    }
 141    finally {
 142  0 transport.close();
 143    }
 144    }
 145   
 146    // if we have an exception chain then we need to throw a new exception giving the failure
 147    // information.
 148  0 if (chainedException != null) {
 149    // if we're only sending to a single transport (common), and we received a SendFailedException
 150    // as a result, then we have a fully formed exception already. Rather than wrap this in another
 151    // exception, we can just rethrow the one we have.
 152  0 if (msgsByTransport.size() == 1 && chainedException instanceof SendFailedException) {
 153  0 throw chainedException;
 154    }
 155   
 156    // create our lists for notification and exception reporting from this point on.
 157  0 Address[] sent = (Address[])sentAddresses.toArray(new Address[0]);
 158  0 Address[] unsent = (Address[])unsentAddresses.toArray(new Address[0]);
 159  0 Address[] invalid = (Address[])invalidAddresses.toArray(new Address[0]);
 160   
 161  0 throw new SendFailedException("Send failure", chainedException, sent, unsent, invalid);
 162    }
 163    }
 164   
 165    /**
 166    * Constructor taking Session and URLName parameters required for {@link Service#Service(Session, URLName)}.
 167    *
 168    * @param session the Session this transport is for
 169    * @param name the location this transport is for
 170    */
 171  3 public Transport(Session session, URLName name) {
 172  3 super(session, name);
 173    }
 174   
 175    /**
 176    * Send a message to the supplied addresses using this transport; if any of the addresses are
 177    * invalid then a {@link SendFailedException} is thrown. Whether the message is actually sent
 178    * to any of the addresses is undefined.
 179    * <p/>
 180    * Unlike the static {@link #send(Message, Address[])} method, {@link Message#saveChanges()} is
 181    * not called. A {@link TransportEvent} will be sent to registered listeners once the delivery
 182    * attempt has been made.
 183    *
 184    * @param message the message to send
 185    * @param addresses list of addresses to send it to
 186    * @throws SendFailedException if the send failed
 187    * @throws MessagingException if there was a problem sending the message
 188    */
 189    public abstract void sendMessage(Message message, Address[] addresses) throws MessagingException;
 190   
 191    private Vector transportListeners = new Vector();
 192   
 193  0 public void addTransportListener(TransportListener listener) {
 194  0 transportListeners.add(listener);
 195    }
 196   
 197  0 public void removeTransportListener(TransportListener listener) {
 198  0 transportListeners.remove(listener);
 199    }
 200   
 201  0 protected void notifyTransportListeners(int type, Address[] validSent, Address[] validUnsent, Address[] invalid, Message message) {
 202  0 queueEvent(new TransportEvent(this, type, validSent, validUnsent, invalid, message), transportListeners);
 203    }
 204    }