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

import org.jboss.mx.server.Invocation;
import org.jboss.mx.server.MBeanInvoker;

/**
 * Interceptor that provides access to the org.jboss.mx.server.Interceptable hooks
 * for dynamically adding and removing interceptors to an MBean.
 *
 * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>.
 * @version $Revision: 1.2.2.2 $
 */
public class DynamicInterceptor extends AbstractInterceptor
{
   /** methods implemented from org.jboss.mx.server.Interceptable */
   public static final String ADD_INTERCEPTOR = "addOperationInterceptor";
   public static final String REMOVE_INTERCEPTOR = "removeOperationInterceptor";

   /** the invoker implementing Interceptable */
   MBeanInvoker invoker;
   
   /**
    * CTOR
    */
   public DynamicInterceptor(MBeanInvoker invoker)
   {
      super("DynamicInterceptor");
      
      this.invoker = invoker;
   }

   /**
    * Do the trick
    */
   public Object invoke(Invocation invocation)
      throws Throwable
   {
      String type = invocation.getType();
      
      // implement Interceptable by delegating to MBeanInvoker
      if (type.equals(Invocation.OP_INVOKE))
      {
         String name = invocation.getName();
         
         if (name.equals(ADD_INTERCEPTOR))
         {
            Object args[] = invocation.getArgs();
            Object retn = invocation.getReturnTypeClass();
            
            if ((args.length == 1) && (args[0] instanceof Interceptor) && (retn == null))
            {
               invoker.addOperationInterceptor((Interceptor)args[0]);
               return null;
            }
         }
         else if (name.equals(REMOVE_INTERCEPTOR))
         {
            Object args[] = invocation.getArgs();
            Object retn = invocation.getReturnTypeClass();
            
            if ((args.length == 1) && (args[0] instanceof Interceptor) && (retn == null))
            {
               invoker.removeOperationInterceptor((Interceptor)args[0]);
               return null;
            }            
         }
      }

      // call the next in the interceptor chain,
      // if nobody follows dispatch the call
      Interceptor next = invocation.nextInterceptor();
      if (next != null)
      {
         return next.invoke(invocation);
      }
      else
      {
         return invocation.dispatch();
      }
   }
}
