You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by im...@apache.org on 2008/04/04 08:45:41 UTC
svn commit: r644625 - in /myfaces/core/trunk_1.2.x:
api/src/main/java/javax/faces/component/_ComponentAttributesMap.java
impl/src/test/java/org/apache/myfaces/application/jsp/JspStateManagerImplTest.java
Author: imario
Date: Thu Apr 3 23:45:40 2008
New Revision: 644625
URL: http://svn.apache.org/viewvc?rev=644625&view=rev
Log:
MYFACES-1850: quick fix for attributes problem with server side state saving and "serialize stat in session"=false. Will think about something more performant asap.
Modified:
myfaces/core/trunk_1.2.x/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java
myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/jsp/JspStateManagerImplTest.java
Modified: myfaces/core/trunk_1.2.x/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java?rev=644625&r1=644624&r2=644625&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java (original)
+++ myfaces/core/trunk_1.2.x/api/src/main/java/javax/faces/component/_ComponentAttributesMap.java Thu Apr 3 23:45:40 2008
@@ -15,35 +15,29 @@
*/
package javax.faces.component;
+import javax.el.ValueExpression;
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-import javax.el.ValueExpression;
-import javax.faces.FacesException;
-import javax.faces.context.FacesContext;
+import java.util.*;
/**
* A custom implementation of the Map interface, where get and put calls
* try to access getter/setter methods of an associated UIComponent before
* falling back to accessing a real Map object.
- * <p>
+ * <p/>
* Some of the behaviours of this class don't really comply with the
* definitions of the Map class; for example the key parameter to all
* methods is required to be of type String only, and after clear(),
* calls to get can return non-null values. However the JSF spec
* requires that this class behave in the way implemented below. See
* UIComponent.getAttributes for more details.
- * <p>
+ * <p/>
* The term "property" is used here to refer to real javabean properties
* on the underlying UIComponent, while "attribute" refers to an entry
* in the associated Map.
@@ -54,9 +48,9 @@
class _ComponentAttributesMap
implements Map, Serializable
{
- private static final long serialVersionUID = -9106832179394257866L;
+ private static final long serialVersionUID = -9106832179394257866L;
- private static final Object[] EMPTY_ARGS = new Object[0];
+ private static final Object[] EMPTY_ARGS = new Object[0];
// The component that is read/written via this map.
private UIComponent _component;
@@ -72,11 +66,11 @@
private transient Map<String, PropertyDescriptor> _propertyDescriptorMap = null;
// Cache for component property descriptors
- private static Map<Class, Map<String, PropertyDescriptor>> _propertyDescriptorCache = new WeakHashMap<Class, Map<String,PropertyDescriptor>>();
+ private static Map<Class, Map<String, PropertyDescriptor>> _propertyDescriptorCache = new WeakHashMap<Class, Map<String, PropertyDescriptor>>();
/**
* Create a map backed by the specified component.
- * <p>
+ * <p/>
* This method is expected to be called when a component is first created.
*/
_ComponentAttributesMap(UIComponent component)
@@ -90,8 +84,8 @@
* associated with the component are provided in the specified Map
* class. A reference to the provided map is kept; this object's contents
* are updated during put calls on this instance.
- * <p>
- * This method is expected to be called during the "restore view" phase.
+ * <p/>
+ * This method is expected to be called during the "restore view" phase.
*/
_ComponentAttributesMap(UIComponent component, Map<Object, Object> attributes)
{
@@ -102,7 +96,7 @@
/**
* Return the number of <i>attributes</i> in this map. Properties of the
* underlying UIComponent are not counted.
- * <p>
+ * <p/>
* Note that because the get method can read properties of the
* UIComponent and evaluate value-bindings, it is possible to have
* size return zero while calls to the get method return non-null
@@ -116,7 +110,7 @@
/**
* Clear all the <i>attributes</i> in this map. Properties of the
* underlying UIComponent are not modified.
- * <p>
+ * <p/>
* Note that because the get method can read properties of the
* UIComponent and evaluate value-bindings, it is possible to have
* calls to the get method return non-null values immediately after
@@ -130,7 +124,7 @@
/**
* Return true if there are no <i>attributes</i> in this map. Properties
* of the underlying UIComponent are not counted.
- * <p>
+ * <p/>
* Note that because the get method can read properties of the
* UIComponent and evaluate value-bindings, it is possible to have
* isEmpty return true, while calls to the get method return non-null
@@ -145,26 +139,26 @@
* Return true if there is an <i>attribute</i> with the specified name,
* but false if there is a javabean <i>property</i> of that name on the
* associated UIComponent.
- * <p>
+ * <p/>
* Note that it should be impossible for the attributes map to contain
* an entry with the same name as a javabean property on the associated
* UIComponent.
- *
+ *
* @param key <i>must</i> be a String. Anything else will cause a
- * ClassCastException to be thrown.
+ * ClassCastException to be thrown.
*/
public boolean containsKey(Object key)
{
checkKey(key);
-
- return getPropertyDescriptor((String)key) == null ? _attributes.containsKey(key) : false;
+
+ return getPropertyDescriptor((String) key) == null ? _attributes.containsKey(key) : false;
}
/**
* Returns true if there is an <i>attribute</i> with the specified
* value. Properties of the underlying UIComponent aren't examined,
* nor value-bindings.
- *
+ *
* @param value null is allowed
*/
public boolean containsValue(Object value)
@@ -186,9 +180,9 @@
*/
public void putAll(Map t)
{
- for (Iterator it = t.entrySet().iterator(); it.hasNext(); )
+ for (Iterator it = t.entrySet().iterator(); it.hasNext();)
{
- Map.Entry entry = (Entry)it.next();
+ Map.Entry entry = (Entry) it.next();
put(entry.getKey(), entry.getValue());
}
}
@@ -215,28 +209,28 @@
* In order: get the value of a <i>property</i> of the underlying
* UIComponent, read an <i>attribute</i> from this map, or evaluate
* the component's value-binding of the specified name.
- *
+ *
* @param key must be a String. Any other type will cause ClassCastException.
*/
public Object get(Object key)
{
checkKey(key);
-
+
// is there a javabean property to read?
PropertyDescriptor propertyDescriptor
- = getPropertyDescriptor((String)key);
+ = getPropertyDescriptor((String) key);
if (propertyDescriptor != null)
{
return getComponentProperty(propertyDescriptor);
}
-
+
// is there a literal value to read?
Object mapValue = _attributes.get(key);
if (mapValue != null)
{
return mapValue;
}
-
+
// is there a value-binding to read?
ValueExpression ve = _component.getValueExpression((String) key);
if (ve != null)
@@ -252,14 +246,14 @@
* Remove the attribute with the specified name. An attempt to
* remove an entry whose name is that of a <i>property</i> on
* the underlying UIComponent will cause an IllegalArgumentException.
- * Value-bindings for the underlying component are ignored.
- *
+ * Value-bindings for the underlying component are ignored.
+ *
* @param key must be a String. Any other type will cause ClassCastException.
*/
public Object remove(Object key)
{
checkKey(key);
- PropertyDescriptor propertyDescriptor = getPropertyDescriptor((String)key);
+ PropertyDescriptor propertyDescriptor = getPropertyDescriptor((String) key);
if (propertyDescriptor != null)
{
throw new IllegalArgumentException("Cannot remove component property attribute");
@@ -273,12 +267,12 @@
* exists. Value-bindings associated with the component are ignored; to
* write to a value-binding, the value-binding must be explicitly
* retrieved from the component and evaluated.
- * <p>
+ * <p/>
* Note that this method is different from the get method, which
* does read from a value-binding if one exists. When a value-binding
* exists for a non-property, putting a value here essentially "masks"
* the value-binding until that attribute is removed.
- * <p>
+ * <p/>
* The put method is expected to return the previous value of the
* property/attribute (if any). Because UIComponent property getter
* methods typically try to evaluate any value-binding expression of
@@ -290,19 +284,21 @@
* attributes). Because the UIComponent.getAttributes method
* only returns a Map class and this class must be package-private,
* there is no way of exposing a "putNoReturn" type method.
- *
- * @param key String, null is not allowed
+ *
+ * @param key String, null is not allowed
* @param value null is allowed
*/
public Object put(Object key, Object value)
{
checkKey(key);
- PropertyDescriptor propertyDescriptor = getPropertyDescriptor((String)key);
- if(propertyDescriptor == null)
+ PropertyDescriptor propertyDescriptor = getPropertyDescriptor((String) key);
+ if (propertyDescriptor == null)
{
- if(value==null)
- throw new NullPointerException("value is null for a not available property: " + key);
+ if (value == null)
+ {
+ throw new NullPointerException("value is null for a not available property: " + key);
+ }
}
else
{
@@ -321,11 +317,11 @@
/**
* Retrieve info about getter/setter methods for the javabean property
* of the specified name on the underlying UIComponent object.
- * <p>
+ * <p/>
* This method optimises access to javabean properties of the underlying
* UIComponent by maintaining a cache of ProperyDescriptor objects for
* that class.
- * <p>
+ * <p/>
* TODO: Consider making the cache shared between component instances;
* currently 100 UIInputText components means performing introspection
* on the UIInputText component 100 times.
@@ -334,12 +330,12 @@
{
if (_propertyDescriptorMap == null)
{
- // Try to get descriptor map from cache
- _propertyDescriptorMap = _propertyDescriptorCache.get(_component.getClass());
- // Cache miss: create descriptor map and put it in cache
- if (_propertyDescriptorMap == null)
- {
- // Create descriptor map...
+ // Try to get descriptor map from cache
+ _propertyDescriptorMap = _propertyDescriptorCache.get(_component.getClass());
+ // Cache miss: create descriptor map and put it in cache
+ if (_propertyDescriptorMap == null)
+ {
+ // Create descriptor map...
BeanInfo beanInfo;
try
{
@@ -357,13 +353,13 @@
if (propertyDescriptor.getReadMethod() != null)
{
_propertyDescriptorMap.put(propertyDescriptor.getName(),
- propertyDescriptor);
+ propertyDescriptor);
}
}
// ... and put it in cache
_propertyDescriptorCache.put(_component.getClass(), _propertyDescriptorMap);
- }
- }
+ }
+ }
return _propertyDescriptorMap.get(key);
}
@@ -371,12 +367,12 @@
/**
* Execute the getter method of the specified property on the underlying
* component.
- *
+ *
* @param propertyDescriptor specifies which property to read.
* @return the value returned by the getter method.
* @throws IllegalArgumentException if the property is not readable.
- * @throws FacesException if any other problem occurs while invoking
- * the getter method.
+ * @throws FacesException if any other problem occurs while invoking
+ * the getter method.
*/
private Object getComponentProperty(PropertyDescriptor propertyDescriptor)
{
@@ -399,11 +395,11 @@
/**
* Execute the setter method of the specified property on the underlying
* component.
- *
+ *
* @param propertyDescriptor specifies which property to write.
* @throws IllegalArgumentException if the property is not writable.
- * @throws FacesException if any other problem occurs while invoking
- * the getter method.
+ * @throws FacesException if any other problem occurs while invoking
+ * the getter method.
*/
private void setComponentProperty(PropertyDescriptor propertyDescriptor, Object value)
{
@@ -414,26 +410,32 @@
}
try
{
- writeMethod.invoke(_component, new Object[] {value});
+ writeMethod.invoke(_component, new Object[]{value});
}
catch (Exception e)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
throw new FacesException("Could not set property " + propertyDescriptor.getName() +
- " of component " + _component.getClientId(facesContext) +" to value : "+value+" with type : "+
- (value==null?"null":value.getClass().getName()), e);
+ " of component " + _component.getClientId(facesContext) + " to value : " + value + " with type : " +
+ (value == null ? "null" : value.getClass().getName()), e);
}
}
private void checkKey(Object key)
{
- if (key == null) throw new NullPointerException("key");
- if (!(key instanceof String)) throw new ClassCastException("key is not a String");
+ if (key == null)
+ {
+ throw new NullPointerException("key");
+ }
+ if (!(key instanceof String))
+ {
+ throw new ClassCastException("key is not a String");
+ }
}
/**
* Return the map containing the attributes.
- * <p>
+ * <p/>
* This method is package-scope so that the UIComponentBase class can access it
* directly when serializing the component.
*/
Modified: myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/jsp/JspStateManagerImplTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/jsp/JspStateManagerImplTest.java?rev=644625&r1=644624&r2=644625&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/jsp/JspStateManagerImplTest.java (original)
+++ myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/jsp/JspStateManagerImplTest.java Thu Apr 3 23:45:40 2008
@@ -60,4 +60,29 @@
UIViewRoot restoredViewRoot = stateManager.restoreView(facesContext, "/root", RenderKitFactory.HTML_BASIC_RENDER_KIT);
assertNotNull("restored view root should not be null", restoredViewRoot);
}
+
+ public void testSaveInSessionWithoutSerialize() throws Exception
+ {
+ // create a fake viewRoot
+ UIViewRoot root = new UIViewRoot();
+ root.getAttributes().put("key", "value");
+
+ // simulate server-side-state-saving without serialization
+ Object state = root.saveState(facesContext);
+
+ // restore view
+ UIViewRoot root1 = new UIViewRoot();
+ root1.restoreState(facesContext, state);
+
+ // restore view .. next request
+ UIViewRoot root2 = new UIViewRoot();
+ root2.restoreState(facesContext, state);
+
+ // chaange attribute in root1
+ root1.getAttributes().put("key", "borken");
+
+ // other values should not have been changed
+ assertEquals("value", root2.getAttributes().get("key"));
+ assertEquals("value", root.getAttributes().get("key"));
+ }
}