[jboss-cvs] JBossAS SVN: r78090 - in projects/aop/trunk/aop/src/main/org/jboss/aop: advice and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Sep 5 11:59:50 EDT 2008


Author: kabir.khan at jboss.com
Date: 2008-09-05 11:59:49 -0400 (Fri, 05 Sep 2008)
New Revision: 78090

Modified:
   projects/aop/trunk/aop/src/main/org/jboss/aop/AspectManager.java
   projects/aop/trunk/aop/src/main/org/jboss/aop/ClassAdvisor.java
   projects/aop/trunk/aop/src/main/org/jboss/aop/ClassContainer.java
   projects/aop/trunk/aop/src/main/org/jboss/aop/Domain.java
   projects/aop/trunk/aop/src/main/org/jboss/aop/InstanceDomain.java
   projects/aop/trunk/aop/src/main/org/jboss/aop/ReflectiveAspectBinder.java
   projects/aop/trunk/aop/src/main/org/jboss/aop/advice/ClassifiedBindingCollection.java
Log:
[JBAOP-632] Attempt to fix ConcurrentModificationException. Replace the internal collections in ClassifiedBindingCollection with CopyOnWriteArraySets, and initialise those when needed. As part of this replace the use of synchronized with read/write locks

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/AspectManager.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/AspectManager.java	2008-09-05 15:33:32 UTC (rev 78089)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/AspectManager.java	2008-09-05 15:59:49 UTC (rev 78090)
@@ -135,7 +135,7 @@
    protected volatile LinkedHashMap<String, AnnotationIntroduction> annotationOverrides = UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP;
    @Deprecated
    protected volatile LinkedHashMap<String, AdviceBinding> bindings = UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP;
-   volatile ClassifiedBindingCollection bindingCollection;
+   protected volatile ClassifiedBindingCollection bindingCollection = new ClassifiedBindingCollection();
    protected volatile LinkedHashMap<String, Typedef> typedefs = UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP;
    protected volatile HashMap<String, InterceptorFactory> interceptorFactories = UnmodifiableEmptyCollections.EMPTY_HASHMAP;
    protected volatile HashMap<String,ClassMetaDataLoader> classMetaDataLoaders = UnmodifiableEmptyCollections.EMPTY_HASHMAP;
@@ -478,7 +478,6 @@
     */
    public AspectManager()
    {
-      this.bindingCollection = new ClassifiedBindingCollection();
    }
    /**
     * Every &lt;class-metadata&gt; tag corresponds to
@@ -1408,7 +1407,9 @@
 
       HashSet<Advisor> bindingAdvisors = new HashSet<Advisor>();
       ArrayList<AdviceBinding> removedBindings = null;
-      synchronized (bindingCollection)
+      
+      bindingCollection.lockWrite();
+      try
       {
          removedBindings = this.bindingCollection.remove(binds);
          for (AdviceBinding removedBinding: removedBindings)
@@ -1419,6 +1420,11 @@
             this.removePointcut(pointcut.getName());
          }
       }
+      finally
+      {
+         bindingCollection.unlockWrite();
+      }
+      
       Iterator<Advisor> it = bindingAdvisors.iterator();
       while (it.hasNext())
       {
@@ -1468,11 +1474,7 @@
             updatePointcutStats(pointcut);
          }
          
-         initBindingsMap();
-         synchronized (bindingCollection)
-         {
-            bindingCollection.add(binding);
-         }
+         bindingCollection.add(binding);
       }
       synchronized (advisors)
       {
@@ -2094,7 +2096,8 @@
     */
    private synchronized AdviceBinding internalRemoveBinding(String name)
    {
-      synchronized (bindingCollection)
+      bindingCollection.lockWrite();
+      try
       {
          AdviceBinding binding = bindingCollection.remove(name);
          if (binding == null)
@@ -2105,6 +2108,10 @@
          this.removePointcut(pointcut.getName());
          return binding;
       }
+      finally
+      {
+         bindingCollection.unlockWrite();
+      }
    }
 
 //   public void setBindings(LinkedHashMap bindings)
@@ -2375,21 +2382,6 @@
       }
    }
 
-   protected void initBindingsMap()
-   {
-      if (!bindingCollection.isInitialized())
-      {
-         synchronized(lazyCollectionLock)
-         {
-            if (!bindingCollection.isInitialized())
-            {
-               bindingCollection.initialize();
-               bindings = bindingCollection.getBindings();
-            }
-         }
-      }
-   }
-
    protected void initTypedefsMap()
    {
       if (typedefs == UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP)

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/ClassAdvisor.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/ClassAdvisor.java	2008-09-05 15:33:32 UTC (rev 78089)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/ClassAdvisor.java	2008-09-05 15:59:49 UTC (rev 78090)
@@ -619,8 +619,9 @@
    @SuppressWarnings("deprecation")
    private void resolveBindings(AspectManager manager)
    {
-      ClassifiedBindingCollection bindingCol = manager.bindingCollection;
-      synchronized (bindingCol)
+      ClassifiedBindingCollection bindingCol = manager.getBindingCollection();
+      bindingCol.lockRead(true);
+      try
       {
          for (AdviceBinding binding: bindingCol.getFieldReadBindings())
          {
@@ -668,6 +669,10 @@
             resolveMethodPointcut(binding);
          }
       }
+      finally
+      {
+         bindingCol.unlockRead(true);
+      }
    }
    
    protected void updateInterceptorChains() throws Exception
@@ -1589,15 +1594,12 @@
 
          boolean matched = false;
          ClassifiedBindingCollection bindingCol = manager.getBindingCollection();
-         synchronized (bindingCol)
+         for (AdviceBinding binding : bindingCol.getConstructorCallBindings())
          {
-            for (AdviceBinding binding : bindingCol.getConstructorCallBindings())
+            if (binding.getPointcut().matchesCall(this, callingConstructor, called, calledMethod))
             {
-               if (binding.getPointcut().matchesCall(this, callingConstructor, called, calledMethod))
-               {
-                  addConstructorCallerPointcut(callingIndex, calledClass, calledMethodHash, binding);
-                  matched = true;
-               }
+               addConstructorCallerPointcut(callingIndex, calledClass, calledMethodHash, binding);
+               matched = true;
             }
          }
          if (!matched) initializeEmptyConstructorCallerChain(callingIndex, calledClass, calledMethodHash);
@@ -1654,15 +1656,12 @@
 
          boolean matched = false;
          ClassifiedBindingCollection bindingCol = manager.getBindingCollection();
-         synchronized (bindingCol)
+         for (AdviceBinding binding : bindingCol.getConstructorCallBindings())
          {
-            for (AdviceBinding binding : bindingCol.getConstructorCallBindings())
+            if (binding.getPointcut().matchesCall(this, callingConstructor, called, calledCon))
             {
-               if (binding.getPointcut().matchesCall(this, callingConstructor, called, calledCon))
-               {
-                  addConstructorCalledByConPointcut(callingIndex, calledClass, calledConHash, binding);
-                  matched = true;
-               }
+               addConstructorCalledByConPointcut(callingIndex, calledClass, calledConHash, binding);
+               matched = true;
             }
          }
          if (!matched) initializeConCalledByConEmptyChain(callingIndex, calledClass, calledConHash);
@@ -2742,15 +2741,12 @@
 
             boolean matched = false;
             ClassifiedBindingCollection bindingCol = manager.getBindingCollection();
-            synchronized (bindingCol)
+            for (AdviceBinding binding : bindingCol.getConstructorCallBindings())
             {
-               for (AdviceBinding binding : bindingCol.getConstructorCallBindings())
+               if (binding.getPointcut().matchesCall(ClassAdvisor.this, callingMethod, called, calledCon))
                {
-                  if (binding.getPointcut().matchesCall(ClassAdvisor.this, callingMethod, called, calledCon))
-                  {
-                     addConstructorCalledByMethodPointcut(callingMethodHash, calledClass, calledConHash, binding);
-                     matched = true;
-                  }
+                  addConstructorCalledByMethodPointcut(callingMethodHash, calledClass, calledConHash, binding);
+                  matched = true;
                }
             }
             if (!matched) initializeConCalledByMethodEmptyChain(callingMethodHash, calledClass, calledConHash);

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/ClassContainer.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/ClassContainer.java	2008-09-05 15:33:32 UTC (rev 78089)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/ClassContainer.java	2008-09-05 15:59:49 UTC (rev 78090)
@@ -323,7 +323,8 @@
    private void makeInterceptorChains()
    {
       ClassifiedBindingCollection bindingCol = manager.getBindingCollection();
-      synchronized (bindingCol)
+      bindingCol.lockRead(true);
+      try
       {
          Collection<AdviceBinding> bindings = bindingCol.getConstructorExecutionBindings(); 
          for (AdviceBinding binding : bindings)
@@ -338,6 +339,10 @@
             resolveMethodPointcut(binding);
          }
       }
+      finally
+      {
+         bindingCol.unlockRead(true);
+      }
       finalizeChain(constructorInfos);
       finalizeMethodChain();
       populateInterceptorsFromInfos();

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/Domain.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/Domain.java	2008-09-05 15:33:32 UTC (rev 78089)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/Domain.java	2008-09-05 15:59:49 UTC (rev 78090)
@@ -82,7 +82,7 @@
 
    public Domain(AspectManager manager, String name, boolean parentFirst)
    {
-      bindingCollection = new DomainClassifiedBindingCollection();
+      this.bindingCollection = new DomainClassifiedBindingCollection();
       this.parent = manager;
       this.parentFirst = parentFirst;
       this.name = name;
@@ -1105,60 +1105,123 @@
    
    private class DomainClassifiedBindingCollection extends ClassifiedBindingCollection
    {
+      @Override
       public Collection<AdviceBinding> getFieldReadBindings()
       {
-         Collection<AdviceBinding> result = super.getFieldReadBindings();
-         Collection<AdviceBinding> parentResult = parent.getBindingCollection().
-            getFieldReadBindings();
-         return unifyCollections(result, parentResult, parentFirst);
+         lockRead(true);
+         try
+         {
+            Collection<AdviceBinding> result = super.getFieldReadBindings();
+            Collection<AdviceBinding> parentResult = parent.getBindingCollection().
+               getFieldReadBindings();
+            return unifyCollections(result, parentResult, parentFirst);
+         }
+         finally
+         {
+            unlockRead(true);
+         }
       }
       
+      @Override
       public Collection<AdviceBinding> getFieldWriteBindings()
       {
-         Collection<AdviceBinding> result = super.getFieldWriteBindings();
-         Collection<AdviceBinding> parentResult = parent.getBindingCollection().
-            getFieldWriteBindings();
-         return unifyCollections(result, parentResult, parentFirst);
+         lockRead(true);
+         try
+         {
+            Collection<AdviceBinding> result = super.getFieldWriteBindings();
+            Collection<AdviceBinding> parentResult = parent.getBindingCollection().
+               getFieldWriteBindings();
+            return unifyCollections(result, parentResult, parentFirst);
+         }
+         finally
+         {
+            unlockRead(true);
+         }
       }
       
+      @Override
       public Collection<AdviceBinding> getConstructionBindings()
       {
-         Collection<AdviceBinding> result = super.getConstructionBindings();
-         Collection<AdviceBinding> parentResult = parent.getBindingCollection().
-            getConstructionBindings();
-         return unifyCollections(result, parentResult, parentFirst);
+         lockRead(true);
+         try
+         {
+            Collection<AdviceBinding> result = super.getConstructionBindings();
+            Collection<AdviceBinding> parentResult = parent.getBindingCollection().
+               getConstructionBindings();
+            return unifyCollections(result, parentResult, parentFirst);
+         }
+         finally
+         {
+            unlockRead(true);
+         }
       }
       
+      @Override
       public Collection<AdviceBinding> getConstructorExecutionBindings()
       {
-         Collection<AdviceBinding> result = super.getConstructorExecutionBindings();
-         Collection<AdviceBinding> parentResult = parent.getBindingCollection().
-            getConstructorExecutionBindings();
-         return unifyCollections(result, parentResult, parentFirst);
+         lockRead(true);
+         try
+         {
+            Collection<AdviceBinding> result = super.getConstructorExecutionBindings();
+            Collection<AdviceBinding> parentResult = parent.getBindingCollection().
+               getConstructorExecutionBindings();
+            return unifyCollections(result, parentResult, parentFirst);
+         }
+         finally
+         {
+            unlockRead(true);
+         }
       }
       
+      @Override
       public Collection<AdviceBinding> getMethodExecutionBindings()
       {
-         Collection<AdviceBinding> result = super.getMethodExecutionBindings();
-         Collection<AdviceBinding> parentResult = parent.getBindingCollection().
-            getMethodExecutionBindings();
-         return unifyCollections(result, parentResult, parentFirst);
+         lockRead(true);
+         try
+         {
+            Collection<AdviceBinding> result = super.getMethodExecutionBindings();
+            Collection<AdviceBinding> parentResult = parent.getBindingCollection().
+               getMethodExecutionBindings();
+            return unifyCollections(result, parentResult, parentFirst);
+         }
+         finally
+         { 
+            unlockRead(true);
+         }
       }
       
+      @Override
       public Collection<AdviceBinding> getConstructorCallBindings()
       {
-         Collection<AdviceBinding> result = super.getConstructorCallBindings();
-         Collection<AdviceBinding> parentResult = parent.getBindingCollection().
-            getConstructorCallBindings();
-         return unifyCollections(result, parentResult, parentFirst);
+         lockRead(true);
+         try
+         {
+            Collection<AdviceBinding> result = super.getConstructorCallBindings();
+            Collection<AdviceBinding> parentResult = parent.getBindingCollection().
+               getConstructorCallBindings();
+            return unifyCollections(result, parentResult, parentFirst);
+         }
+         finally
+         {
+            unlockRead(true);
+         }
       }
       
+      @Override
       public Collection<AdviceBinding> getMethodCallBindings()
       {
-         Collection<AdviceBinding> result = super.getMethodCallBindings();
-         Collection<AdviceBinding> parentResult = parent.getBindingCollection().
-            getMethodCallBindings();
-         return unifyCollections(result, parentResult, parentFirst);
+         lockRead(true);
+         try
+         {
+            Collection<AdviceBinding> result = super.getMethodCallBindings();
+            Collection<AdviceBinding> parentResult = parent.getBindingCollection().
+               getMethodCallBindings();
+            return unifyCollections(result, parentResult, parentFirst);
+         }
+         finally
+         {
+            unlockRead(true);
+         }
       }
       
       private <T> Collection<T> unifyCollections(Collection<T> collection1,
@@ -1185,5 +1248,45 @@
          }
          return collection1;
       }
+
+      @Override
+      public void lockRead(boolean lockParents)
+      {
+         if (lockParents)
+         {
+            parent.getBindingCollection().lockRead(lockParents);
+         }
+         super.lockRead();
+      }
+
+      @Override
+      public void lockWrite(boolean lockParents)
+      {
+         if (lockParents)
+         {
+            parent.getBindingCollection().lockWrite(lockParents);
+         }
+         super.lockWrite();
+      }
+
+      @Override
+      public void unlockRead(boolean lockParents)
+      {
+         super.unlockRead();
+         if (lockParents)
+         {
+            parent.getBindingCollection().unlockRead(lockParents);
+         }
+      }
+
+      @Override
+      public void unlockWrite(boolean lockParents)
+      {
+         super.unlockWrite();
+         if (lockParents)
+         {
+            parent.getBindingCollection().unlockWrite(lockParents);
+         }
+      }
    }
 }
\ No newline at end of file

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/InstanceDomain.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/InstanceDomain.java	2008-09-05 15:33:32 UTC (rev 78089)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/InstanceDomain.java	2008-09-05 15:59:49 UTC (rev 78090)
@@ -52,11 +52,7 @@
    public synchronized void addBinding(AdviceBinding binding)
    {
       removeBinding(binding.getName());
-      super.initBindingsMap();
-      synchronized (bindingCollection)
-      {
-         bindingCollection.add(binding);
-      }
+      bindingCollection.add(binding);
       super.addPointcut(binding.getPointcut());
       if (advisor != null) advisor.newBindingAdded();
    }

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/ReflectiveAspectBinder.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/ReflectiveAspectBinder.java	2008-09-05 15:33:32 UTC (rev 78089)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/ReflectiveAspectBinder.java	2008-09-05 15:59:49 UTC (rev 78090)
@@ -93,9 +93,17 @@
       if (!initialisedAspects)
       {
          ClassifiedBindingCollection bindingCol = advisor.getManager().getBindingCollection();
-         bindMethodAdvices(clazz, bindingCol);
-         bindConstructorAdvices(bindingCol);
-         bindFieldAdvices(bindingCol);
+         bindingCol.lockRead(true);
+         try
+         {
+            bindMethodAdvices(clazz, bindingCol);
+            bindConstructorAdvices(bindingCol);
+            bindFieldAdvices(bindingCol);
+         }
+         finally
+         {
+            bindingCol.unlockRead(true);
+         }
       }
       return aspects;
    }

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/advice/ClassifiedBindingCollection.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/advice/ClassifiedBindingCollection.java	2008-09-05 15:33:32 UTC (rev 78089)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/advice/ClassifiedBindingCollection.java	2008-09-05 15:59:49 UTC (rev 78090)
@@ -24,11 +24,13 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.jboss.aop.AspectManager;
 import org.jboss.aop.util.BindingClassifier;
 import org.jboss.aop.util.UnmodifiableEmptyCollections;
+import org.jboss.aop.util.UnmodifiableLinkedHashMap;
 import org.jboss.aop.util.logging.AOPLogger;
 
 /**
@@ -42,6 +44,8 @@
 public class ClassifiedBindingCollection
 {
    private static final AOPLogger logger = AOPLogger.getLogger(AspectManager.class);
+   
+   private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
   
    private volatile LinkedHashMap<String, AdviceBinding> bindings;
    private volatile Collection<AdviceBinding> fieldReadBindings;
@@ -52,12 +56,12 @@
    private volatile Collection<AdviceBinding> constructorCallBindings;
    private volatile Collection<AdviceBinding> methodCallBindings;
    
-   @SuppressWarnings("all")
    /**
     * Constructor.<p>
     * All created instances must be initialized before being used for addition and
     * removal operations, by calling {@code initialize()}.
     */
+   @SuppressWarnings("all")
    public ClassifiedBindingCollection()
    {
       bindings = UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP;
@@ -78,9 +82,17 @@
     * @return a collection containing exclusively the bindings that may match field
     *         read pointcuts
     */
-   public synchronized Collection<AdviceBinding> getFieldReadBindings()
+   public Collection<AdviceBinding> getFieldReadBindings()
    {
-      return this.fieldReadBindings;
+      lockRead();
+      try
+      {
+         return this.fieldReadBindings;
+      }
+      finally
+      {
+         unlockRead();
+      }
    }
    
    /**
@@ -91,9 +103,17 @@
     * @return a collection containing exclusively the bindings that may match field
     *         write pointcuts
     */
-   public synchronized Collection<AdviceBinding> getFieldWriteBindings()
+   public Collection<AdviceBinding> getFieldWriteBindings()
    {
-      return this.fieldWriteBindings;
+      lockRead();
+      try
+      {
+         return this.fieldWriteBindings;
+      }
+      finally
+      {
+         unlockRead();
+      }
    }
    
    /**
@@ -104,9 +124,17 @@
     * @return a collection containing exclusively the bindings that may match
     *         construction pointcuts
     */
-   public synchronized Collection<AdviceBinding> getConstructionBindings()
+   public Collection<AdviceBinding> getConstructionBindings()
    {
-      return this.constructionBindings;
+      lockRead();
+      try
+      {
+         return this.constructionBindings;
+      }
+      finally
+      {
+         unlockRead();
+      }
    }
    
    /**
@@ -117,9 +145,17 @@
     * @return a collection containing exclusively the bindings that may match
     *         constructor execution pointcuts
     */
-   public synchronized Collection<AdviceBinding> getConstructorExecutionBindings()
+   public Collection<AdviceBinding> getConstructorExecutionBindings()
    {
-      return this.constructorExecutionBindings;
+      lockRead();
+      try
+      {
+         return this.constructorExecutionBindings;
+      }
+      finally
+      {
+         unlockRead();
+      }
    }
    
    /**
@@ -130,9 +166,17 @@
     * @return a collection containing exclusively the bindings that may match
     *         method execution pointcuts
     */
-   public synchronized Collection<AdviceBinding> getMethodExecutionBindings()
+   public Collection<AdviceBinding> getMethodExecutionBindings()
    {
-      return this.methodExecutionBindings;
+      lockRead();
+      try
+      {
+         return this.methodExecutionBindings;
+      }
+      finally
+      {
+         unlockRead();
+      }
    }
    
    /**
@@ -144,9 +188,17 @@
     * @return a collection containing exclusively the bindings that may match
     *         constructor call pointcuts
     */
-   public synchronized Collection<AdviceBinding> getConstructorCallBindings()
+   public Collection<AdviceBinding> getConstructorCallBindings()
    {
-      return this.constructorCallBindings;
+      lockRead();
+      try
+      {
+         return this.constructorCallBindings;
+      }
+      finally
+      {
+         unlockRead();
+      }
    }
    
    /**
@@ -157,17 +209,33 @@
     * @return a collection containing exclusively the bindings that may match
     *         method call pointcuts
     */
-   public synchronized Collection<AdviceBinding> getMethodCallBindings()
+   public Collection<AdviceBinding> getMethodCallBindings()
    {
-      return this.methodCallBindings;
+      lockRead();
+      try
+      {
+         return this.methodCallBindings;
+      }
+      finally
+      {
+         unlockRead();
+      }
    }
    
    /**
     * Indicate whether this collection is empty.
     */
-   public synchronized boolean isEmpty()
+   public boolean isEmpty()
    {
-      return this.bindings.isEmpty();
+      lockRead();
+      try
+      {
+         return this.bindings.isEmpty();
+      }
+      finally
+      {
+         unlockRead();
+      }
    }
    
    /**
@@ -177,45 +245,40 @@
     */
    public LinkedHashMap<String, AdviceBinding> getBindings()
    {
-      return bindings;
+      lockRead();
+      try
+      {
+         return new UnmodifiableLinkedHashMap<String, AdviceBinding>(bindings);
+      }
+      finally
+      { 
+         unlockRead();
+      }
    }
    
    /**
     * Adds a binding to this collection.
     */
-   public synchronized void add(AdviceBinding binding)
+   public void add(AdviceBinding binding)
    {
-      bindings.put(binding.getName(), binding);
-      if (BindingClassifier.isGet(binding))
+      lockWrite();
+      try
       {
-         this.fieldReadBindings.add(binding);
+         addBinding(binding);
+         addGet(binding);
+         addSet(binding);
+         addConstruction(binding);
+         addConstructorExecution(binding);
+         addMethodExecution(binding);
+         addConstructorCall(binding);
+         addMethodCall(binding);
       }
-      if (BindingClassifier.isSet(binding))
+      finally
       {
-         this.fieldWriteBindings.add(binding);
+         unlockWrite();
       }
-      if (BindingClassifier.isConstruction(binding))
-      {
-         this.constructionBindings.add(binding);
-      }
-      if (BindingClassifier.isConstructorExecution(binding))
-      {
-         this.constructorExecutionBindings.add(binding);
-      }
-      if (BindingClassifier.isMethodExecution(binding))
-      {
-         this.methodExecutionBindings.add(binding);
-      }
-      if (BindingClassifier.isConstructorCall(binding))
-      {
-         this.constructorCallBindings.add(binding);
-      }
-      if (BindingClassifier.isMethodCall(binding))
-      {
-         this.methodCallBindings.add(binding);
-      }
    }
-   
+
    /**
     * Removes the binding named {@code name}.
     * 
@@ -223,20 +286,28 @@
     * @return the removed binding. If {@code null}, indicates that there is no
     *         binding with name equal to {@code name} in this collection.
     */
-   public synchronized AdviceBinding remove(String name)
+   public AdviceBinding remove(String name)
    {
-      AdviceBinding binding = bindings.remove(name);
-      if (binding != null)
+      lockWrite();
+      try
       {
-         this.fieldReadBindings.remove(binding);
-         this.fieldWriteBindings.remove(binding);
-         this.constructionBindings.remove(binding);
-         this.constructorExecutionBindings.remove(binding);
-         this.methodExecutionBindings.remove(binding);
-         this.constructorCallBindings.remove(binding);
-         this.methodCallBindings.remove(binding);
+         AdviceBinding binding = bindings.remove(name);
+         if (binding != null)
+         {
+            this.fieldReadBindings.remove(binding);
+            this.fieldWriteBindings.remove(binding);
+            this.constructionBindings.remove(binding);
+            this.constructorExecutionBindings.remove(binding);
+            this.methodExecutionBindings.remove(binding);
+            this.constructorCallBindings.remove(binding);
+            this.methodCallBindings.remove(binding);
+         }
+         return binding;
       }
-      return binding;
+      finally
+      {
+         unlockWrite();
+      }
    }
    
    /**
@@ -245,44 +316,188 @@
     * @param names names of all bindings to be removed
     * @return the collection of the removed bindings
     */
-   public synchronized ArrayList<AdviceBinding> remove(ArrayList<String> names)
+   public ArrayList<AdviceBinding> remove(ArrayList<String> names)
    {
-      ArrayList<AdviceBinding> removedBindings = new ArrayList<AdviceBinding>();
-      for (String name: names)
+      lockWrite();
+      try
       {
-         AdviceBinding binding = this.remove(name);
-         if (binding == null)
+         ArrayList<AdviceBinding> removedBindings = new ArrayList<AdviceBinding>();
+         for (String name: names)
          {
-            logger.debug("ClassifiedBindingCollection.removeBindings() no binding found with name " + name);
-            continue;
+            AdviceBinding binding = this.remove(name);
+            if (binding == null)
+            {
+               logger.debug("ClassifiedBindingCollection.removeBindings() no binding found with name " + name);
+               continue;
+            }
+            removedBindings.add(binding);
          }
-         removedBindings.add(binding);
+         return removedBindings;
       }
-      return removedBindings;
+      finally
+      {
+         unlockWrite();
+      }
    }
+
+   /**
+    * Read-lock just this collection
+    */
+   public final void lockRead()
+   {
+      lock.readLock().lock();
+   }
    
    /**
-    * Indicates if this collection is initialized. If it is not, no addition
-    * operation can be performed.
+    * Read-unlock just this collection
     */
-   public synchronized boolean isInitialized()
+   protected final void unlockRead()
    {
-      return bindings != UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP;
+      lock.readLock().unlock();
    }
    
    /**
-    * Initializes this collection. This method must be called only if this collection
-    * is not initialized.
+    * Write-lock just this collection
     */
-   public synchronized void initialize()
+   public final void lockWrite()
    {
-      bindings = new LinkedHashMap<String, AdviceBinding>();
-      this.fieldReadBindings = new LinkedHashSet<AdviceBinding>(0);
-      this.fieldWriteBindings = new LinkedHashSet<AdviceBinding>(0);
-      this.constructionBindings = new LinkedHashSet<AdviceBinding>(0);
-      this.constructorExecutionBindings = new LinkedHashSet<AdviceBinding>(0);
-      this.methodExecutionBindings = new LinkedHashSet<AdviceBinding>(0);
-      this.constructorCallBindings = new LinkedHashSet<AdviceBinding>(0);
-      this.methodCallBindings = new LinkedHashSet<AdviceBinding>(0);
+      lock.writeLock().lock();
    }
+   
+   /**
+    * Write-unlock this collection
+    */
+   public final void unlockWrite()
+   {
+      lock.writeLock().unlock();
+   }
+
+   /**
+    * Read-lock this collection
+    * @param if true, parent collections will be locked too
+    */
+   public void lockRead(boolean lockParents)
+   {
+      lockRead();
+   }
+   
+   /**
+    * Read-unlock this collection
+    * @param if true, parent collections will be unlocked too
+    */
+   public void unlockRead(boolean lockParents)
+   {
+      unlockRead();
+   }
+   
+   /**
+    * Write-lock this collection
+    * @param if true, parent collections will be locked too
+    */
+   public void lockWrite(boolean lockParents)
+   {
+      lockWrite();
+   }
+   
+   /**
+    * Write-unlock this collection
+    * @param if true, parent collections will be unlocked too
+    */
+   public void unlockWrite(boolean lockParents)
+   {
+      unlockWrite();
+   }
+   
+   private void addBinding(AdviceBinding binding)
+   {
+      if (bindings == UnmodifiableEmptyCollections.EMPTY_LINKED_HASHMAP)
+      {
+         bindings = new LinkedHashMap<String, AdviceBinding>();
+      }
+      bindings.put(binding.getName(), binding);
+   }
+   
+   private void addGet(AdviceBinding binding)
+   {
+      if (BindingClassifier.isGet(binding))
+      {
+         if (fieldReadBindings == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+         {
+            fieldReadBindings = new CopyOnWriteArraySet<AdviceBinding>();
+         }
+         this.fieldReadBindings.add(binding);
+      }
+   }
+   
+   private void addSet(AdviceBinding binding)
+   {
+      if (BindingClassifier.isSet(binding))
+      {
+         if (fieldWriteBindings == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+         {
+            fieldWriteBindings = new CopyOnWriteArraySet<AdviceBinding>();
+         }
+         this.fieldWriteBindings.add(binding);
+      }
+   }
+   
+   private void addConstruction(AdviceBinding binding)
+   {
+      if (BindingClassifier.isConstruction(binding))
+      {
+         if (constructionBindings == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+         {
+            constructionBindings = new CopyOnWriteArraySet<AdviceBinding>();
+         }
+         this.constructionBindings.add(binding);
+      }
+   }
+   
+   private void addConstructorExecution(AdviceBinding binding)
+   {
+      if (BindingClassifier.isConstructorExecution(binding))
+      {
+         if (constructorExecutionBindings == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+         {
+            constructorExecutionBindings = new CopyOnWriteArraySet<AdviceBinding>();
+         }
+         this.constructorExecutionBindings.add(binding);
+      }
+   }
+   
+   private void addMethodExecution(AdviceBinding binding)
+   {
+      if (BindingClassifier.isMethodExecution(binding))
+      {
+         if (methodExecutionBindings == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+         {
+            methodExecutionBindings = new CopyOnWriteArraySet<AdviceBinding>();
+         }
+         this.methodExecutionBindings.add(binding);
+      }
+   }
+   
+   private void addMethodCall(AdviceBinding binding)
+   {
+      if (BindingClassifier.isMethodCall(binding))
+      {
+         if (methodCallBindings == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+         {
+            methodCallBindings = new CopyOnWriteArraySet<AdviceBinding>();
+         }
+         this.methodCallBindings.add(binding);
+      }
+   }
+   
+   private void addConstructorCall(AdviceBinding binding)
+   {
+      if (BindingClassifier.isConstructorCall(binding))
+      {
+         if (constructorCallBindings == UnmodifiableEmptyCollections.EMPTY_ARRAYLIST)
+         {
+            constructorCallBindings = new CopyOnWriteArraySet<AdviceBinding>();
+         }
+         this.constructorCallBindings.add(binding);
+      }
+   }
 }




More information about the jboss-cvs-commits mailing list