Package org.jboss.aop

Source Code of org.jboss.aop.GeneratedClassAdvisor$InstanceAdvisorStrategy

/*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt 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.aop;

import gnu.trove.TLongObjectHashMap;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.jboss.aop.advice.AdviceBinding;
import org.jboss.aop.advice.AspectDefinition;
import org.jboss.aop.advice.GeneratedAdvisorInterceptor;
import org.jboss.aop.advice.InterceptorFactory;
import org.jboss.aop.advice.PrecedenceSorter;
import org.jboss.aop.advice.annotation.JoinPoint;
import org.jboss.aop.instrument.ConByConJoinPointGenerator;
import org.jboss.aop.instrument.ConByMethodJoinPointGenerator;
import org.jboss.aop.instrument.ConstructionJoinPointGenerator;
import org.jboss.aop.instrument.ConstructorJoinPointGenerator;
import org.jboss.aop.instrument.FieldJoinPointGenerator;
import org.jboss.aop.instrument.JoinPointGenerator;
import org.jboss.aop.instrument.MethodByConJoinPointGenerator;
import org.jboss.aop.instrument.MethodByMethodJoinPointGenerator;
import org.jboss.aop.instrument.MethodJoinPointGenerator;
import org.jboss.aop.joinpoint.FieldJoinpoint;
import org.jboss.aop.joinpoint.Joinpoint;
import org.jboss.aop.joinpoint.MethodJoinpoint;
import org.jboss.aop.pointcut.PointcutMethodMatch;
import org.jboss.aop.util.UnmodifiableEmptyCollections;

/**
* Comment
*
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @version $Revision$
*/
public class GeneratedClassAdvisor extends ClassAdvisor
{
   public static final String ADD_METHOD_INFO = "addMethodInfo";
   public static final String ADD_CONSTRUCTOR_INFO = "addConstructorInfo";
   public static final String ADD_CONSTRUCTION_INFO = "addConstructionInfo";
   public static final String ADD_FIELD_READ_INFO = "addFieldReadInfo";
   public static final String ADD_FIELD_WRITE_INFO = "addFieldWriteInfo";
   public static final String GET_PARENT_ADVISOR = "getParentAdvisor";

   MethodInterceptors methodInfos = new MethodInterceptors(this);
   ArrayList constructorInfos = new ArrayList();
   ArrayList constructionInfos = new ArrayList();
   ArrayList fieldReadInfos = new ArrayList();
   ArrayList fieldWriteInfos = new ArrayList();
   /** Super class methods that have been overrridden - these need special handling in this weaving mode */
   ArrayList overriddenMethods = new ArrayList();

   //TODO These are only needed for the class advisor really
   //All joinpoint generators apart from field reads and constructions go in here
   private volatile ConcurrentHashMap joinPointGenerators = UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP;
   //Needs its own map to avoid crashing with the field write generators
   private volatile ConcurrentHashMap fieldReadJoinPoinGenerators = UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP;
   //Needs its own map to avoid crashing with the constructor generators
   private volatile ConcurrentHashMap constructionJoinPointGenerators = UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP;
  
   ConcurrentHashMap oldInfos = UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP;
   ConcurrentHashMap oldFieldReadInfos = UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP;
   ConcurrentHashMap oldConstructionInfos = UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP;

   boolean initialisedSuperClasses;

   private int version;
  
   /**
    * Different behaviour depending on if we are a class advisor or instance advisor
    */
   AdvisorStrategy advisorStrategy;

   protected GeneratedClassAdvisor(String classname)
   {
      //Generated advisors will not pass in an aspectmanager
      //This will be passed in via the initialise() method
      super(classname, null);
      advisorStrategy = new ClassAdvisorStrategy();
   }
  
   protected GeneratedClassAdvisor(String classname, GeneratedClassAdvisor parent)
   {
      super(classname, null);
      advisorStrategy = new InstanceAdvisorStrategy(parent);
   }

   @Override
   public void cleanup()
   {
      super.cleanup();
      methodInfos = null;
      advisorStrategy = null;
     
      Map subscribedSubDomains = getManager().getSubscribedSubDomains();
      synchronized (subscribedSubDomains)
      {
         for (Iterator it = subscribedSubDomains.keySet().iterator() ; it.hasNext() ; )
         {
            GeneratedAdvisorDomain manager = (GeneratedAdvisorDomain)it.next();
            Map advisors = manager.getAdvisors();
            it.remove();
         }
      }
   }

   protected void initialise(Class clazz, AspectManager manager)
   {
      advisorStrategy.initialise(clazz, manager);
   }

   /**
    * Generated class advisor sub class will override
    */
   protected void initialiseCallers()
   {
   }

   /**
    * Generated instance advisor sub class will override
    */
   protected void initialiseInfosForInstance()
   {
     

   }
  
   /**
    * To be called by initialiseInfosForInstance() in the generated instance advisors
    */
   protected MethodInfo copyInfoFromClassAdvisor(MethodInfo info)
   {
      MethodInfo copy = (MethodInfo)info.copy();
      copy.setAdvisor(this);
      addMethodInfo(copy);
      return copy;
   }
  
   /**
    * To be called by initialiseInfosForInstance() in the generated instance advisors
    */
   protected FieldInfo copyInfoFromClassAdvisor(FieldInfo info)
   {
      FieldInfo copy = (FieldInfo)info.copy();
      copy.setAdvisor(this);
      if (copy.isRead())
      {
         addFieldReadInfo(copy);
      }
      else
      {
         addFieldWriteInfo(copy);
      }
      return copy;
   }

   /**
    * To be called by initialiseInfosForInstance() in the generated instance advisors
    */
   protected ConByConInfo copyInfoFromClassAdvisor(ConByConInfo info)
   {
      ConByConInfo copy = (ConByConInfo)info.copy();
      copy.setAdvisor(this);
      return copy;
   }

   /**
    * To be called by initialiseInfosForInstance() in the generated instance advisors
    */
   protected MethodByConInfo copyInfoFromClassAdvisor(MethodByConInfo info)
   {
      MethodByConInfo copy = (MethodByConInfo)info.copy();
      copy.setAdvisor(this);
      return copy;
   }

   /**
    * To be called by initialiseInfosForInstance() in the generated instance advisors
    */
   protected ConByMethodInfo copyInfoFromClassAdvisor(ConByMethodInfo info)
   {
      ConByMethodInfo copy = (ConByMethodInfo)info.copy();
      copy.setAdvisor(this);
      return copy;
   }
  
   /**
    * To be called by initialiseInfosForInstance() in the generated instance advisors
    */
   protected MethodByMethodInfo copyInfoFromClassAdvisor(MethodByMethodInfo info)
   {
      MethodByMethodInfo copy = (MethodByMethodInfo)info.copy();
      copy.setAdvisor(this);
      return copy;
   }
  
  
   @Override
   protected void rebuildInterceptors()
   {
      version++;
      advisorStrategy.rebuildInterceptors();
   }
  
   /**
    * Callback for instance advisors to rebuild their interceptors when their
    * version number is out of sync
    */
   protected synchronized void internalRebuildInterceptors()
   {
      super.rebuildInterceptors();
   }

   /**
    * Callback for generated instance advisors to check if the version has been updated
    */
   protected void checkVersion()
   {
      advisorStrategy.checkVersion();
   }

   /**
    * Will be overridden by generated instanceadvisor classes and perform a rebuild
    */
   protected void doRebuildForInstance()
   {
     
   }

   protected void handleOverriddenMethods(AdviceBinding binding)
   {
      if (overriddenMethods != null && overriddenMethods.size() > 0)
      {
         for (Iterator it = overriddenMethods.iterator() ; it.hasNext() ; )
         {
            MethodInfo info = (MethodInfo)it.next();
            Method method = info.getMethod();
            PointcutMethodMatch match = binding.getPointcut().matchesExecution(this, method);
           
            if (match != null && match.isMatch())
            {
               adviceBindings.add(binding);
               if (AspectManager.verbose)
               {
                  System.err.println("method matched binding " + binding.getPointcut().getExpr() + " " + method.toString());    
               }
               binding.addAdvisor(this);
               pointcutResolved(info, binding, new MethodJoinpoint(method));
            }
         }
      }     
   }

   @Override
   protected void resolveMethodPointcut(MethodInterceptors newMethodInterceptors, AdviceBinding binding)
   {
      GeneratedClassAdvisor classAdvisor = getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices();
      if (classAdvisor == null)
      {
         //We are either the class advisor or an instanceadvisor with own data so we need to do all the work
         super.resolveMethodPointcut(newMethodInterceptors, binding);
         handleOverriddenMethods(binding);
      }

   }

   @Override
   protected void resolveFieldPointcut(ArrayList newFieldInfos, AdviceBinding binding, boolean write)
   {
      GeneratedClassAdvisor classAdvisor = getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices();
      if (classAdvisor == null)
      {
         //We are either the class advisor or an instanceadvisor with own data so we need to do all the work
         super.resolveFieldPointcut(newFieldInfos, binding, write);
      }
   }

   @Override
   protected void resolveConstructorPointcut(ArrayList newConstructorInfos, AdviceBinding binding)
   {
      advisorStrategy.resolveConstructorPointcut(newConstructorInfos, binding);
   }

   @Override
   protected void resolveConstructionPointcut(ArrayList newConstructionInfos, AdviceBinding binding)
   {
      advisorStrategy.resolveConstructionPointcut(newConstructionInfos, binding);
   }
  
   /**
    * Generated class advisor sub class will override
    */
   protected void initialiseMethods()
   {
   }
  
   /**
    * Called by initialiseMethods() in generated advisor sub classes
    */
   protected void addMethodInfo(MethodInfo mi)
   {
      MethodInfo old = methodInfos.getMethodInfo(mi.getHash());
      if (old != null)
      {
         overriddenMethods.add(old);
      }
      methodInfos.put(mi.getHash(), mi);
     
      advisorStrategy.makeAccessibleMethod(mi);
   }

   @Override
   protected MethodInterceptors initializeMethodChain()
   {
      //We have all the advised methods here, need to get all the others here too

      long[] keys = advisedMethods.keys();
      for (int i = 0; i < keys.length; i++)
      {
         MethodMatchInfo matchInfo = methodInfos.getMatchInfo(keys[i]);

         if (super.initialized && matchInfo != null)
         {
            matchInfo.clear();
         }

         if (matchInfo == null)
         {
            MethodInfo info = new MethodInfo();
            Method amethod = (Method) advisedMethods.get(keys[i]);
            info.setAdvisedMethod(amethod);
            info.setUnadvisedMethod(amethod);
            info.setHash(keys[i]);
            info.setAdvisor(this);
            methodInfos.put(keys[i], info);
         }
      }

      return methodInfos;
   }


   /**
    * Generated class advisor sub class will override
    */
   protected void initialiseConstructors()
   {
   }

   /**
    * Called by initialiseConstructors() in generated advisor sub classes
    */
   protected void addConstructorInfo(ConstructorInfo ci)
   {
      constructorInfos.add(ci);
      //If we do dynamic invokes the constructor will need to be accessible via reflection
      SecurityActions.setAccessible(ci.getConstructor());
   }

   @Override
   protected void createInterceptorChains() throws Exception
   {
      advisorStrategy.createInterceptorChains();
   }
  
   @Override
   protected ArrayList initializeConstructorChain()
   {
      if (super.initialized)
      {
         for (Iterator it = constructorInfos.iterator() ; it.hasNext() ; )
         {
            ((ConstructorInfo)it.next()).clear();
         }
      }
      return constructorInfos;
   }

   /**
    * Generated class advisor sub class will override
    */
   protected void initialiseConstructions()
   {
   }

   /**
    * Called by initialiseConstructions() in generated advisor sub classes
    */
   protected void addConstructionInfo(ConstructionInfo ci)
   {
      constructionInfos.add(ci);
   }

   @Override
   protected ArrayList initializeConstructionChain()
   {
      if (super.initialized)
      {
         for (Iterator it = constructionInfos.iterator() ; it.hasNext() ; )
         {
            ((ConstructionInfo)it.next()).clear();
         }
      }
      return constructionInfos;
   }

   /**
    * Generated class advisor sub class will override
    */
   protected void initialiseFieldReads()
   {
   }

   /**
    * Called by initialiseFieldReads() in generated advisor sub classes
    */
   protected void addFieldReadInfo(FieldInfo fi)
   {
      fieldReadInfos.add(fi);
      //If we do dynamic invokes the field will need to be accessible via reflection
      advisorStrategy.makeAccessibleField(fi);
   }

   @Override
   protected ArrayList initializeFieldReadChain()
   {
      return mergeFieldInfos(fieldReadInfos, true);
   }

   /**
    * Generated class advisor sub class will override
    */
   protected void initialiseFieldWrites()
   {
   }

   /**
    * Called by initialiseFieldWrites() in generated advisor sub classes
    */
   protected void addFieldWriteInfo(FieldInfo fi)
   {
      fieldWriteInfos.add(fi);
      //If we do dynamic invokes the field will need to be accessible via reflection
      advisorStrategy.makeAccessibleField(fi);
   }

   @Override
   protected ArrayList initializeFieldWriteChain()
   {
      return mergeFieldInfos(fieldWriteInfos, false);
   }

   /* Creates a full list of field infos for all fields, using the ones added by
    * generated advisor for advised fields.
    */
   private ArrayList mergeFieldInfos(ArrayList advisedInfos, boolean read)
   {
      ArrayList newInfos = new ArrayList(advisedFields.length);

      FieldInfo nextFieldInfo = null;
      Iterator it = advisedInfos.iterator();
      if (it.hasNext())
      {
         nextFieldInfo = (FieldInfo)it.next();
      }

      for (int i = 0 ; i < advisedFields.length ; i++)
      {
         if (nextFieldInfo != null && nextFieldInfo.getIndex() == i)
         {
            if (super.initialized)
            {
               nextFieldInfo.clear();
            }

            newInfos.add(nextFieldInfo);
            if (it.hasNext())
            {
               nextFieldInfo = (FieldInfo)it.next();
            }
            else
            {
               nextFieldInfo = null;
            }
         }
         else
         {
            FieldInfo info = new FieldInfo(this, read);
            info.setAdvisedField(advisedFields[i]);
            info.setIndex(i);
            newInfos.add(info);
         }
      }

      return newInfos;
   }

   @Override
   protected void finalizeChains(MethodInterceptors newMethodInfos, ArrayList newFieldReadInfos, ArrayList newFieldWriteInfos, ArrayList newConstructorInfos, ArrayList newConstructionInfos)
   {
      ClassAdvisor classAdvisor = getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices();
      if (classAdvisor != null)
      {
         //We are an instance advisor who has not resolved their own pointcuts, make sure that we set the bindings that are referenced
         //so that they can be removed properly
         //Make sure that all the adviceBindings for the class advisor are referenced from us
         synchronized(this.adviceBindings)
         {
            this.adviceBindings.addAll(classAdvisor.adviceBindings);
            for (Iterator it = this.adviceBindings.iterator() ; it.hasNext() ; )
            {
               AdviceBinding binding = (AdviceBinding)it.next();
               binding.addAdvisor(this);
            }
         }
      }
      super.finalizeChains(newMethodInfos, newFieldReadInfos, newFieldWriteInfos, newConstructorInfos, newConstructionInfos);
   }

   @Override
   protected void finalizeMethodChain(MethodInterceptors newMethodInterceptors)
   {
      ClassAdvisor classAdvisor = getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices();
      if (classAdvisor != null)
      {
         //We are an instance advisor with no own data influencing the chains, copy these from the parent advisor
         easyFinalizeMethodChainForInstance(classAdvisor, newMethodInterceptors);
      }
      else
      {
         //We are either the class advisor or an instanceadvisor with own data so we need to do all the work
         fullWorkFinalizeMethodChain(newMethodInterceptors);
      }
   }

   private void easyFinalizeMethodChainForInstance(ClassAdvisor classAdvisor, MethodInterceptors newMethodInterceptors)
   {
      long[] keys = newMethodInterceptors.keys();
      for (int i = 0; i < keys.length; i++)
      {
         MethodInfo classMethodInfo = classAdvisor.getMethodInfo(keys[i]);
         MethodMatchInfo matchInfo = newMethodInterceptors.getMatchInfo(keys[i]);
         MethodInfo myMethodInfo = matchInfo.getInfo();
         myMethodInfo.cloneChains(classMethodInfo);
        
         if (updateOldInfo(oldInfos, myMethodInfo, OldInfoMaps.INFOS))
         {
            MethodJoinPointGenerator generator = getJoinPointGenerator(myMethodInfo);
            generator.rebindJoinpoint(myMethodInfo);
         }
      }
   }
  
   private void fullWorkFinalizeMethodChain(MethodInterceptors newMethodInterceptors)
   {
      //We are either the class advisor or an instanceadvisor with own data so we need to do all the work
      TLongObjectHashMap newMethodInfos = new TLongObjectHashMap();

      long[] keys = newMethodInterceptors.keys();
      for (int i = 0; i < keys.length; i++)
      {
         MethodMatchInfo matchInfo = newMethodInterceptors.getMatchInfo(keys[i]);
         matchInfo.populateBindings();

         MethodInfo info = matchInfo.getInfo();
         newMethodInfos.put(keys[i], info);

         MethodJoinPointGenerator generator = getJoinPointGenerator(info);
         finalizeChainAndRebindJoinPoint(oldInfos, info, generator, OldInfoMaps.INFOS);
      }
      methodInterceptors = newMethodInfos;
     
      //Handle the overridden methods
      if (overriddenMethods != null && overriddenMethods.size() > 0)
      {
         for (Iterator it = overriddenMethods.iterator() ; it.hasNext() ; )
         {
            MethodInfo info = (MethodInfo)it.next();

            MethodJoinPointGenerator generator = getJoinPointGenerator(info);
            finalizeChainAndRebindJoinPoint(oldInfos, info, generator, OldInfoMaps.INFOS);
         }
      }     
   }

   @Override
   protected void finalizeFieldReadChain(ArrayList newFieldInfos)
   {
      ClassAdvisor classAdvisor = getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices();
      if (classAdvisor != null)
      {
         //We are an instance advisor with no own data influencing the chains, copy these from the parent advisor
         easyFinalizeFieldChainForInstance(oldFieldReadInfos, classAdvisor.getFieldReadInfos(), newFieldInfos, OldInfoMaps.FIELD_READ_INFOS);
      }
      else
      {
         //We are either the class advisor or an instanceadvisor with own data so we need to do all the work
         fullWorkFinalizeFieldChain(oldFieldReadInfos, newFieldInfos, OldInfoMaps.FIELD_READ_INFOS);
      }
   }

   @Override
   protected void finalizeFieldWriteChain(ArrayList newFieldInfos)
   {
      ClassAdvisor classAdvisor = getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices();
      if (classAdvisor != null)
      {
         //We are an instance advisor with no own data influencing the chains, copy these from the parent advisor
         easyFinalizeFieldChainForInstance(oldInfos, classAdvisor.getFieldWriteInfos(), newFieldInfos, OldInfoMaps.INFOS);
      }
      else
      {
         //We are either the class advisor or an instanceadvisor with own data so we need to do all the work
         fullWorkFinalizeFieldChain(oldInfos, newFieldInfos, OldInfoMaps.INFOS);
      }
   }

   private void easyFinalizeFieldChainForInstance(Map oldFieldInfos, FieldInfo[] classFieldInfos, ArrayList newFieldInfos, OldInfoMaps oldInfoMapInstance)
   {
      //We are an instance advisor with no own data influencing the chains, copy these from the parent advisor
      if (newFieldInfos.size() > 0)
      {
         for (int i = 0; i < newFieldInfos.size(); i++)
         {
            FieldInfo myInfo = (FieldInfo)newFieldInfos.get(i);
            myInfo.cloneChains(classFieldInfos[i]);
           
            if (updateOldInfo(oldFieldInfos, myInfo, oldInfoMapInstance))
            {
               FieldJoinPointGenerator generator = getJoinPointGenerator(myInfo);
               generator.rebindJoinpoint(myInfo);
            }
         }
      }
   }
  
   private void fullWorkFinalizeFieldChain(Map oldFieldInfos, ArrayList newFieldInfos, OldInfoMaps oldInfoMapInstance)
   {
      //We are either the class advisor or an instanceadvisor with own data so we need to do all the work
      for (int i = 0; i < newFieldInfos.size(); i++)
      {
         FieldInfo info = (FieldInfo)newFieldInfos.get(i);
         FieldJoinPointGenerator generator = getJoinPointGenerator(info);
         finalizeChainAndRebindJoinPoint(oldFieldInfos, info, generator, oldInfoMapInstance);
      }
   }
  
   @Override
   protected void finalizeConstructorChain(ArrayList newConstructorInfos)
   {
      advisorStrategy.finalizeConstructorChain(newConstructorInfos);
   }

   @Override
   protected void finalizeConstructionChain(ArrayList newConstructionInfos)
   {
      advisorStrategy.finalizeConstructionChain(newConstructionInfos);
   }

   @Override
   protected void finalizeMethodCalledByMethodInterceptorChain(MethodByMethodInfo info)
   {
      MethodByMethodJoinPointGenerator generator = getJoinPointGenerator(info);
      finalizeChainAndRebindJoinPoint(oldInfos, info, generator, OldInfoMaps.INFOS);
   }

   @Override
   protected void finalizeConCalledByMethodInterceptorChain(ConByMethodInfo info)
   {
      ConByMethodJoinPointGenerator generator = getJoinPointGenerator(info);
      finalizeChainAndRebindJoinPoint(oldInfos, info, generator, OldInfoMaps.INFOS);
   }

   @Override
   protected void finalizeConCalledByConInterceptorChain(ConByConInfo info)
   {
      ConByConJoinPointGenerator generator = getJoinPointGenerator(info);
      finalizeChainAndRebindJoinPoint(oldInfos, info, generator, OldInfoMaps.INFOS);
   }

   @Override
   protected void finalizeMethodCalledByConInterceptorChain(MethodByConInfo info)
   {
      //An extra level of indirection since we distinguish between callers of method depending on
      //where the called method is defined (sub/super interfaces)
      ConcurrentHashMap map = (ConcurrentHashMap)joinPointGenerators.get(info.getJoinpoint());
      if (map == null)
      {
         map = new ConcurrentHashMap();
         initJoinPointGeneratorsMap();
         joinPointGenerators.put(info.getJoinpoint(), map);
         map = (ConcurrentHashMap)joinPointGenerators.get(info.getJoinpoint());
      }

      MethodByConJoinPointGenerator generator = getJoinPointGenerator(info);
      finalizeChainAndRebindJoinPoint(oldInfos, info, generator, OldInfoMaps.INFOS);
   }

   private JoinPointGenerator getJoinPointGenerator(JoinPointInfo info)
   {
      if (info instanceof MethodInfo)
      {
         return getJoinPointGenerator((MethodInfo)info);
      }
      else if (info instanceof FieldInfo)
      {
         return getJoinPointGenerator((FieldInfo)info);
      }
      else if (info instanceof ConstructionInfo)
      {
         return getJoinPointGenerator((ConstructionInfo)info);
      }
      else if (info instanceof ConstructorInfo)
      {
         return getJoinPointGenerator((ConstructorInfo)info);
      }
      else if (info instanceof ConByConInfo)
      {
         return getJoinPointGenerator((ConByConInfo)info);
      }
      else if (info instanceof ConByMethodInfo)
      {
         return getJoinPointGenerator((ConByMethodInfo)info);
      }
      else if (info instanceof MethodByMethodInfo)
      {
         return getJoinPointGenerator((MethodByMethodInfo)info);
      }
      else if (info instanceof MethodByConInfo)
      {
         return getJoinPointGenerator((MethodByConInfo)info);
      }
      else
      {
         throw new RuntimeException("Invalid JoinPointInfo passed in: " + info.getClass().getName());
      }
   }

   protected MethodJoinPointGenerator getJoinPointGenerator(MethodInfo info)
   {
      return advisorStrategy.getJoinPointGenerator(info);
   }

   protected FieldJoinPointGenerator getJoinPointGenerator(FieldInfo info)
   {
      return advisorStrategy.getJoinPointGenerator(info);
   }
  
   protected ConstructorJoinPointGenerator getJoinPointGenerator(ConstructorInfo info)
   {
      return advisorStrategy.getJoinPointGenerator(info);
   }

   protected ConstructionJoinPointGenerator getJoinPointGenerator(ConstructionInfo info)
   {
      return advisorStrategy.getJoinPointGenerator(info);
   }

   protected MethodByMethodJoinPointGenerator getJoinPointGenerator(MethodByMethodInfo info)
   {
      return advisorStrategy.getJoinPointGenerator(info);
   }

   protected ConByMethodJoinPointGenerator getJoinPointGenerator(ConByMethodInfo info)
   {
      return advisorStrategy.getJoinPointGenerator(info);
   }

   protected ConByConJoinPointGenerator getJoinPointGenerator(ConByConInfo info)
   {
      return advisorStrategy.getJoinPointGenerator(info);
   }

   protected MethodByConJoinPointGenerator getJoinPointGenerator(MethodByConInfo info)
   {
      return advisorStrategy.getJoinPointGenerator(info);
   }

   /**
    * Override default behaviour of when a pointcut is matched, populate the factories since this
    * is what is needed for generating the optimized invocation method
    */
   @Override
   protected void pointcutResolved(JoinPointInfo info, AdviceBinding binding, Joinpoint joinpoint)
   {
      ArrayList curr = info.getInterceptorChain();
      if (binding.getCFlow() != null)
      {
         //TODO Handle CFlow
         InterceptorFactory[] factories = binding.getInterceptorFactories();
         for (int i = 0 ; i < factories.length ; i++)
         {
            curr.add(new GeneratedAdvisorInterceptor(factories[i], this, joinpoint, binding.getCFlowString(), binding.getCFlow()));
         }
      }
      else
      {
         InterceptorFactory[] factories = binding.getInterceptorFactories();
         for (int i = 0 ; i < factories.length ; i++)
         {
            curr.add(new GeneratedAdvisorInterceptor(factories[i], this, joinpoint));
         }
      }
   }

   private void finalizeChainAndRebindJoinPoint(Map oldInfos, JoinPointInfo info, JoinPointGenerator generator, OldInfoMaps oldInfoMapInstance)
   {
      ArrayList list = info.getInterceptorChain();
      GeneratedAdvisorInterceptor[] factories = null;
      if (list.size() > 0)
      {
         factories = applyPrecedence((GeneratedAdvisorInterceptor[]) list.toArray(new GeneratedAdvisorInterceptor[list.size()]));
      }
      info.setInterceptors(factories);

      if (updateOldInfo(oldInfos, info, oldInfoMapInstance))
      {
         generator.rebindJoinpoint(info);
      }
   }

   @Override
   public String toString()
   {
      Class clazz = this.getClass();
      StringBuffer sb = new StringBuffer("CLASS: " + clazz.getName());

      Field[] fields = clazz.getFields();
      for (int i = 0 ; i < fields.length ; i++)
      {
         sb.append("\n\t" + fields[i]);
      }
      return sb.toString();
   }

   GeneratedAdvisorInterceptor[] applyPrecedence(GeneratedAdvisorInterceptor[] interceptors)
   {
      return PrecedenceSorter.applyPrecedence(interceptors, manager);
   }

   /**
    * If this is an instance advisor, will check with parent class advisor if the aspect
    * is already registered. If so, we should use the one from the parent advisor
    */
   @Override
   public Object getPerClassAspect(AspectDefinition def)
   {
      return advisorStrategy.getPerClassAspect(def);
   }

   /**
    * Generated ClassAdvisors and InstanceAdvisors will be different instances,
    * so keep track of what per_class_joinpoint aspects have been added where
    */
   ConcurrentHashMap perClassJoinpointAspectDefinitions = new ConcurrentHashMap();


   public Object getPerClassJoinpointAspect(AspectDefinition def, Joinpoint joinpoint)
   {
      return advisorStrategy.getPerClassJoinpointAspect(def, joinpoint);
   }

   public synchronized void addPerClassJoinpointAspect(AspectDefinition def, Joinpoint joinpoint)
   {
      Map joinpoints = (Map)perClassJoinpointAspectDefinitions.get(def);
      if (joinpoints == null)
      {
         joinpoints = new ConcurrentHashMap();
         perClassJoinpointAspectDefinitions.put(def, joinpoints);
      }

      if (joinpoints.get(joinpoint) == null)
      {
         joinpoints.put(joinpoint, def.getFactory().createPerJoinpoint(this, joinpoint));
      }
      def.registerAdvisor(this);
   }

   public synchronized void removePerClassJoinpointAspect(AspectDefinition def)
   {
      perClassJoinpointAspectDefinitions.remove(def);
   }
  
   /**
    * @see Advisor#chainOverridingForInheritedMethods()
    */
   @Override
   public boolean chainOverridingForInheritedMethods()
   {
      return true;
   }

   @Override
   public Object getFieldAspect(FieldJoinpoint joinpoint, AspectDefinition def)
   {
      Object instance = getPerClassJoinpointAspect(def, joinpoint);
      if (instance == null)
      {
         addPerClassJoinpointAspect(def, joinpoint);
         instance = getPerClassJoinpointAspect(def, joinpoint);
      }
      return instance;
   }

   private GeneratedClassAdvisor getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices()
   {
      return advisorStrategy.getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices();
   }
  
   /**
    * Optimization so that when we create instance advisors we don't have to create the method tables again,
    * they were already created for the class advisor
    */
   @Override
   protected void createMethodTables() throws Exception
   {
      advisorStrategy.createMethodTables();
   }
  
   /**
    * Optimization so that when we create instance advisors we don't have to create the field tables again,
    * they were already created for the class advisor
    */
   @Override
   protected void createFieldTable() throws Exception
   {
      advisorStrategy.createFieldTable();
   }
  
   /**
    * Optimization so that when we create instance advisors we don't have to create the constructor tables again,
    * they were already created for the class advisor
    */
   @Override
   protected void createConstructorTables() throws Exception
   {
      advisorStrategy.createConstructorTables();
   }

   @Override
   public Set getPerInstanceAspectDefinitions()
   {
      return advisorStrategy.getPerInstanceAspectDefinitions();
   }

   @Override
   public Map getPerInstanceJoinpointAspectDefinitions()
   {
      return advisorStrategy.getPerInstanceJoinpointAspectDefinitions();
   }

   /**
    * Caches the old info and checks if the chains have been updated
    */
   private boolean updateOldInfo(Map oldInfos, JoinPointInfo newInfo, OldInfoMaps oldInfoMapInstance)
   {
      JoinPointInfo oldInfo = (JoinPointInfo)oldInfos.get(newInfo.getJoinpoint());
      if (oldInfo != null)
      {
         //We are not changing any of the bindings
         if (oldInfo.equalChains(newInfo))
         {
            return false;
         }
      }
      oldInfo = newInfo.copy();
     
      if (oldInfoMapInstance == OldInfoMaps.INFOS)
      {
         oldInfos = initOldInfosMap();
      }
      else if (oldInfoMapInstance == OldInfoMaps.FIELD_READ_INFOS)
      {
         oldInfos = initOldFieldReadInfosMap();
      }
      else if (oldInfoMapInstance == OldInfoMaps.CONSTRUCTION_INFOS)
      {
         oldInfos = initOldConstructionInfosMap();
      }
      else
      {
         throw new RuntimeException("Unrecognised map");
      }
     
      oldInfos.put(newInfo.getJoinpoint(), oldInfo);
      return true;
   }

   protected void generateJoinPointClass(MethodInfo info)
   {
      MethodJoinPointGenerator generator = getJoinPointGenerator(info);
      generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }

   protected void generateJoinPointClass(FieldInfo info)
   {
      FieldJoinPointGenerator generator = getJoinPointGenerator(info);
      generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }

   protected void generateJoinPointClass(ConstructorInfo info)
   {
      ConstructorJoinPointGenerator generator = getJoinPointGenerator(info);
      generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }

   protected void generateJoinPointClass(ConstructionInfo info)
   {
      ConstructionJoinPointGenerator generator = getJoinPointGenerator(info);
      generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }

   protected void generateJoinPointClass(MethodByMethodInfo info)
   {
      MethodByMethodJoinPointGenerator generator = getJoinPointGenerator(info);
      generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }

   protected void generateJoinPointClass(ConByMethodInfo info)
   {
      ConByMethodJoinPointGenerator generator = getJoinPointGenerator(info);
      generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }

   protected void generateJoinPointClass(ConByConInfo info)
   {
      ConByConJoinPointGenerator generator = getJoinPointGenerator(info);
      generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }

   protected void generateJoinPointClass(MethodByConInfo info)
   {
      MethodByConJoinPointGenerator generator = getJoinPointGenerator(info);
      generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }
  
   protected Object rebindJoinPointWithInstanceInformation(JoinPointInfo info)
   {
      JoinPointGenerator generator = getJoinPointGenerator(info);
      generator.rebindJoinpoint(info);
      return generator.generateJoinPointClass(this.getClass().getClassLoader(), info);
   }
  
   /**
    * Called back from generated code
    */
   public Object createAndRebindJoinPointForInstance(JoinPointInfo info)
   {
      JoinPointInfo newinfo = info.copy();
      newinfo.setAdvisor(this);
      return rebindJoinPointWithInstanceInformation(newinfo);
   }
  
  
   protected void initJoinPointGeneratorsMap()
   {
      if (joinPointGenerators == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
      {
         lockWrite();
         try
         {
            if (joinPointGenerators == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
            {
               joinPointGenerators = new ConcurrentHashMap();
            }
         }
         finally
         {
            unlockWrite();
         }
      }
   }
  
   protected void initFieldReadJoinPointGeneratorsMap()
   {
      if (fieldReadJoinPoinGenerators == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
      {
         lockWrite();
         try
         {
            if (fieldReadJoinPoinGenerators == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
            {
               fieldReadJoinPoinGenerators = new ConcurrentHashMap();
            }
         }
         finally
         {
            unlockWrite();
         }
      }
   }
  
   protected void initConstructionJoinPointGeneratorsMap()
   {
      if (constructionJoinPointGenerators == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
      {
         lockWrite();
         try
         {
            if (constructionJoinPointGenerators == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
            {
               constructionJoinPointGenerators = new ConcurrentHashMap();
            }
         }
         finally
         {
            unlockWrite();
         }
      }
   }
  
   protected ConcurrentHashMap initOldInfosMap()
   {
      if (oldInfos == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
      {
         lockWrite();
         try
         {
            if (oldInfos == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
            {
               oldInfos = new ConcurrentHashMap();
            }
         }
         finally
         {
            unlockWrite();
         }
      }
      return oldInfos;
   }
  
   protected ConcurrentHashMap initOldFieldReadInfosMap()
   {
      if (oldFieldReadInfos == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
      {
         lockWrite();
         try
         {
            if (oldFieldReadInfos == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
            {
               oldFieldReadInfos = new ConcurrentHashMap();
            }
         }
         finally
         {
            unlockWrite();
         }
      }
      return oldFieldReadInfos;
   }
  
   protected ConcurrentHashMap initOldConstructionInfosMap()
   {
      if (oldConstructionInfos == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
      {
         lockWrite();
         try
         {
            if (oldConstructionInfos == UnmodifiableEmptyCollections.EMPTY_CONCURRENT_HASHMAP)
            {
               oldConstructionInfos = new ConcurrentHashMap();
            }
         }
         finally
         {
            unlockWrite();
         }
      }
      return oldConstructionInfos;
   }
  
   /**
    * Encapsulates different behaviours depending on if this is an instance or class advisor
    */
   private interface AdvisorStrategy
   {
      void initialise(Class clazz, AspectManager manager);
      void checkVersion();
      void createInterceptorChains() throws Exception;
      MethodJoinPointGenerator getJoinPointGenerator(MethodInfo info);
      FieldJoinPointGenerator getJoinPointGenerator(FieldInfo info);
      ConstructorJoinPointGenerator getJoinPointGenerator(ConstructorInfo info);
      ConstructionJoinPointGenerator getJoinPointGenerator(ConstructionInfo info);
      MethodByMethodJoinPointGenerator getJoinPointGenerator(MethodByMethodInfo info);
      ConByMethodJoinPointGenerator getJoinPointGenerator(ConByMethodInfo info);
      ConByConJoinPointGenerator getJoinPointGenerator(ConByConInfo info);
      MethodByConJoinPointGenerator getJoinPointGenerator(MethodByConInfo info);
      Object getPerClassAspect(AspectDefinition def);
      Object getPerClassJoinpointAspect(AspectDefinition def, Joinpoint joinpoint);
      GeneratedClassAdvisor getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices();
      void createMethodTables() throws Exception;
      void createFieldTable() throws Exception;
      void createConstructorTables() throws Exception;
      Set getPerInstanceAspectDefinitions();
      Map getPerInstanceJoinpointAspectDefinitions();
      void rebuildInterceptors();
      void resolveConstructorPointcut(ArrayList newConstructorInfos, AdviceBinding binding);
      void resolveConstructionPointcut(ArrayList newConstructionInfos, AdviceBinding binding);
      void finalizeConstructorChain(ArrayList newConstructorInfos);
      void finalizeConstructionChain(ArrayList newConstructionInfos);
      void makeAccessibleField(FieldInfo fi);
      void makeAccessibleMethod(MethodInfo mi);
   }
  
   private class ClassAdvisorStrategy implements AdvisorStrategy
   {
      GeneratedClassAdvisor parent;

      public void initialise(Class clazz, AspectManager manager)
      {
         initialiseMethods();
         initialiseConstructors();
         initialiseConstructions();
         initialiseFieldReads();
         initialiseFieldWrites();
        
         GeneratedClassAdvisor.super.setManager(manager);

         //Make sure that we copy across per class and per joinpoint aspects from the old advisor if it exists
         //Generated advisors get created when the class is first accessed (not loaded), meaning that there could be an exisiting advisor
         //used for mathcing already when setting up the microcontainer.
         Advisor existing = AspectManager.instance().getAnyAdvisorIfAdvised(clazz);
         if (existing != null)
         {
            GeneratedClassAdvisor.this.aspects = existing.aspects;
            if (existing instanceof GeneratedClassAdvisor)
            {
               GeneratedClassAdvisor.this.perClassJoinpointAspectDefinitions = ((GeneratedClassAdvisor)existing).perClassJoinpointAspectDefinitions;
            }
         }
        
         manager.initialiseClassAdvisor(clazz, GeneratedClassAdvisor.this);
        
         initialiseCallers();
      }

      public void checkVersion()
      {
         //The version is only has any significance for instance advisors
      }

      public void createInterceptorChains() throws Exception
      {
         GeneratedClassAdvisor.super.createInterceptorChains();
      }
     
      public MethodJoinPointGenerator getJoinPointGenerator(MethodInfo info)
      {
         MethodJoinPointGenerator generator = (MethodJoinPointGenerator)joinPointGenerators.get(info.getJoinpoint());
         if (generator == null)
         {
            generator = new MethodJoinPointGenerator(GeneratedClassAdvisor.this, info);
            initJoinPointGeneratorsMap();
            MethodJoinPointGenerator existing = (MethodJoinPointGenerator)joinPointGenerators.putIfAbsent(info.getJoinpoint(), generator);
            if (existing != null)
            {
               generator = existing;
            }
         }
         return generator;
      }

      public FieldJoinPointGenerator getJoinPointGenerator(FieldInfo info)
      {
         if (info.isRead())
         {
            FieldJoinPointGenerator generator = (FieldJoinPointGenerator)fieldReadJoinPoinGenerators.get(info.getJoinpoint());
            if (generator == null)
            {
               generator = new FieldJoinPointGenerator(GeneratedClassAdvisor.this, info);
               initFieldReadJoinPointGeneratorsMap();
               FieldJoinPointGenerator existing = (FieldJoinPointGenerator)fieldReadJoinPoinGenerators.putIfAbsent(info.getJoinpoint(), generator);
               if (existing != null)
               {
                  generator = existing;
               }
            }
            return generator;
         }
         else
         {
            FieldJoinPointGenerator generator = (FieldJoinPointGenerator)joinPointGenerators.get(info.getJoinpoint());
            if (generator == null)
            {
               generator = new FieldJoinPointGenerator(GeneratedClassAdvisor.this, info);
               initJoinPointGeneratorsMap();
               FieldJoinPointGenerator existing = (FieldJoinPointGenerator)joinPointGenerators.putIfAbsent(info.getJoinpoint(), generator);
               if (existing != null)
               {
                  generator = existing;
               }
            }
            return generator;
         }
      }
     
      public ConstructorJoinPointGenerator getJoinPointGenerator(ConstructorInfo info)
      {
         //We are the class advisor
         ConstructorJoinPointGenerator generator = (ConstructorJoinPointGenerator)constructionJoinPointGenerators.get(info.getJoinpoint());
         if (generator == null)
         {
            generator = new ConstructorJoinPointGenerator(GeneratedClassAdvisor.this, info);
            initConstructionJoinPointGeneratorsMap();
            ConstructorJoinPointGenerator existing = (ConstructorJoinPointGenerator)constructionJoinPointGenerators.putIfAbsent(info.getJoinpoint(), generator);
            if (existing != null)
            {
               generator = existing;
            }
         }
         return generator;
      }

      public ConstructionJoinPointGenerator getJoinPointGenerator(ConstructionInfo info)
      {
         ConstructionJoinPointGenerator generator = (ConstructionJoinPointGenerator)joinPointGenerators.get(info.getJoinpoint());
         if (generator == null)
         {
            generator = new ConstructionJoinPointGenerator(GeneratedClassAdvisor.this, info);
            initJoinPointGeneratorsMap();
            ConstructionJoinPointGenerator existing = (ConstructionJoinPointGenerator)joinPointGenerators.putIfAbsent(info.getJoinpoint(), generator);
            if (existing != null)
            {
               generator = existing;
            }
         }
         return generator;
      }

      public MethodByMethodJoinPointGenerator getJoinPointGenerator(MethodByMethodInfo info)
      {
         //An extra level of indirection since we distinguish between callers of method depending on
         //where the called method is defined (sub/super interfaces)
         ConcurrentHashMap map = (ConcurrentHashMap)joinPointGenerators.get(info.getJoinpoint());
         if (map == null)
         {
            map = new ConcurrentHashMap();
            initJoinPointGeneratorsMap();
            ConcurrentHashMap existing = (ConcurrentHashMap)joinPointGenerators.putIfAbsent(info.getJoinpoint(), map);
            if (existing != null)
            {
               map = existing;
            }
         }

         MethodByMethodJoinPointGenerator generator = (MethodByMethodJoinPointGenerator)map.get(info.getCalledClass());
         if (generator == null)
         {
            generator = new MethodByMethodJoinPointGenerator(GeneratedClassAdvisor.this, info);
            MethodByMethodJoinPointGenerator existing = (MethodByMethodJoinPointGenerator)map.putIfAbsent(info.getCalledClass(), generator);
            if (existing != null)
            {
               generator = existing;
            }
         }
         return generator;
      }

      public ConByMethodJoinPointGenerator getJoinPointGenerator(ConByMethodInfo info)
      {
         ConByMethodJoinPointGenerator generator = (ConByMethodJoinPointGenerator)joinPointGenerators.get(info.getJoinpoint());
         if (generator == null)
         {
            generator = new ConByMethodJoinPointGenerator(GeneratedClassAdvisor.this, info);
            initJoinPointGeneratorsMap();
            ConByMethodJoinPointGenerator existing = (ConByMethodJoinPointGenerator)joinPointGenerators.putIfAbsent(info.getJoinpoint(), generator);
            if (existing != null)
            {
               generator = existing;
            }
         }
         return generator;
      }

      public ConByConJoinPointGenerator getJoinPointGenerator(ConByConInfo info)
      {
         //We are the class advisor
         ConByConJoinPointGenerator generator = (ConByConJoinPointGenerator)joinPointGenerators.get(info.getJoinpoint());
         if (generator == null)
         {
            generator = new ConByConJoinPointGenerator(GeneratedClassAdvisor.this, info);
            initJoinPointGeneratorsMap();
            ConByConJoinPointGenerator existing = (ConByConJoinPointGenerator)joinPointGenerators.putIfAbsent(info.getJoinpoint(), generator);
            if (existing != null)
            {
               generator = existing;
            }
         }
         return generator;
      }

      public MethodByConJoinPointGenerator getJoinPointGenerator(MethodByConInfo info)
      {
         //An extra level of indirection since we distinguish between callers of method depending on
         //where the called method is defined (sub/super interfaces)
         ConcurrentHashMap map = (ConcurrentHashMap)joinPointGenerators.get(info.getJoinpoint());
         if (map == null)
         {
            map = new ConcurrentHashMap();
            initJoinPointGeneratorsMap();
            ConcurrentHashMap exisiting = (ConcurrentHashMap)joinPointGenerators.putIfAbsent(info.getJoinpoint(), map);
            if (exisiting != null)
            {
               map = exisiting;
            }
         }

         MethodByConJoinPointGenerator generator = (MethodByConJoinPointGenerator)map.get(info.getCalledClass());
         if (generator == null)
         {
            generator = new MethodByConJoinPointGenerator(GeneratedClassAdvisor.this, info);
            MethodByConJoinPointGenerator existing = (MethodByConJoinPointGenerator)map.putIfAbsent(info.getCalledClass(), generator);
            if (existing != null)
            {
               generator = existing;
            }
         }
         return generator;
      }

      public Object getPerClassAspect(AspectDefinition def)
      {
         return GeneratedClassAdvisor.super.getPerClassAspect(def);
      }

      public Object getPerClassJoinpointAspect(AspectDefinition def, Joinpoint joinpoint)
      {
         Map joinpoints = (Map) perClassJoinpointAspectDefinitions.get(def);
         if (joinpoints != null)
         {
            return joinpoints.get(joinpoint);
         }
         return null;
      }
     
      public GeneratedClassAdvisor getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices()
      {
         return null;
      }
     
      public void createMethodTables() throws Exception
      {
         GeneratedClassAdvisor.super.createMethodTables();
      }
     
      public void createFieldTable() throws Exception
      {
         GeneratedClassAdvisor.super.createFieldTable();
      }

      public void createConstructorTables() throws Exception
      {
         GeneratedClassAdvisor.super.createConstructorTables();
      }
     
      public Set getPerInstanceAspectDefinitions()
      {
         return GeneratedClassAdvisor.super.getPerInstanceAspectDefinitions();
      }

      public Map getPerInstanceJoinpointAspectDefinitions()
      {
         return GeneratedClassAdvisor.super.getPerInstanceJoinpointAspectDefinitions();
      }
     
      public void rebuildInterceptors()
      {
         version++;
         GeneratedClassAdvisor.super.rebuildInterceptors();
      }

      public void resolveConstructorPointcut(ArrayList newConstructorInfos, AdviceBinding binding)
      {
         GeneratedClassAdvisor.super.resolveConstructorPointcut(newConstructorInfos, binding);
      }

      public void resolveConstructionPointcut(ArrayList newConstructionInfos, AdviceBinding binding)
      {
         GeneratedClassAdvisor.super.resolveConstructionPointcut(newConstructionInfos, binding);
      }

      public void finalizeConstructorChain(ArrayList newConstructorInfos)
      {
         for (int i = 0; i < newConstructorInfos.size(); i++)
         {
            ConstructorInfo info = (ConstructorInfo) newConstructorInfos.get(i);
            ConstructorJoinPointGenerator generator = getJoinPointGenerator(info);
            finalizeChainAndRebindJoinPoint(oldInfos, info, generator, OldInfoMaps.INFOS);
         }
      }

      public void finalizeConstructionChain(ArrayList newConstructionInfos)
      {
         for (int i = 0; i < newConstructionInfos.size(); i++)
         {
            ConstructionInfo info = (ConstructionInfo) newConstructionInfos.get(i);
            ConstructionJoinPointGenerator generator = getJoinPointGenerator(info);
            finalizeChainAndRebindJoinPoint(oldConstructionInfos, info, generator, OldInfoMaps.CONSTRUCTION_INFOS);
         }
      }

      public void makeAccessibleField(FieldInfo fi)
      {
         //If we do dynamic invokes the field will need to be accessible via reflection
         SecurityActions.setAccessible(fi.getField());
      }
     
      public void makeAccessibleMethod(MethodInfo mi)
      {
         //If we do dynamic invokes the method will need to be accessible via reflection if private/protected
         SecurityActions.setAccessible(mi.getMethod());
      }
   }
  
   private class InstanceAdvisorStrategy implements AdvisorStrategy
   {
      GeneratedClassAdvisor parent;
      boolean needsRebuild = true;
     
      public InstanceAdvisorStrategy(GeneratedClassAdvisor parent)
      {
         this.parent = parent;
         GeneratedClassAdvisor.this.version = parent.version;        
      }
     
      public void initialise(Class clazz, AspectManager manager)
      {
         initialiseInfosForInstance();
        
         GeneratedClassAdvisor.super.setManager(manager);

         manager.initialiseClassAdvisor(clazz, GeneratedClassAdvisor.this);
      }

      public void checkVersion()
      {
         if (needsRebuild || parent.version != GeneratedClassAdvisor.this.version)
         {
            doRebuildForInstance();
            needsRebuild = false;
         }
      }
     
      public void createInterceptorChains() throws Exception
      {
         if (GeneratedClassAdvisor.super.initialized)
         {
            GeneratedClassAdvisor.super.createInterceptorChains();
         }
         else
         {
            //Instance advisor copies the chains from the class advisor during its initialise stage
            GeneratedClassAdvisor.super.initialized = true;
         }
      }

      public MethodJoinPointGenerator getJoinPointGenerator(MethodInfo info)
      {
         //We are an instance advisor, get the generator from the class advisor
         return parent.getJoinPointGenerator(info);
      }

      public FieldJoinPointGenerator getJoinPointGenerator(FieldInfo info)
      {
         //We are an instance advisor, get the generator from the class advisor
         return parent.getJoinPointGenerator(info);
      }
     
      public ConstructorJoinPointGenerator getJoinPointGenerator(ConstructorInfo info)
      {
         //We are an instance advisor, get the generator from the class advisor
         return parent.getJoinPointGenerator(info);
      }

      public ConstructionJoinPointGenerator getJoinPointGenerator(ConstructionInfo info)
      {
         //We are an instance advisor, get the generator from the class advisor
         return parent.getJoinPointGenerator(info);
      }

      public MethodByMethodJoinPointGenerator getJoinPointGenerator(MethodByMethodInfo info)
      {
         //We are an instance advisor, get the generator from the class advisor
         return parent.getJoinPointGenerator(info);
      }

      public ConByMethodJoinPointGenerator getJoinPointGenerator(ConByMethodInfo info)
      {
         //We are an instance advisor, get the generator from the class advisor
         return parent.getJoinPointGenerator(info);
      }

      public ConByConJoinPointGenerator getJoinPointGenerator(ConByConInfo info)
      {
         //We are an instance advisor, get the generator from the class advisor
         return parent.getJoinPointGenerator(info);
      }

      public MethodByConJoinPointGenerator getJoinPointGenerator(MethodByConInfo info)
      {
         //We are an instance advisor, get the generator from the class advisor
         return parent.getJoinPointGenerator(info);
      }

      /**
       * This is an instance advisor, so we will check with parent class advisor if the aspect
       * is already registered. If so, we should use the one from the parent advisor
       */
      public Object getPerClassAspect(AspectDefinition def)
      {
         Object aspect = parent.getPerClassAspect(def);
         if (aspect != null) return aspect;
         return GeneratedClassAdvisor.super.getPerClassAspect(def);
      }

      /**
       * This is an instance advisor, so we will check with parent class advisor if the aspect
       * is already registered. If so, we should use the one from the parent advisor
       */
      public Object getPerClassJoinpointAspect(AspectDefinition def, Joinpoint joinpoint)
      {
         Object aspect = parent.getPerClassJoinpointAspect(def, joinpoint);
         if (aspect != null)return aspect;
         return parent.getPerClassJoinpointAspect(def, joinpoint);
      }

      public GeneratedClassAdvisor getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices()
      {
         if (((Domain)getManager()).hasOwnDataWithEffectOnAdvices())
         {
            return null;
         }
         return parent;
      }
     
      public void createMethodTables() throws Exception
      {
         GeneratedClassAdvisor.this.unadvisedMethods = parent.unadvisedMethods;
         GeneratedClassAdvisor.this.advisedMethods = parent.advisedMethods;
      }

      public void createFieldTable() throws Exception
      {
         GeneratedClassAdvisor.this.advisedFields = parent.advisedFields;
      }

      public void createConstructorTables() throws Exception
      {
         GeneratedClassAdvisor.this.constructors = parent.constructors;
        
         methodCalledByConBindings = new HashMap[constructors.length];
         methodCalledByConInterceptors = new HashMap[constructors.length];

         conCalledByConBindings = new HashMap[constructors.length];
         conCalledByConInterceptors = new HashMap[constructors.length];
      }

      public Set getPerInstanceAspectDefinitions()
      {
         return parent.getPerInstanceAspectDefinitions();
      }

      public Map getPerInstanceJoinpointAspectDefinitions()
      {
         return parent.getPerInstanceJoinpointAspectDefinitions();
      }

     
      public synchronized void rebuildInterceptors()
      {
         if (getClassAdvisorIfInstanceAdvisorWithNoOwnDataWithEffectOnAdvices() != null && GeneratedClassAdvisor.this.version != parent.version)
         {
            adviceBindings.clear();
            needsRebuild = true;
         }
         else
         {
            GeneratedClassAdvisor.super.rebuildInterceptors();
         }
      }

      public void resolveConstructorPointcut(ArrayList newConstructorInfos, AdviceBinding binding)
      {
         //Since the instance already exists it makes no sense to have bindings for constructors
      }

      public void resolveConstructionPointcut(ArrayList newConstructionInfos, AdviceBinding binding)
      {
         //Since the instance already exists it makes no sense to have bindings for constructors        
      }

      public void finalizeConstructorChain(ArrayList newConstructorInfos)
      {
         //Since the instance already exists it makes no sense to have bindings for constructors
      }

      public void finalizeConstructionChain(ArrayList newConstructionInfos)
      {
         //Since the instance already exists it makes no sense to have bindings for constructors
      }

      public void makeAccessibleField(FieldInfo fi)
      {
         //Do nothing, field was already made accessible in class advisor
      }

      public void makeAccessibleMethod(MethodInfo mi)
      {
         //Do nothing, field was already made accessible in class advisor
      }
   }
  
   enum OldInfoMaps{
      INFOS, FIELD_READ_INFOS, CONSTRUCTION_INFOS;
   }

}
TOP

Related Classes of org.jboss.aop.GeneratedClassAdvisor$InstanceAdvisorStrategy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.