myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mat...@apache.org
Subject svn commit: r702351 - in /myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad: bean/util/StateUtils.java model/ChildPropertyMenuModel.java model/ChildPropertyTreeModel.java util/CollectionUtils.java
Date Tue, 07 Oct 2008 05:39:44 GMT
Author: matzew
Date: Mon Oct  6 22:39:43 2008
New Revision: 702351

URL: http://svn.apache.org/viewvc?rev=702351&view=rev
Log:
TRINIDAD-1251 - Work-around buggy implementation of Collections.checkedList(), Collections.synchronizedList(),
Collections.unmodifiableList()

Modified:
    myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java
    myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java
    myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java
    myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java

Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java?rev=702351&r1=702350&r2=702351&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java
(original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java
Mon Oct  6 22:39:43 2008
@@ -77,7 +77,7 @@
       checkSerializationProperty = checkSerializationProperty.toUpperCase();
       
       // comma-separated list with allowed whitespace
-      String[] paramArray = checkSerializationProperty.split(",\\s*");
+      String[] paramArray = checkSerializationProperty.split(",");
       
       Set<String> serializationFlags = new HashSet<String>(Arrays.asList(paramArray));
       
@@ -593,3 +593,4 @@
 
 
 
+

Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java?rev=702351&r1=702350&r2=702351&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java
(original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java
Mon Oct  6 22:39:43 2008
@@ -190,7 +190,7 @@
     
     // wrap sublist in a Serializable copy, since sublist usually returns non-Serializable
     // instances
-    return CollectionUtils.getSerializableList(path.subList(0, path.size() - 1));
+    return CollectionUtils.newSerializableList(path.subList(0, path.size() - 1));
   }
 
   @Override

Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java?rev=702351&r1=702350&r2=702351&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java
(original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java
Mon Oct  6 22:39:43 2008
@@ -192,7 +192,7 @@
 
     // wrap sublist in a Serializable copy, since sublist usually returns non-Serializable
     // instances
-    return CollectionUtils.getSerializableList(path.subList(0, path.size() - 1));
+    return CollectionUtils.newSerializableList(path.subList(0, path.size() - 1));
   }
 
   @Override

Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java?rev=702351&r1=702350&r2=702351&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
(original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
Mon Oct  6 22:39:43 2008
@@ -27,8 +27,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.ConcurrentModificationException;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
@@ -74,6 +76,43 @@
 
   /**
    * Returns a List based on the passed in List <code>l</code>,
+   * guaranteed to be Serializable. List <code>l</code> will be
+   * wrapped in a List that implements Serializable and upon
+   * Serialization the contents of <code>l</code> will be copied into
+   * the result.
+   * <p>
+   * If <code>l</code> implements RandomAccess, any returned List will also
+   * implement RandomAccess.
+   * <p>
+   * The results is very similar to creating a new ArrayList with the
+   * contents of <code>l</code>, but no wrapper is created unless necessary
+   * and the actual creation of the Serializable copy is deferred until
+   * Serialization occurs.
+   * <p>
+   * Code that calls List.subList() and needs the result to be Serializable should always
+   * use <code>newSerializableList</code> rather than <code>getSerializableList</code>
because
+   * the <code>java.util.Collections</code> implementations of <code>checkedList</code>,
+   * <code>unmodifiableList</code>, and <code>synchronizedList</code>
all lie and always implement
+   * Serializable, regardless of the serializability of their backing List.
+   * @param l The List to get a Serializable version of
+   * @return A Serializable version of List <code>l</code>
+   * @see #getSerializableList
+   * @see #getSerializableCollection
+   */
+  public static <T> List<T> newSerializableList(List<T> l)
+  {
+    if (l instanceof RandomAccess)
+    {
+      return new SerializableRandomAccessList<T>(l);
+    }
+    else
+    {
+      return new SerializableList<T>(l);
+    }
+  }
+
+  /**
+   * Returns a List based on the passed in List <code>l</code>,
    * guaranteed to be Serializable. If <code>l</code> is Serializable,
    * <code>l</code> will be returned, otherwise, <code>l</code> will
be
    * wrapped in a List that implements Serializable and upon
@@ -87,24 +126,29 @@
    * contents of <code>l</code>, but no wrapper is created unless necessary
    * and the actual creation of the Serializable copy is deferred until
    * Serialization occurs.
+   * <p>
+   * Code that calls List.subList() and needs the result to be Serializable should always
+   * use <code>newSerializableList</code> rather than <code>getSerializableList</code>
because
+   * the <code>java.util.Collections</code> implementations of <code>checkedList</code>,
+   * <code>unmodifiableList</code>, and <code>synchronizedList</code>
all lie and always implement
+   * Serializable, regardless of the serializability of their backing List.
    * @param l The List to get a Serializable version of
    * @return A Serializable version of List <code>l</code>
+   * @see #newSerializableList
    * @see #getSerializableCollection
    */
   public static <T> List<T> getSerializableList(List<T> l)
   {
-    if (l instanceof Serializable)
+    // because we can't trust the implementations of the checked, unmodifiable, and synchronized
+    // versions, always create a Serializable wrapper if we see one of these classes
+    if ((l instanceof Serializable) &&
+         !_CHECKED_LIST.isInstance(l) &&
+         !_UNMODIFIABLE_LIST.isInstance(l) &&
+         !_SYNCHRONIZED_LIST.isInstance(l))
       return l;
     else
     {
-      if (l instanceof RandomAccess)
-      {
-        return new SerializableRandomAccessList<T>(l);
-      }
-      else
-      {
-        return new SerializableList<T>(l);
-      }
+      return newSerializableList(l);
     }
   }
   
@@ -224,12 +268,11 @@
   {
     SerializableCollection(Collection<E> delegate)
     {
+      // we don't check that the delegate is Serializable because of the Collections
+      // classes that lie about Serializability
       if (delegate == null)
         throw new NullPointerException();
-      
-      if (delegate instanceof Serializable)
-        throw new IllegalArgumentException();
-      
+           
       _delegate = delegate;
     }
 
@@ -667,6 +710,25 @@
     private final Map<K, V> _delegate;
   }
 
+  //
+  // Build up references to implementation classes used by Collections to implement the following
+  // features.  This way we can detect when these classes are used and work around problems.
+  //
+  private static final Class<? extends List> _CHECKED_LIST;
+  private static final Class<? extends List> _UNMODIFIABLE_LIST;
+  private static final Class<? extends List> _SYNCHRONIZED_LIST;
+  
+  static
+  {
+    // use a LinkedList as it doesn't implement RandomAccess, so that we don't accidentally
get
+    // the RandomAccess subclasses
+    LinkedList<Object> dummyList = new LinkedList<Object>();
+    
+    _CHECKED_LIST      = Collections.checkedList(dummyList, Object.class).getClass();
+    _UNMODIFIABLE_LIST = Collections.unmodifiableList(dummyList).getClass();
+    _SYNCHRONIZED_LIST = Collections.synchronizedList(dummyList).getClass();
+  }
+  
   private static final TrinidadLogger _LOG = 
                                         TrinidadLogger.createTrinidadLogger(CollectionUtils.class);
 



Mime
View raw message