Save This Page
Home » glassfish-v2ur2-b04-src » javax » mail » [javadoc | source]
    1   /*
    2    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    3    *
    4    * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    5    *
    6    * The contents of this file are subject to the terms of either the GNU
    7    * General Public License Version 2 only ("GPL") or the Common Development
    8    * and Distribution License("CDDL") (collectively, the "License").  You
    9    * may not use this file except in compliance with the License. You can obtain
   10    * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
   11    * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
   12    * language governing permissions and limitations under the License.
   13    *
   14    * When distributing the software, include this License Header Notice in each
   15    * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
   16    * Sun designates this particular file as subject to the "Classpath" exception
   17    * as provided by Sun in the GPL Version 2 section of the License file that
   18    * accompanied this code.  If applicable, add the following below the License
   19    * Header, with the fields enclosed by brackets [] replaced by your own
   20    * identifying information: "Portions Copyrighted [year]
   21    * [name of copyright owner]"
   22    *
   23    * Contributor(s):
   24    *
   25    * If you wish your version of this file to be governed by only the CDDL or
   26    * only the GPL Version 2, indicate your decision by adding "[Contributor]
   27    * elects to include this software in this distribution under the [CDDL or GPL
   28    * Version 2] license."  If you don't indicate a single choice of license, a
   29    * recipient has the option to distribute your version of this file under
   30    * either the CDDL, the GPL Version 2 or to extend the choice of license to
   31    * its licensees as provided above.  However, if you add GPL Version 2 code
   32    * and therefore, elected the GPL Version 2 license, then the option applies
   33    * only if the new code is made subject to such option by the copyright
   34    * holder.
   35    */
   36   
   37   /*
   38    * @(#)Transport.java	1.40 07/05/17
   39    */
   40   
   41   package javax.mail;
   42   
   43   import java.io.IOException;
   44   import java.net;
   45   import java.util.Vector;
   46   import java.util.Hashtable;
   47   import java.util.Enumeration;
   48   import javax.mail.event;
   49   
   50   /**
   51    * An abstract class that models a message transport.
   52    * Subclasses provide actual implementations. <p>
   53    *
   54    * Note that <code>Transport</code> extends the <code>Service</code>
   55    * class, which provides many common methods for naming transports,
   56    * connecting to transports, and listening to connection events.
   57    *
   58    * @author John Mani
   59    * @author Max Spivak
   60    * @author Bill Shannon
   61    * @version 1.40, 07/05/17
   62    * 
   63    * @see javax.mail.Service
   64    * @see javax.mail.event.ConnectionEvent
   65    * @see javax.mail.event.TransportEvent
   66    */
   67   
   68   public abstract class Transport extends Service {
   69   
   70       /**
   71        * Constructor.
   72        *
   73        * @param	session Session object for this Transport.
   74        * @param	urlname	URLName object to be used for this Transport
   75        */
   76       public Transport(Session session, URLName urlname) {
   77   	super(session, urlname);
   78       }
   79   
   80       /**
   81        * Send a message.  The message will be sent to all recipient
   82        * addresses specified in the message (as returned from the
   83        * <code>Message</code> method <code>getAllRecipients</code>),
   84        * using message transports appropriate to each address.  The
   85        * <code>send</code> method calls the <code>saveChanges</code>
   86        * method on the message before sending it. <p>
   87        *
   88        * If any of the recipient addresses is detected to be invalid by
   89        * the Transport during message submission, a SendFailedException
   90        * is thrown. Clients can get more detail about the failure by examining
   91        * the exception. Whether or not the message is still sent succesfully to
   92        * any valid addresses depends on the Transport implementation. See 
   93        * SendFailedException for more details. Note also that success does 
   94        * not imply that the message was delivered to the ultimate recipient,
   95        * as failures may occur in later stages of delivery.  Once a Transport 
   96        * accepts a message for delivery to a recipient, failures that occur later
   97        * should be reported to the user via another mechanism, such as
   98        * returning the undeliverable message. <p>
   99        *
  100        * Note that <code>send</code> is a static method that creates and
  101        * manages its own connection.  Any connection associated with any
  102        * Transport instance used to invoke this method is ignored and not
  103        * used.  This method should only be invoked using the form
  104        * <code>Transport.send(msg);</code>, and should never be invoked
  105        * using an instance variable.
  106        *
  107        * @param	msg	the message to send
  108        * @exception	SendFailedException if the message could not
  109        *			be sent to some or any of the recipients.
  110        * @exception	MessagingException
  111        * @see		Message#saveChanges
  112        * @see		Message#getAllRecipients
  113        * @see		#send(Message, Address[])
  114        * @see		javax.mail.SendFailedException
  115        */
  116       public static void send(Message msg) throws MessagingException {
  117   	msg.saveChanges(); // do this first
  118   	send0(msg, msg.getAllRecipients());
  119       }
  120   
  121       /**
  122        * Send the message to the specified addresses, ignoring any
  123        * recipients specified in the message itself. The
  124        * <code>send</code> method calls the <code>saveChanges</code>
  125        * method on the message before sending it. <p>
  126        *
  127        * @param	msg	the message to send
  128        * @param	addresses the addresses to which to send the message
  129        * @exception	SendFailedException if the message could not
  130        *			be sent to some or any of the recipients.
  131        * @exception	MessagingException
  132        * @see		Message#saveChanges
  133        * @see             #send(Message)
  134        * @see		javax.mail.SendFailedException
  135        */
  136       public static void send(Message msg, Address[] addresses) 
  137   		throws MessagingException {
  138   
  139   	msg.saveChanges();
  140   	send0(msg, addresses);
  141       }
  142   
  143       // send, but without the saveChanges
  144       private static void send0(Message msg, Address[] addresses) 
  145   		throws MessagingException {
  146   
  147   	if (addresses == null || addresses.length == 0)
  148   	    throw new SendFailedException("No recipient addresses");
  149   
  150   	/*
  151   	 * protocols is a hashtable containing the addresses
  152   	 * indexed by address type
  153   	 */
  154   	Hashtable protocols = new Hashtable();
  155   
  156   	// Vectors of addresses
  157   	Vector invalid = new Vector();
  158   	Vector validSent = new Vector();
  159   	Vector validUnsent = new Vector();
  160   
  161   	for (int i = 0; i < addresses.length; i++) {
  162   	    // is this address type already in the hashtable?
  163   	    if (protocols.containsKey(addresses[i].getType())) {
  164   		Vector v = (Vector)protocols.get(addresses[i].getType());
  165   		v.addElement(addresses[i]);
  166   	    } else {
  167   		// need to add a new protocol
  168   		Vector w = new Vector();
  169   		w.addElement(addresses[i]);
  170   		protocols.put(addresses[i].getType(), w);
  171   	    }
  172   	}
  173   
  174   	int dsize = protocols.size();
  175   	if (dsize == 0)
  176   	    throw new SendFailedException("No recipient addresses");
  177   
  178   	Session s = (msg.session != null) ? msg.session :
  179   		     Session.getDefaultInstance(System.getProperties(), null);
  180   	Transport transport;
  181   
  182   	/*
  183   	 * Optimize the case of a single protocol.
  184   	 */
  185   	if (dsize == 1) {
  186   	    transport = s.getTransport(addresses[0]);
  187   	    try {
  188   		transport.connect();
  189   		transport.sendMessage(msg, addresses);
  190   	    } finally {
  191   		transport.close();
  192   	    }
  193   	    return;
  194   	}
  195   
  196   	/*
  197   	 * More than one protocol.  Have to do them one at a time
  198   	 * and collect addresses and chain exceptions.
  199   	 */
  200   	MessagingException chainedEx = null;
  201   	boolean sendFailed = false;
  202   
  203   	Enumeration e = protocols.elements();
  204   	while (e.hasMoreElements()) {
  205   	    Vector v = (Vector)e.nextElement();
  206   	    Address[] protaddresses = new Address[v.size()];
  207   	    v.copyInto(protaddresses);
  208   
  209   	    // Get a Transport that can handle this address type.
  210   	    if ((transport = s.getTransport(protaddresses[0])) == null) {
  211   		// Could not find an appropriate Transport ..
  212   		// Mark these addresses invalid.
  213   		for (int j = 0; j < protaddresses.length; j++)
  214   		    invalid.addElement(protaddresses[j]);
  215   		continue;
  216   	    }
  217   	    try {
  218   		transport.connect();
  219   		transport.sendMessage(msg, protaddresses);
  220   	    } catch (SendFailedException sex) {
  221   		sendFailed = true;
  222   		// chain the exception we're catching to any previous ones
  223   		if (chainedEx == null)
  224   		    chainedEx = sex;
  225   		else
  226   		    chainedEx.setNextException(sex);
  227   
  228   		// retrieve invalid addresses
  229   		Address[] a = sex.getInvalidAddresses();
  230   		if (a != null)
  231   		    for (int j = 0; j < a.length; j++) 
  232   			invalid.addElement(a[j]);
  233   
  234   		// retrieve validSent addresses
  235   		a = sex.getValidSentAddresses();
  236   		if (a != null)
  237   		    for (int k = 0; k < a.length; k++) 
  238   			validSent.addElement(a[k]);
  239   
  240   		// retrieve validUnsent addresses
  241   		Address[] c = sex.getValidUnsentAddresses();
  242   		if (c != null)
  243   		    for (int l = 0; l < c.length; l++) 
  244   			validUnsent.addElement(c[l]);
  245   	    } catch (MessagingException mex) {
  246   		sendFailed = true;
  247   		// chain the exception we're catching to any previous ones
  248   		if (chainedEx == null)
  249   		    chainedEx = mex;
  250   		else
  251   		    chainedEx.setNextException(mex);
  252   	    } finally {
  253   		transport.close();
  254   	    }
  255   	}
  256   
  257   	// done with all protocols. throw exception if something failed
  258   	if (sendFailed || invalid.size() != 0 || validUnsent.size() != 0) { 
  259   	    Address[] a = null, b = null, c = null;
  260   
  261   	    // copy address vectors into arrays
  262   	    if (validSent.size() > 0) {
  263   		a = new Address[validSent.size()];
  264   		validSent.copyInto(a);
  265   	    }
  266   	    if (validUnsent.size() > 0) {
  267   		b = new Address[validUnsent.size()];
  268   		validUnsent.copyInto(b);
  269   	    }
  270   	    if (invalid.size() > 0) {
  271   		c = new Address[invalid.size()];
  272   		invalid.copyInto(c);
  273   	    }
  274   	    throw new SendFailedException("Sending failed", chainedEx, 
  275   					  a, b, c);
  276   	}
  277       }
  278   
  279       /**
  280        * Send the Message to the specified list of addresses. An appropriate
  281        * TransportEvent indicating the delivery status is delivered to any 
  282        * TransportListener registered on this Transport. Also, if any of
  283        * the addresses is invalid, a SendFailedException is thrown.
  284        * Whether or not the message is still sent succesfully to
  285        * any valid addresses depends on the Transport implementation. <p>
  286        *
  287        * Unlike the static <code>send</code> method, the <code>sendMessage</code>
  288        * method does <em>not</em> call the <code>saveChanges</code> method on
  289        * the message; the caller should do so.
  290        *
  291        * @param msg	The Message to be sent
  292        * @param addresses	array of addresses to send this message to
  293        * @see 		javax.mail.event.TransportEvent
  294        * @exception SendFailedException if the send failed because of
  295        *			invalid addresses.
  296        * @exception MessagingException if the connection is dead or not in the 
  297        * 				connected state
  298        */
  299       public abstract void sendMessage(Message msg, Address[] addresses) 
  300   				throws MessagingException;
  301   
  302       // Vector of Transport listeners
  303       private Vector transportListeners = null;
  304   
  305       /**
  306        * Add a listener for Transport events. <p>
  307        *
  308        * The default implementation provided here adds this listener
  309        * to an internal list of TransportListeners.
  310        *
  311        * @param l         the Listener for Transport events
  312        * @see             javax.mail.event.TransportEvent
  313        */
  314       public synchronized void addTransportListener(TransportListener l) {
  315   	if (transportListeners == null)
  316   	    transportListeners = new Vector();
  317   	transportListeners.addElement(l);
  318       }
  319   
  320       /**
  321        * Remove a listener for Transport events. <p>
  322        *
  323        * The default implementation provided here removes this listener
  324        * from the internal list of TransportListeners.
  325        *
  326        * @param l         the listener
  327        * @see             #addTransportListener
  328        */
  329       public synchronized void removeTransportListener(TransportListener l) {
  330   	if (transportListeners != null)
  331   	    transportListeners.removeElement(l);
  332       }
  333   
  334       /**
  335        * Notify all TransportListeners. Transport implementations are
  336        * expected to use this method to broadcast TransportEvents.<p>
  337        *
  338        * The provided default implementation queues the event into
  339        * an internal event queue. An event dispatcher thread dequeues
  340        * events from the queue and dispatches them to the registered
  341        * TransportListeners. Note that the event dispatching occurs
  342        * in a separate thread, thus avoiding potential deadlock problems.
  343        */
  344       protected void notifyTransportListeners(int type, Address[] validSent,
  345   					    Address[] validUnsent,
  346   					    Address[] invalid, Message msg) {
  347   	if (transportListeners == null)
  348   	    return;
  349   	
  350   	TransportEvent e = new TransportEvent(this, type, validSent, 
  351   					      validUnsent, invalid, msg);
  352   	queueEvent(e, transportListeners);
  353       }
  354   }

Save This Page
Home » glassfish-v2ur2-b04-src » javax » mail » [javadoc | source]