You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by an...@apache.org on 2014/06/23 18:33:10 UTC

svn commit: r1604869 - /myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleProvider.java

Author: andys
Date: Mon Jun 23 16:33:09 2014
New Revision: 1604869

URL: http://svn.apache.org/r1604869
Log:
TRINIDAD-2484 Threadsafety issue in SkinStyleProvider leading to missing styles and distorted ui

Thanks for the fix, Prakash!


Modified:
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleProvider.java

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleProvider.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleProvider.java?rev=1604869&r1=1604868&r2=1604869&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleProvider.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleProvider.java Mon Jun 23 16:33:09 2014
@@ -18,19 +18,19 @@
  */
 package org.apache.myfaces.trinidadinternal.skin;
 
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.faces.context.FacesContext;
 
+import org.apache.myfaces.trinidad.context.RequestContext;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.skin.Skin;
 import org.apache.myfaces.trinidadinternal.style.StyleContext;
 import org.apache.myfaces.trinidadinternal.style.StyleProvider;
 import org.apache.myfaces.trinidadinternal.style.cache.FileSystemStyleCache;
 import org.apache.myfaces.trinidadinternal.style.xml.StyleSheetDocumentUtils;
 import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetDocument;
-import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidadinternal.util.LRUCache;
 
 
@@ -52,8 +52,7 @@ public class SkinStyleProvider extends F
    * style sheet take precedence over styles provided by the
    * Skin.
    *
-   * @param context The current RenderingContext, which provides
-   *          access to the current Skin.
+   * @param skin The skin for which the style provider is needed.
    * @param targetDirectoryPath The full file system path of the
    *          directory where generated CSS files are stored.
    *          If the directory does not exist and cannot be
@@ -67,7 +66,6 @@ public class SkinStyleProvider extends F
     String targetDirectoryPath
     ) throws IllegalArgumentException
   {
-
     if (skin == null)
       throw new IllegalArgumentException(_LOG.getMessage(
         "NO_SKIN_SPECIFIED"));
@@ -225,52 +223,69 @@ public class SkinStyleProvider extends F
     return name;
   }
 
-  // Returns a Map which hashes ProviderKeys to shared instances
-  // of SkinStyleProviders.
+  // Returns a Map which hashes ProviderKeys to shared instances of SkinStyleProviders.
   private static Map<ProviderKey, StyleProvider> _getProviders()
   {
-    // =-=ags For now, we just use a global variable.  But
-    //        really, our cache should probably be hanging off
-    //        of the ServletContext.
-    if (_sSharedProviders == null)
-    {
-      FacesContext context = FacesContext.getCurrentInstance();
-      String lruCacheSize =
-        context.getExternalContext().
-        getInitParameter(_MAX_SKINS_CACHED); 
+    ConcurrentMap<String, Object> appMap = 
+      RequestContext.getCurrentInstance().getApplicationScopedConcurrentMap();
+
+    Map<ProviderKey, StyleProvider> styleProviders = 
+      (Map<ProviderKey, StyleProvider>)appMap.get(_SKIN_PROVIDERS_KEY);
+
+    if (styleProviders == null)
+    {
+      styleProviders = _createProvidersMap();
       
-      int lruCacheSizeInt = _MAX_SKINS_CACHED_DEFAULT;
-      boolean invalidInt = false;
+      Map<ProviderKey, StyleProvider> oldStyleProviders = 
+        (Map<ProviderKey, StyleProvider>)appMap.putIfAbsent(_SKIN_PROVIDERS_KEY, styleProviders);
+      
+      if (oldStyleProviders != null)
+      {
+        styleProviders = oldStyleProviders;
+      }
+    }
+
+    return styleProviders;
+  }
+  
+  private static Map<ProviderKey, StyleProvider> _createProvidersMap()
+  {
+    FacesContext context = FacesContext.getCurrentInstance();
+    String lruCacheSize = context.getExternalContext().getInitParameter(_MAX_SKINS_CACHED); 
+    
+    int lruCacheSizeInt = _MAX_SKINS_CACHED_DEFAULT;
+    boolean invalidInt = false;
 
-      if (lruCacheSize != null && !lruCacheSize.equals(""))
+    if (lruCacheSize != null && !lruCacheSize.equals(""))
+    {
+      try
       {
-        try
-        {
-          lruCacheSizeInt = Integer.parseInt(lruCacheSize);
-        }
-        catch (NumberFormatException nfe)
-        {
-          invalidInt = true;
-        }
-        if (lruCacheSizeInt <= 0)
-        {
-          invalidInt = true;
-        }
+        lruCacheSizeInt = Integer.parseInt(lruCacheSize);
+      }
+      catch (NumberFormatException nfe)
+      {
+        invalidInt = true;
       }
+      if (lruCacheSizeInt <= 0)
+      {
+        invalidInt = true;
+      }
+    }
+    
+    // The user typed in an invalid integer ( <=0 or a value that couldn't be formatted to a number)
+    // so log a warning
+    if (invalidInt)
+    {
+      lruCacheSizeInt = _MAX_SKINS_CACHED_DEFAULT;
       
-      // The user typed in an invalid integer ( <=0 or a value that couldn't be formatted to a number)
-      // so log a warning
-      if (invalidInt)
+      if (_LOG.isWarning())
       {
-        lruCacheSizeInt = _MAX_SKINS_CACHED_DEFAULT;
-        if (_LOG.isWarning())
-          _LOG.warning("INVALID_INTEGER_MAX_SKINS_CACHED", new Object[]{lruCacheSize, _MAX_SKINS_CACHED_DEFAULT});        
+        _LOG.warning("INVALID_INTEGER_MAX_SKINS_CACHED", 
+                     new Object[]{lruCacheSize, _MAX_SKINS_CACHED_DEFAULT});        
       }
-        
-      _sSharedProviders = new LRUCache<ProviderKey, StyleProvider>(lruCacheSizeInt);
     }
-
-    return _sSharedProviders;
+      
+    return new LRUCache<ProviderKey, StyleProvider>(lruCacheSizeInt);
   }
 
   // Key that we use to retrieve a shared SkinStyleProvider
@@ -330,12 +345,13 @@ public class SkinStyleProvider extends F
 
   // The Skin which provides styles
   private Skin _skin;
-  
+
   // The Skin-specific StyleSheetDocument
   private StyleSheetDocument _skinDocument;
 
-  // Cache of shared SkinStyleProvider instances
-  private static Map<ProviderKey, StyleProvider> _sSharedProviders;
+  // Key to cache of shared SkinStyleProvider instances
+  private static final String _SKIN_PROVIDERS_KEY = 
+    "org.apache.myfaces.trinidadinternal.skin.SKIN_PROVIDERS_KEY";
   private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
     SkinStyleProvider.class);
   private static final String _MAX_SKINS_CACHED =