/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.ejb.plugins;

import java.rmi.RemoteException;
import java.util.Map;

import org.jboss.ejb.Container;
import org.jboss.ejb.EnterpriseContext;
import org.jboss.ejb.InstancePool;
import org.jboss.ejb.MessageDrivenContainer;
import org.jboss.ejb.MethodInvocation;

/**
 * This container acquires an MDB instance and context.
 *
 * @author <a href="mailto:peter.antman@tim.se">Peter Antman</a>.
 * @author <a href="mailto:rickard.oberg@telkel.com">Rickard Öberg</a>
 * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
 * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
 * @version $Revision: 1.3.6.4 $
 */
public class MessageDrivenInstanceInterceptor
   extends AbstractInterceptor
{
   /** The container for this interceptor. */
   protected MessageDrivenContainer container;

   /**
    * Set the container for this interceptor.
    *
    * @param container    A <tt>MessageDrivenContainer</tt>.
    *
    * @throws ClassCastException    Not a <tt>MessageDrivenContainer</tt>.
    */
   public void setContainer(final Container container) 
   { 
      this.container = (MessageDrivenContainer)container; 
   }

   /**
    * Return the container for this interceptor.
    *
    * @return   The <tt>MessageDrivenContainer</tt> for this interceptor.
    */
   public Container getContainer()
   {
      return container;
   }
   
   /**
    * Message driven beans do not have homes.
    *
    * @throws Error    Not valid for MessageDriven beans.
    */
   public Object invokeHome(final MethodInvocation mi)
      throws Exception
   {
      throw new Error("Not valid for MessageDriven beans");
   }
   
   // Interceptor implementation --------------------------------------

   public Object invoke(final MethodInvocation mi)
      throws Exception
   {
      // Get context
      InstancePool pool = container.getInstancePool();
      EnterpriseContext ctx = pool.get();
      mi.setEnterpriseContext(ctx);
      
      // There is no need for synchronization since the instance is always
      // fresh also there should never be a tx associated with the instance.
      try
      {
         // Invoke through interceptors
         return getNext().invoke(mi);
      } catch (RuntimeException e) // Instance will be GC'ed at MI return
      {
         mi.setEnterpriseContext(null);
         pool.discard(ctx);
         throw e;
      } catch (RemoteException e) // Instance will be GC'ed at MI return
      {
         mi.setEnterpriseContext(null);
         pool.discard(ctx);
         throw e;
      } catch (Error e) // Instance will be GC'ed at MI return
      {
         mi.setEnterpriseContext(null);
         pool.discard(ctx);
         throw e;
      } finally
      {
         // Return context, when can this be null?
         ctx = mi.getEnterpriseContext();
         if( ctx != null )
            pool.free(ctx);
      }
   }
  // Monitorable implementation ------------------------------------
  public void sample(Object s)
  {
    // Just here to because Monitorable request it but will be removed soon
  }
  public Map retrieveStatistic()
  {
    return null;
  }
  public void resetStatistic()
  {
  }
}

