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 [2/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...

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/TokenCache.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/TokenCache.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/TokenCache.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/TokenCache.java Thu Oct 28 00:40:23 2010
@@ -66,33 +66,51 @@ public class TokenCache implements Seria
    */
   @SuppressWarnings("unchecked")
   static public TokenCache getTokenCacheFromSession(
-    FacesContext context,
-    String       cacheName,
-    boolean      createIfNeeded,
-    int          defaultSize)
-  {
-    ExternalContext external = context.getExternalContext();
-    Object session = external.getSession(true);
-    assert(session != null);
-
-    TokenCache cache;
-    // Synchronize on the session object to ensure that
-    // we don't ever create two different caches
-    synchronized (session)
+    ExternalContext extContext,
+    String          cacheName,
+    boolean         createIfNeeded,
+    int             defaultSize)
+  {
+    Map<String, Object> sessionMap = extContext.getSessionMap();
+
+    TokenCache cache = (TokenCache)sessionMap.get(cacheName);
+    
+    if (cache == null)
     {
-      cache = (TokenCache) external.getSessionMap().get(cacheName);
-      if ((cache == null) && createIfNeeded)
+      if (createIfNeeded)
       {
-        // create the TokenCache with the crytographically random seed
-        cache = new TokenCache(defaultSize, _getSeed());
-
-        external.getSessionMap().put(cacheName, cache);
+        Object session = extContext.getSession(true);
+  
+        // Synchronize on the session object to ensure that
+        // we don't ever create two different caches
+        synchronized (session)
+        {
+          cache = (TokenCache)sessionMap.get(cacheName);
+          
+          if (cache == null)
+          {
+            // create the TokenCache with the crytographically random seed
+            cache = new TokenCache(defaultSize, _getSeed(), sessionMap, cacheName);
+    
+            sessionMap.put(cacheName, cache);
+          }
+          else
+          {
+            // make sure the existing cache has its own attached so it can dirty itself
+            cache.reattachOwner(sessionMap);
+          }
+        }
       }
     }
+    else
+    {
+      // make sure the existing cache has its own attached so it can dirty itself
+      cache.reattachOwner(sessionMap);
+    }
 
     return cache;
   }
-  
+    
   /**
    * Returns a cryptographically secure random number to use as the TokenCache seed
    */
@@ -124,11 +142,10 @@ public class TokenCache implements Seria
   /**
    * For serialization only
    */
-  public TokenCache()
+  TokenCache()
   {
-    this(_DEFAULT_SIZE, 0L);
-  }
-
+    this(_DEFAULT_SIZE, 0L, null, null);
+  }   
 
   /**
    * Create a TokenCache that will store the last "size" entries.  This version should
@@ -138,30 +155,37 @@ public class TokenCache implements Seria
    */
   public TokenCache(int size)
   {
-    this(size, 0L);
-  }
-
-  /**
-   * Create a TokenCache that will store the last "size" entries,
-   * and begins its tokens based on the seed (instead of always
-   * starting at "0").
-   * @Deprecated Use version using a long size instead for greater security
-   */
-  public TokenCache(int size, int seed)
-  {
-    this(size, (long)seed);
+    this(size, 0L, null, null);
   }
 
  /**
   * Create a TokenCache that will store the last "size" entries,
   * and begins its tokens based on the seed (instead of always
   * starting at "0").
+  * @patam owner      Optional Cache that stores the token cache
+  * @param keyInOwner Optional Name under which this cache is stored in the owner
   */
- public TokenCache(int size, long seed)
+  private TokenCache(int size, long seed, Map<String, Object> owner, String keyInOwner)
+  {
+    _cache      = new LRU(size);
+    _pinned     = new ConcurrentHashMap<String, String>(size);
+    _count      = new AtomicLong(seed);
+    _owner      = owner;
+    _keyInOwner = keyInOwner;
+  } 
+
+  /**
+   * Reattaches the owner after Serialization since the owner might not be Serializable or it
+   * might not be a good idea to serialize the owner.
+   * @param owner
+   * @throws NullPointerException if owner is null
+   */
+  public void reattachOwner(Map<String, Object> owner)
   {
-    _cache = new LRU(size);
-    _pinned = new ConcurrentHashMap<String, String>(size);
-    _count = new AtomicLong(seed);
+    if (owner == null)
+      throw new NullPointerException("Can't set owner to null");
+      
+    _owner = owner;
   }
 
   /**
@@ -222,6 +246,9 @@ public class TokenCache implements Seria
     
     targetStore.put(token, value);
 
+    // our contents have changed, so mark ourselves as dirty in our owner
+    _dirty();
+    
     return token;
   }
 
@@ -289,14 +316,22 @@ public class TokenCache implements Seria
       String token, 
       Map<String, V> targetStore)
   {
+    V oldValue;
+    
     synchronized (this)
     {
       _LOG.finest("Removing token {0} from cache", token);
       _cache.remove(token);
+      
       // TODO: should removing a value that is "pinned" take?
       // Or should it stay in memory?
-      return _removeTokenIfReady(targetStore, token);
+      oldValue = _removeTokenIfReady(targetStore, token);
     }
+
+    // our contents have changed, so mark ourselves as dirty in our owner
+    _dirty();
+    
+    return oldValue;
   }
 
   /**
@@ -314,6 +349,9 @@ public class TokenCache implements Seria
 
       _cache.clear();
     }
+
+    // our contents have changed, so mark ourselves as dirty in our owner
+    _dirty();
   }
 
   private String _getNextToken()
@@ -324,6 +362,17 @@ public class TokenCache implements Seria
     // convert using base 36 because it is a fast efficient subset of base-64
     return Long.toString(nextToken, 36);
   }
+  
+  /**
+   * Mark the cache as dirty in the owner
+   */
+  private void _dirty()
+  {
+    if (_keyInOwner != null)
+    {
+      _owner.put(_keyInOwner, this);
+    }
+  }
 
   private class LRU extends LRUCache<String, String>
   {
@@ -351,10 +400,15 @@ public class TokenCache implements Seria
   // the current token value
   private final AtomicLong _count;
 
+  private final String _keyInOwner;
+  
   // Hack instance parameter used to communicate between the LRU cache's
   // removing() method, and the addNewEntry() method that may trigger it
   private transient String _removed;
 
+  // owning cache
+  private transient Map<String, Object> _owner;
+
   static private final int _DEFAULT_SIZE = 15;
   static private final long serialVersionUID = 1L;
   static private final TrinidadLogger _LOG =

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.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/webapp/TrinidadFilterImpl.java (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java Thu Oct 28 00:40:23 2010
@@ -39,11 +39,14 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import javax.servlet.http.HttpSession;
+
 import org.apache.myfaces.trinidad.context.RequestContext;
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
 import org.apache.myfaces.trinidad.util.ExternalContextUtils;
 import org.apache.myfaces.trinidad.util.RequestStateMap;
+import org.apache.myfaces.trinidadinternal.config.CheckSerializationConfigurator;
 import org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl;
 import org.apache.myfaces.trinidadinternal.config.dispatch.DispatchResponseConfiguratorImpl;
 import org.apache.myfaces.trinidadinternal.config.dispatch.DispatchServletResponse;
@@ -94,10 +97,14 @@ public class TrinidadFilterImpl implemen
 
   public void init(FilterConfig filterConfig) throws ServletException
   {
+    // potentially wrap the FilterConfig to catch Serialization changes
+    filterConfig = CheckSerializationConfigurator.getFilterConfig(filterConfig);
+    
     _servletContext = filterConfig.getServletContext();
             
     //There is some functionality that still might require servlet-only filter services.
     _filters = ClassLoaderUtils.getServices(TrinidadFilterImpl.class.getName());
+    
     for(Filter f:_filters)
     {
       f.init(filterConfig);
@@ -130,7 +137,20 @@ public class TrinidadFilterImpl implemen
     // properly installed.
     request.setAttribute(_FILTER_EXECUTED_KEY, Boolean.TRUE);
 
-    ExternalContext externalContext = new ServletExternalContext(_servletContext, request, response);    
+    // potentially wrap the request in order to check managed bean HA
+    if (request instanceof HttpServletRequest)
+    {
+      request = CheckSerializationConfigurator.getHttpServletRequest(
+                                    new ServletExternalContext(_servletContext, request, response),
+                                    (HttpServletRequest)request);
+    }
+    
+    // potentially wrap the ServletContext in order to check managed bean HA
+    ExternalContext externalContext = new ServletExternalContext(
+                                        _getPotentiallyWrappedServletContext(request),
+                                        request,
+                                        response);
+    
     GlobalConfiguratorImpl config = GlobalConfiguratorImpl.getInstance();
     config.beginRequest(externalContext);
     
@@ -207,7 +227,11 @@ public class TrinidadFilterImpl implemen
   {
     // -= Scott O'Bryan =-
     // Added for backward compatibility
-    ExternalContext ec = new ServletExternalContext(_servletContext, request, response);
+    // potentially wrap the ServletContext to check ManagerBean HA
+    ExternalContext ec = new ServletExternalContext(_getPotentiallyWrappedServletContext(request),
+                                                    request,
+                                                    response);
+    
     boolean isHttpReq = ExternalContextUtils.isHttpServletRequest(ec);
     
     if(isHttpReq)
@@ -423,6 +447,24 @@ public class TrinidadFilterImpl implemen
     }
   }
 
+  /**
+   * Returns a potentially wrapped ServletContext for ManagedBean HA
+   */
+  private ServletContext _getPotentiallyWrappedServletContext(ServletRequest request)
+  {
+    if (request instanceof HttpServletRequest)
+    {
+      HttpSession session = ((HttpServletRequest)request).getSession(false);
+      
+      if (session != null)
+      {
+        return session.getServletContext();
+      }
+    }
+    
+    return _servletContext;
+  }
+
   private ServletContext _servletContext;
   private List<Filter> _filters = null;
 

Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts?rev=1028150&r1=1028149&r2=1028150&view=diff
==============================================================================
--- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts (original)
+++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts Thu Oct 28 00:40:23 2010
@@ -1080,4 +1080,14 @@ The skin {0} specified on the requestMap
 <resource key="INVALID_LOCALE_VARIANT_HAS_SLASH">Invalid variant for Locale identifier {0} - cannot contain slashes to avoid XSS attack. Will use empty string for variant.</resource>
 
 <resource key="COULD_NOT_DELETE_FILE">Could not delete the file {0}</resource>
+
+<!-- ATTRIBUTE_SERIALIZATION_FAILED -->
+<resource key="ATTRIBUTE_SERIALIZATION_FAILED">Error serializing {0} attribute:{1} value:{2}</resource>
+
+<!-- ATTRIBUTE_NOT_SERIALIABLE -->
+<resource key="ATTRIBUTE_NOT_SERIALIABLE">Failover error: {0} attribute:{1} of type {2} is not Serializable</resource>
+
+<!-- SERIALIZABLE_ATTRIBUTE_MUTATED -->
+<resource key="SERIALIZABLE_ATTRIBUTE_MUTATED">Failover error: Serialization of {0} attribute:{1} has changed from {2} to {3} without the attribute being dirtied</resource>
+
 </resources>