/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@objectweb.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Initial developer(s): Florent BENOIT & Ludovic BERT
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package mailsb;

//import java
import java.rmi.RemoteException;

//import javax
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * Implementation of the mailer Session Bean. It uses javax.mail.Session This
 * bean is a statefull, and synchronized bean. The container uses the
 * SessionBean methods to notify the enterprise Bean instances of the instance's
 * life cycle events.
 * @author Florent Benoit
 * @author Ludovic Bert
 */
public class SessionMailerBean implements SessionBean {

    /**
     * Name of the bean
     */
    private String name = null;

    /**
     * Session context that the container provides for a session enterprise Bean
     * instance.
     */
    private SessionContext sessionContext = null;

    /**
     * Reference to the javax.mail.Message object which is the message to send
     * with javamail
     */
    private Message message = null;

    /* ========================= ejbCreate methods =========================== */

    /**
     * There must be one ejbCreate() method per create() method on the Home
     * interface, and with the same signature.
     * @param name the name of the bean
     */
    public void ejbCreate(String name) {
        this.name = name;
    }

    /* =============== javax.ejb.SessionBean 2.0 implementation ============== */

    /**
     * Set the associated session context. The container calls this method after
     * the instance creation. The enterprise Bean instance should store the
     * reference to the context object in an instance variable. This method is
     * called with no transaction context.
     * @param sessionContext A SessionContext interface for the instance.
     * @throws EJBException Thrown by the method to indicate a failure caused by
     *         a system-level error.
     * @throws java.rmi.RemoteException This exception is defined in the method
     *         signature to provide backward compatibility for applications
     *         written for the EJB 1.0 specification. Enterprise beans written
     *         for the EJB 1.1 specification should throw the
     *         javax.ejb.EJBException instead of this exception. Enterprise
     *         beans written for the EJB2.0 and higher specifications must throw
     *         the javax.ejb.EJBException instead of this exception.
     */
    public void setSessionContext(SessionContext sessionContext) throws EJBException, java.rmi.RemoteException {
        this.sessionContext = sessionContext;
    }

    /**
     * A container invokes this method before it ends the life of the session
     * object. This happens as a result of a client's invoking a remove
     * operation, or when a container decides to terminate the session object
     * after a timeout. This method is called with no transaction context.
     * @throws EJBException Thrown by the method to indicate a failure caused by
     *         a system-level error.
     * @throws java.rmi.RemoteException This exception is defined in the method
     *         signature to provide backward compatibility for enterprise beans
     *         written for the EJB 1.0 specification. Enterprise beans written
     *         for the EJB 1.1 specification should throw the
     *         javax.ejb.EJBException instead of this exception. Enterprise
     *         beans written for the EJB2.0 and higher specifications must throw
     *         the javax.ejb.EJBException instead of this exception.
     */
    public void ejbRemove() throws EJBException, java.rmi.RemoteException {
        // Nothing to do for this simple mailer example
    }

    /**
     * The activate method is called when the instance is activated from its
     * "passive" state. The instance should acquire any resource that it has
     * released earlier in the ejbPassivate() method. This method is called with
     * no transaction context.
     * @throws EJBException Thrown by the method to indicate a failure caused by
     *         a system-level error.
     * @throws java.rmi.RemoteException This exception is defined in the method
     *         signature to provide backward compatibility for enterprise beans
     *         written for the EJB 1.0 specification. Enterprise beans written
     *         for the EJB 1.1 specification should throw the
     *         javax.ejb.EJBException instead of this exception. Enterprise
     *         beans written for the EJB2.0 and higher specifications must throw
     *         the javax.ejb.EJBException instead of this exception.
     */
    public void ejbActivate() throws EJBException, java.rmi.RemoteException {
        // Nothing to do for this simple mailer example
    }

    /**
     * The passivate method is called before the instance enters the "passive"
     * state. The instance should release any resources that it can re-acquire
     * later in the ejbActivate() method. After the passivate method completes,
     * the instance must be in a state that allows the container to use the Java
     * Serialization protocol to externalize and store away the instance's
     * state. This method is called with no transaction context.
     * @throws EJBException Thrown by the method to indicate a failure caused by
     *         a system-level error.
     * @throws java.rmi.RemoteException This exception is defined in the method
     *         signature to provide backward compatibility for enterprise beans
     *         written for the EJB 1.0 specification. Enterprise beans written
     *         for the EJB 1.1 specification should throw the
     *         javax.ejb.EJBException instead of this exception. Enterprise
     *         beans written for the EJB2.0 and higher specifications must throw
     *         the javax.ejb.EJBException instead of this exception.
     */
    public void ejbPassivate() throws EJBException, java.rmi.RemoteException {
        // Nothing to do for this simple mailer example
    }

    /* ======================== Mailer implementation ======================== */

    /**
     * Set the message with a specific recipient, subject and content.
     * @param recipient the 'TO' field of the message.
     * @param subject the subject of the message.
     * @param content the content of the message.
     * @throws Exception if a problem occurs.
     * @throws RemoteException if the call failed.
     */
    public void setMessage(String recipient, String subject, String content) throws Exception, RemoteException {

        //Get the initial context
        InitialContext ictx = null;
        try {
            ictx = new InitialContext();
        } catch (NamingException e) {
            throw new Exception("Can not get an inital context : " + e.getMessage());
        }

        //get a new Session from our ENC envirnoment java:comp/env
        Session session = null;
        try {
            session = (Session) ictx.lookup("java:comp/env/mail/MailSession");
        } catch (NamingException e) {
            throw new Exception("You have not configure the mail factory with the name specified"
                    + " in the jonas-ejb-jar.xml file for java:comp/env/mail/MailSession ."
                    + " By default, the factory's name is mailSession_1 :" + e.getMessage());
        }

        try {
            //Create the message
            message = new MimeMessage(session);
            InternetAddress[] toRecipients = new InternetAddress[] {new InternetAddress(recipient)};
            /*
             * try { toRecipients[0].validate(); } catch (AddressException e) {
             * throw new Exception("A failure occurs when validating the email
             * address '" + recipient + "' :" + e.getMessage()); }
             */
            message.setRecipients(Message.RecipientType.TO, toRecipients);
            message.setSubject(subject);
            message.setContent(content, "text/plain");
        } catch (MessagingException e) {
            throw new Exception("A failure occurs when getting a message from the session and setting "
                    + "the different parameters :" + e.getMessage());
        }

    }

    /**
     * Send the message which was previously configured.
     * @throws Exception if a problem occurs.
     * @throws RemoteException if the send failed.
     */
    public void send() throws Exception, RemoteException {

        if (message == null) {
            throw new Exception("The message can not be send because the method setMessage() "
                    + " was not called before the send() method.");
        }

        try {
            Transport.send(message);
        } catch (MessagingException e) {
            throw new Exception("The message can not be send : " + e.getMessage());
        }
    }

}