You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gc...@apache.org on 2012/02/27 23:58:49 UTC

svn commit: r1294382 - in /myfaces/trinidad/trunk: trinidad-api/src/main/java/org/apache/myfaces/trinidad/config/ trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/ trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/ trinidad-imp...

Author: gcrawford
Date: Mon Feb 27 22:58:48 2012
New Revision: 1294382

URL: http://svn.apache.org/viewvc?rev=1294382&view=rev
Log:
TRINIDAD-2226 Provide mechanism to reload skin definitions from trinidad-skins.xml

Thanks to Prakash

Modified:
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/config/Configurator.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinFactory.java
    myfaces/trinidad/trunk/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinFactoryImpl.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/config/Configurator.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/config/Configurator.java?rev=1294382&r1=1294381&r2=1294382&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/config/Configurator.java (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/config/Configurator.java Mon Feb 27 22:58:48 2012
@@ -19,8 +19,10 @@
 package org.apache.myfaces.trinidad.config;
 
 import javax.faces.context.ExternalContext;
+
 import javax.servlet.ServletRequest;
 
+import org.apache.myfaces.trinidad.skin.SkinFactory;
 import org.apache.myfaces.trinidad.util.RequestStateMap;
 
 /**
@@ -144,6 +146,14 @@ public abstract class Configurator
    * @param externalContext the external context
    */
   public void endRequest(ExternalContext externalContext){}
+  
+  /**
+    * The skinning framework calls this method to notify Configurators that the specified SkinFactory has been reloaded.
+    * In response the Configurators can add their skins to the specified SkinFactory.
+    * @param externalContext the external context
+    * @param factory the SkinFactory instance to which the skins can be reloaded
+    */
+  public void reloadSkins(ExternalContext externalContext, SkinFactory factory){}
 
   /**
    * Disables Configurator services for the current request.  When this method

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinFactory.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinFactory.java?rev=1294382&r1=1294381&r2=1294382&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinFactory.java (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinFactory.java Mon Feb 27 22:58:48 2012
@@ -18,17 +18,18 @@
  */
 package org.apache.myfaces.trinidad.skin;
 
-import java.util.WeakHashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.WeakHashMap;
 
 import javax.faces.context.FacesContext;
+
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 
 
 /**
  * Factory for creating Skin objects.
- * 
+ *
  */
 abstract public class SkinFactory
 {
@@ -60,7 +61,16 @@ abstract public class SkinFactory
       _FACTORIES.put(cl, factory);
     }
   }
-
+  
+  /**
+   * Reloads the skins that was registered with this factory. 
+   * Subclassers can choose to provide the implementation.
+   */
+  public void reload()
+  {
+    _LOG.warning("SKIN_FACTORY_NO_RELOAD_SUPPORT", this);
+  }
+  
   /**
    * <p>Register the specified {@link Skin} instance, associated with
    * the specified <code>skinId</code>, to be supported by this

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts?rev=1294382&r1=1294381&r2=1294382&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts Mon Feb 27 22:58:48 2012
@@ -381,7 +381,10 @@
  <!-- FACTORY_ALREADY_AVAILABlE_FOR_THIS_CLASS_LOADER -->
  <resource key="FACTORY_ALREADY_AVAILABlE_FOR_THIS_CLASS_LOADER">Factory already available for this class loader.</resource>
  
- <!-- BYTE_ARRAY_CANNOT_BE_NULL -->
+ <!-- SKIN_FACTORY_NO_RELOAD_SUPPORT -->
+<resource key="SKIN_FACTORY_NO_RELOAD_SUPPORT">There was an attempt to reload a SkinFactory implementation "{0}" that does not support reloading.</resource>
+
+<!-- BYTE_ARRAY_CANNOT_BE_NULL -->
  <resource key="BYTE_ARRAY_CANNOT_BE_NULL">byte[] cannot be null</resource>
  
  <!-- ACTUAL_LENGTH_OFFSET -->

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java?rev=1294382&r1=1294381&r2=1294382&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java Mon Feb 27 22:58:48 2012
@@ -440,6 +440,25 @@ public final class GlobalConfiguratorImp
   }
 
   /**
+   * @inheritDoc
+   */
+  @Override  
+  public void reloadSkins(ExternalContext externalContext, SkinFactory skinFactory)
+  {
+    // register trinidad's base skins
+    SkinUtils.registerBaseSkins();
+    
+    // ask all subordinate configurators to reload their skins
+    for (final Configurator config: _services)
+    {
+      config.reloadSkins(externalContext, skinFactory);
+    }
+    
+    // recompute skins from the various trinidad-skins.xml
+    SkinUtils.registerSkinExtensions(externalContext, skinFactory);
+  }
+  
+  /**
    * Hackily called by the ThreadLocalResetter to register itself so that the
    * GlobalConfiguratorImpl can tell the ThreadLocalResetter to clean up the
    * ThreadLocals at the appropriate time.

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinFactoryImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinFactoryImpl.java?rev=1294382&r1=1294381&r2=1294382&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinFactoryImpl.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinFactoryImpl.java Mon Feb 27 22:58:48 2012
@@ -24,12 +24,14 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.skin.Skin;
 import org.apache.myfaces.trinidad.skin.SkinFactory;
 import org.apache.myfaces.trinidad.skin.SkinVersion;
+import org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl;
 import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlConstants;
 
 
@@ -46,7 +48,7 @@ public class SkinFactoryImpl extends Ski
   public SkinFactoryImpl()
   {
     super();
-    _skins = new LinkedHashMap<String, Skin>();
+    _initalizeSkins();
 
   }
   
@@ -73,8 +75,17 @@ public class SkinFactoryImpl extends Ski
       return;
     }
 
-    synchronized (_skins)
+    synchronized (this)
     {
+      // we could be called when 
+      // 1. skin is in READY state -> allow skin addition
+      // 2. _reloadIfDirty() is in call stack (in which case we will be in RELOADABLE state) -> allow skin addition
+      // 3. _reloadIfDirty() is not in call stack, we could possibly be in DIRTY state -> do not allow skin addition
+      if (_skinsState == SkinsState.DIRTY)
+      {
+        throw new IllegalStateException(_LOG.getMessage("SKIN_ADDITION_ATEMPT_WHEN_FACTORY_DIRTY"));
+      }
+      
       Skin previousValue = _skins.put(skinId, skin);
       if (previousValue != null)
         _LOG.warning("DUPLICATE_ADD_SKIN_TO_SKIN_FACTORY", skinId);
@@ -101,8 +112,14 @@ public class SkinFactoryImpl extends Ski
     }
 
     Skin skin = null;
-    synchronized (_skins)
+    synchronized (this)
     {
+      // we can be called at deploy time, so, it is possible that faces context is null
+      if (context != null)
+      {
+        _reloadIfDirty(context.getExternalContext());
+      }
+
       if (_skins.containsKey(skinId))
       {
         skin = _skins.get(skinId);
@@ -166,6 +183,9 @@ public class SkinFactoryImpl extends Ski
     // renderKitId (simple.desktop or simple.pda)
     if (family == null)
      throw new NullPointerException("Null skin family");
+    
+    // we are in JSF lifecycle when this method gets called, so this time we will have the faces context
+    _reloadIfDirty(context.getExternalContext());
 
     // default render-kit-id, if needed.
     if (renderKitId == null)
@@ -281,6 +301,58 @@ public class SkinFactoryImpl extends Ski
     return (matchingSkin == null) ? null : new RequestSkinWrapper(matchingSkin); 
   }
 
+  @Override
+  public Iterator<String> getSkinIds()
+  {
+    return (_skins.keySet().iterator());
+  }
+
+  @Override
+  public void reload()
+  {
+    synchronized (this)
+    {
+      // just mark it dirty, we will do the reload on next request
+      _skinsState = SkinsState.DIRTY;
+    }
+  }
+  
+  private void _reloadIfDirty(ExternalContext context)
+  {
+    synchronized (this)
+    {
+      // dont try to reload if we are done with or in process of reloading
+      if (_skinsState == SkinsState.DIRTY)
+      {
+        _LOG.fine("Reloading skins begin");
+        _skinsState = SkinsState.RELOADING;
+        
+        // backup the old skins to help in recovery if need be
+        Map<String, Skin> oldSkins = _skins;
+        
+        _initalizeSkins();
+        
+        try
+        {
+          // give chance for configurator services to attach any skins that was not defined trinidad-skins.xml
+          GlobalConfiguratorImpl.getInstance().reloadSkins(context, this);
+        }
+        catch (Exception e)
+        {
+          _LOG.severe("SKIN_RELOAD_FAILURE", e);
+          
+          // recover to the skins before the reload attempt
+          _skins = oldSkins;
+        }
+        finally
+        {
+          _skinsState = SkinsState.READY;
+          _LOG.fine("Reloading skins complete");
+        }
+      }
+    }
+  }
+
   /**
    * Given a list of Skins, find the one that has its SkinVersion set to 'default', if it exists.
    * @param matchingSkinList A list of Skins that we will look through to find the 'default'.
@@ -303,16 +375,35 @@ public class SkinFactoryImpl extends Ski
     }
     return matchingSkin;
   }
+  
+  private void _initalizeSkins()
+  {
+    _skins = new LinkedHashMap<String, Skin>();
+  }
 
-  @Override
-  public Iterator<String> getSkinIds()
+  /**
+   * State of the skins attached to this factory
+   */
+  private enum SkinsState
   {
-    return (_skins.keySet().iterator());
+    /**
+     * Ready to be used
+     */
+    READY,
+    /**
+     * Marked dirty, reload pending
+     */
+    DIRTY,
+    /**
+     * Reload in progress
+     */
+    RELOADING
   }
 
   // Stores all the Skins in this SkinFactory
   private Map<String, Skin> _skins = null;
-
+  private SkinsState _skinsState = SkinsState.READY;
+  
   static private final String _SIMPLE_PDA = "simple.pda";
   static private final String _SIMPLE_DESKTOP = "simple.desktop";
   static private final String _SIMPLE_PORTLET = "simple.portlet";

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java?rev=1294382&r1=1294381&r2=1294382&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java Mon Feb 27 22:58:48 2012
@@ -108,6 +108,24 @@ public class SkinUtils
 
   /**
    * Register any custom skin extensions (and skin-additions) found in the
+   * trinidad-skins.xml file with the supplied SkinFactory.
+   * You should call registerBaseSkins() before calling this method.
+   * 
+   * @param context ServletContext, used to get the trinidad-skins.xml file.
+   * @param skinFactory the factory for which the skins are to be registered
+   */
+  static public void registerSkinExtensions(
+    ExternalContext context,
+    SkinFactory     skinFactory)
+  {
+    boolean fine = _LOG.isFine();
+    if (fine) _LOG.fine("Begin registerSkinExtensions");
+    _registerSkinExtensionsAndAdditions(context, skinFactory);
+    if (fine) _LOG.fine("End registerSkinExtensions");
+  }
+
+  /**
+   * Register any custom skin extensions (and skin-additions) found in the
    * trinidad-skins.xml file with the SkinFactory.
    *
    * Make sure the SkinFactory.getFactory() does not return null before
@@ -128,12 +146,8 @@ public class SkinUtils
       SkinFactory.setFactory(new SkinFactoryImpl());
       skinFactory = SkinFactory.getFactory();
     }
-    boolean fine = _LOG.isFine();
-    if (fine) _LOG.fine("Begin registerSkinExtensions");
-    _registerSkinExtensionsAndAdditions(context, skinFactory);
-    if (fine) _LOG.fine("End registerSkinExtensions");
-
-
+    
+    registerSkinExtensions(context, skinFactory);
   }
 
   /**

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts?rev=1294382&r1=1294381&r2=1294382&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts Mon Feb 27 22:58:48 2012
@@ -470,6 +470,12 @@ The skin {0} specified on the requestMap
 <!-- DUPLICATE_ADD_SKIN_TO_SKIN_FACTORY -->
 <resource key="DUPLICATE_ADD_SKIN_TO_SKIN_FACTORY">The previously added {0} skin has been added again. If you cached this skin in your application, you might get inconsistent results. Check for duplicate trinidad-skins.xml files on the classpath.</resource>
 
+<!-- SKIN_ADDITION_ATEMPT_WHEN_FACTORY_DIRTY -->
+<resource key="SKIN_ADDITION_ATEMPT_WHEN_FACTORY_DIRTY">There was an attempt to add a Skin to SkinFactory when the SkinFactory was in a dirty state.</resource>
+
+<!-- SKIN_RELOAD_FAILURE -->
+<resource key="SKIN_RELOAD_FAILURE">Error was encountered while reloading skins. Recovering to previous skin definitions.</resource>
+
 <!-- CANNOT_GET_SKIN_WITH_NULL_SKINID -->
 <resource key="CANNOT_GET_SKIN_WITH_NULL_SKINID">Can't get Skin with null skinId</resource>