/*
 * JBoss, the OpenSource J2EE webOS
 * 
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.resource.adapter.jms.inflow.dlq;

import java.util.HashMap;

import javax.jms.Message;

/**
 * A Generic DLQ Handler
 * 
 * @author <a href="adrian@jboss.com">Adrian Brock</a>
 * @version $Revision: 1.1.2.1 $
 */
public class GenericDLQHandler extends JBossMQDLQHandler
{
   // Constants -----------------------------------------------------
   
   // Attributes ----------------------------------------------------
   
   /** Resent messages Map<MessageID, Integer> */
   protected HashMap resent = new HashMap();
   
   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   // Public --------------------------------------------------------
   
   // JBossMQDLQHandler overrides -----------------------------------

   public void messageDelivered(Message msg)
   {
      try
      {
         String id = msg.getJMSMessageID();
         if (id == null)
         {
            log.error("Message id is null? " + msg);
            return;
         }

         clearResentCounter(id);
      }
      catch (Throwable t)
      {
         log.warn("Unexpected error processing delivery notification " + msg, t);
      }
   }

   protected boolean handleDelivery(Message msg)
   {
      // Check for JBossMQ specific
      boolean handled = super.handleDelivery(msg);
      if (handled)
         return true;
      
      try
      {
         if (msg.propertyExists(JMS_JBOSS_REDELIVERY_COUNT))
            return false;

         String id = msg.getJMSMessageID();
         if (id == null)
         {
            log.error("Message id is null? " + msg);
            return false;
         }
         
         int count = incrementResentCounter(id);
         
         if (count > maxResent)
         {
            warnDLQ(msg, count, maxResent);
            clearResentCounter(id);
            return true;
         }
      }
      catch (Throwable t)
      {
         log.warn("Unexpected error checking whether dlq should be used " + msg, t);
      }
      
      return false;
   }

   // Protected -----------------------------------------------------
   
   /**
    * Increment the resent counter for the message id
    * 
    * @param id the message id of the message
    */
   protected int incrementResentCounter(String id)
   {
      ResentInfo info;
      synchronized (resent)
      {
         info = (ResentInfo) resent.get(id);
         if (info == null)
         {
            info = new ResentInfo();
            resent.put(id, info);
         }
      }
      return ++info.count;
   }
   
   /**
    * Remove the resent counter for the message id
    * 
    * @param id the message id of the message
    */
   protected void clearResentCounter(String id)
   {
      synchronized (resent)
      {
         resent.remove(id);
      }
   }
   
   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------
   
   /**
    * Resent Info
    */
   protected static class ResentInfo
   {
      int count = 0;
   }
}