You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by bs...@apache.org on 2010/10/28 02:40:24 UTC

svn commit: r1028150 [1/2] - in /myfaces/trinidad/branches/trinidad-1.2.x: trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/ trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ trinidad-impl/src/main/java/org/apache/myfaces/tri...

Author: bsullivan
Date: Thu Oct 28 00:40:23 2010
New Revision: 1028150

URL: http://svn.apache.org/viewvc?rev=1028150&view=rev
Log:
[Trinidad-1858] Fix fail-over bugs where session state is mutated without dirtying the Session objects

Backport to 1.2.x

Modified:
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PageFlowScopeMap.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/SubKeyMap.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/TokenCache.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java
    myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java?rev=1028150&r1=1028149&r2=1028150&view=diff
==============================================================================
--- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java Thu Oct 28 00:40:23 2010
@@ -57,6 +57,7 @@ public final class StateUtils
     boolean checkComponentTreeStateSerialization = false;
     boolean checkSessionSerialization = false;
     boolean checkApplicationSerialization = false;
+    boolean checkMangedBeanMutation = false;
 
     String checkSerializationProperty;
 
@@ -90,6 +91,7 @@ public final class StateUtils
           checkComponentTreeStateSerialization = true;
           checkSessionSerialization = true;
           checkApplicationSerialization = true;
+          checkMangedBeanMutation = true;
         }
         else
         {
@@ -98,6 +100,7 @@ public final class StateUtils
           checkComponentTreeStateSerialization = serializationFlags.contains("TREE");       
           checkSessionSerialization = serializationFlags.contains("SESSION");
           checkApplicationSerialization = serializationFlags.contains("APPLICATION");
+          checkMangedBeanMutation = serializationFlags.contains("BEANS");
         }
       }
     }
@@ -107,6 +110,7 @@ public final class StateUtils
     _CHECK_COMPONENT_TREE_STATE_SERIALIZATION = checkComponentTreeStateSerialization;
     _CHECK_SESSION_SERIALIZATION = checkSessionSerialization;
     _CHECK_APPLICATION_SERIALIZATION = checkApplicationSerialization;
+    _CHECK_MANAGED_BEAN_MUTATATION = checkMangedBeanMutation;
   }
 
   private static final boolean _CHECK_COMPONENT_TREE_STATE_SERIALIZATION;
@@ -114,6 +118,7 @@ public final class StateUtils
   private static final boolean _CHECK_PROPERTY_STATE_SERIALIZATION;
   private static final boolean _CHECK_SESSION_SERIALIZATION;
   private static final boolean _CHECK_APPLICATION_SERIALIZATION;
+  private static final boolean _CHECK_MANAGED_BEAN_MUTATATION;
 
   /**
    * Returns <code>true</code> if properties should be checked for
@@ -200,6 +205,7 @@ public final class StateUtils
    * @see #checkComponentStateSerialization
    * @see #checkComponentTreeStateSerialization
    * @see #checkApplicationSerialization
+   * @see #checkManagedBeanMutation
    */
   public static boolean checkSessionSerialization(ExternalContext extContext)
   {
@@ -222,6 +228,7 @@ public final class StateUtils
    * @see #checkComponentStateSerialization
    * @see #checkComponentTreeStateSerialization
    * @see #checkSessionSerialization
+   * @see #checkManagedBeanMutation
    */
   public static boolean checkApplicationSerialization(ExternalContext extContext)
   {
@@ -229,6 +236,22 @@ public final class StateUtils
   }
 
   /**
+   * Returns <code>true</code> if the attributes of the session and application Maps should be
+   * checked for cases where the attribute was mutated but not dirtied for failover.  If
+   * <code>checkSessionSerialization</code> returns <code>true</code>, the contents of the
+   * Session should be checked.  If <code>checkApplicationSerialization</code> returns
+   * <code>true</code>, the Serializable content of the Application should be checked.
+   * @return true if the contents of scopes should be checked for mutation without dirtying.
+   * @see #checkApplicationSerialization
+   * @see #checkSessionSerialization
+   */
+  public static boolean checkManagedBeanMutation(ExternalContext extContext)
+  {
+    return _CHECK_MANAGED_BEAN_MUTATATION;
+  }
+  
+    
+  /**
    * Persists a property key.
    */
   static public Object saveKey(PropertyKey key)
@@ -591,6 +614,3 @@ public final class StateUtils
 
 }
 
-
-
-

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java?rev=1028150&r1=1028149&r2=1028150&view=diff
==============================================================================
--- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java Thu Oct 28 00:40:23 2010
@@ -1720,7 +1720,7 @@ public final class CollectionUtils
                                                      e);
         }
       }
-      else
+      else if (value != null)
       {
         if (_requireSerializable)
         {

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java?rev=1028150&r1=1028149&r2=1028150&view=diff
==============================================================================
--- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java Thu Oct 28 00:40:23 2010
@@ -6,9 +6,9 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- * 
+ *
  *  http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,12 +18,15 @@
  */
 package org.apache.myfaces.trinidadinternal.application;
 
+import com.sun.facelets.FaceletViewHandler;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -60,7 +63,6 @@ import org.apache.myfaces.trinidadintern
 import org.apache.myfaces.trinidadinternal.util.SubKeyMap;
 import org.apache.myfaces.trinidadinternal.util.TokenCache;
 
-import com.sun.facelets.FaceletViewHandler;
 
 /**
  * StateManager that handles a hybrid client/server strategy:  a
@@ -101,6 +103,7 @@ public class StateManagerImpl extends St
   static public final String CACHE_VIEW_ROOT_INIT_PARAM =
     "org.apache.myfaces.trinidad.CACHE_VIEW_ROOT";
 
+
   /**
    * Servlet context initialization parameter used by
    * StateManagerImpl to decide what sort of state should be saved
@@ -119,12 +122,13 @@ public class StateManagerImpl extends St
     "org.apache.myfaces.trinidad.CLIENT_STATE_MAX_TOKENS";
 
   /**
-   * Servlet context initialization parameter used by
-   * StateManagerImpl to decide whether to zip state.
-   * Valid values are true and false
-   */
-  static public final String COMPRESS_VIEW_STATE_PARAM_NAME =
-    "org.apache.myfaces.trinidadinternal.COMPRESS_VIEW_STATE";
+     * Servlet context initialization parameter used by
+     * StateManagerImpl to decide whether to zip state.
+     * Valid values are true and false
+     */
+    static public final String COMPRESS_VIEW_STATE_PARAM_NAME =
+      "org.apache.myfaces.trinidad.COMPRESS_VIEW_STATE";
+
 
   /**
    * Value indicating that only a simple token will be stored
@@ -143,7 +147,7 @@ public class StateManagerImpl extends St
   {
     _delegate = delegate;
   }
-  
+
   @Override
   protected StateManager getWrapped()
   {
@@ -155,13 +159,13 @@ public class StateManagerImpl extends St
   public Object saveView(FacesContext context)
   {
     assert(context != null);
-    
+
     if(isSavingStateInClient(context))
     {
       SerializedView view = _saveSerializedView(context);
       return new Object[]{view.getStructure(), view.getState()};
     }
-    
+
     return super.saveView(context);
   }
 
@@ -169,12 +173,12 @@ public class StateManagerImpl extends St
   public SerializedView saveSerializedView(FacesContext context)
   {
     assert(context != null);
-    
+
     if(isSavingStateInClient(context))
     {
       return _saveSerializedView(context);
     }
-    
+
     return _delegate.saveSerializedView(context);
   }
 
@@ -190,7 +194,7 @@ public class StateManagerImpl extends St
     Object state = component.processSaveState(context);
     return new PageState(context, new Object[]{structure, state}, null);
   }
-  
+
   /**
    * Take an object created by saveComponentTree()
    * and instantiate it as a UIComponent.
@@ -268,7 +272,7 @@ public class StateManagerImpl extends St
       root.processRestoreState(context, state);
 
     return root;
-  }  
+  }
 
   @SuppressWarnings({"unchecked", "deprecation"})
   private SerializedView _saveSerializedView(FacesContext context)
@@ -319,19 +323,20 @@ public class StateManagerImpl extends St
       String token;
       ExternalContext extContext = context.getExternalContext();
 
-
       if (applicationViewCache == null)
       {
         assert(!dontSave);
-        TokenCache cache = _getViewCache(context);
+        
+        RequestContext trinContext = RequestContext.getCurrentInstance();
+
+        TokenCache cache = _getViewCache(trinContext, extContext);
         assert(cache != null);
 
-        Map<String, Object> sessionMap = extContext.getSessionMap();
-        RequestContext trinContext     = RequestContext.getCurrentInstance();
-        
+        Map<String, Object> sessionMap  = extContext.getSessionMap();
+
         // get view cache key with "." separator suffix to separate the SubKeyMap keys
         String subkey = _getViewCacheKey(extContext, trinContext, _SUBKEY_SEPARATOR);
-        
+
         Map<String, PageState> stateMap = new SubKeyMap<PageState>(sessionMap, subkey);
 
         // Sadly, we can't save just a SerializedView, because we should
@@ -343,9 +348,9 @@ public class StateManagerImpl extends St
             // Save the view root into the page state as a transient
             // if this feature has not been disabled
             _useViewRootCache(context) ? root : null);
-        
+
         String requestToken = _getRequestTokenForResponse(context);
-        
+
         // If we have a cached token that we want to reuse,
         // and that token hasn't disappeared from the cache already
         // (unlikely, but not impossible), use the stateMap directly
@@ -383,15 +388,15 @@ public class StateManagerImpl extends St
           // See Trinidad-1779
           String activePageStateKey = _getActivePageTokenKey(extContext, trinContext);
           String activeToken = (String)sessionMap.get(activePageStateKey);
-          
+
           // we only need to clear out the state if we're actually changing pages and thus tokens.
-          // Since we have already updated the state for 
+          // Since we have already updated the state for
           if (!token.equals(activeToken))
           {
             if (activeToken != null)
             {
               PageState activePageState = stateMap.get(activeToken);
-        
+
               if (activePageState != null)
                 activePageState.clearViewRootState();
             }
@@ -405,7 +410,7 @@ public class StateManagerImpl extends St
       {
         // use null viewRoot since this state is shared across users:
         PageState applicationState = new PageState(context, new Object[]{structure, state}, null);
-        
+
         // If we need to, stash the state off in our cache
         if (!dontSave)
         {
@@ -426,7 +431,7 @@ public class StateManagerImpl extends St
       // Create a "tokenView" which abuses SerializedView to store
       // our token only
       view = new SerializedView(token, null);
-      
+
       // And store the token for this request
       extContext.getRequestMap().put(_REQUEST_STATE_TOKEN_KEY, token);
     }
@@ -452,9 +457,9 @@ public class StateManagerImpl extends St
   {
     context.getExternalContext().getRequestMap().put(
             _PINNED_STATE_TOKEN_KEY, stateToken);
-    
+
   }
-  
+
   /**
    * @return the state token for the current request
    */
@@ -463,24 +468,24 @@ public class StateManagerImpl extends St
     return (String) context.getExternalContext().getRequestMap().get(
             _REQUEST_STATE_TOKEN_KEY);
   }
-  
-  
+
+
   /**
    * Mark the the incoming request token should be used for the response
    */
   @SuppressWarnings("unchecked")
   static public void reuseRequestTokenForResponse(ExternalContext ec)
   {
-    ec.getRequestMap().put(_REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY, Boolean.TRUE);    
+    ec.getRequestMap().put(_REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY, Boolean.TRUE);
   }
-  
+
   /**
    * Clears the flag indicating that the old request token should be used for the response.
    */
   @SuppressWarnings("unchecked")
   static public void clearReuseRequestTokenForResponse(ExternalContext ec)
   {
-    ec.getRequestMap().remove(_REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY);    
+    ec.getRequestMap().remove(_REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY);
   }
 
   /**
@@ -516,8 +521,8 @@ public class StateManagerImpl extends St
 
     return (String) token;
   }
-    
-  
+
+
   @Override @SuppressWarnings("deprecation")
   public void writeState(FacesContext context,
                          SerializedView state) throws IOException
@@ -531,8 +536,8 @@ public class StateManagerImpl extends St
                                 String renderKitId)
   {
     final ExternalContext extContext = context.getExternalContext();
-    
-    // If we're being asked to execute a "return" event from, say, a dialog, always 
+
+    // If we're being asked to execute a "return" event from, say, a dialog, always
     // restore the "launch view", which was set over in the TrinidadFilter.
     UIViewRoot launchView = (UIViewRoot)
                             extContext.getRequestMap().remove(RequestContextImpl.LAUNCH_VIEW);
@@ -541,7 +546,7 @@ public class StateManagerImpl extends St
       TrinidadPhaseListener.markPostback(context);
       return launchView;
     }
-    
+
     if (!isSavingStateInClient(context))
       return _delegate.restoreView(context, viewId, renderKitId);
 
@@ -586,21 +591,21 @@ public class StateManagerImpl extends St
             if (viewState != null)
               perSessionCache.put(viewId, viewState);
           }
-          
+
           // If the view was found in the application cache then we
           // know it would be unsafe to use its locale for this session.
-          // Same conclusion, however, even if found in the per-session 
+          // Same conclusion, however, even if found in the per-session
           // cache, since the latter is just a mirror of the former.
           recalculateLocale = true;
         }
       }
       else
       {
+        RequestContext trinContext = RequestContext.getCurrentInstance();
+
         // get view cache key with "." separator suffix to separate the SubKeyMap keys
-        String subkey = _getViewCacheKey(extContext,
-                                         RequestContext.getCurrentInstance(),
-                                         _SUBKEY_SEPARATOR);
-        
+        String subkey = _getViewCacheKey(extContext, trinContext, _SUBKEY_SEPARATOR);
+
         Map<String, PageState> stateMap = new SubKeyMap<PageState>(
                          extContext.getSessionMap(),
                          subkey);
@@ -616,8 +621,7 @@ public class StateManagerImpl extends St
         // token cache here, not just inside the assert.  If we don't,
         // then we don't actually access the token, so it doesn't
         // get bumped up to the front in the LRU Cache!
-        boolean isAvailable =
-          _getViewCache(context).isAvailable((String) token);
+        boolean isAvailable = _getViewCache(trinContext, extContext).isAvailable((String) token);
         assert ((viewState != null) == isAvailable);
       }
 
@@ -677,7 +681,7 @@ public class StateManagerImpl extends St
 
         if (state != null)
           root.processRestoreState(context, state);
-        
+
         if (recalculateLocale)
         {
           // Ensure that locale gets re-calculated when next fetched.
@@ -708,12 +712,12 @@ public class StateManagerImpl extends St
    * The given parameter (<code>perViewStateSaving</code>) indicates
    * if we need to enable client- OR server-side state-saving
    * for the current VIEW.
-   * 
+   *
    * <p>
    * <b>This is an internal method, that is ONLY called by the
    * Trinidad Document</b>
    * </p>
-   * 
+   *
    * @param perViewStateSaving <code>default</code>, <code>server</code> or <code>client</code> for stateSaving
    */
   public void setPerViewStateSaving(String perViewStateSaving)
@@ -760,21 +764,19 @@ public class StateManagerImpl extends St
     throw new UnsupportedOperationException();
   }
 
-
-  private TokenCache _getViewCache(FacesContext context)
+  /**
+   * Returns the TokenCache for the current window
+   * @param trinContext
+   * @param extContext
+   * @return
+   */
+  private TokenCache _getViewCache(RequestContext trinContext, ExternalContext extContext)
   {
-    ExternalContext extContext = context.getExternalContext();
+    String cacheKey = _getViewCacheKey(extContext, trinContext, null);
     
-    return TokenCache.getTokenCacheFromSession(context,
-                                               _getViewCacheKey(extContext,
-                                                                RequestContext.getCurrentInstance(),
-                                                                null),
-                                               true,
-                                               _getCacheSize(extContext));
+    return TokenCache.getTokenCacheFromSession(extContext,cacheKey, true,_getCacheSize(extContext));
   }
 
-  
-
   /**
    * Returns a key suitable for finding the per-window active page state key
    * @param extContext
@@ -785,9 +787,9 @@ public class StateManagerImpl extends St
     ExternalContext extContext,
     RequestContext trinContext)
   {
-    return _getPerWindowCacheKey(extContext, trinContext, _ACTIVE_PAGE_STATE_SESSION_KEY, null);
+    return _getPerWindowCacheKey(extContext, trinContext, _ACTIVE_PAGE_TOKEN_SESSION_KEY, null);
   }
-  
+
   /**
    * Returns a key suitable for finding the per-window cache key
    * @param extContext
@@ -802,7 +804,7 @@ public class StateManagerImpl extends St
   {
     return _getPerWindowCacheKey(extContext, trinContext, _VIEW_CACHE_KEY, suffix);
   }
-  
+
   /**
    * Returns a key of the form <prefix>.<windowid><suffix> if a window and a suffix are available
    *                           <prefix>.<window> if just a window is available
@@ -820,18 +822,18 @@ public class StateManagerImpl extends St
     Character suffix)
   {
     Window currWindow = trinContext.getWindowManager().getCurrentWindow(eContext);
-    
+
     // if we have a current window or a suffix, we need a StringBuilder to calculate the cache key
     if ((currWindow != null) || (suffix != null))
     {
       // get the window id and the extra size neeeded to store it and its separator
       String windowId;
       int windowPartSize;
-    
+
       if (currWindow != null)
       {
         windowId = currWindow.getId();
-        
+
         // add 1 for separator
         windowPartSize = windowId.length() + 1;
       }
@@ -840,28 +842,28 @@ public class StateManagerImpl extends St
         windowId = null;
         windowPartSize = 0;
       }
-      
+
       int builderSize =  prefix.length() + windowPartSize;
-      
+
       // add extra space for the suffix Character
       if (suffix != null)
         builderSize += 1;
-      
+
       // add the constant part to the StringBuilder
       StringBuilder keyBuilder = new StringBuilder(builderSize);
       keyBuilder.append(prefix);
-      
+
       // add the windowId and its separator
       if (currWindow != null)
       {
         keyBuilder.append('.');
         keyBuilder.append(windowId);
       }
-      
+
       // add the suffix if any
       if (suffix != null)
         keyBuilder.append(suffix);
-      
+
       return keyBuilder.toString();
     }
     else
@@ -907,7 +909,7 @@ public class StateManagerImpl extends St
 
     ExternalContext external = context.getExternalContext();
     Object stateSavingMethod =
-      external.getInitParameterMap().get(StateManager.STATE_SAVING_METHOD_PARAM_NAME);    
+      external.getInitParameterMap().get(StateManager.STATE_SAVING_METHOD_PARAM_NAME);
 
     // on "SERVER" state-saving we return TRUE, since we want send down a token string.
     if ((stateSavingMethod == null) ||
@@ -926,7 +928,7 @@ public class StateManagerImpl extends St
       return false;
     }
 
-    // if the user has used the <document> 'stateSaving' attribute to specify 
+    // if the user has used the <document> 'stateSaving' attribute to specify
     // client, we force the state mananger (see above) to render the entire
     // state on the client. The indicator is stashed on the FacesContext and
     // is therefore NOT visible during "restoreView" phase. So if we reach this point
@@ -989,7 +991,7 @@ public class StateManagerImpl extends St
       return cache;
     }
   }
-  
+
   @SuppressWarnings("unchecked")
   static private Map<String, PageState> _getPerSessionApplicationViewCache(FacesContext context)
   {
@@ -1052,7 +1054,7 @@ public class StateManagerImpl extends St
       }
       if (Boolean.TRUE.equals(_useApplicationViewCache))
       {
-         _LOG.severe("USE_APPLICATION_VIEW_CACHE_UNSUPPORTED");        
+         _LOG.severe("USE_APPLICATION_VIEW_CACHE_UNSUPPORTED");
       }
       return _useApplicationViewCache.booleanValue();
     }
@@ -1125,18 +1127,18 @@ public class StateManagerImpl extends St
       // Nope, guess it's a facet
       // 2006-08-02: -= Simon Lessard
       //             Not 1.5 structure and inefficient loop
-      //             values() is more efficient as you don't have 
+      //             values() is more efficient as you don't have
       //             to do a second lookup for the value.
       Map<String, UIComponent> facets = parent.getFacets();
-      for(Iterator<UIComponent> facetIter = facets.values().iterator(); 
+      for(Iterator<UIComponent> facetIter = facets.values().iterator();
           facetIter.hasNext();)
       {
         if(facetIter.next() == kid)
         {
           facetIter.remove();
           // FIXME: -= Simon Lessard
-          //        Is that continue need to labeled to go all the way up to 
-          //        the first while? Currently it won't cause any problem, but 
+          //        Is that continue need to labeled to go all the way up to
+          //        the first while? Currently it won't cause any problem, but
           //        it's a performance loss.
           continue;
         }
@@ -1192,11 +1194,11 @@ public class StateManagerImpl extends St
     {
       if (viewRoot == null)
         throw new NullPointerException();
-      
+
       _viewRoot = viewRoot;
       _viewRootState = viewRoot.saveState(context);
     }
-    
+
     public UIViewRoot getViewRoot()
     {
       return _viewRoot;
@@ -1206,7 +1208,7 @@ public class StateManagerImpl extends St
     {
       return _viewRootState;
     }
-   
+
     private final UIViewRoot _viewRoot;
     private final Object _viewRootState;
   }
@@ -1216,7 +1218,7 @@ public class StateManagerImpl extends St
     private static final long serialVersionUID = 1L;
 
     private Object _viewState;
-    
+
     // use transient since UIViewRoots are not Serializable.
     private transient ViewRootState _cachedState;
 
@@ -1236,19 +1238,20 @@ public class StateManagerImpl extends St
         }
         else
         {
-      // if component tree serialization checking is on (in order to validate
-      // fail over support, attempt to Serialize all of the component state
-      //  immediately
-        try
-        {
-          new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(viewState);
-        }
-        catch (IOException e)
-        {          
-          throw new RuntimeException(_LOG.getMessage("COMPONENT_TREE_SERIALIZATION_FAILED"), e);
+          // if component tree serialization checking is on (in order to validate
+          // fail over support, attempt to Serialize all of the component state
+          //  immediately
+          try
+          {
+            new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(viewState);
+          }
+          catch (IOException e)
+          {
+            throw new RuntimeException(_LOG.getMessage("COMPONENT_TREE_SERIALIZATION_FAILED"), e);
+          }
         }
       }
-      }
+
       // we need this state, as we are going to recreate the UIViewRoot later. see
       // the popRoot() method:
       _cachedState = (root != null)
@@ -1273,7 +1276,7 @@ public class StateManagerImpl extends St
         _cachedState = null;
       }
     }
-    
+
     @SuppressWarnings("unchecked")
     public UIViewRoot popRoot(FacesContext fc)
     {
@@ -1294,7 +1297,7 @@ public class StateManagerImpl extends St
           _cachedState = null;
         }
       }
-      
+
       if (root != null)
       {
         // If an error happens during updateModel, JSF 1.1 does not
@@ -1303,11 +1306,11 @@ public class StateManagerImpl extends St
         // so to clear the events, we create a new UIViewRoot.
         // must get the UIViewRoot from the application so that
         // we pick up any custom ViewRoot defined in faces-config.xml:
-        UIViewRoot newRoot = (UIViewRoot) 
+        UIViewRoot newRoot = (UIViewRoot)
           fc.getApplication().createComponent(UIViewRoot.COMPONENT_TYPE);
-        
+
         //This code handles automatic namespacing in a JSR-301 environment
-        if(ExternalContextUtils.isPortlet(fc.getExternalContext())) 
+        if(ExternalContextUtils.isPortlet(fc.getExternalContext()))
         {
           //IMPORTANT: To avoid introducing a runtime dependency on the bridge,
           //this method should only be executed when we have a portlet
@@ -1326,7 +1329,7 @@ public class StateManagerImpl extends St
           }
         }
 
-        
+
         // must call restoreState so that we setup attributes, listeners,
         // uniqueIds, etc ...
         newRoot.restoreState(fc, viewRootState);
@@ -1342,9 +1345,10 @@ public class StateManagerImpl extends St
         newRoot.getChildren().addAll(temp);
         return newRoot;
       }
-      
+
       return null;
     }
+
     private boolean _zipState(FacesContext fc)
     {
       // default is false
@@ -1379,22 +1383,22 @@ public class StateManagerImpl extends St
           decompressor = new Inflater();
         }
 
-        decompressor.setInput(zippedBytes);
+		    decompressor.setInput(zippedBytes);
         ByteArrayOutputStream bos = new ByteArrayOutputStream(zippedBytes.length);
         byte[] buf = new byte[zippedBytes.length*5];
 
         while (!decompressor.finished())
         {
-          try
-          {
-            int count = decompressor.inflate(buf);
-            bos.write(buf, 0, count);
-          }
-          catch (DataFormatException e)
-          {
+	        try
+		      {
+		        int count = decompressor.inflate(buf);
+		        bos.write(buf, 0, count);
+		      }
+		      catch (DataFormatException e)
+		      {
             throw new RuntimeException(_LOG.getMessage("UNZIP_STATE_FAILED"), e);
           }
-        }
+		    }
 
         ByteArrayInputStream baos = new ByteArrayInputStream(bos.toByteArray());
         ObjectInputStream ois = new ObjectInputStreamResolveClass(baos);
@@ -1454,7 +1458,7 @@ public class StateManagerImpl extends St
 
         byte[] ret =  baos.toByteArray();
         compresser.setInput(ret);
-        compresser.finish();
+		    compresser.finish();
 
         baos.reset();
         byte[] buf = new byte[ret.length/5];
@@ -1485,7 +1489,7 @@ public class StateManagerImpl extends St
   }
 
   /**
-   * Static ENUM to capture the values of the <document>'s 
+   * Static ENUM to capture the values of the <document>'s
    * 'stateSaving' attribute
    */
   static private enum StateSaving
@@ -1508,11 +1512,11 @@ public class StateManagerImpl extends St
   private       Boolean      _structureGeneratedByTemplate;
 
   private static final Character _SUBKEY_SEPARATOR = new Character('.');
-  
+
   private static final int _DEFAULT_CACHE_SIZE = 15;
 
   private static final Object _APPLICATION_VIEW_CACHE_LOCK = new Object();
-  
+
   // base key used to identify the view cache.  The window name, if any, is appended to this
   private static final String _VIEW_CACHE_KEY =
     "org.apache.myfaces.trinidadinternal.application.VIEW_CACHE";
@@ -1521,7 +1525,7 @@ public class StateManagerImpl extends St
     "org.apache.myfaces.trinidadinternal.application.APPLICATION_VIEW_CACHE";
 
   // key to stash the per_page_state_saving during rendering
-  private static final String _PER_PAGE_STATE_SAVING = 
+  private static final String _PER_PAGE_STATE_SAVING =
     "org.apache.myfaces.trinidadimpl.PER_PAGE_STATE_SAVING";
 
   private static final String _CACHED_SERIALIZED_VIEW =
@@ -1536,8 +1540,8 @@ public class StateManagerImpl extends St
   private static final String _REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY =
     "org.apache.myfaces.trinidadinternal.application.REUSE_REQUEST_TOKEN_FOR_RESPONSE";
 
-  // key for saving the PageState for the last accessed view in this Session
-  private static final String _ACTIVE_PAGE_STATE_SESSION_KEY =
+  // key for saving the token to the PageState for the last accessed view in this Session
+  private static final String _ACTIVE_PAGE_TOKEN_SESSION_KEY =
               "org.apache.myfaces.trinidadinternal.application.StateManagerImp.ACTIVE_PAGE_STATE";
 
   private static final String _APPLICATION_CACHE_TOKEN = "_a_";

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java?rev=1028150&r1=1028149&r2=1028150&view=diff
==============================================================================
--- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java Thu Oct 28 00:40:23 2010
@@ -18,18 +18,57 @@
  */
 package org.apache.myfaces.trinidadinternal.config;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.faces.context.ExternalContext;
 
+import org.apache.myfaces.trinidad.context.ExternalContextDecorator;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpSession;
+
+import javax.servlet.http.HttpSessionContext;
+
 import org.apache.myfaces.trinidad.bean.util.StateUtils;
 import org.apache.myfaces.trinidad.config.Configurator;
-import org.apache.myfaces.trinidad.context.ExternalContextDecorator;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.util.CollectionUtils;
+import org.apache.myfaces.trinidad.util.CollectionUtils.MapMutationHooks;
+import org.apache.myfaces.trinidad.util.TransientHolder;
+
+import org.apache.myfaces.trinidadinternal.context.external.ServletApplicationMap;
 
 /**
- * Configurator that uses a wrapped ExternalContext to return a Session Map that validates that
- * only Serializable Objects are placed in the Map.
+ * Configurator that uses both wrapped ExternalContext (for Portlet cases) and wrapped
+ * ServletContext and HttpSession (for HttpServlet cases) to validate that
+ * only Serializable Objects are placed in the Sesssion Map and that mutations to the
+ * Session and ApplicationMap content dirty the entries.
  * @version $Revision$ $Date$
  */
 public final class CheckSerializationConfigurator extends Configurator
@@ -37,89 +76,1171 @@ public final class CheckSerializationCon
 
   /**
    * Override to return our ExternalContext wrapped if session serialization checking is enabled
-   * @param externalContext
+   * @param extContext
    * @return
    */
   @Override
-  public ExternalContext getExternalContext(ExternalContext externalContext)
+  public ExternalContext getExternalContext(ExternalContext extContext)
   {
-    boolean checkSession = StateUtils.checkSessionSerialization(externalContext);
-    boolean checkApplication = StateUtils.checkApplicationSerialization(externalContext);
-      
-    if (checkSession || checkApplication)
+    // retrieve our wrapped ExternalContext, creating it if necessary.  We wrap the external
+    // context to trap calls to retrieve the Session and Application Maps in the portal case.
+    // For the HttpServlet case, we rely on 
+    ExternalContext checkingContext = 
+                             SerializationCheckingWrapper.getSerializationWrapper(extContext, true);
+    
+    if (checkingContext != null)
+    {
+      return checkingContext;
+    }
+    else
+    {
+      return extContext;
+    }
+  }
+  
+  /**
+   * Check if any of the non-dirtied checked managed beans have been mutated in this request
+   * @param extContext
+   */
+  @Override
+  public void endRequest(ExternalContext extContext)
+  {
+    // get the wrapper without creating it if it doesn't already exist
+    SerializationCheckingWrapper checkingWrapper =
+                          SerializationCheckingWrapper.getSerializationWrapper(extContext, false);
+
+    
+    if (checkingWrapper != null)
+    {
+      checkingWrapper.checkForMutations();
+    }
+  }
+
+  /**
+   * Returns the FilterConfig to use for initializing the filters so that we can wrap it
+   * if necessary
+   * @param filterConfig
+   * @return
+   */
+  public static FilterConfig getFilterConfig(FilterConfig filterConfig)
+  {
+    // skankily don't pass the ExternalContext since we don't have one when the filters are
+    // initialized.  This only really works because checkApplicvationSerialization doesn't
+    // need the ExternalContext
+    if (StateUtils.checkApplicationSerialization(null))
+    {
+      return new FilterConfigWrapper(filterConfig);
+    }
+    else
     {
-      return new SessionSerializationChecker(externalContext, checkSession, checkApplication);
+      return filterConfig;
+    }
+  }
+
+  /**
+   * Returns the HttpServletRequest to use for this request, so that we can wrap it if
+   * necessary.
+   * @param extContext
+   * @param request
+   * @return
+   */
+  public static HttpServletRequest getHttpServletRequest(
+    ExternalContext    extContext,
+    HttpServletRequest request)
+  {
+    SerializationChecker checker = SerializationChecker.getSerializationChecker(extContext, true);
+    
+    if (checker != null)
+    {
+      return checker.getWrappedRequest(request);
     }
     else
     {
-      return externalContext;
+      return request;
     }
   }
   
+  
+  /**
+   * Unregisters the checking of the specified session attribute
+   * @param external ExternalContext
+   * @param key      Name of session attribute to unregister
+   */
+  public static void unregisterSessionAttribute(ExternalContext external, String key)
+  {
+    SerializationChecker checker = SerializationChecker.getSerializationChecker(external, false);
+    
+    if (checker != null)
+    {
+      checker.unregisterSessionAttribute(external, key);
+    }    
+  }
+
+  /**
+   * Unregisters the checking of the specified application attribute
+   * @param external ExternalContext
+   * @param key      Name of session attribute to unregister
+   */
+  public static void unregisterApplicationAttribute(ExternalContext external, String key)
+  {
+    SerializationChecker checker = SerializationChecker.getSerializationChecker(external, false);
+    
+    if (checker != null)
+    {
+      checker.unregisterApplicationAttribute(external, key);
+    }    
+  }
+
+  /**
+   * Returns the list of in-flight MutatedBeanCheckers for the specified Map and its associated
+   * lock object
+   * @param checkedMap   Map checked by the MutatedBeanCheckers
+   * @param mapWriteLock Lock object to synchronize on when mutatating the amp
+   * @return
+   */
+  private static List<MutatedBeanChecker> _getMutatedBeanList(
+    Map<String, Object> checkedMap,
+    Object              mapWriteLock)
+  {
+    Object list = checkedMap.get(_CHECKED_MAPS_KEY);
+    
+    if (list == null)
+    {
+      // make sure that the list is only created once per map
+      synchronized(mapWriteLock)
+      {
+        // check again in case we value was written by the previou lock holder
+        list = checkedMap.get(_CHECKED_MAPS_KEY);
+        
+        if (list == null)
+        {
+          // mutations to the list itself need to be thread-safe
+          List<MutatedBeanChecker> beanList = new CopyOnWriteArrayList<MutatedBeanChecker>();
+          
+          // use a TransientHolder since we don't care if this gets failed over
+          checkedMap.put(_CHECKED_MAPS_KEY, TransientHolder.newTransientHolder(beanList));
+          
+          return beanList;
+        }
+      }
+    }
+    
+    return ((TransientHolder<List<MutatedBeanChecker>>)list).getValue();
+  }
+
+  /**
+   * Remove the modified key from all of the in-flight bean checking requests
+   * @param beanCheckers
+   * @param key
+   */
+  private static void _notifyBeanCheckersOfChange(
+    List<MutatedBeanChecker> beanCheckers,
+    Object                   key)
+  {
+    for (MutatedBeanChecker beanChecker : beanCheckers)
+    {
+      beanChecker._unmutatedKeyValues.remove(key);
+    }
+  }
+
+  /**
+   * Wraps the FilterConfig so that we can wrap the ServletContext that it returns so that
+   * we can trap calls the setting and removing ServletContext attributes.  Phew!
+   */
+  private static class FilterConfigWrapper implements FilterConfig
+  {
+    FilterConfigWrapper(FilterConfig filterConfig)
+    {
+      _delegate = filterConfig;
+      
+      // create ServletContext wrapper to catch sets and removes from the ServletContext
+      _wrappedContext = new ContextWrapper(filterConfig.getServletContext(), null);
+    }
+    
+    public String getFilterName()
+    {
+      return _delegate.getFilterName();
+    }
+
+    public ServletContext getServletContext()
+    {
+      return _wrappedContext;
+    }
+
+    public String getInitParameter(String paramName)
+    {
+      return _delegate.getInitParameter(paramName);
+    }
+
+    public Enumeration getInitParameterNames()
+    {
+      return _delegate.getInitParameterNames();
+    }
+    
+    private final FilterConfig   _delegate;
+    private final ServletContext _wrappedContext;
+  }
+
+
   /**
-   * ExternalContextDecorator returning our wrapped SessionMap
+   * ExternalContextWrapper that returns wrapped versions of the Session and ApplicationMaps that
+   * we can track changes to.  This is needed for the Portlet case.  For the HttpServel case,
+   * it is redundant with the ServletContext and Session wrapping but shouldn't do any harm.
    */
-  private static class SessionSerializationChecker extends ExternalContextDecorator
+  private static class SerializationCheckingWrapper extends ExternalContextDecorator
   {
-    public SessionSerializationChecker(
+    /**
+     * Retrieves the current SerializationCheckingWrapper for this request
+     * @param extContext
+     * @param create If <code>true</code>, create the SerializationCheckingWrapper for this
+     *               request if it doesn't already exist.
+     * @return 
+     */
+    public static SerializationCheckingWrapper getSerializationWrapper(
       ExternalContext extContext,
-      boolean checkSession,
-      boolean checkApplication)
+      boolean         create)
+    {
+      // get the SerializationCheckingWrapper for this request
+      Map<String, Object> requestMap = extContext.getRequestMap();
+      
+      Object wrapper = requestMap.get(_SERIALIZATION_WRAPPER_KEY);
+      
+      if (wrapper != null)
+      {
+        return (SerializationCheckingWrapper)wrapper;
+      }
+      else if (create)
+      {
+        // create the wrapper for this request and store it on the request so that we don't
+        // recreate it
+        SerializationChecker checker = SerializationChecker.getSerializationChecker(extContext,
+                                                                                    create);
+        
+        if (checker != null)
+        {
+          SerializationCheckingWrapper checkingWrapper = new SerializationCheckingWrapper(extContext,
+                                                                                          checker);
+
+          requestMap.put(_SERIALIZATION_WRAPPER_KEY, checkingWrapper);
+       
+          return checkingWrapper;
+        }
+      }
+      
+      return null;
+    }
+
+    /**
+     * Create a SerializationCheckingWrapper
+     * @param extContext ExternalContext to wrap
+     * @param checker    SerializationChecker to call back on mutations
+     */
+    private SerializationCheckingWrapper(
+      ExternalContext      extContext,
+      SerializationChecker checker)
     {
       _extContext = extContext;
+      _checker    = checker;
+    }
+
+    /**
+     * Check for mutations to beans trancked by the SerializationCheckingWrapper
+     */
+    public void checkForMutations()
+    {
+      _checker.checkForMutations();
+    }
+
+    @Override
+    public ExternalContext getExternalContext()
+    {
+      return _extContext;
+    }
+
+    /**
+     * Override to delegate to the SerializationChecker
+     * @return
+     */
+    @Override
+    public Map<String, Object> getSessionMap()
+    {
+      return _checker.getSessionMap();
+    }
+
+    /**
+     * Override to delegate to the SerializationChecker
+     * @return
+     */
+    @Override
+    public Map<String, Object> getApplicationMap()
+    {
+      return _checker.getApplicationMap();
+    }
+
+    private static final String _SERIALIZATION_WRAPPER_KEY = 
+                                         CheckSerializationConfigurator.class.getName() + "#WRAPPER";
+    
+    private final ExternalContext      _extContext;
+    private final SerializationChecker _checker;
+  }
+
+  /**
+   * Checks a Map for mutations to the contents of its Serializable attributes that weren't
+   * dirtied in the current request.
+   * The mutations are checked by snapshotting the serialized bytes of the current Serializable
+   * values of the Map at the beginning of the request.  We then catch all puts and removes to
+   * the Map across any request and remove those entries, since they have been correctly dirtied.
+   * At the end of the request. <code>checkForMutations</code> is called and we iterate over
+   * the remaining entries and compared their serialized bytes against the serialized bytes
+   * of the current values.  If the bytes are different, we assume that some part of the
+   * attribute's object subtree has been changed without appropriately dirtying it and we
+   * log an errror.
+   * @see #checkForMutations
+   */
+  private static class MutatedBeanChecker implements MapMutationHooks<String, Object>
+  {
+    /**
+     * Creates a MutatedBeanChecker to check for undirtied mutations to the Serialized state
+     * of a Map in the current request.
+     * @param checkedMap Map containing attributes to check for mutations
+     * @param mapName Name of map used when logging
+     * @param mapLock Lock to use when mutating the map
+     * @param requireSerialization <code>true</code> if all of the attributes are required to be
+     *                             Serializable (Sesssion Map attributes are.  Application Map
+     *                             aren't)
+     */
+    public MutatedBeanChecker(
+      Map<String, Object> checkedMap,
+      String              mapName,
+      Object              mapLock,
+      boolean             requireSerialization)
+    {
+      _checkedMap           = checkedMap;
+      _mapName              = mapName;
+      _mapLock              = mapLock;
+            
+      // snapshot the initial serialized bytes of the mutable values in the Map so that we
+      // can compare them at the end of the request to see if they have changed
+      _unmutatedKeyValues = new ConcurrentHashMap<String, Object>(checkedMap.size() * 2);
+      _unmutatedKeyValues.putAll(checkedMap);
+      
+      // register this request with the list of checkers for this map.
+      // I think there is a possible race condition between the keys being added to the map and
+      // our registering ourselves as listening for puts and removes made by other requests.
+      // This makes me sad
+      _getMutatedBeanList().add(this);
+      
+      // loop through the map's valid keys getting the serialized bytes
+      for (String key : _unmutatedKeyValues.keySet())
+      {
+        Object value = checkedMap.get(key);
+        
+        // get the serialized bytes for this key.  If the key's vale isn't serializable or is
+        // immutable, this will be an empty array and we won't need to check it
+        byte[] serializedBytes = _getSerializedValue(key, value, requireSerialization);
+        
+        if (serializedBytes.length > 0)
+        {
+          // save the bytes for comparing at the end of the request
+          _unmutatedKeyValues.put(key, serializedBytes);
+        }
+        else
+        {
+          // either not serializable or immutable, so we don't need to worry about checking it
+          _unmutatedKeyValues.remove(key);
+        }
+      }
+    }
+
+    /**
+     * Unregisters the checking of the specified attribute
+     * @param key      Name of session attribute to unregister
+     */
+    public void unregisterAttribute(String key)
+    {
+      CheckSerializationConfigurator._notifyBeanCheckersOfChange(_getMutatedBeanList(), key);
+    }
+    
+    /** Implement to catch writes to the Map, since that means that the Map has been dirtied */
+    @Override
+    public void writeNotify(Map<String, Object> map, String key, Object value)
+    {
+      unregisterAttribute(key);
+    }
+
+    /** Implement to catch remove from the Map, since that means the attribute won't
+     *  be failed over
+     */
+    @Override
+    public void removeNotify(Map<String, Object> map, Object key)
+    {      
+      unregisterAttribute((String)key);
+    }
+
+    /** Implement to catch clear of Map, since that means the attributes won't
+     *  be failed over
+     */
+    @Override
+    public void clearNotify(Map<String, Object> map)
+    {
+      // clear all of the keys across all of the beans      
+      for (String key : map.keySet())
+      {
+        unregisterAttribute(key);
+      }
+    }
+    
+    /**
+     * Clear all of the values we were checking.  This is called if the Session is invalidated,
+     * for example.
+     */
+    public void clearCheckedValues()
+    {
+      for (MutatedBeanChecker beanChecker : _getMutatedBeanList())
+      {
+        beanChecker._unmutatedKeyValues.clear();
+      }
+    }
+    
+    /**
+     * Check for any undirtied mutations of this map, logging severe messages if there are
+     */
+    public void checkForMutations()
+    {
+      // loop through the unmodified items in the Map and verify that the curent
+      // Serialized values haven't changed
+      for (Map.Entry<String, Object> checkedEntry : _unmutatedKeyValues.entrySet())
+      {
+        String key = checkedEntry.getKey();
+        
+        Object currValue = _checkedMap.get(key);
+        byte[] currentBytes = _getSerializedValue(key, currValue, false);
+        byte[] oldBytes     = (byte[])checkedEntry.getValue();
+        
+        // check if the bytes are different
+        if (!Arrays.equals(oldBytes, currentBytes))
+        {
+          // deserialize the original object so we can dump it out (hopefully it has a
+          // good toString())  We also do this so we can 
+          Object oldValue = _deserializeObject(oldBytes);
+          
+          // deserialize the new bytes so that we are comparing two deserialized objects
+          Object newValue = _deserializeObject(currentBytes);
+          
+          // This doesn't do anything, but is a handy comparison of debugging when things go awry
+          oldValue.equals(newValue);
+          
+          // build up the message 
+          String message = _LOG.getMessage("SERIALIZABLE_ATTRIBUTE_MUTATED",
+                                           new Object[]{_mapName, key, oldValue, newValue});
+         
+          // Log message because user might not notice exception since we are at the end of the
+          // request
+          _LOG.severe(message);
+        }
+      }
+      
+      // we no longer need to track changes to the map
+      _getMutatedBeanList().remove(this);
+    }
+    
+
+    /**
+     * Given the serialized bytes of an Object, return the Object itself
+     * @param serializedBytes
+     * @return
+     */
+    private Object _deserializeObject(byte[] serializedBytes)
+    {
+      Object deserializedObject;
+      
+      try
+      {
+        // copy the bytes before passing to the ByteArrayInputStream, since it mutates
+        // the array
+        byte[] copyBytes = Arrays.copyOf(serializedBytes, serializedBytes.length);
+        
+        ByteArrayInputStream baos = new ByteArrayInputStream(copyBytes);
+        ObjectInputStream ois = new ObjectInputStream(baos);
+        deserializedObject = ois.readObject();
+        ois.close();
+      }
+      catch (IOException e)
+      {
+        throw new IllegalArgumentException(e);
+      }
+      catch (ClassNotFoundException e)
+      {
+        throw new IllegalArgumentException(e);
+      }
+      
+      return deserializedObject;
+    }
+    
+    /**
+     * Returns the List of MutatedBeanCheckers across all in flight requests listening for changes
+     * to this Map
+     * @return
+     */
+    private List<MutatedBeanChecker> _getMutatedBeanList()
+    {
+      return CheckSerializationConfigurator._getMutatedBeanList(_checkedMap, _mapLock);
+    }
+    
+    /**
+     * Returns the serialized value of the object as a byte[] or an empty array if the object is
+     * immutable and therefore doesn't need to be checked
+     * @param key   Key in map to get the serialized value of
+     * @param value Value in map to serialize
+     * @param requireSerialization <code>true</code> if this value is required to be serializable
+     * @return The serialized bytes for the Object if serializable and mutable
+     * @throws IllegalStateException if the Object is not serializable or serialization fails
+     */
+    private byte[] _getSerializedValue(String key, Object value, boolean requireSerialization)
+    {
+      if (value == null)
+        return _EMPTY_BYTE_ARRAY;
+      
+      Class valueClass = value.getClass();
+      
+      // check against the lsit of classes to ignore for performance reasons
+      if (_INGNORE_CLASS_NAMES.contains(valueClass.getName()))
+        return _EMPTY_BYTE_ARRAY;
+      
+      if (!(value instanceof Serializable))
+      {
+        if (requireSerialization)
+        {
+          String message = _LOG.getMessage("ATTRIBUTE_NOT_SERIALIZABLE",
+                                           new Object[]{_mapName, key, valueClass});
+      
+          // throw new IllegalStateException(message);
+        }
+        
+        return _EMPTY_BYTE_ARRAY;
+      }
       
-      Map<String, Object> sessionMap = extContext.getSessionMap();
       
-      if (checkSession)
+      // verify that the contents of the value are in fact Serializable
+      try
       {
-        // skank using type erasure to finess the fact that Collections.checkedMap() expects and
-        // will return a Map<String, Serializable> when in fact, we should be returning a
-        // Map<String, Onject>.  Using checkedMap also has the disadvantage that a ClassCastException
-        // is thrown when we would really prefer to throw a more-explanatory message
-        //Map erasedMap = sessionMap;
-        //_sessionMap = (Map)Collections.checkedMap(erasedMap, String.class, Serializable.class);
-        _sessionMap =  CollectionUtils.getCheckedSerializationMap(sessionMap);
+        ByteArrayOutputStream outputByteStream = new ByteArrayOutputStream();
+        
+        new ObjectOutputStream(outputByteStream).writeObject(value);
+        
+        return outputByteStream.toByteArray();
+      }
+      catch (IOException e)
+      {
+        if (requireSerialization)
+        {
+          String message = _LOG.getMessage("ATTRIBUTE_SERIALIZATION_FAILED",
+                                           new Object[]{_mapName, key, value});
+          
+          throw new IllegalArgumentException(message, e);            
+        }
+
+        return _EMPTY_BYTE_ARRAY;
+      }      
+    }
+
+    private static final byte[] _EMPTY_BYTE_ARRAY = new byte[0];
+    
+    private static final Set<String> _INGNORE_CLASS_NAMES;
+    
+    static
+    {
+      // initialize Set of class names to ignore for Serialization tracking because they
+      // are immutable or not serialiable
+      String[] classNames = new String[]
+      {
+       "java.lang.Boolean",    // immutable
+       "java.lang.Character",  // immutable
+       "java.lang.Double",     // immutable
+       "java.lang.Float",      // immutable
+       "java.lang.Integer",    // immutable
+       "java.lang.Long",       // immutable
+       "java.lang.Short",      // immutable
+       "java.lang.String",     // immutable
+       "java.math.BigDecimal", // immutable
+       "java.math.BigInteger", // immutable
+       "org.apache.myfaces.trinidad.util.TransientHolder" // Not serializable
+      };
+        
+
+      _INGNORE_CLASS_NAMES = new HashSet<String>();
+      _INGNORE_CLASS_NAMES.addAll(Arrays.asList(classNames));        
+    }
+    
+    private static final TrinidadLogger _LOG = 
+                                   TrinidadLogger.createTrinidadLogger(MutatedBeanChecker.class);
+
+    private final Map<String, Object> _unmutatedKeyValues;
+    private final Map<String, Object> _checkedMap;
+    private final String _mapName;
+    private final Object _mapLock;
+  }
+  
+  /**
+   * Wraps the ServletContext so that we can catch modifications to the attributes
+   */
+  private static final class ContextWrapper implements ServletContext
+  {
+    ContextWrapper(
+      ServletContext      servletContext,
+      Map<String, Object> applicationMap)
+    {
+      _delegate = servletContext;
+      
+      // if we already have an Application Map, use it, otherwise create a wrapper around
+      // the ServletContext
+      if (applicationMap != null)
+      {
+        _applicationMap = applicationMap;
       }
       else
       {
-        _sessionMap = sessionMap;
+        _applicationMap = new ServletApplicationMap(servletContext);
       }
- 
+    }
+
+    public String getContextPath()
+    {
+      return _delegate.getContextPath();
+    }
+
+    public ServletContext getContext(String string)
+    {
+      return _delegate.getContext(string);
+    }
+
+    public int getMajorVersion()
+    {
+      return _delegate.getMajorVersion();
+    }
+
+    public int getMinorVersion()
+    {
+      return _delegate.getMinorVersion();
+    }
+
+    public String getMimeType(String string)
+    {
+      return _delegate.getMimeType(string);
+    }
+
+    public Set getResourcePaths(String string)
+    {
+      return _delegate.getResourcePaths(string);
+    }
+
+    public URL getResource(String string) throws MalformedURLException
+    {
+      return _delegate.getResource(string);
+    }
+
+    public InputStream getResourceAsStream(String string)
+    {
+      return _delegate.getResourceAsStream(string);
+    }
+
+    public RequestDispatcher getRequestDispatcher(String string)
+    {
+      return _delegate.getRequestDispatcher(string);
+    }
+
+    public RequestDispatcher getNamedDispatcher(String string)
+    {
+      return _delegate.getNamedDispatcher(string);
+    }
+
+    public Servlet getServlet(String string) throws ServletException
+    {
+      return _delegate.getServlet(string);
+    }
+
+    public Enumeration getServlets()
+    {
+      return _delegate.getServlets();
+    }
+
+    public Enumeration getServletNames()
+    {
+      return _delegate.getServletNames();
+    }
+
+    public void log(String string)
+    {
+      _delegate.log(string);
+    }
+
+    public void log(Exception exception, String string)
+    {
+      _delegate.log(exception, string);
+    }
+
+    public void log(String string, Throwable throwable)
+    {
+      _delegate.log(string, throwable);
+    }
+
+    public String getRealPath(String string)
+    {
+      return _delegate.getRealPath(string);
+    }
+
+    public String getServerInfo()
+    {
+      return _delegate.getServerInfo();
+    }
+
+    public String getInitParameter(String string)
+    {
+      return _delegate.getInitParameter(string);
+    }
+
+    public Enumeration getInitParameterNames()
+    {
+      return _delegate.getInitParameterNames();
+    }
+
+    public Object getAttribute(String key)
+    {
+      return _delegate.getAttribute(key);
+    }
+
+    public Enumeration getAttributeNames()
+    {
+      return _delegate.getAttributeNames();
+    }
+
+    /**
+     * Override to remove the attribute from the list of attributes to fail over
+     * @param key
+     * @param value
+     */
+    public void setAttribute(String key, Object value)
+    {
+      _delegate.setAttribute(key, value);
+      
+      _notifyBeanCheckersOfChange(_getMutatedBeanList(), key);      
+    }
+
+    /**
+     * Override to remove the attribute from the list of attributes to fail over
+     * @param key
+     */
+    public void removeAttribute(String key)
+    {
+      _delegate.removeAttribute(key);
+
+      _notifyBeanCheckersOfChange(_getMutatedBeanList(), key);
+    }
+
+    public String getServletContextName()
+    {
+      return _delegate.getServletContextName();
+    }
+
+    private List<MutatedBeanChecker> _getMutatedBeanList()
+    {
+      return CheckSerializationConfigurator._getMutatedBeanList(_applicationMap, _delegate);
+    }
+
+    private final ServletContext      _delegate;
+    private final Map<String, Object> _applicationMap;
+  }
+
+  /**
+   * Performs any configured serialization checking of the Session or Application Maps including
+   * whether the contents are Serializable and whether the contents have changed.
+   */
+  private static class SerializationChecker
+  {
+    /**
+     * Get the current SerializaionChecker for this request, potentially creating one
+     * @param extContext ExternalContext to use to create the SerializationChecker
+     * @param create If <code>true</code> a SerializationChecker will be created and registered
+     *               for this request if one does not alreadfy exist.
+     * @return
+     */
+    public static SerializationChecker getSerializationChecker(
+      ExternalContext extContext,
+      boolean         create)
+    {
+      Map<String, Object> requestMap = extContext.getRequestMap();
+      
+      Object checker = requestMap.get(_SERIALIZATION_CHECKER_KEY);
+      
+      if (checker != null)
+      {
+        return (SerializationChecker)checker;
+      }
+      else if (create)
+      {
+        boolean checkSession = StateUtils.checkSessionSerialization(extContext);
+        boolean checkApplication = StateUtils.checkApplicationSerialization(extContext);
+        boolean checkManagedBeanMutation = StateUtils.checkManagedBeanMutation(extContext);
+        
+        // check the possible conditions under which we would need to create a SerializationChecker
+        if (checkSession || checkApplication || checkManagedBeanMutation)
+        {
+          SerializationChecker serializationChecker = new SerializationChecker(
+                                                                           extContext,
+                                                                           checkSession,
+                                                                           checkApplication,
+                                                                           checkManagedBeanMutation);
+          requestMap.put(_SERIALIZATION_CHECKER_KEY, serializationChecker);
+          
+          return serializationChecker;
+        }
+      }
+      
+      return null;
+    }
+    
+    /**
+     * Creates a SerializationChecker for this request
+     * @param extContext               ExternalContext to use to initialize the SerializationChecker
+     * @param checkSession If true check serializability of session attributes 
+     * @param checkApplication if true, check serializability of application attributes
+     * @param checkManagedBeanMutation if true, check for mutations to attributes in the session
+     *                                 if checkSession is true and the application if
+     *                                 checkApplication is true.
+     */
+    private SerializationChecker(
+      ExternalContext extContext,
+      boolean checkSession,
+      boolean checkApplication,
+      boolean checkManagedBeanMutation)
+    {
+      Map<String, Object> sessionMap = extContext.getSessionMap();
       Map<String, Object> applicationMap = extContext.getApplicationMap();
       
-      if (checkApplication)
+      if (checkManagedBeanMutation)
       {
-        // skank using type erasure to finess the fact that Collections.checkedMap() expects and
-        // will return a Map<String, Serializable> when in fact, we should be returning a
-        // Map<String, Onject>.  Using checkedMap also has the disadvantage that a ClassCastException
-        // is thrown when we would really prefer to throw a more-explanatory message
-        //Map erasedMap = applicationMap;
-        //_applicationMap = (Map)Collections.checkedMap(erasedMap, String.class, Serializable.class);
-        _applicationMap =  CollectionUtils.getCheckedSerializationMap(applicationMap);
+        // note that the mutated bean checekd implicitly checks for attribute serialization as well.
+        _sessionBeanChecker = new MutatedBeanChecker(sessionMap,
+                                                     "Session",
+                                                     extContext.getSession(true),
+                                                     true);
+        sessionMap = CollectionUtils.newMutationHookedMap(sessionMap, _sessionBeanChecker);
+        
+        // only check the application for mutations if the application checking is enabled
+        if (checkApplication)
+        {
+          _applicationBeanChecker = new MutatedBeanChecker(applicationMap,
+                                                           "Application",
+                                                           extContext.getContext(),
+                                                           false);
+          applicationMap = CollectionUtils.newMutationHookedMap(applicationMap,
+                                                                _applicationBeanChecker);
+        }
+        else
+        {
+          _applicationBeanChecker = null;
+        }
       }
       else
       {
-        _applicationMap = applicationMap;
+        _sessionBeanChecker     = null;
+        _applicationBeanChecker = null;
+        
+        if (checkSession)
+        {
+          sessionMap = CollectionUtils.getCheckedSerializationMap(sessionMap, true);
+        }
+
+        if (checkApplication)
+        {
+          applicationMap =  CollectionUtils.getCheckedSerializationMap(applicationMap, false);
+        }        
       }
-   }
+            
+      _sessionMap     = sessionMap;
+      _applicationMap = applicationMap;
+    }
 
-    protected ExternalContext getExternalContext()
+    /**
+     * Unregisters the checking of the specified session attribute
+     * @param external ExternalContext
+     * @param key      Name of session attribute to unregister
+     */
+    public void unregisterSessionAttribute(ExternalContext external, String key)
     {
-      return _extContext;
+      SerializationChecker checker = SerializationChecker.getSerializationChecker(external, false);
+      
+      if (checker != null)
+      {
+        if (_sessionBeanChecker != null)
+        {
+          _sessionBeanChecker.unregisterAttribute(key);
+        }
+      }    
     }
 
+    /**
+     * Unregisters the checking of the specified session attribute
+     * @param external ExternalContext
+     * @param key      Name of session attribute to unregister
+     */
+    public void unregisterApplicationAttribute(ExternalContext external, String key)
+    {
+      SerializationChecker checker = SerializationChecker.getSerializationChecker(external, false);
+      
+      if (checker != null)
+      {
+        if (_applicationBeanChecker != null)
+        {
+          _applicationBeanChecker.unregisterAttribute(key);
+        }
+      }    
+    }
+
+    /**
+     * Return a wrapped HttpServletRequest if necessary to implement the checking features
+     * @param request
+     * @return
+     */
+    public HttpServletRequest getWrappedRequest(HttpServletRequest request)
+    {
+      if (_sessionBeanChecker != null)
+      {
+        return new SessionBeanTracker(request, _sessionBeanChecker, _sessionMap, _applicationMap);
+      }
+      else
+      {
+        return request;
+      }
+    }
+    
+    /**
+     * Returns the potentially wrapped Session Map
+     * @return
+     */
     public Map<String, Object> getSessionMap()
     {
       return _sessionMap;
     }
 
+    /**
+     * Returns the potentially wrapped Application Map
+     * @return
+     */
     public Map<String, Object> getApplicationMap()
     {
       return _applicationMap;
     }
+ 
+    /**
+     * Check the session and application for mutations if configured to do so
+     */
+    public void checkForMutations()
+    {
+      if (_sessionBeanChecker != null)
+        _sessionBeanChecker.checkForMutations();
+    
+      if (_applicationBeanChecker != null)
+        _applicationBeanChecker.checkForMutations();
+    }
    
-    private final ExternalContext _extContext;
-    private final Map _sessionMap;
-    private final Map _applicationMap;
+    /**
+     * Wraps the HttpServletRequest so that we can return a wrapped Session so that we can catch
+     * changes to the Session attributes and/or return a wrapped ServletContext so that we can
+     * catch changes to the SevletContext attributes.
+     */
+    private static class SessionBeanTracker extends HttpServletRequestWrapper
+    {
+      public SessionBeanTracker(
+        HttpServletRequest  request,
+        MutatedBeanChecker  sessionBeanChecker,
+        Map<String, Object> sessionMap,
+        Map<String, Object> applicationMap)
+      {
+        super(request);
+        
+        _wrappedSession = new SessionWrapper(request.getSession(),
+                                             sessionBeanChecker,
+                                             sessionMap,
+                                             applicationMap);
+      }
+
+      @Override
+      public HttpSession getSession()
+      {
+        return _wrappedSession;
+      }
+      
+      @Override
+      public HttpSession getSession(boolean p1)
+      {
+        return _wrappedSession;
+      }
+      
+      /**
+       * Wraps the HttpSession sso that we can catch
+       * changes to the Session attributes and/or return a wrapped ServletContext so that we can
+       * catch changes to the SevletContext attributes.
+       */
+      private static final class SessionWrapper implements HttpSession
+      {        
+        SessionWrapper(
+          HttpSession         session,
+          MutatedBeanChecker  sessionChecker,
+          Map<String, Object> sessionMap,
+          Map<String, Object> applicationMap)
+        {
+          _delegate        = session;
+          _sessionChecker  = sessionChecker;
+          _sessionMap      = sessionMap;
+          // determine whether we need to return a wrapped ServletContext as well
+          if (applicationMap != null)
+          {
+            _wrappedContext = new ContextWrapper(session.getServletContext(), applicationMap);
+          }
+          else
+          {
+            _wrappedContext = null;
+          }
+        }
+        
+        public long getCreationTime()
+        {
+          return _delegate.getCreationTime();
+        }
+
+        public String getId()
+        {
+          return _delegate.getId();
+        }
+
+        public long getLastAccessedTime()
+        {
+          return _delegate.getLastAccessedTime();
+        }
+
+        public ServletContext getServletContext()
+        {
+          if (_wrappedContext != null)
+          {
+            return _wrappedContext;
+          }
+          else
+          {
+            return _delegate.getServletContext();
+          }
+        }
+
+        public void setMaxInactiveInterval(int maxInterval)
+        {
+          _delegate.setMaxInactiveInterval(maxInterval);
+        }
+
+        public int getMaxInactiveInterval()
+        {
+          return _delegate.getMaxInactiveInterval();
+        }
+
+        public HttpSessionContext getSessionContext()
+        {
+          return _delegate.getSessionContext();
+        }
+
+        public Object getAttribute(String attrName)
+        {
+          return _delegate.getAttribute(attrName);
+        }
+
+        public Object getValue(String attrName)
+        {
+          return _delegate.getValue(attrName);
+        }
+
+        public Enumeration getAttributeNames()
+        {
+          return _delegate.getAttributeNames();
+        }
+
+        public String[] getValueNames()
+        {
+          return _delegate.getValueNames();
+        }
+
+        /**
+         * Implement to delegate and inform the sessionChecker that the attribute is dirty
+         * @param key
+         * @param value
+         */
+        public void setAttribute(String key, Object value)
+        {
+          _delegate.setAttribute(key, value);
+          _sessionChecker.writeNotify(_sessionMap, key, value);
+        }
+
+        /**
+         * Implement to delegate and inform the sessionChecker that the attribute is dirty
+         * @param key
+         * @param value
+         */
+        public void putValue(String key, Object value)
+        {
+          _delegate.putValue(key, value);
+          _sessionChecker.writeNotify(_sessionMap, key, value);
+        }
+
+        /**
+         * Implement to delegate and inform the sessionChecker that the attribute is dirty
+         * @param key
+         */
+        public void removeAttribute(String key)
+        {
+          _delegate.removeAttribute(key);
+          _sessionChecker.removeNotify(_sessionMap, key);
+        }
+
+        /**
+         * Implement to delegate and inform the sessionChecker that the attribute is dirty
+         * @param key
+         */
+        public void removeValue(String key)
+        {
+          _delegate.removeValue(key);
+          _sessionChecker.removeNotify(_sessionMap, key);
+        }
+
+        /**
+         * Implement to delegate and inform the sessionChecker that all atrributes are dirty since
+         * the session has been blown away
+         */
+        public void invalidate()
+        {
+          _delegate.invalidate();
+          _sessionChecker.clearCheckedValues();
+        }
+
+        public boolean isNew()
+        {
+          return _delegate.isNew();
+        }
+                
+        private final HttpSession         _delegate;
+        private final MutatedBeanChecker  _sessionChecker;
+        private final Map<String, Object> _sessionMap;
+        private final ServletContext      _wrappedContext;
+      }
+
+      private final HttpSession _wrappedSession;
+    }
+       
+    private final MutatedBeanChecker _sessionBeanChecker;
+    private final MutatedBeanChecker _applicationBeanChecker;
+
+    private final Map<String, Object> _sessionMap;
+    private final Map<String, Object> _applicationMap;
   }
+
+  private static final String _CHECKED_MAPS_KEY = MutatedBeanChecker.class.getName() +"#MAPS";
+
+  private static final String _SERIALIZATION_CHECKER_KEY = 
+                                       CheckSerializationConfigurator.class.getName() + "#CHECKER";
 }

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java?rev=1028150&r1=1028149&r2=1028150&view=diff
==============================================================================
--- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java Thu Oct 28 00:40:23 2010
@@ -19,22 +19,16 @@
 
 package org.apache.myfaces.trinidadinternal.config;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import java.util.concurrent.atomic.AtomicReference;
 
 import javax.faces.context.ExternalContext;
 
-import javax.faces.context.FacesContext;
-
 import javax.servlet.ServletRequest;
-
 import javax.servlet.ServletRequestWrapper;
-
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.myfaces.trinidad.config.Configurator;
@@ -45,6 +39,9 @@ import org.apache.myfaces.trinidad.loggi
 import org.apache.myfaces.trinidad.skin.SkinFactory;
 import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
 import org.apache.myfaces.trinidad.util.ComponentReference;
+import org.apache.myfaces.trinidad.util.ExternalContextUtils;
+import org.apache.myfaces.trinidad.util.RequestStateMap;
+import org.apache.myfaces.trinidad.util.RequestType;
 import org.apache.myfaces.trinidadinternal.context.RequestContextFactoryImpl;
 import org.apache.myfaces.trinidadinternal.context.external.ServletCookieMap;
 import org.apache.myfaces.trinidadinternal.context.external.ServletRequestHeaderMap;
@@ -54,9 +51,6 @@ import org.apache.myfaces.trinidadintern
 import org.apache.myfaces.trinidadinternal.context.external.ServletRequestParameterValuesMap;
 import org.apache.myfaces.trinidadinternal.skin.SkinFactoryImpl;
 import org.apache.myfaces.trinidadinternal.skin.SkinUtils;
-import org.apache.myfaces.trinidad.util.ExternalContextUtils;
-import org.apache.myfaces.trinidad.util.RequestStateMap;
-import org.apache.myfaces.trinidad.util.RequestType;
 
 /**
  * This is the implementation of the Trinidad's Global configurator. It provides the entry point for
@@ -414,7 +408,7 @@ public final class GlobalConfiguratorImp
       }
       finally
       {
-        //Do cleanup of anything which may have use the thread local manager durring
+        //Do cleanup of anything which may have use the thread local manager during
         //init.
         _releaseManagedThreadLocals();
       }

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PageFlowScopeMap.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PageFlowScopeMap.java?rev=1028150&r1=1028149&r2=1028150&view=diff
==============================================================================
--- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PageFlowScopeMap.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/PageFlowScopeMap.java Thu Oct 28 00:40:23 2010
@@ -368,7 +368,7 @@ class PageFlowScopeMap implements Map<St
   static private TokenCache _getRootTokenCache(FacesContext context,
                                                int lifetime)
   {
-    return TokenCache.getTokenCacheFromSession(context,
+    return TokenCache.getTokenCacheFromSession(context.getExternalContext(),
                                                _PAGE_FLOW_SCOPE_CACHE,
                                                true,
                                                lifetime);
@@ -416,6 +416,7 @@ class PageFlowScopeMap implements Map<St
     // =-=AEW Make transient for efficiency
     private PageFlowScopeMap _parent;
     private TokenCache      _children;
+    private static final long serialVersionUID = 1L;
   }
 
   // DELETE AFTER DIALOG SERVICE IS CLEANED UP
@@ -425,7 +426,8 @@ class PageFlowScopeMap implements Map<St
   private String     _token;
   private HashMap<String, Object> _map;
 
-  static private final String _PAGE_FLOW_SCOPE_CACHE =
+  private static final String _PAGE_FLOW_SCOPE_CACHE =
     "org.apache.myfaces.trinidadinternal.application.PageFlowScope";
-  static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(PageFlowScopeMap.class);
+  private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(PageFlowScopeMap.class);
+  private static final long serialVersionUID = 1L;
 }

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/SubKeyMap.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/SubKeyMap.java?rev=1028150&r1=1028149&r2=1028150&view=diff
==============================================================================
--- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/SubKeyMap.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/SubKeyMap.java Thu Oct 28 00:40:23 2010
@@ -104,7 +104,7 @@ final public class SubKeyMap<V> extends 
   public Set<Map.Entry<String, V>> entrySet()
   {
     if (_entrySet == null)
-      _entrySet = new Entries<V>();
+      _entrySet = new Entries();
     return _entrySet;
   }
 
@@ -131,7 +131,7 @@ final public class SubKeyMap<V> extends 
   //
   // Set implementation for SubkeyMap.entrySet()
   //
-  private class Entries<V> extends AbstractSet<Map.Entry<String, V>>
+  private class Entries extends AbstractSet<Map.Entry<String, V>>
   {
     public Entries()
     {
@@ -145,7 +145,7 @@ final public class SubKeyMap<V> extends 
       // exceptions.  Consequently, gather the keys in a list
       // and iterator over that.
       List<String> keyList = _gatherKeys();
-      return new EntryIterator<V>(keyList.iterator());
+      return new EntryIterator(keyList.iterator());
     }
 
     @Override
@@ -193,7 +193,7 @@ final public class SubKeyMap<V> extends 
     }
   }
 
-  private class EntryIterator<V> implements Iterator<Map.Entry<String, V>>
+  private class EntryIterator implements Iterator<Map.Entry<String, V>>
   {
     public EntryIterator(Iterator<String> iterator)
     {
@@ -209,7 +209,7 @@ final public class SubKeyMap<V> extends 
     {
       String baseKey = _iterator.next();
       _currentKey = baseKey;
-      return new Entry<V>(baseKey);
+      return new Entry(baseKey);
     }
 
     public void remove()
@@ -226,7 +226,7 @@ final public class SubKeyMap<V> extends 
     private String    _currentKey;
   }
 
-  private class Entry<V> implements Map.Entry<String, V>
+  private class Entry implements Map.Entry<String, V>
   {
     public Entry(String baseKey)
     {