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());
+ }
}