FileDocCategorySizeDatePackage
Transport.javaAPI DocGlassfish v2 API12644Wed May 23 10:57:54 BST 2007javax.mail

Transport

public abstract class Transport extends Service
An abstract class that models a message transport. Subclasses provide actual implementations.

Note that Transport extends the Service class, which provides many common methods for naming transports, connecting to transports, and listening to connection events.

author
John Mani
author
Max Spivak
author
Bill Shannon
version
1.40, 07/05/17
see
javax.mail.Service
see
javax.mail.event.ConnectionEvent
see
javax.mail.event.TransportEvent

Fields Summary
private Vector
transportListeners
Constructors Summary
public Transport(Session session, URLName urlname)
Constructor.

param
session Session object for this Transport.
param
urlname URLName object to be used for this Transport

	super(session, urlname);
    
Methods Summary
public synchronized voidaddTransportListener(javax.mail.event.TransportListener l)
Add a listener for Transport events.

The default implementation provided here adds this listener to an internal list of TransportListeners.

param
l the Listener for Transport events
see
javax.mail.event.TransportEvent


                                                           
         
	if (transportListeners == null)
	    transportListeners = new Vector();
	transportListeners.addElement(l);
    
protected voidnotifyTransportListeners(int type, javax.mail.Address[] validSent, javax.mail.Address[] validUnsent, javax.mail.Address[] invalid, Message msg)
Notify all TransportListeners. Transport implementations are expected to use this method to broadcast TransportEvents.

The provided default implementation queues the event into an internal event queue. An event dispatcher thread dequeues events from the queue and dispatches them to the registered TransportListeners. Note that the event dispatching occurs in a separate thread, thus avoiding potential deadlock problems.

	if (transportListeners == null)
	    return;
	
	TransportEvent e = new TransportEvent(this, type, validSent, 
					      validUnsent, invalid, msg);
	queueEvent(e, transportListeners);
    
public synchronized voidremoveTransportListener(javax.mail.event.TransportListener l)
Remove a listener for Transport events.

The default implementation provided here removes this listener from the internal list of TransportListeners.

param
l the listener
see
#addTransportListener

	if (transportListeners != null)
	    transportListeners.removeElement(l);
    
public static voidsend(Message msg)
Send a message. The message will be sent to all recipient addresses specified in the message (as returned from the Message method getAllRecipients), using message transports appropriate to each address. The send method calls the saveChanges method on the message before sending it.

If any of the recipient addresses is detected to be invalid by the Transport during message submission, a SendFailedException is thrown. Clients can get more detail about the failure by examining the exception. Whether or not the message is still sent succesfully to any valid addresses depends on the Transport implementation. See SendFailedException for more details. Note also that success does not imply that the message was delivered to the ultimate recipient, as failures may occur in later stages of delivery. Once a Transport accepts a message for delivery to a recipient, failures that occur later should be reported to the user via another mechanism, such as returning the undeliverable message.

Note that send is a static method that creates and manages its own connection. Any connection associated with any Transport instance used to invoke this method is ignored and not used. This method should only be invoked using the form Transport.send(msg);, and should never be invoked using an instance variable.

param
msg the message to send
exception
SendFailedException if the message could not be sent to some or any of the recipients.
exception
MessagingException
see
Message#saveChanges
see
Message#getAllRecipients
see
#send(Message, Address[])
see
javax.mail.SendFailedException

	msg.saveChanges(); // do this first
	send0(msg, msg.getAllRecipients());
    
public static voidsend(Message msg, javax.mail.Address[] addresses)
Send the message to the specified addresses, ignoring any recipients specified in the message itself. The send method calls the saveChanges method on the message before sending it.

param
msg the message to send
param
addresses the addresses to which to send the message
exception
SendFailedException if the message could not be sent to some or any of the recipients.
exception
MessagingException
see
Message#saveChanges
see
#send(Message)
see
javax.mail.SendFailedException


	msg.saveChanges();
	send0(msg, addresses);
    
private static voidsend0(Message msg, javax.mail.Address[] addresses)


	if (addresses == null || addresses.length == 0)
	    throw new SendFailedException("No recipient addresses");

	/*
	 * protocols is a hashtable containing the addresses
	 * indexed by address type
	 */
	Hashtable protocols = new Hashtable();

	// Vectors of addresses
	Vector invalid = new Vector();
	Vector validSent = new Vector();
	Vector validUnsent = new Vector();

	for (int i = 0; i < addresses.length; i++) {
	    // is this address type already in the hashtable?
	    if (protocols.containsKey(addresses[i].getType())) {
		Vector v = (Vector)protocols.get(addresses[i].getType());
		v.addElement(addresses[i]);
	    } else {
		// need to add a new protocol
		Vector w = new Vector();
		w.addElement(addresses[i]);
		protocols.put(addresses[i].getType(), w);
	    }
	}

	int dsize = protocols.size();
	if (dsize == 0)
	    throw new SendFailedException("No recipient addresses");

	Session s = (msg.session != null) ? msg.session :
		     Session.getDefaultInstance(System.getProperties(), null);
	Transport transport;

	/*
	 * Optimize the case of a single protocol.
	 */
	if (dsize == 1) {
	    transport = s.getTransport(addresses[0]);
	    try {
		transport.connect();
		transport.sendMessage(msg, addresses);
	    } finally {
		transport.close();
	    }
	    return;
	}

	/*
	 * More than one protocol.  Have to do them one at a time
	 * and collect addresses and chain exceptions.
	 */
	MessagingException chainedEx = null;
	boolean sendFailed = false;

	Enumeration e = protocols.elements();
	while (e.hasMoreElements()) {
	    Vector v = (Vector)e.nextElement();
	    Address[] protaddresses = new Address[v.size()];
	    v.copyInto(protaddresses);

	    // Get a Transport that can handle this address type.
	    if ((transport = s.getTransport(protaddresses[0])) == null) {
		// Could not find an appropriate Transport ..
		// Mark these addresses invalid.
		for (int j = 0; j < protaddresses.length; j++)
		    invalid.addElement(protaddresses[j]);
		continue;
	    }
	    try {
		transport.connect();
		transport.sendMessage(msg, protaddresses);
	    } catch (SendFailedException sex) {
		sendFailed = true;
		// chain the exception we're catching to any previous ones
		if (chainedEx == null)
		    chainedEx = sex;
		else
		    chainedEx.setNextException(sex);

		// retrieve invalid addresses
		Address[] a = sex.getInvalidAddresses();
		if (a != null)
		    for (int j = 0; j < a.length; j++) 
			invalid.addElement(a[j]);

		// retrieve validSent addresses
		a = sex.getValidSentAddresses();
		if (a != null)
		    for (int k = 0; k < a.length; k++) 
			validSent.addElement(a[k]);

		// retrieve validUnsent addresses
		Address[] c = sex.getValidUnsentAddresses();
		if (c != null)
		    for (int l = 0; l < c.length; l++) 
			validUnsent.addElement(c[l]);
	    } catch (MessagingException mex) {
		sendFailed = true;
		// chain the exception we're catching to any previous ones
		if (chainedEx == null)
		    chainedEx = mex;
		else
		    chainedEx.setNextException(mex);
	    } finally {
		transport.close();
	    }
	}

	// done with all protocols. throw exception if something failed
	if (sendFailed || invalid.size() != 0 || validUnsent.size() != 0) { 
	    Address[] a = null, b = null, c = null;

	    // copy address vectors into arrays
	    if (validSent.size() > 0) {
		a = new Address[validSent.size()];
		validSent.copyInto(a);
	    }
	    if (validUnsent.size() > 0) {
		b = new Address[validUnsent.size()];
		validUnsent.copyInto(b);
	    }
	    if (invalid.size() > 0) {
		c = new Address[invalid.size()];
		invalid.copyInto(c);
	    }
	    throw new SendFailedException("Sending failed", chainedEx, 
					  a, b, c);
	}
    
public abstract voidsendMessage(Message msg, javax.mail.Address[] addresses)
Send the Message to the specified list of addresses. An appropriate TransportEvent indicating the delivery status is delivered to any TransportListener registered on this Transport. Also, if any of the addresses is invalid, a SendFailedException is thrown. Whether or not the message is still sent succesfully to any valid addresses depends on the Transport implementation.

Unlike the static send method, the sendMessage method does not call the saveChanges method on the message; the caller should do so.

param
msg The Message to be sent
param
addresses array of addresses to send this message to
see
javax.mail.event.TransportEvent
exception
SendFailedException if the send failed because of invalid addresses.
exception
MessagingException if the connection is dead or not in the connected state