[jboss-cvs] JBossAS SVN: r59240 - in projects/aop/branches/arrays/aop/src: main/org/jboss/aop/array main/org/jboss/aop/instrument resources/test/array test/org/jboss/test/aop/array

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Dec 28 16:18:19 EST 2006


Author: kabir.khan at jboss.com
Date: 2006-12-28 16:18:10 -0500 (Thu, 28 Dec 2006)
New Revision: 59240

Modified:
   projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayAdvisor.java
   projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayElementInvocation.java
   projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayRegistry.java
   projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayRegistryEntry.java
   projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ElementArrayRegistryEntry.java
   projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/FieldArrayRegistryEntry.java
   projects/aop/branches/arrays/aop/src/main/org/jboss/aop/instrument/FieldAccessTransformer.java
   projects/aop/branches/arrays/aop/src/main/org/jboss/aop/instrument/GeneratedAdvisorFieldAccessTransformer.java
   projects/aop/branches/arrays/aop/src/resources/test/array/jboss-aop.xml
   projects/aop/branches/arrays/aop/src/test/org/jboss/test/aop/array/AOPArrayTestCase.java
   projects/aop/branches/arrays/aop/src/test/org/jboss/test/aop/array/ClassWithArrayFields.java
Log:
Avoid duplicate interception if an array element is set to the same as its existing value
Add method to ArrayRegistry to get hold of references to an advised array

Modified: projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayAdvisor.java
===================================================================
--- projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayAdvisor.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayAdvisor.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -57,25 +57,27 @@
       {
          //The old value might be an array, remove references to that
          Object oldValue = ((Object[])array)[index];
-         registry.removeElementReference(array, index, oldValue);
-         
-         //The new value might be an array
-         if (value.getClass().isArray())
+         boolean ignoreUpdate = (oldValue == value);
+         if (!ignoreUpdate)
          {
-            registry.addElementReference(array, index, value);
+            registry.removeElementReference(array, index, oldValue);
+            
+            //The new value might be an array
+            if (value != null && value.getClass().isArray())
+            {
+               registry.addElementReference(array, index, value);
+            }
+            ObjectArrayElementWriteInvocation invocation = new ObjectArrayElementWriteInvocation(interceptors, (Object[])array, index, value);
+            invocation.invokeNext();
+            return;
          }
-         ObjectArrayElementWriteInvocation invocation = new ObjectArrayElementWriteInvocation(interceptors, (Object[])array, index, value);
-         invocation.invokeNext();
       }
-      else
-      {
-         ((Object[])array)[index] = value;
-      }
+      ((Object[])array)[index] = value;
    }
    
    public static void arrayWriteInt(Object array, int index, int value) throws Throwable
    {
-      if (ArrayRegistry.getInstance().isRegistered(array))
+      if (ArrayRegistry.getInstance().isRegistered(array) && ((int[])array)[index] != value)
       {
          IntArrayElementWriteInvocation invocation = new IntArrayElementWriteInvocation(interceptors, ((int[])array), index, value);
          invocation.invokeNext();
@@ -92,23 +94,23 @@
       {
          if (array instanceof boolean[])
          {
-            BooleanArrayElementWriteInvocation invocation = new BooleanArrayElementWriteInvocation(interceptors, ((boolean[])array), index, ByteBooleanConverter.toBoolean(value));
-            invocation.invokeNext();
-         }
-         else
-         {
-            ByteArrayElementWriteInvocation invocation = new ByteArrayElementWriteInvocation(interceptors, ((byte[])array), index, value);
-            invocation.invokeNext();
-         }
-      }
-      else
-      {
-         if (array instanceof boolean[])
-         {
+            if (((boolean[])array)[index] != ByteBooleanConverter.toBoolean(value))
+            
+            {
+               BooleanArrayElementWriteInvocation invocation = new BooleanArrayElementWriteInvocation(interceptors, ((boolean[])array), index, ByteBooleanConverter.toBoolean(value));
+               invocation.invokeNext();
+               return;
+            }
             ((boolean[])array)[index] = ByteBooleanConverter.toBoolean(value);
          }
-         else
+         else 
          {
+            if (((byte[])array)[index] != value)
+            {
+               ByteArrayElementWriteInvocation invocation = new ByteArrayElementWriteInvocation(interceptors, ((byte[])array), index, value);
+               invocation.invokeNext();
+               return;
+            }
             ((byte[])array)[index] = value;
          }
       }
@@ -116,7 +118,7 @@
 
    public static void arrayWriteChar(Object array, int index, char value) throws Throwable
    {
-      if (ArrayRegistry.getInstance().isRegistered(array))
+      if (ArrayRegistry.getInstance().isRegistered(array) && ((char[])array)[index] != value)
       {
          CharArrayElementWriteInvocation invocation = new CharArrayElementWriteInvocation(interceptors, ((char[])array), index, value);
          invocation.invokeNext();
@@ -129,7 +131,7 @@
 
    public static void arrayWriteDouble(Object array, int index, double value) throws Throwable
    {
-      if (ArrayRegistry.getInstance().isRegistered(array))
+      if (ArrayRegistry.getInstance().isRegistered(array) && ((double[])array)[index] != value)
       {
          DoubleArrayElementWriteInvocation invocation = new DoubleArrayElementWriteInvocation(interceptors, ((double[])array), index, value);
          invocation.invokeNext();
@@ -142,7 +144,7 @@
 
    public static void arrayWriteShort(Object array, int index, short value) throws Throwable
    {
-      if (ArrayRegistry.getInstance().isRegistered(array))
+      if (ArrayRegistry.getInstance().isRegistered(array) && ((short[])array)[index] != value)
       {
          ShortArrayElementWriteInvocation invocation = new ShortArrayElementWriteInvocation(interceptors, ((short[])array), index, value);
          invocation.invokeNext();
@@ -155,7 +157,7 @@
 
    public static void arrayWriteFloat(Object array, int index, float value) throws Throwable
    {
-      if (ArrayRegistry.getInstance().isRegistered(array))
+      if (ArrayRegistry.getInstance().isRegistered(array) && ((float[])array)[index] != value)
       {
          FloatArrayElementWriteInvocation invocation = new FloatArrayElementWriteInvocation(interceptors, ((float[])array), index, value);
          invocation.invokeNext();
@@ -168,7 +170,7 @@
 
    public static void arrayWriteLong(Object array, int index, long value) throws Throwable
    {
-      if (ArrayRegistry.getInstance().isRegistered(array))
+      if (ArrayRegistry.getInstance().isRegistered(array) && ((long[])array)[index] != value)
       {
          LongArrayElementWriteInvocation invocation = new LongArrayElementWriteInvocation(interceptors, ((long[])array), index, value);
          invocation.invokeNext();

Modified: projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayElementInvocation.java
===================================================================
--- projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayElementInvocation.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayElementInvocation.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -164,4 +164,10 @@
    {
       throw new NotImplementedException();
    }
+   
+   public void getReferences()
+   {
+      ArrayRegistry registry = ArrayRegistry.getInstance();
+      registry.getArrayOwners(targetObject);
+   }
 }

Modified: projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayRegistry.java
===================================================================
--- projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayRegistry.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayRegistry.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -21,8 +21,9 @@
 */ 
 package org.jboss.aop.array;
 
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 import java.util.WeakHashMap;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
@@ -35,9 +36,12 @@
  */
 public class ArrayRegistry
 {
+   private final static ArrayRegistryEntryFactory ELEMENT_ARRAY_REGISTRY_ENTRY_FACTORY = new ElementArrayRegistryEntryFactory();
+   private final static ArrayRegistryEntryFactory FIELD_ARRAY_REGISTRY_ENTRY_FACTORY = new FieldArrayRegistryEntryFactory();
+   private ArrayReferenceBuilder referenceBuilder = new ArrayReferenceBuilder();
    private static ArrayRegistry singleton = new ArrayRegistry();
    private ReadWriteLock lock = new ReentrantReadWriteLock();
-   private WeakHashMap<Object, WeakHashMap<Object, ArrayRegistryEntry>> cache = new WeakHashMap<Object, WeakHashMap<Object, ArrayRegistryEntry>>();
+   private WeakHashMap<Object, WeakHashMap<Object, HashMap<Object, ArrayRegistryEntry>>> cache = new WeakHashMap<Object, WeakHashMap<Object, HashMap<Object, ArrayRegistryEntry>>>();
    
    public static ArrayRegistry getInstance()
    {
@@ -55,24 +59,47 @@
       {
          return;
       }
+      addReference(owner, fieldName, array, FIELD_ARRAY_REGISTRY_ENTRY_FACTORY);
+   }
+
+   public void addElementReference(Object owner, int index, Object array)
+   {
+      if (array == null)
+      {
+         return;
+      }
+      addReference(owner, new Integer(index), array, ELEMENT_ARRAY_REGISTRY_ENTRY_FACTORY);
+   }
+   
+   public void addReference(Object owner, Object qualifier, Object array, ArrayRegistryEntryFactory factory)
+   {
+      if (array == null)
+      {
+         return;
+      }
       Lock writeLock = lock.writeLock();
       writeLock.lock();
       try
       {
-         WeakHashMap<Object, ArrayRegistryEntry> arrayReferences = cache.get(array);
+         WeakHashMap<Object, HashMap<Object, ArrayRegistryEntry>> arrayReferences = cache.get(array);
          if (arrayReferences == null)
          {
-            arrayReferences = new WeakHashMap<Object, ArrayRegistryEntry>();
+            arrayReferences = new WeakHashMap<Object, HashMap<Object, ArrayRegistryEntry>>();
             cache.put(array, arrayReferences);
          }
-         ArrayRegistryEntry regEntry = arrayReferences.get(owner);
-         if (regEntry != null)
+         
+         HashMap<Object, ArrayRegistryEntry> ownerReferences = arrayReferences.get(owner);
+         if (ownerReferences == null)
          {
-            ((FieldArrayRegistryEntry)regEntry).addFieldName(fieldName);
+            ownerReferences = new HashMap<Object, ArrayRegistryEntry>();
+            arrayReferences.put(owner, ownerReferences);
          }
-         else
+         
+         ArrayRegistryEntry regEntry = ownerReferences.get(qualifier);
+         if (regEntry == null || regEntry.getArray() != array)
          {
-            arrayReferences.put(owner, new FieldArrayRegistryEntry(owner, fieldName, array));
+            ArrayRegistryEntry entry = factory.createArrayRegistryEntry(owner, qualifier, factory);
+            ownerReferences.put(qualifier, entry);
          }
          addNestedArrays(array);
       }
@@ -82,72 +109,27 @@
       }
    }
    
-   public void removeFieldReference(Object owner, String field, Object array)
+   public void removeFieldReference(Object owner, String fieldName, Object array)
    {
       if (array == null)
       {
          return;
       }
 
-      Lock writeLock = lock.writeLock();
-      writeLock.lock();
-      try
-      {
-         WeakHashMap<Object, ArrayRegistryEntry> arrayReferences = cache.get(array);
-         if (arrayReferences != null)
-         {
-            ArrayRegistryEntry regEntry = arrayReferences.get(owner);
-            if (owner != null)
-            {
-               ((FieldArrayRegistryEntry)regEntry).removeFieldName(field);
-               if (!regEntry.ownerHasReferences())
-               {
-                  arrayReferences.remove(owner);
-               }
-            }
-         }
-         removeNestedArrays(owner, array);
-      }
-      finally
-      {
-         writeLock.unlock();
-      }
+      removeReference(owner, fieldName, array);
    }
 
-   public void addElementReference(Object owner, int index, Object array)
+   public void removeElementReference(Object owner, int index, Object array)
    {
       if (array == null)
       {
          return;
       }
-      Lock writeLock = lock.writeLock();
-      writeLock.lock();
-      try
-      {
-         WeakHashMap<Object, ArrayRegistryEntry> arrayReferences = cache.get(array);
-         if (arrayReferences == null)
-         {
-            arrayReferences = new WeakHashMap<Object, ArrayRegistryEntry>();
-            cache.put(array, arrayReferences);
-         }
-         ArrayRegistryEntry regEntry = arrayReferences.get(owner);
-         if (regEntry != null)
-         {
-            ((ElementArrayRegistryEntry)regEntry).addIndex(index);
-         }
-         else
-         {
-            arrayReferences.put(owner, new ElementArrayRegistryEntry(owner, index, array));
-         }
-         addNestedArrays(array);
-      }
-      finally
-      {
-         writeLock.unlock();
-      }
+
+      removeReference(owner, new Integer(index), array);
    }
-   
-   public void removeElementReference(Object owner, int index, Object array)
+
+   public void removeReference(Object owner, Object qualifier, Object array)
    {
       if (array == null)
       {
@@ -158,20 +140,31 @@
       writeLock.lock();
       try
       {
-         WeakHashMap<Object, ArrayRegistryEntry> arrayReferences = cache.get(array);
+         WeakHashMap<Object, HashMap<Object,ArrayRegistryEntry>> arrayReferences = cache.get(array);
          if (arrayReferences != null)
          {
-            ArrayRegistryEntry regEntry = arrayReferences.get(owner);
-            if (owner != null)
+            HashMap<Object,ArrayRegistryEntry> ownerReferences = arrayReferences.get(owner);
+            if (ownerReferences != null)
             {
-               ((ElementArrayRegistryEntry)regEntry).removeIndex(index);
-               if (!regEntry.ownerHasReferences())
+               ArrayRegistryEntry regEntry = ownerReferences.remove(qualifier);
+               if (regEntry != null)
                {
-                  arrayReferences.remove(owner);
+                  if (ownerReferences.size() == 0)
+                  {
+                     arrayReferences.remove(owner);
+                     
+                     if (arrayReferences.size() == 0)
+                     {
+                        cache.remove(array);
+                     }
+                  }
+                  ///Should this be here or below?
+                  removeNestedArrays(array);
                }
+               
             }
          }
-         removeNestedArrays(owner, array);
+//         removeNestedArrays(owner, array);
       }
       finally
       {
@@ -186,8 +179,8 @@
       
       try
       {
-         WeakHashMap<Object, ArrayRegistryEntry> arrayReferences = cache.get(array);
-         if (arrayReferences == null || arrayReferences.size() == 0)
+         WeakHashMap<Object, HashMap<Object, ArrayRegistryEntry>> arrayReferences = cache.get(array);
+         if (arrayReferences == null)
          {
             return false;
          }
@@ -198,36 +191,31 @@
          readLock.unlock();
       }
    }
-   
-   public Set getOwners(Object owner, Object array)
+
+   public List<ArrayReference> getArrayOwners(Object array)
    {
+      System.out.println("----> getArrayOwners " + array);
       Lock readLock = lock.readLock();
       readLock.lock();
       
       try
       {
-         WeakHashMap<Object, ArrayRegistryEntry> arrayReferences = cache.get(array);
-         if (arrayReferences != null)
-         {
-            HashSet set = new HashSet();
-            set.addAll(arrayReferences.keySet());
-            return set;
-         }
-         return null;
+         return referenceBuilder.getArrayReferences(array);
       }
       finally
       {
          readLock.unlock();
       }
    }
-
+   
    private void addNestedArrays(Object array)
    {
       if (array == null)
       {
          return;
       }
-      if (isArray(array))
+      ArrayType type = isArray(array);
+      if (type == ArrayType.MULTIDIM_ARRAY)
       {
          for (int i = 0 ; i < ((Object[])array).length ; i++)
          {
@@ -235,32 +223,165 @@
             addNestedArrays(((Object[])array)[i]);
          }
       }
+      else if (type == ArrayType.OBJECT_ARRAY)
+      {
+         for (int i = 0 ; i < ((Object[])array).length ; i++)
+         {
+            Object val = ((Object[])array)[i];
+            if (val != null && val.getClass().isArray())
+            {
+               addElementReference(array, i, ((Object[])array)[i]);
+               addNestedArrays(((Object[])array)[i]);
+            }
+         }
+      }
    }
    
-   private void removeNestedArrays(Object owner, Object array)
+   private void removeNestedArrays(Object array)
    {
       if (array == null)
       {
          return;
       }
-      if (isArray(array))
+      ArrayType type = isArray(array);
+      if (type == ArrayType.MULTIDIM_ARRAY)
       {
          for (int i = 0 ; i < ((Object[])array).length ; i++)
          {
             removeElementReference(array, i, ((Object[])array)[i]);
-            removeNestedArrays(array, ((Object[])array)[i]);
+            removeNestedArrays(((Object[])array)[i]);
          }
       }
+      else if (type == ArrayType.OBJECT_ARRAY)
+      {
+         for (int i = 0 ; i < ((Object[])array).length ; i++)
+         {
+            Object val = ((Object[])array)[i];
+            if (val != null && val.getClass().isArray())
+            {
+               removeElementReference(array, i, ((Object[])array)[i]);
+               removeNestedArrays(((Object[])array)[i]);
+            }
+         }
+      }
    }
    
-   private boolean isArray(Object arrayCandidate)
+   private ArrayType isArray(Object arrayCandidate)
    {
       Class candidateClass = arrayCandidate.getClass();
       if (candidateClass.isArray())
       {
          Class componentType = candidateClass.getComponentType();
-         return componentType.isArray();
+         if (componentType.isArray())
+         {
+            return ArrayType.MULTIDIM_ARRAY;
+         }
+         if (componentType == Object.class)
+         {
+            return ArrayType.OBJECT_ARRAY;
+         }
       }
-      return false;
+      return ArrayType.NOT_ARRAY;
    }
+   
+   private interface ArrayRegistryEntryFactory
+   {
+      ArrayRegistryEntry createArrayRegistryEntry(Object owner, Object qualifier, Object array);
+   }
+   
+   private static class FieldArrayRegistryEntryFactory implements ArrayRegistryEntryFactory
+   {
+      public ArrayRegistryEntry createArrayRegistryEntry(Object owner, Object qualifier, Object array)
+      {
+         return new FieldArrayRegistryEntry(owner, (String)qualifier, array);
+      }
+   }
+
+   private static class ElementArrayRegistryEntryFactory implements ArrayRegistryEntryFactory
+   {
+      public ArrayRegistryEntry createArrayRegistryEntry(Object owner, Object qualifier, Object array)
+      {
+         return new ElementArrayRegistryEntry(owner, (Integer)qualifier, array);
+      }
+   }
+   
+   private class ArrayReferenceBuilder
+   {
+      private List<ArrayReference> getArrayReferences(Object array)
+      {
+         List<ArrayReference> references = null;
+         WeakHashMap<Object, HashMap<Object, ArrayRegistryEntry>> arrayReferences = cache.get(array);
+         if (arrayReferences != null && arrayReferences.size() > 0)
+         {
+            for (Object owner : arrayReferences.keySet())
+            {
+               HashMap<Object, ArrayRegistryEntry> ownerReferences = arrayReferences.get(owner);
+               for (Object qualifier : ownerReferences.keySet())
+               {
+                  ArrayRegistryEntry regEntry = ownerReferences.get(qualifier);
+                  
+                  if (regEntry.isOwnerRoot())
+                  {
+                     ArrayReference reference = getRootReference((FieldArrayRegistryEntry)regEntry);
+                     if (reference != null)
+                     {
+                        if (references == null)
+                        {
+                           references = new ArrayList<ArrayReference>();
+                        }
+                        references.add(reference);
+                     }
+                  }
+                  else
+                  {
+                     List<ArrayReference> parentReferences = getElementReferences((ElementArrayRegistryEntry)regEntry);
+                     if (parentReferences != null)
+                     {
+                        if (references == null)
+                        {
+                           references = new ArrayList<ArrayReference>();
+                        }
+                        references.addAll(parentReferences);
+                     }
+                  }
+               }
+            }
+         }
+         return references;
+      }
+      
+      private ArrayReference getRootReference(FieldArrayRegistryEntry regEntry)
+      {
+         Object root = regEntry.getOwner();
+         if (root != null)
+         {
+            String fieldName = regEntry.getFieldName();
+            return new ArrayReferenceImpl(root, fieldName);
+         }
+         return null;
+      }
+      
+      private List<ArrayReference> getElementReferences(ElementArrayRegistryEntry regEntry)
+      {
+         Object ownerArray = regEntry.getOwner();
+         if (ownerArray != null)
+         {
+            List<ArrayReference> references = getArrayReferences(ownerArray);
+            if (references != null && references.size() > 0)
+            {
+               for (ArrayReference reference : references)
+               {
+                  ((ArrayReferenceImpl)reference).addNestedArrayIndex(regEntry.getIndex());
+               }
+            }
+            return references;
+         }
+         return null;
+      }
+   }
+   
+   private enum ArrayType
+   {
+      NOT_ARRAY,MULTIDIM_ARRAY,OBJECT_ARRAY; 
+   }
 }

Modified: projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayRegistryEntry.java
===================================================================
--- projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayRegistryEntry.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ArrayRegistryEntry.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -52,20 +52,26 @@
       }
    }
 
-   public WeakReference getArray()
+   public Object getArray()
    {
-      return array;
+      if (array != null)
+      {
+         return array.get();
+      }
+      return null;
    }
 
-   public WeakReference getOwner()
+   public Object getOwner()
    {
-      return owner;
+      if (owner != null)
+      {
+         return owner.get();
+      }
+      return null;
    }
 
    public boolean isOwnerRoot()
    {
       return ownerIsRoot;
    }
-   
-   public abstract boolean ownerHasReferences();
 }

Modified: projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ElementArrayRegistryEntry.java
===================================================================
--- projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ElementArrayRegistryEntry.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/ElementArrayRegistryEntry.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -30,27 +30,16 @@
  */
 public class ElementArrayRegistryEntry extends ArrayRegistryEntry
 {
-   HashSet<Integer> indices = new HashSet<Integer>();
+   Integer index;;
    
-   ElementArrayRegistryEntry(Object owner, int index, Object array)
+   ElementArrayRegistryEntry(Object owner, Integer index, Object array)
    {
       super(owner, false, array);
-      this.indices.add(index); 
+      this.index = index; 
    }
-   
-   public void addIndex(int index)
-   {
-      indices.add(index);
-   }
-   
-   public void removeIndex(int index)
-   {
-      indices.remove(index);
-   }
 
-   @Override
-   public boolean ownerHasReferences()
+   public Integer getIndex()
    {
-      return indices.size() > 0;
+      return index;
    }
 }

Modified: projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/FieldArrayRegistryEntry.java
===================================================================
--- projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/FieldArrayRegistryEntry.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/main/org/jboss/aop/array/FieldArrayRegistryEntry.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -30,28 +30,17 @@
  */
 public class FieldArrayRegistryEntry extends ArrayRegistryEntry
 {
-   HashSet fields = new HashSet<String>();
+   String fieldName;
    
    FieldArrayRegistryEntry(Object owner, String fieldName, Object array)
    {
       // FIXME FieldArrayRegistryEntry constructor
       super(owner, true, array);
-      this.fields.add(fieldName);
+      this.fieldName = fieldName;
    }
    
-   public void addFieldName(String fieldName)
+   public String getFieldName()
    {
-      fields.add(fieldName);
+      return fieldName;
    }
-   
-   public void removeFieldName(String fieldName)
-   {
-      fields.remove(fieldName);
-   }
-   
-   @Override
-   public boolean ownerHasReferences()
-   {
-      return fields.size() > 0;
-   }
 }
\ No newline at end of file

Modified: projects/aop/branches/arrays/aop/src/main/org/jboss/aop/instrument/FieldAccessTransformer.java
===================================================================
--- projects/aop/branches/arrays/aop/src/main/org/jboss/aop/instrument/FieldAccessTransformer.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/main/org/jboss/aop/instrument/FieldAccessTransformer.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -118,11 +118,10 @@
    
    protected abstract void doBuildFieldWrappers(CtClass clazz, CtField field, int index, boolean shouldReplaceArrayAccess, JoinpointClassification classificationGet, JoinpointClassification classificationSet) throws NotFoundException, CannotCompileException;
    
-   protected String getArrayWriteRegistration(boolean shouldReplaceArrayAccess, CtField field, String oldValue, String newValue) throws NotFoundException
+   protected String getArrayWriteRegistration(boolean shouldReplaceArrayAccess, String target, CtField field, String oldValue, String newValue) throws NotFoundException
    {
-      if (field.getType().isArray() && shouldReplaceArrayAccess)
+      if (shouldReplaceArrayAccess && (field.getType().isArray() || field.getType().getName().equals("java.lang.Object")))
       {
-         String target = Modifier.isStatic(field.getModifiers()) ? "java.lang.Class.forName(" + field.getType().getName() + ")" : "this";  
          return "org.jboss.aop.array.ArrayAdvisor.updateArrayField(" + target + ", \"" + field.getName() + "\", " + oldValue + ", " + newValue + ");";
       }
       return "";

Modified: projects/aop/branches/arrays/aop/src/main/org/jboss/aop/instrument/GeneratedAdvisorFieldAccessTransformer.java
===================================================================
--- projects/aop/branches/arrays/aop/src/main/org/jboss/aop/instrument/GeneratedAdvisorFieldAccessTransformer.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/main/org/jboss/aop/instrument/GeneratedAdvisorFieldAccessTransformer.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -307,10 +307,11 @@
       String generatorName = FieldJoinPointGenerator.getJoinPointGeneratorFieldName(field.getName(), false);
       if (isStatic)
       {
-         String fieldString = clazz.getName() + "." + field.getName();
+         String targetString = "java.lang.Class.forName(\"" + clazz.getName() + "\")";
+         String fieldString = clazz.getName() +  "." + field.getName();
          code =
             "{" +
-            "    " + getArrayWriteRegistration(shouldReplaceArrayAccess, field, fieldString, "$2") +
+            "    " + getArrayWriteRegistration(shouldReplaceArrayAccess, targetString, field, fieldString, "$2") +
             "   if (" + infoName + " == null && " + generatorName + " != null)" +
             "   {" +
             "   " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "(this.getClass().getClassLoader());" +
@@ -327,10 +328,11 @@
       }
       else
       {
-         String fieldString = "((" + clazz.getName() + ")$1)." + field.getName();
+         String targetString = "((" + clazz.getName() + ")$1)";
+         String fieldString = targetString + "." + field.getName();
          code =
             "{" +
-            "    " + getArrayWriteRegistration(shouldReplaceArrayAccess, field, fieldString, "$2") +
+            "    " + getArrayWriteRegistration(shouldReplaceArrayAccess, targetString, field, fieldString, "$2") +
             "   if (" + infoName + " == null && " + generatorName + " != null)" +
             "   {" +
             "   " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "(this.getClass().getClassLoader());" +

Modified: projects/aop/branches/arrays/aop/src/resources/test/array/jboss-aop.xml
===================================================================
--- projects/aop/branches/arrays/aop/src/resources/test/array/jboss-aop.xml	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/resources/test/array/jboss-aop.xml	2006-12-28 21:18:10 UTC (rev 59240)
@@ -1,7 +1,10 @@
 <aop>
    <arrayreplacement class="org.jboss.test.aop.array.AOPArrayTestCase"/>
+   <arrayreplacement class="org.jboss.test.aop.array.ArrayReferenceTestCase"/>
    <arrayreplacement expr="class(org.jboss.test.aop.array.ClassWithArrayFields) OR class(org.jboss.test.aop.array.ClassWithSeveralReferencesToSameArray)"/>
+   <arrayreplacement expr="class($instanceof{org.jboss.test.aop.array.ClassForReference})"/>
    <prepare expr="field(* org.jboss.test.aop.array.ClassWithArrayFields->*)"/>
    <prepare expr="field(* org.jboss.test.aop.array.ClassWithSeveralReferencesToSameArray->*)"/> 
+   <prepare expr="field(* org.jboss.test.aop.array.ClassForReference->*)"/> 
 </aop>
 

Modified: projects/aop/branches/arrays/aop/src/test/org/jboss/test/aop/array/AOPArrayTestCase.java
===================================================================
--- projects/aop/branches/arrays/aop/src/test/org/jboss/test/aop/array/AOPArrayTestCase.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/test/org/jboss/test/aop/array/AOPArrayTestCase.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -29,6 +29,7 @@
 
 
 /**
+ * Test that arrays get advised properly
  * 
  * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
  * @version $Revision: 1.1 $
@@ -101,14 +102,14 @@
    {
       ClassWithArrayFields obj = new ClassWithArrayFields();
       TestArrayElementInterceptor.clear();
-      obj.booleans[1] = false; 
+      obj.booleans[1] = true;
       assertEquals(1, TestArrayElementInterceptor.index);
       assertNotNull(TestArrayElementInterceptor.value);
-      assertEquals(false, ((Boolean)TestArrayElementInterceptor.value).booleanValue());
+      assertEquals(true, ((Boolean)TestArrayElementInterceptor.value).booleanValue());
 
       TestArrayElementInterceptor.clear();
       boolean val = obj.booleans[1];
-      assertEquals(false, val);
+      assertEquals(true, val);
       assertEquals(1, TestArrayElementInterceptor.index);
       assertNull(TestArrayElementInterceptor.value);
    }
@@ -472,6 +473,305 @@
       
    }
    
+   public void testObjectArrayWithArrayAsObjectEntry2()
+   {
+      ClassWithArrayFields obj = new ClassWithArrayFields();
+      Object[] original = obj.objects;
+      obj.objects = new Object[] {new int[] {1,2,3}};
+      
+      //Add an array as one of the elements in the object array
+      TestArrayElementInterceptor.clear();
+      original[0] = "X";
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      Object val = original[0];
+      assertEquals("X", val);
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      int[] i = (int[])obj.objects[0];
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      i[1] = 10;
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertEquals(10, TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      int ival = i[1];
+      assertEquals(10, ival);
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+   }
+   
+   public void testObjectFieldWithArray()
+   {
+      ClassWithArrayFields obj = new ClassWithArrayFields();
+      obj.objectField = new int[] {1,2,3};
+      
+      TestArrayElementInterceptor.clear();
+      ((int[])obj.objectField)[1] = 10;
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertEquals(10, TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      int val = ((int[])obj.objectField)[2];
+      assertEquals(3, val);
+      assertEquals(2, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      int[] array = (int[])obj.objectField;
+      TestArrayElementInterceptor.clear();
+      val = array[2];
+      assertEquals(3, val);
+      assertEquals(2, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      obj.objectField = null;
+      TestArrayElementInterceptor.clear();
+      val = array[2];
+      assertEquals(3, val);
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+   }
+   
+   public void testObjectFieldWithNestedArrays()
+   {
+      ClassWithArrayFields obj = new ClassWithArrayFields();
+      obj.objectField = new Object[] {new int[] {1, 2}, new Object[] {"X", "Y"}};
+      
+      Object[] objArray = (Object[])obj.objectField;
+      
+      TestArrayElementInterceptor.clear();
+      int[] intArray = (int[])((Object[])obj.objectField)[0]; 
+      assertEquals(0, TestArrayElementInterceptor.index);
+      
+      TestArrayElementInterceptor.clear();
+      Object[] objArray2 = (Object[])((Object[])obj.objectField)[1]; 
+      assertEquals(1, TestArrayElementInterceptor.index);
+
+      TestArrayElementInterceptor.clear();
+      intArray[1] = 10;
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertEquals(10, TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      int val = intArray[1];
+      assertEquals(10, val);
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      objArray2[1] = "ZZZ";
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertEquals("ZZZ", TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      Object oval = objArray2[1];
+      assertEquals("ZZZ", oval);
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      int[] intArray2 = new int[] {11, 22};
+      objArray[0] = intArray2;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(intArray2, TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      intArray2[1] = 10;
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertEquals(10, TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      val = intArray2[1];
+      assertEquals(10, val);
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      intArray[1] = 10;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      val = intArray[1];
+      assertEquals(10, val);
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      objArray[0] = null;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      objArray[1] = null;
+      assertEquals(1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      intArray2[1] = 10;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      val = intArray2[1];
+      assertEquals(10, val);
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      objArray2[1] = "ZZZ";
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      TestArrayElementInterceptor.clear();
+      oval = objArray2[1];
+      assertEquals("ZZZ", oval);
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+   }
+   
+   public void testIgnoreDoubleUpdate()
+   {
+      ClassWithArrayFields obj = new ClassWithArrayFields();
+      
+      String sval = "X";
+      TestArrayElementInterceptor.clear();
+      obj.objects[0] = sval;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(sval, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.objects[0] = sval;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+
+      byte byteVal = 10;
+      TestArrayElementInterceptor.clear();
+      obj.bytes[0] = byteVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(byteVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.bytes[0] = byteVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+
+      //Set the value to be different
+      obj.booleans[0] = false;
+      boolean booleanVal = true;
+      TestArrayElementInterceptor.clear();
+      obj.booleans[0] = booleanVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(booleanVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.booleans[0] = booleanVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      booleanVal = false;
+      TestArrayElementInterceptor.clear();
+      obj.booleans[0] = booleanVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(booleanVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.booleans[0] = booleanVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      char charVal = 'h';
+      TestArrayElementInterceptor.clear();
+      obj.chars[0] = charVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(charVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.chars[0] = charVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      double doubleVal = 101.1d;
+      TestArrayElementInterceptor.clear();
+      obj.doubles[0] = doubleVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(doubleVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.doubles[0] = doubleVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      
+      float floatVal = 66.6f;
+      TestArrayElementInterceptor.clear();
+      obj.floats[0] = floatVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(floatVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.floats[0] = floatVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+
+      int intVal = 1000;
+      TestArrayElementInterceptor.clear();
+      obj.ints[0] = intVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(intVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.ints[0] = intVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+
+      int[][] intVal2d = new int[][]{new int[]{1}, new int[]{2}};
+      TestArrayElementInterceptor.clear();
+      obj.ints3d[0] = intVal2d;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(intVal2d, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.ints3d[0] = intVal2d;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+
+      long longVal = 10001;
+      TestArrayElementInterceptor.clear();
+      obj.longs[0] = longVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(longVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.longs[0] = longVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+
+      short shortVal = 999;
+      TestArrayElementInterceptor.clear();
+      obj.shorts[0] = shortVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(shortVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.shorts[0] = shortVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+
+      Object objectVal = new int[] {1,2,3};
+      TestArrayElementInterceptor.clear();
+      obj.objects[0] = objectVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(objectVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      obj.objects[0] = objectVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+      intVal = 100;
+      TestArrayElementInterceptor.clear();
+      ((int[])objectVal)[0] = intVal;
+      assertEquals(0, TestArrayElementInterceptor.index);
+      assertEquals(intVal, TestArrayElementInterceptor.value);
+      TestArrayElementInterceptor.clear();
+      ((int[])objectVal)[0] = intVal;
+      assertEquals(-1, TestArrayElementInterceptor.index);
+      assertNull(TestArrayElementInterceptor.value);
+   }
+   
    public void testUnadvisedArrayFields()
    {
       ClassWithUnadvisedArrayFields obj = new ClassWithUnadvisedArrayFields();
@@ -520,6 +820,6 @@
       obj.shorts[0] = 100;
       assertEquals(100, obj.shorts[0]);
       assertEquals(-1, TestArrayElementInterceptor.index);
-
    }
+   
 }

Modified: projects/aop/branches/arrays/aop/src/test/org/jboss/test/aop/array/ClassWithArrayFields.java
===================================================================
--- projects/aop/branches/arrays/aop/src/test/org/jboss/test/aop/array/ClassWithArrayFields.java	2006-12-27 18:02:24 UTC (rev 59239)
+++ projects/aop/branches/arrays/aop/src/test/org/jboss/test/aop/array/ClassWithArrayFields.java	2006-12-28 21:18:10 UTC (rev 59240)
@@ -21,8 +21,6 @@
 */ 
 package org.jboss.test.aop.array;
 
-import java.util.Arrays;
-
 /**
  * 
  * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
@@ -51,6 +49,7 @@
    };
    public long[] longs = new long[] {1L, 2L, 3L};
    public short[] shorts = new short[] {1,2,3};
+   public Object objectField = new int[] {1, 2, 3};
    
    public ClassWithArrayFields()
    {




More information about the jboss-cvs-commits mailing list