/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 *
 * Created on Mar 12, 2004
 */
package org.jboss.net.axis.transport.mailto.client;

import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.message.addressing.AddressingHeaders;
import org.apache.axis.message.addressing.Constants;
import org.apache.axis.message.addressing.MessageID;

/**
 * <dl>
 * <dt><b>Title: </b><dd>Client Side Email Transport</dd>
 * <p>
 * <dt><b>Description: </b><dd>This transport uses the asynchronous capabilities of axis to send a request. This
 * transport works in cooperation with the AsyncMailClientService. The call is created in the normal way, but rather than
 * issuing a call.invoke() the call is passed to the AsyncMailClinetService along with a callback, and its arguments.
 * the service starts a new thread that invokes the call. The call progresses normally until it gets to the transport
 * (here) where the request is sent, but then the thread is put to sleep. The AsyncMailClientService keeps a reference
 * to the MessageContext of every message it has sent. Every so often, the service checks the inbox for messages that
 * correlate to ones it has sent. When it finds one of these response messages, it adds it to the corresponding
 * message context, and notifies the thread. If the thread wakes up on it's own, it assumes that no response has been
 * received and faults.</dd>
 * <p>
 * </dl>
 * @author <a href="mailto:jasone@greenrivercomputing.com">Jason Essington</a>
 * @version $Revision: 1.1 $
 */
public class AsyncMailSender extends BaseMailSender
{

   public static final String TIMEOUT = "Timeout";
   public static final long DEFAULT_TIMEOUT = 1800000; // 30 minutes

   protected long getTimeout()
   {
      long timeout = DEFAULT_TIMEOUT;
      String to = (String) getOption(TIMEOUT);
      if (to != null)
      {
         try
         {
            timeout = Long.parseLong(to) * 60 * 1000;
         } catch (NumberFormatException e)
         {
            // this isn't really a big deal, we have a default timeout
            log.warn(to + "is not a valid number we will use 30 minutes instead.", e);
         }
      }
      return timeout;
   }

   private String getMessageID(MessageContext ctx)
   {
      String id = "no message-id";
      
      if (ctx.containsProperty(Constants.ENV_ADDRESSING_REQUEST_HEADERS))
      {
         AddressingHeaders headers = (AddressingHeaders) ctx.getProperty(Constants.ENV_ADDRESSING_REQUEST_HEADERS);
         MessageID msgid = headers.getMessageID();
         if (msgid != null)
         {
            id = msgid.toString();
         }
      }
      return id;
   }

   /**
    * Instead of checking mail, we'll just go to sleep, and when we wake up, hopefully a response message will have
    * appeared in our message context.
    * Really the response handling is done in the AsyncMailClientService
    */
   protected void checkResponse(MessageContext ctx) throws AxisFault
   {
      String id = getMessageID(ctx);
      
      if (log.isDebugEnabled())
         log.debug("Entering: checkResponse [" + id + "]");

      try
      {
         // nap time . . .
         Thread.sleep(getTimeout());

         // Whoa, nobody woke us up! Better pitch a fit.
         if (log.isDebugEnabled())
            log.debug("This request " + id + " timed out.");
         throw new AxisFault("Request Timed Out");
      }
      catch (InterruptedException e)
      {
         // O.K. I'm awake, *YAWN*
         if (log.isDebugEnabled())
            log.debug("The request " + id + " received a response.");
         
         //TODO Now we should be in State.Success. Maybe we should check for that?
      }
      if (log.isDebugEnabled())
         log.debug("Leaving: checkResponse [" + id + "]");
   }
}