FileDocCategorySizeDatePackage
InterceptorInfo.javaAPI DocJBoss 4.2.19386Fri Jul 13 20:53:52 BST 2007org.jboss.ejb3.interceptor

InterceptorInfo.java

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This 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 (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */ 
package org.jboss.ejb3.interceptor;

import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;

import org.jboss.ejb3.metamodel.Interceptor;

/**
 * We cannot use annotation overrides for the interceptor stuff since they do not have a 
 * container associated with them
 * 
 * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
 * @version $Revision: 60233 $
 */
public class InterceptorInfo
{
   Class clazz;
   Interceptor xml;
   
   //interceptor methods defined by this class
   protected Method aroundInvoke;
   protected Method postConstruct;
   protected Method postActivate;
   protected Method preDestroy;
   protected Method prePassivate;
   
   //Interceptor methods defined by this class and all superclasses
   protected Method[] aroundInvokeHierarchy;
   protected Method[] postConstructHierarchy;
   protected Method[] postActivateHierarchy;
   protected Method[] preDestroyHierarchy;
   protected Method[] prePassivateHierarchy;
   
   boolean haveCalculatedHierarchy;
 
   protected InterceptorInfo()
   {
   }

   public InterceptorInfo(Class clazz)
   {
      this.clazz = clazz;
   }
   
   public InterceptorInfo(InterceptorInfo interceptorInfo)
   {
      this.clazz = interceptorInfo.clazz;
      this.aroundInvoke = interceptorInfo.aroundInvoke;
      this.postConstruct = interceptorInfo.postConstruct;
      this.postActivate = interceptorInfo.postActivate;
      this.preDestroy = interceptorInfo.preDestroy;
      this.prePassivate = interceptorInfo.prePassivate;
      this.aroundInvokeHierarchy = interceptorInfo.aroundInvokeHierarchy;
      this.postConstructHierarchy = interceptorInfo.postConstructHierarchy;
      this.postActivateHierarchy = interceptorInfo.postActivateHierarchy;
      this.preDestroyHierarchy = interceptorInfo.preDestroyHierarchy;
      this.prePassivateHierarchy = interceptorInfo.prePassivateHierarchy;
   }

   protected void setXml(Interceptor xml)
   {
      this.xml = xml;
   }
   
   public Interceptor getXml()
   {
      return xml;
   }
   
   public Method getAroundInvoke()
   {
      return aroundInvoke;
   }

   protected void setAroundInvoke(Method aroundInvoke)
   {
      if (aroundInvoke == null) return;
      
      if (this.aroundInvoke != null && !this.aroundInvoke.equals(aroundInvoke))
      {
         throw new RuntimeException("Interceptors can only have one around-invoke/@AroundInvoke method - " + clazz.getName());
      }
      this.aroundInvoke = makeAccessible(aroundInvoke);
   }

   public Class getClazz()
   {
      return clazz;
   }

   public boolean haveCalculatedHierarchy()
   {
      return haveCalculatedHierarchy;
   }
   
   public Method getPostActivate()
   {
      return postActivate;
   }

   protected void setPostActivate(Method postActivate)
   {
      if (postActivate == null) return;
      
      if (this.postActivate != null && !this.postActivate.equals(postActivate))
      {
         throw new RuntimeException("Interceptors can only have one post-activate/@PostActivate method - " + clazz.getName());
      }
      this.postActivate = makeAccessible(postActivate);
   }

   public Method getPostConstruct()
   {
      return postConstruct;
   }

   protected void setPostConstruct(Method postConstruct)
   {
      if (postConstruct == null) return;
      
      if (this.postConstruct != null && !this.postConstruct.equals(postConstruct))
      {
         throw new RuntimeException("Interceptors can only have one post-construct/@PostConstruct method - " + clazz.getName());
      }
      this.postConstruct = makeAccessible(postConstruct);
   }

   public Method getPreDestroy()
   {
      return preDestroy;
   }

   protected void setPreDestroy(Method preDestroy)
   {
      if (preDestroy == null) return;
      
      if (this.preDestroy != null && !this.preDestroy.equals(preDestroy))
      {
         throw new RuntimeException("Interceptors can only have one pre-destroy/@PreDestroy method - " + clazz.getName());
      }
      this.preDestroy = makeAccessible(preDestroy);
   }

   public Method getPrePassivate()
   {
      return prePassivate;
   }

   protected void setPrePassivate(Method prePassivate)
   {
      if (prePassivate == null) return;
      
      if (this.prePassivate != null && !this.prePassivate.equals(prePassivate))
      {
         throw new RuntimeException("Interceptors can only have one pre-passivate/@PrePassivate method - " + clazz.getName());
      }
      this.prePassivate = makeAccessible(prePassivate);
   }
   
   public Method[] getAroundInvokes()
   {
      return aroundInvokeHierarchy;
   }

   public Method[] getPostActivates()
   {
      return postActivateHierarchy;
   }

   public Method[] getPostConstructs()
   {
      return postConstructHierarchy;
   }

   public Method[] getPreDestroys()
   {
      return preDestroyHierarchy;
   }

   public Method[] getPrePassivates()
   {
      return prePassivateHierarchy;
   }

   private Method makeAccessible(final Method method)
   {
      try
      {
         AccessController.doPrivileged(new PrivilegedExceptionAction() {
            public Object run()
            {
               method.setAccessible(true);
               return null;
            }
         });
      }
      catch (PrivilegedActionException e)
      {
         throw new RuntimeException(e.getException());
      }
      
      return method;
   }
   
   public String toString()
   {
      StringBuffer sb = new StringBuffer("InterceptorInfo{class=" + clazz);
      appendMethods(sb);
      sb.append("}");
      return sb.toString();
   }

   protected void appendMethods(StringBuffer sb)
   {
      appendMethodString(sb, "aroundInvoke", aroundInvoke);
      appendMethodString(sb, "postConstruct", postConstruct);
      appendMethodString(sb, "postActivate", postActivate);
      appendMethodString(sb, "prePassivate", prePassivate);
      appendMethodString(sb, "preDestroy", preDestroy);
   }
   
   protected void appendMethodString(StringBuffer buf, String methodType, Method m)
   {
      if (m != null)
      {
         buf.append(", " + methodType + "=" + m.getName());
      }
   }
   
   public void calculateHierarchy(InterceptorInfo superInfo)
   {
      if (haveCalculatedHierarchy)
      {
         return;
      }
      
      postConstructHierarchy = initaliseMethods((superInfo != null) ? superInfo.postConstructHierarchy : null, postConstruct);
      postActivateHierarchy = initaliseMethods((superInfo != null) ? superInfo.postActivateHierarchy : null, postActivate);
      aroundInvokeHierarchy = initaliseMethods((superInfo != null) ? superInfo.aroundInvokeHierarchy : null, aroundInvoke);
      prePassivateHierarchy = initaliseMethods((superInfo != null) ? superInfo.prePassivateHierarchy : null, prePassivate);
      preDestroyHierarchy = initaliseMethods((superInfo != null) ? superInfo.preDestroyHierarchy : null, preDestroy);
      
      haveCalculatedHierarchy = true;
   }
   
   private Method[] initaliseMethods(Method[] superMethods, Method myMethod)
   {
      if (superMethods == null && myMethod == null)
      {
         return null;
      }
      ArrayList hierarchy = new ArrayList();
      if (superMethods != null)
      {
         //We only want to add superclass interceptor/lifecycle methods if we do not override them
         for (int i = 0 ; i < superMethods.length ; ++i)
         {
            if (!haveMethod(superMethods[i]))
            {
               hierarchy.add(superMethods[i]);
            }
         }
      }
      
      if (myMethod != null)
      {
         hierarchy.add(myMethod);
      }
      
      return (Method[])hierarchy.toArray(new Method[hierarchy.size()]);
   }
   
   private boolean haveMethod(Method method)
   {
      try
      {
         clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
         return true;
      }
      catch (NoSuchMethodException e)
      {
         return false;
      }
   }

   @Override
   public boolean equals(Object obj)
   {
      if (obj instanceof InterceptorInfo)
      {
         return clazz.equals(((InterceptorInfo)obj).getClazz());
      }
      return false;
   }

   @Override
   public int hashCode()
   {
      return clazz.getName().hashCode();
   }
   
   
}