You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/01/15 05:53:46 UTC

svn commit: r899525 - in /myfaces/core/trunk/api/src: main/java/javax/faces/component/_DeltaList.java test/java/javax/faces/component/_DeltaListTest.java

Author: lu4242
Date: Fri Jan 15 04:53:46 2010
New Revision: 899525

URL: http://svn.apache.org/viewvc?rev=899525&view=rev
Log:
MYFACES-2487 DeltaList does not deal correctly with transient objects

Modified:
    myfaces/core/trunk/api/src/main/java/javax/faces/component/_DeltaList.java
    myfaces/core/trunk/api/src/test/java/javax/faces/component/_DeltaListTest.java

Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/_DeltaList.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/_DeltaList.java?rev=899525&r1=899524&r2=899525&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/_DeltaList.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/_DeltaList.java Fri Jan 15 04:53:46 2010
@@ -18,14 +18,11 @@
  */
 package javax.faces.component;
 
-import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
-import java.util.Map;
 
 import javax.faces.context.FacesContext;
 
@@ -49,8 +46,6 @@
 {
 
     private List<T> _delegate;
-    //private UIComponent _component;
-    private Map<Object,Boolean> _deltas;
     private boolean _initialStateMarked;
     
     public _DeltaList()
@@ -62,71 +57,33 @@
         _delegate = delegate;
     }
     
-    private boolean _createDeltas()
-    {
-        if (initialStateMarked())
-        {
-            if (_deltas == null)
-            {
-                _deltas = new HashMap<Object, Boolean>(4);
-            }
-            return true;
-        }
-
-        return false;
-    }    
-
     public void add(int index, T element)
     {
-        if (_createDeltas())
-        {
-            _deltas.put(element, Boolean.TRUE);
-        }
+        clearInitialState();
         _delegate.add(index, element);
     }
 
     public boolean add(T e)
     {
-        if (_createDeltas())
-        {
-            _deltas.put(e, Boolean.TRUE);
-        }
+        clearInitialState();
         return _delegate.add(e);
     }
 
     public boolean addAll(Collection<? extends T> c)
     {
-        if (_createDeltas())
-        {
-            for (Iterator<? extends T> it = c.iterator(); it.hasNext();)
-            {
-                _deltas.put(it.next(), Boolean.TRUE);
-            }
-        }        
+        clearInitialState();
         return _delegate.addAll(c);
     }
 
     public boolean addAll(int index, Collection<? extends T> c)
     {
-        if (_createDeltas())
-        {
-            for (Iterator<? extends T> it = c.iterator(); it.hasNext();)
-            {
-                _deltas.put(it.next(), Boolean.TRUE);
-            }
-        }        
+        clearInitialState();
         return _delegate.addAll(index, c);
     }
 
     public void clear()
     {
-        if (_createDeltas())
-        {
-            for (Iterator<? extends T> it = _delegate.iterator(); it.hasNext();)
-            {
-                _deltas.put(it.next(), Boolean.FALSE);
-            }
-        }        
+        clearInitialState();
         _delegate.clear();
     }
 
@@ -187,31 +144,19 @@
 
     public T remove(int index)
     {
-        if (_createDeltas())
-        {
-            _deltas.put(_delegate.get(index), Boolean.FALSE);
-        }        
+        clearInitialState();
         return _delegate.remove(index);
     }
 
     public boolean remove(Object o)
     {
-        if (_createDeltas())
-        {
-            _deltas.put(o, Boolean.FALSE);
-        }                
+        clearInitialState();
         return _delegate.remove(o);
     }
 
     public boolean removeAll(Collection<?> c)
     {
-        if (_createDeltas())
-        {
-            for (Iterator it = c.iterator(); it.hasNext();)
-            {
-                _deltas.put(it.next(), Boolean.FALSE);
-            }
-        }
+        clearInitialState();
         return _delegate.removeAll(c);
     }
 
@@ -222,11 +167,7 @@
 
     public T set(int index, T element)
     {
-        if (_createDeltas())
-        {
-            _deltas.put(_delegate.get(index), Boolean.FALSE);
-            _deltas.put(element, Boolean.TRUE);
-        }
+        clearInitialState();
         return _delegate.set(index, element);
     }
 
@@ -267,48 +208,37 @@
             return;
         }
         
-        if (_createDeltas())
+        if (initialStateMarked())
         {            
             //Restore delta
-            Object[] listAsMap = (Object[]) state;
-            for (int cnt = 0; cnt < listAsMap.length; cnt += 2)
-            {   
-                if (listAsMap[cnt] instanceof Boolean)
+            Object[] lst = (Object[]) state;
+            int j = 0;
+            int i = 0;
+            while (i < lst.length)
+            {
+                if (lst[i] instanceof _AttachedDeltaWrapper)
                 {
-                    Boolean value = (Boolean) listAsMap[cnt];
-                    T key = (T) UIComponentBase.
-                        restoreAttachedState(context, listAsMap[cnt+1]);
-                    _deltas.put(key,value);
-                    if (key != null)
-                    {
-                        if (value.booleanValue())
-                        {
-                            _delegate.add(key);
-                        }
-                        else
-                        {
-                            _delegate.remove(key);
-                        }
-                    }
+                    //Delta
+                    ((StateHolder)_delegate.get(j)).restoreState(context, ((_AttachedDeltaWrapper) lst[i]).getWrappedStateObject());
+                    j++;
                 }
-                else if (listAsMap[cnt+1] != null)
+                else if (lst[i] != null)
                 {
-                    if (listAsMap[cnt+1] instanceof _AttachedDeltaWrapper)
-                    {
-                        _AttachedDeltaWrapper wrapper = (_AttachedDeltaWrapper) listAsMap[cnt+1];
-                        //Restore delta state
-                        ((PartialStateHolder)_delegate.get((Integer)listAsMap[cnt])).restoreState(context, wrapper.getWrappedStateObject());
-                    }
-                    else
-                    {
-                        //Replace it
-                        _delegate.set((Integer)listAsMap[cnt], (T) UIComponentBase.restoreAttachedState(context, listAsMap[cnt+1]));
-                    }
+                    //Full
+                    _delegate.set(j, (T) UIComponentBase.restoreAttachedState(context, lst[i]));
+                    j++;
                 }
-                else if (listAsMap[cnt] != null)
+                else
                 {
-                    _delegate.set((Integer)listAsMap[cnt],null);
+                    _delegate.remove(j);
                 }
+                i++;
+            }
+            if (i != j)
+            {
+                // StateHolder transient objects found, next time save and restore it fully
+                //because the size of the list changes.
+                clearInitialState();
             }
         }
         else
@@ -318,7 +248,11 @@
             _delegate = new ArrayList<T>(lst.length);
             for (int i = 0; i < lst.length; i++)
             {
-                _delegate.add((T) UIComponentBase.restoreAttachedState(context, lst[i]));
+                T value = (T) UIComponentBase.restoreAttachedState(context, lst[i]);
+                if (value != null)
+                {
+                    _delegate.add(value);
+                }
             }
         }
     }
@@ -327,155 +261,45 @@
     {
         if (initialStateMarked())
         {
-            if (_deltas != null)
+            Object [] lst = new Object[_delegate.size()];
+            boolean nullDelta = true;
+            for (int i = 0; i < _delegate.size(); i++)
             {
-                //Count stateHolder instances to keep track
-                int stateHolderKeyCount = 0;
-                for (int i = 0; i < _delegate.size(); i++)
-                {
-                    T key = _delegate.get(i);
-                    if (key instanceof StateHolder && !_deltas.containsKey(key))
-                    {
-                        stateHolderKeyCount+=2;
-                    }
-                }
-                
-                int cnt = 0;
-                boolean nullDelta = true;
-                Object[] mapArr = (Object[]) new Object[_deltas.size() * 2+stateHolderKeyCount];
-                for (Map.Entry<Object, Boolean> entry : _deltas.entrySet())
-                {
-                    mapArr[cnt] = entry.getValue();
-                    Object value = entry.getKey();
-                    if (value instanceof StateHolder ||
-                        value instanceof List ||
-                        !(value instanceof Serializable))
-                    {
-                        mapArr[cnt+1] = UIComponentBase.saveAttachedState(context, value);
-                    }
-                    else
-                    {
-                        mapArr[cnt+1] = value;
-                    }
-                    cnt += 2;
-                    nullDelta = false;
-                }
-    
-                //Deal with StateHolder instances
-                for (int i = 0; i < _delegate.size(); i++)
+                Object value = _delegate.get(i);
+                if (value instanceof PartialStateHolder)
                 {
-                    T value = _delegate.get(i);
-                    if (value instanceof StateHolder && !_deltas.containsKey(value))
+                    //Delta
+                    PartialStateHolder holder = (PartialStateHolder) value;
+                    if (!holder.isTransient())
                     {
-                        mapArr[cnt] = i;
-                        if (value instanceof PartialStateHolder)
+                        Object attachedState = holder.saveState(context);
+                        if (attachedState != null)
                         {
-                            //Could contain delta, save it as _AttachedDeltaState
-                            PartialStateHolder holder = (PartialStateHolder) value;
-                            if (holder.isTransient())
-                            {                                
-                                mapArr[cnt + 1] = null;
-                                nullDelta = false;
-                            }
-                            else
-                            {
-                                Object savedValue = holder.saveState(context);
-                                if (savedValue != null)
-                                {
-                                    mapArr[cnt+1] = new _AttachedDeltaWrapper(value.getClass(), savedValue);
-                                    nullDelta = false;
-                                }
-                                else
-                                {
-                                    mapArr[cnt] = null;
-                                    mapArr[cnt+1] = null;
-                                }
-                            }
-                        }
-                        else
-                        {
-                            mapArr[cnt+1] = UIComponentBase.saveAttachedState(context, value);
                             nullDelta = false;
                         }
-                        cnt+=2;
+                        lst[i] = new _AttachedDeltaWrapper(value.getClass(),
+                            attachedState);
                     }
                 }
-                if (nullDelta)
+                else
                 {
-                    return null;
+                    //Full
+                    lst[i] = UIComponentBase.saveAttachedState(context, value);
+                    nullDelta = false;
                 }
-                return mapArr;
             }
-            else
+            if (nullDelta)
             {
-                //Count stateHolder instances to keep track
-                int stateHolderKeyCount = 0;
-                for (int i = 0; i < _delegate.size(); i++)
-                {
-                    T key = _delegate.get(i);
-                    if (key instanceof StateHolder)
-                    {
-                        stateHolderKeyCount += 2;
-                    }
-                }
-
-                int cnt = 0;
-                Object[] mapArr = (Object[]) new Object[stateHolderKeyCount];
-                boolean nullDelta = true;
-                //Deal with StateHolder instances
-                for (int i = 0; i < _delegate.size(); i++)
-                {
-                    T value = _delegate.get(i);
-                    if (value instanceof StateHolder)
-                    {
-                        mapArr[cnt] = i;
-                        if (value instanceof PartialStateHolder)
-                        {
-                            //Could contain delta, save it as _AttachedDeltaState
-                            PartialStateHolder holder = (PartialStateHolder) value;
-                            if (holder.isTransient())
-                            {                                
-                                mapArr[cnt + 1] = null;
-                                nullDelta = false;
-                            }
-                            else
-                            {
-                                Object savedValue = holder.saveState(context);
-                                if (savedValue != null)
-                                {
-                                    mapArr[cnt+1] = new _AttachedDeltaWrapper(value.getClass(), savedValue);
-                                    nullDelta = false;
-                                }
-                                else
-                                {
-                                    mapArr[cnt] = null;
-                                    mapArr[cnt+1] = null;
-                                }
-                            }
-                        }
-                        else
-                        {
-                            mapArr[cnt+1] = UIComponentBase.saveAttachedState(context, value);
-                            nullDelta = false;
-                        }
-                        cnt+=2;
-                    }
-                }
-                if (nullDelta)
-                {
-                    return null;
-                }
-                return mapArr;                
+                return null;
             }
+            return lst;
         }
         else
         {
-            Object [] lst = new Object[this.size()];
-            int i = 0;
-            for (Iterator it = _delegate.iterator(); it.hasNext();)
+            Object [] lst = new Object[_delegate.size()];
+            for (int i = 0; i < _delegate.size(); i++)
             {
-                lst[i] = UIComponentBase.saveAttachedState(context, it.next());
-                i++;
+                lst[i] = UIComponentBase.saveAttachedState(context, _delegate.get(i));
             }
             return lst;
         }
@@ -484,15 +308,17 @@
     public void clearInitialState()
     {
         //Reset delta setting to null
-        _deltas = null;
-        _initialStateMarked = false;
-        if (_delegate != null)
+        if (_initialStateMarked)
         {
-            for (T value : _delegate)
+            _initialStateMarked = false;
+            if (_delegate != null)
             {
-                if (value instanceof PartialStateHolder)
+                for (T value : _delegate)
                 {
-                    ((PartialStateHolder)value).clearInitialState();
+                    if (value instanceof PartialStateHolder)
+                    {
+                        ((PartialStateHolder)value).clearInitialState();
+                    }
                 }
             }
         }

Modified: myfaces/core/trunk/api/src/test/java/javax/faces/component/_DeltaListTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/test/java/javax/faces/component/_DeltaListTest.java?rev=899525&r1=899524&r2=899525&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/test/java/javax/faces/component/_DeltaListTest.java (original)
+++ myfaces/core/trunk/api/src/test/java/javax/faces/component/_DeltaListTest.java Fri Jan 15 04:53:46 2010
@@ -283,6 +283,63 @@
         }
     }
     
+    public static class TransientStateFacesListener implements FacesListener, StateHolder
+    {
+        String value;
+        
+        public TransientStateFacesListener()
+        {
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (obj instanceof TransientStateFacesListener)
+            {
+                if (value == null)
+                {
+                    if (((TransientStateFacesListener)obj).value == null)
+                    {
+                        return true;
+                    }
+                }
+                else if (value.equals(((TransientStateFacesListener)obj).value))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public boolean isTransient()
+        {
+            return true;
+        }
+
+        public void setTransient(boolean _transient)
+        {
+        }
+
+        public void restoreState(FacesContext context, Object state)
+        {
+        }
+
+        public Object saveState(FacesContext context)
+        {
+            return null;
+        }
+
+        public String getValue()
+        {
+            return value;
+        }
+
+        public void setValue(String value)
+        {
+            this.value = value;
+        }
+    }
+    
     public static class PartialStateFacesListener extends StateFacesListener implements PartialStateHolder
     {
         private boolean initialStateMarked;
@@ -389,7 +446,6 @@
         a.markInitialState();
         b.markInitialState();
         Object [] savedState1 = (Object[]) a.saveState(facesContext);
-        assertNull(savedState1 == null ? null : savedState1[1]);
         b.restoreState(facesContext, savedState1);        
         assertTrue(a._facesListeners.contains(listener1));
         assertTrue(b._facesListeners.contains(listener1));
@@ -583,6 +639,7 @@
         b.restoreState(facesContext, a.saveState(facesContext));
         assertTrue(a._facesListeners.contains(listener1));
         assertFalse(b._facesListeners.contains(listener1));
+        assertTrue(b._facesListeners.isEmpty());
     }
     
     public void testSimpleSaveRestoreTransient2()
@@ -661,4 +718,47 @@
         assertTrue(b._facesListeners.contains(listener2));
         assertEquals("value2", ((StateFacesListener)b._facesListeners.get(b._facesListeners.indexOf(listener2))).getValue());
     }
+    
+    public void testSimpleSaveRestoreTransient6()
+    {
+        UITestComponent a = new UITestComponent();
+        UITestComponent b = new UITestComponent();
+        TransientStateFacesListener listener1 = new TransientStateFacesListener();
+        listener1.setValue("value");
+        a.addTestFacesListener(listener1);
+        b.addTestFacesListener(listener1);
+        a.markInitialState();
+        b.markInitialState();
+        //Since listener1 is transient
+        Object [] savedState1 = (Object[]) a.saveState(facesContext);
+        b.restoreState(facesContext, savedState1);  
+        assertTrue(a._facesListeners.contains(listener1));
+        assertFalse(b._facesListeners.contains(listener1));
+    }
+
+    public void testSimpleSaveRestoreTransient7()
+    {
+        UITestComponent a = new UITestComponent();
+        UITestComponent b = new UITestComponent();
+        TransientStateFacesListener listener1 = new TransientStateFacesListener();
+        listener1.setTransient(true);
+        listener1.setValue("value");
+        StateFacesListener listener2 = new StateFacesListener();
+        listener2.setValue("value");
+        a.addTestFacesListener(listener1);
+        a.addTestFacesListener(listener2);
+        b.addTestFacesListener(listener1);
+        b.addTestFacesListener(listener2);
+        a.markInitialState();
+        b.markInitialState();
+        listener2.setValue("value2");
+        //Since listener1 is transient
+        Object [] savedState1 = (Object[]) a.saveState(facesContext);
+        b.restoreState(facesContext, savedState1);  
+        assertTrue(a._facesListeners.contains(listener1));
+        assertFalse(b._facesListeners.contains(listener1));
+        assertTrue(a._facesListeners.contains(listener2));
+        assertTrue(b._facesListeners.contains(listener2));
+        assertEquals("value2", ((StateFacesListener)b._facesListeners.get(b._facesListeners.indexOf(listener2))).getValue());
+    }
 }