You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by jw...@apache.org on 2013/10/17 17:25:59 UTC

svn commit: r1533115 [2/3] - in /myfaces/trinidad/trunk: src/site/xdoc/devguide/ 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/t...

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/skin/SimplePdaSkin.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/skin/SimplePdaSkin.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/skin/SimplePdaSkin.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/skin/SimplePdaSkin.java Thu Oct 17 15:25:57 2013
@@ -18,6 +18,7 @@
  */
 package org.apache.myfaces.trinidadinternal.renderkit.core.skin;
 
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.TrinidadRenderingConstants;
 import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlConstants;
 
 
@@ -35,7 +36,7 @@ public class SimplePdaSkin extends PdaHt
   @Override
   public String getStyleSheetName()
   {
-    return "META-INF/adf/styles/simple-pda.css";
+    return TrinidadRenderingConstants.SIMPLE_PDA_LOCATION;
   }
 
   /**
@@ -45,7 +46,7 @@ public class SimplePdaSkin extends PdaHt
   @Override
   public String getId()
   {
-    return "simple.pda";
+    return TrinidadRenderingConstants.SIMPLE_PDA_ID;
   }
 
   /**
@@ -55,7 +56,7 @@ public class SimplePdaSkin extends PdaHt
   @Override
   public String getFamily()
   {
-    return "simple";
+    return TrinidadRenderingConstants.SIMPLE_SKIN_FAMILY;
   }
 
   /**
@@ -67,4 +68,5 @@ public class SimplePdaSkin extends PdaHt
   {
     return XhtmlConstants.APACHE_TRINIDAD_PDA;
   }
+
 }

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/skin/SimplePortletSkin.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/skin/SimplePortletSkin.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/skin/SimplePortletSkin.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/skin/SimplePortletSkin.java Thu Oct 17 15:25:57 2013
@@ -24,8 +24,8 @@ import java.util.Map;
 
 import org.apache.myfaces.trinidad.context.RenderingContext;
 import org.apache.myfaces.trinidadinternal.renderkit.core.CoreRenderKit;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.BaseDesktopSkin;
 import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SkinSelectors;
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.TrinidadRenderingConstants;
 import org.apache.myfaces.trinidadinternal.style.util.StyleUtils;
 
 /**
@@ -39,7 +39,7 @@ public class SimplePortletSkin  extends 
   @Override
   public String getStyleSheetName()
   {
-    return "META-INF/adf/styles/simple-portlet.css";
+    return TrinidadRenderingConstants.SIMPLE_PORTLET_LOCATION;
   }
 
   /**
@@ -49,7 +49,7 @@ public class SimplePortletSkin  extends 
   @Override
   public String getId()
   {
-    return "simple.portlet";
+    return TrinidadRenderingConstants.SIMPLE_PORTLET_ID;
   }
 
   /**
@@ -59,7 +59,7 @@ public class SimplePortletSkin  extends 
   @Override
   public String getFamily()
   {
-    return "simple";
+    return TrinidadRenderingConstants.SIMPLE_SKIN_FAMILY;
   }
 
   /**
@@ -501,6 +501,4 @@ public class SimplePortletSkin  extends 
      // end menu
 
   }
-
-
 }
\ No newline at end of file

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/TrinidadRenderingConstants.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/TrinidadRenderingConstants.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/TrinidadRenderingConstants.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/TrinidadRenderingConstants.java Thu Oct 17 15:25:57 2013
@@ -193,9 +193,53 @@ public final class TrinidadRenderingCons
   // skin family names constants
   public static final String CASABLANCA_SKIN_FAMILY = "casablanca";
   public static final String MINIMAL_SKIN_FAMILY = "minimal";
+  public static final String SIMPLE_SKIN_FAMILY =  "simple";
+
+  // simple desktop skin
+  public static final String SIMPLE_DESKTOP_ID =  "simple.desktop";
+  public static final String SIMPLE_DESKTOP_LOCATION =  "META-INF/adf/styles/simple-desktop.css";
+
+  // simple pda skin
+  public static final String SIMPLE_PDA_ID =  "simple.pda";
+  public static final String SIMPLE_PDA_LOCATION =  "META-INF/adf/styles/simple-pda.css";
+
+  // simple portlet skin
+  public static final String SIMPLE_PORTLET_ID =  "simple.portlet";
+  public static final String SIMPLE_PORTLET_LOCATION =  "META-INF/adf/styles/simple-portlet.css";
+
+
+  // Minimal desktop skin id
+  public static final String MINIMAL_DESKTOP_ID = "minimal.desktop";
+  // Minimal skin style sheet name
+  public static final String MINIMAL_DESKTOP_STYLE_SHEET_NAME =
+    "META-INF/adf/styles/minimal-desktop.css";
+
+  // Minimal pda skin id
+  public static final String MINIMAL_PDA_ID = "minimal.pda";
+  // Minimal skin style sheet name
+  public static final String MINIMAL_PDA_STYLE_SHEET_NAME =
+    "META-INF/adf/styles/minimal-pda.css";
+
+  // Minimal portlet skin id
+  public static final String MINIMAL_PORTLET_ID = "minimal.portlet";
+  // Minimal skin style sheet name
+  public static final String MINIMAL_PORTLET_STYLE_SHEET_NAME =  "META-INF/adf/styles/simple-portlet.css";
+
+
+  // Casablanca skin style sheet name
+  public static final String CASABLANCA_STYLE_SHEET_NAME = "META-INF/adf/styles/casablancaSkin.css";
+
+  // Casablanca desktop skin id
+  public static final String CASABLANCA_DESKTOP_ID = "casablanca.desktop";
+
+  // Casablanca pda skin id
+  public static final String CASABLANCA_PDA_ID = "casablanca.pda";
+
+  // Casablanca portlet skin id
+  public static final String CASABLANCA_PORTLET_ID = "casablanca.portlet";
 
   public static final String COLOR_PALETTE_TRANSPARENT_ICON_NAME = "cpt.gif";
-  
+
   // 'xc' stands for uiX Composite
   // -= Simon =-
   // FIXME: Should it be renamed to remove UIX reference?

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java Thu Oct 17 15:25:57 2013
@@ -38,8 +38,9 @@ import org.apache.myfaces.trinidad.conte
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.resource.StringContentResourceLoader;
 import org.apache.myfaces.trinidad.skin.Skin;
-import org.apache.myfaces.trinidad.skin.SkinFactory;
 
+import org.apache.myfaces.trinidad.skin.SkinMetadata;
+import org.apache.myfaces.trinidad.skin.SkinProvider;
 import org.apache.myfaces.trinidadinternal.share.nls.LocaleContextImpl;
 import org.apache.myfaces.trinidadinternal.util.nls.LocaleUtils;
 
@@ -191,11 +192,10 @@ abstract public class TranslationsResour
   protected Skin getSkin(FacesContext context)
   {
     Skin skin = null;
-    SkinFactory skinFactory = SkinFactory.getFactory();
-    Object skinIdObj = context.getExternalContext().getRequestParameterMap().
-      get("skinId");
+    SkinProvider skinProvider = SkinProvider.getCurrentInstance(context.getExternalContext());
+    Object skinIdObj = context.getExternalContext().getRequestParameterMap().get("skinId");
     if (skinIdObj != null)
-      skin = skinFactory.getSkin(context, skinIdObj.toString());
+      skin = skinProvider.getSkin(context, new SkinMetadata.Builder().id(skinIdObj.toString()).build());
 
     return skin;
   }

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/share/io/URLInputStreamProvider.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/share/io/URLInputStreamProvider.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/share/io/URLInputStreamProvider.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/share/io/URLInputStreamProvider.java Thu Oct 17 15:25:57 2013
@@ -55,14 +55,14 @@ public class URLInputStreamProvider impl
     // to URL.openConnection
     _lastModifiedTime = URLUtils.getLastModified(_url);
     URLConnection connection = _url.openConnection();
-    // prevent caching during DT where the source may change...
-    if (Beans.isDesignTime())
-    {
-      connection.setUseCaches(false);
-    }
+
+    // avoid URL caching
+    // if we use URL caching the files which changed do not get loaded completely
+    connection.setUseCaches(false);
+
     // In theory, should not need to close
     InputStream base = connection.getInputStream();
-    
+
     if (base instanceof BufferedInputStream)
       return base;
     else

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/RequestSkinWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/RequestSkinWrapper.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/RequestSkinWrapper.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/RequestSkinWrapper.java Thu Oct 17 15:25:57 2013
@@ -324,6 +324,19 @@ public class RequestSkinWrapper extends 
   {
     return _skin.isDirty();
   }
+
+  @Override
+  public boolean isDirty(boolean checkAncestors)
+  {
+    return _skin.isDirty(checkAncestors);
+  }
+
+  @Override
+  public Skin getBaseSkin()
+  {
+    return _skin.getBaseSkin();
+  }
+
   @Override
   public void setDirty(boolean dirty)
   {

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java Thu Oct 17 15:25:57 2013
@@ -19,6 +19,7 @@
 package org.apache.myfaces.trinidadinternal.skin;
 
 import java.io.IOException;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -26,16 +27,18 @@ import java.util.MissingResourceExceptio
 import java.util.Stack;
 
 import javax.el.ValueExpression;
+
 import javax.faces.context.FacesContext;
-import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+
 import org.apache.myfaces.trinidad.context.LocaleContext;
 import org.apache.myfaces.trinidad.context.RenderingContext;
-import org.apache.myfaces.trinidad.skin.Skin;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.skin.Icon;
+import org.apache.myfaces.trinidad.skin.Skin;
 import org.apache.myfaces.trinidad.skin.SkinAddition;
+import org.apache.myfaces.trinidad.skin.SkinMetadata;
 import org.apache.myfaces.trinidad.skin.SkinVersion;
 import org.apache.myfaces.trinidadinternal.skin.icon.ReferenceIcon;
-
 import org.apache.myfaces.trinidadinternal.style.StyleContext;
 import org.apache.myfaces.trinidadinternal.style.xml.StyleSheetDocumentUtils;
 import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetDocument;
@@ -75,9 +78,9 @@ public class SkinExtension extends SkinI
    *    to be used to translate strings that a renderer renders.
 
    * @throws NullPointerException if baseSkin, id, or family is null.
-   * 
+   *
    */
-   public SkinExtension(
+  public SkinExtension(
      Skin baseSkin,
      String id,
      String family,
@@ -86,35 +89,43 @@ public class SkinExtension extends SkinI
      ValueExpression translationSourceValueExpression,
      SkinVersion version,
      Map<String,String> features,
-     String resourceBundleName 
+     String resourceBundleName
      )
-   {
-     if (baseSkin == null)
-       throw new NullPointerException("Null baseSkin");
-     if (id == null)
-       throw new NullPointerException(_LOG.getMessage(
-         "NULL_SKIN_ID"));
-     if (family == null)
-       throw new NullPointerException("Null family");
-     if (renderKitId == null)
-       renderKitId = _DEFAULT_RENDERKIT;
-     if (version == null)
-       version = SkinVersion.EMPTY_SKIN_VERSION;
-     
-     //Since SkinNodeParser makes sure both the bundle and EL are not set, we 
-     //do not need to do it here
-
-     _baseSkin = (SkinImpl)baseSkin;
-     _id = id;
-     _family = family;
-     _renderKitId = renderKitId;
-     _styleSheetName = styleSheetName;
-     _bundleName = resourceBundleName;
-     _translationSourceVE = translationSourceValueExpression;
-     _version = version;
-     _skinFeatures = features;
-   }  
-  
+  {
+    if (baseSkin == null)
+     throw new NullPointerException("Null baseSkin");
+    if (id == null)
+     throw new NullPointerException(_LOG.getMessage(
+       "NULL_SKIN_ID"));
+    if (family == null)
+     throw new NullPointerException("Null family");
+    if (renderKitId == null)
+     renderKitId = _DEFAULT_RENDERKIT;
+    if (version == null)
+     version = SkinVersion.EMPTY_SKIN_VERSION;
+
+    //Since SkinAdditionParser makes sure both the bundle and EL are not set, we
+    //do not need to do it here
+
+    baseSkin = _ensureBaseSkinType(baseSkin);
+
+    //bundle-name takes precedence over translation-source, prevent both from being set
+    if(resourceBundleName != null && translationSourceValueExpression != null)
+    {
+      translationSourceValueExpression = null;
+    }
+
+    _baseSkin = baseSkin;
+    _id = id;
+    _family = family;
+    _renderKitId = renderKitId;
+    _styleSheetName = styleSheetName;
+    _bundleName = resourceBundleName;
+    _translationSourceVE = translationSourceValueExpression;
+    _version = version;
+    _skinFeatures = features;
+  }
+
   @Deprecated
   public SkinExtension(
     Skin baseSkin,
@@ -152,7 +163,9 @@ public class SkinExtension extends SkinI
     if (version == null)
       version = SkinVersion.EMPTY_SKIN_VERSION;
 
-    _baseSkin = (SkinImpl)baseSkin;
+    baseSkin = _ensureBaseSkinType(baseSkin);
+
+    _baseSkin = baseSkin;
     _id = id;
     _family = family;
     _renderKitId = renderKitId;
@@ -199,7 +212,9 @@ public class SkinExtension extends SkinI
     if (version == null)
       version = SkinVersion.EMPTY_SKIN_VERSION;
 
-    _baseSkin = (SkinImpl)baseSkin;
+    baseSkin = _ensureBaseSkinType(baseSkin);
+
+    _baseSkin = baseSkin;
     _id = id;
     _family = family;
     _renderKitId = renderKitId;
@@ -246,7 +261,9 @@ public class SkinExtension extends SkinI
     if (version == null)
       version = SkinVersion.EMPTY_SKIN_VERSION;
 
-    _baseSkin = (SkinImpl)baseSkin;
+    baseSkin = _ensureBaseSkinType(baseSkin);
+
+    _baseSkin = baseSkin;
     _id = id;
     _family = family;
     _renderKitId = renderKitId;
@@ -268,6 +285,14 @@ public class SkinExtension extends SkinI
     this(baseSkin, id, family, renderKitId, null);
   }
 
+  public SkinExtension(Skin baseSkin, SkinMetadata skinMetadata)
+  {
+    this(baseSkin,
+         skinMetadata.getId(), skinMetadata.getFamily(), skinMetadata.getRenderKitId(),
+          skinMetadata.getStyleSheetName(), skinMetadata.getTranslationSource(), skinMetadata.getVersion(),
+          skinMetadata.getFeatures().getFeatures(), skinMetadata.getResourceBundleName());
+  }
+
 
 
   /**
@@ -576,6 +601,9 @@ public class SkinExtension extends SkinI
     // sheet.
 
     // Get the StyleSheetDocument from the base Skin
+    // we assume the base skin to be of SkinImpl type
+    // we ensure that while creating the SkinExtension object
+    // if something else comes here then it should fail
     SkinImpl baseSkin = (SkinImpl) getBaseSkin();
     StyleSheetDocument baseDocument = baseSkin.getStyleSheetDocument(context);
 
@@ -622,6 +650,23 @@ public class SkinExtension extends SkinI
   }
 
   /**
+   * extracts the skin out if we pass a RequestSkinWrapper
+   * ensures that the baseSkin is of SkinImpl type
+   * @param baseSkin
+   * @return SkinImpl object
+   */
+  private Skin _ensureBaseSkinType(Skin baseSkin)
+  {
+    while (baseSkin instanceof RequestSkinWrapper)
+      baseSkin = ((RequestSkinWrapper) baseSkin).getWrappedSkin();
+
+    if (!(baseSkin instanceof SkinImpl))
+      throw new ClassCastException("Base skin is expected to be of type SkinImpl. Obtain the base skin from SkinProvider.");
+
+    return baseSkin;
+  }
+
+  /**
    * Find the actual icon
    * @param refIcon a ReferenceIcon instance
    * @param referencedIconStack  The stack of reference icon names which have
@@ -719,7 +764,7 @@ public class SkinExtension extends SkinI
   private String          _id;
   private String          _family;
   private String          _renderKitId;
-  private SkinImpl        _baseSkin;
+  private Skin            _baseSkin;
   private String          _styleSheetName;
   private ValueExpression _translationSourceVE;
   private String          _bundleName;

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=1533115&r1=1533114&r2=1533115&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 Thu Oct 17 15:25:57 2013
@@ -18,26 +18,28 @@
  */
 package org.apache.myfaces.trinidadinternal.skin;
 
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.Set;
 
-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.SkinFeatures;
+import org.apache.myfaces.trinidad.skin.SkinMetadata;
+import org.apache.myfaces.trinidad.skin.SkinProvider;
 import org.apache.myfaces.trinidad.skin.SkinVersion;
-import org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl;
 import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlConstants;
+import org.apache.myfaces.trinidadinternal.skin.provider.ExternalSkinProvider;
 
 
 /**
  * Factory for creating Skin objects.
- *
+ * To create and manage skins external to skin framework, use SkinProvider.
+ * @see org.apache.myfaces.trinidad.skin.SkinProvider
  */
 public class SkinFactoryImpl extends SkinFactory
 {
@@ -48,10 +50,45 @@ public class SkinFactoryImpl extends Ski
   public SkinFactoryImpl()
   {
     super();
-    _initalizeSkins();
+  }
+
+  /**
+   * @inheritDoc
+   */
+  @Override
+  public Skin createSkin(FacesContext context, SkinMetadata baseSkinMetadata, SkinMetadata skinMetadata)
+  {
+    if (context == null ||  baseSkinMetadata == null || skinMetadata == null)
+      throw new NullPointerException(_LOG.getMessage("NULL_FC_SKIN_BASE_SKIN_METADATA"));
+
+    if (baseSkinMetadata.getId() != null && !baseSkinMetadata.getId().equals(skinMetadata.getBaseSkinId()))
+      throw new IllegalArgumentException(_LOG.getMessage("INVALID_BASE_SKIN_ID"));
+
+    Skin baseSkin = SkinProvider.getCurrentInstance(context.getExternalContext()).getSkin(context, baseSkinMetadata);
 
+    if (baseSkin == null)
+      throw new IllegalArgumentException(_LOG.getMessage("INVALID_BASE_SKIN"));
+
+    return new SkinExtension(baseSkin, skinMetadata);
   }
-  
+
+  /**
+   * @inheritDoc
+   */
+  @Override
+  public Skin createSkin(FacesContext context, SkinMetadata skinMetadata)
+  {
+    if (context == null || skinMetadata == null)
+      throw new NullPointerException(_LOG.getMessage("NULL_FC_SKIN_METADATA"));
+
+    if (skinMetadata.getBaseSkinId() == null)
+      throw new NullPointerException(_LOG.getMessage("NULL_BASE_SKIN_ID"));
+
+    SkinMetadata baseSkinMetadata = new SkinMetadata.Builder().id(skinMetadata.getBaseSkinId()).build();
+
+    return createSkin(context, baseSkinMetadata, skinMetadata);
+  }
+
    /**
     * <p>Register the specified {@link Skin} instance, associated with
     * the specified <code>skinId</code>, to be supported by this
@@ -63,8 +100,10 @@ public class SkinFactoryImpl extends Ski
     *
     * @param skinId Identifier of the {@link Skin} to register
     * @param skin {@link Skin} instance that we are registering
+    * @deprecated use SkinProvider SPI to deal with externals skins
     */
   @Override
+  @Deprecated
   public  void addSkin(
     String skinId,
     Skin   skin)
@@ -75,21 +114,20 @@ public class SkinFactoryImpl extends Ski
       return;
     }
 
-    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);
-    }
+    SkinMetadata.Builder builder = new SkinMetadata.Builder().id(skinId)
+            .family(skin.getFamily()).version(skin.getVersion())
+            .renderKitId(SkinMetadata.RenderKitId.fromId(skin.getRenderKitId()));
+
+    if (skin.getBaseSkin() != null)
+      builder.baseSkinId(skin.getBaseSkin().getId());
+
+    if (skin.getSkinFeatures() != null)
+      builder.features(new SkinFeatures(skin.getSkinFeatures()));
+
+    Skin previousValue = _getExternalSkinProvider(null).addSkin(builder.build(), skin);
+
+    if (previousValue != null)
+      _LOG.warning("DUPLICATE_ADD_SKIN_TO_SKIN_FACTORY", skinId);
   }
 
 
@@ -98,7 +136,9 @@ public class SkinFactoryImpl extends Ski
    * @param context FacesContext. If not available, pass in null.
    * @param skinId
    * @return Skin that is in this SkinFactory and has the skinId.
+   * @deprecated use SkinProvider to query skins
    */
+  @Deprecated
   @Override
   public Skin getSkin(
     FacesContext context,
@@ -111,22 +151,7 @@ public class SkinFactoryImpl extends Ski
       return null;
     }
 
-    Skin skin = null;
-    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);
-      }
-    }
-
-    return skin;
+    return SkinUtils.getSkinProvider(context).getSkin(context, new SkinMetadata.Builder().id(skinId).build());
   }
 
   /**
@@ -138,7 +163,9 @@ public class SkinFactoryImpl extends Ski
    * XhtmlConstants.APACHE_TRINIDAD_DESKTOP, XhtmlConstants.APACHE_TRINIDAD_PDA, or
    * XhtmlConstants.APACHE_TRINIDAD_PORTLET
    *  {@link Skin} instance
+   * @deprecated use SkinProvider to query skins
    */
+  @Deprecated
   @Override
   public Skin getSkin(
     FacesContext context,
@@ -160,10 +187,12 @@ public class SkinFactoryImpl extends Ski
    * @param family
    * @param renderKitId
    * @param version The version of the skin you want to return. This can be 
-   *                "default", or a version name (e.g., "v1"), or null or "" 
+   *                "default", or a version name (e.g., "v1"), or null or ""
    *                (if you want the skin that does not have a version set).
    * @return the best matched Skin given the family, renderKitId, and version.
+   * @deprecated use SkinProvider to query skins
    */
+  @Deprecated
   @Override
   public Skin getSkin(
     FacesContext context,
@@ -183,231 +212,50 @@ 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)
-      renderKitId = XhtmlConstants.APACHE_TRINIDAD_DESKTOP;
-
-    // loop through each skin in the SkinFactory
-    // and see if the family and the renderKitId match
-    Skin matchingSkin = null;
-    List<Skin> matchingSkinList = new ArrayList<Skin>();
 
-    for(Skin skin : _skins.values())
-    {
-      if (family.equalsIgnoreCase(skin.getFamily()) &&
-          renderKitId.equalsIgnoreCase(skin.getRenderKitId()))
-      {
-        // exact family+renderKitId match!
-        matchingSkinList.add(skin);
-      }
-    }
-    
+    Skin matchingSkin = SkinUtils.getSkinProvider(context).getSkin(context, new SkinMetadata.Builder().
+      family(family).version(new SkinVersion(version)).renderKitId(SkinMetadata.RenderKitId.fromId(renderKitId)).build());
 
-    if (matchingSkinList.isEmpty())
-    {
-      // if we get here, that means we couldn't find an exact
-      // family/renderKitId match, so return the simple skin
-      // that matches the renderkitid.
-       if (_LOG.isWarning())
-       {
-         _LOG.warning("CANNOT_FIND_MATCHING_SKIN", new Object[]{family, renderKitId});
-       }
-
-      if (renderKitId.equals(XhtmlConstants.APACHE_TRINIDAD_PORTLET))
-        matchingSkin = getSkin(context, _SIMPLE_PORTLET);
-      else if (renderKitId.equals(XhtmlConstants.APACHE_TRINIDAD_PDA))
-        matchingSkin = getSkin(context, _SIMPLE_PDA);
-      else
-        matchingSkin = getSkin(context, _SIMPLE_DESKTOP);
-    }
-    else
-    {
-      // at this point we know we have something in the matchingSkinList
-      // which is a list of matching family and renderKitId skins. Now match the version
-      // to find the best matched skin.
-      boolean foundMatchingSkin = false;
-      boolean versionIsDefault = (_DEFAULT.compareToIgnoreCase(version) == 0);
-      // if the user didn't ask for the 'default' version, then look for the exact match
-      if (!versionIsDefault)
-      {
-        for (Skin skin : matchingSkinList)
-        {
-          SkinVersion skinVersion = skin.getVersion();
-          if (skinVersion != null)
-          {
-            String name = skinVersion.getName(); 
-            if (version.equals(name))
-            {
-              matchingSkin = skin;
-              break;
-            }
-          }
-        }          
-      }
-      // matchingSkin will be null if an exact version match (family+renderKitId+exact version) was not found;
-      // we can have an exact version match if the user asks for null version, and we find a skin with no
-      // version set.
-      if (matchingSkin == null || versionIsDefault)
-      {
-        // find skin with version= default
-        matchingSkin = _getDefaultVersionSkin(matchingSkinList);
-
-        if (matchingSkin == null)
-        {
-          // get the last skin in the matchingSkinList if there is no skin marked default.
-          matchingSkin = matchingSkinList.get(matchingSkinList.size() -1);
-        }
-        else if ((matchingSkin != null) && versionIsDefault)
-        {
-          // found the default skin the user wanted
-          foundMatchingSkin = true;
-        }
-      } // end matchingSkin == null || versionIsDefault 
-      else
-      {
-        foundMatchingSkin = true;
-      }
-      // log messages
-      if (foundMatchingSkin)
-      {
-        if (_LOG.isFine())
-          _LOG.fine("GET_SKIN_FOUND_SKIN_VERSION", 
-                    new Object[]{family, version, matchingSkin.getId()}); 
-      }
-      else
-      {        
-        if(_LOG.isWarning())
-        {
-          if ("".equals(version))
-          {
-            _LOG.warning("GET_SKIN_CANNOT_FIND_NO_VERSION", 
-                         new Object[]{family, matchingSkin.getId()});
-          }
-          else
-          {    
-            _LOG.warning("GET_SKIN_CANNOT_FIND_SKIN_VERSION", 
-                         new Object[]{family, version, matchingSkin.getId()}); 
-          }
-        }
-      }
-    }
-    
-    // If we've got a matching skin, wrap it in a RequestSkinWrapper
-    // to provide access to request-specific state.
-    return (matchingSkin == null) ? null : new RequestSkinWrapper(matchingSkin); 
+    return (matchingSkin == null) ? null : new RequestSkinWrapper(matchingSkin);
   }
 
+  /**
+   * @inheritDoc
+   */
+  @Deprecated
   @Override
   public Iterator<String> getSkinIds()
   {
-    return (_skins.keySet().iterator());
-  }
+    Collection<SkinMetadata> metadatas = _getExternalSkinProvider(null).getSkinMetadata(null);
+    Set<String> ids = new HashSet<String>();
 
-  @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");
-        }
-      }
-    }
+    for (SkinMetadata metadata : metadatas)
+      ids.add(metadata.getId());
+
+    return ids.iterator();
   }
 
   /**
-   * 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'.
-   * @return Skin with SkinVersion isDefault true, otherwise, null.
+   * @inheritDoc
    */
-  private Skin _getDefaultVersionSkin(List<Skin> matchingSkinList)
-  {
-    Skin matchingSkin = null;
-    for (Skin skin : matchingSkinList)
-    {
-      SkinVersion skinVersion = skin.getVersion();
-      if (skinVersion != null)
-      {
-        if (skinVersion.isDefault())
-        {
-          matchingSkin = skin;
-          break;
-        }
-      }
-    }
-    return matchingSkin;
-  }
-  
-  private void _initalizeSkins()
+  @Deprecated
+  @Override
+  public void reload()
   {
-    _skins = new LinkedHashMap<String, Skin>();
+    _getExternalSkinProvider(null).reload();
   }
 
-  /**
-   * State of the skins attached to this factory
-   */
-  private enum SkinsState
+  private ExternalSkinProvider _getExternalSkinProvider(FacesContext context)
   {
-    /**
-     * Ready to be used
-     */
-    READY,
-    /**
-     * Marked dirty, reload pending
-     */
-    DIRTY,
-    /**
-     * Reload in progress
-     */
-    RELOADING
+    if (context == null)
+      context = FacesContext.getCurrentInstance();
+
+    if (context == null)
+      throw new NullPointerException("Cannot retrieve FacesContext. FacesContext is null.");
+
+    return ExternalSkinProvider.getCurrentInstance(context.getExternalContext());
   }
 
-  // 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";
-  static private final String _DEFAULT = "default";
   static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(SkinFactoryImpl.class);
 
 }

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java Thu Oct 17 15:25:57 2013
@@ -27,9 +27,7 @@ import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.Set;
-
 import java.util.concurrent.ConcurrentHashMap;
-
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.el.ELContext;
@@ -37,21 +35,17 @@ import javax.el.ValueExpression;
 
 import javax.faces.application.ProjectStage;
 import javax.faces.context.ExternalContext;
-
 import javax.faces.context.FacesContext;
-
 import javax.faces.el.ValueBinding;
 
-import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.context.LocaleContext;
 import org.apache.myfaces.trinidad.context.RenderingContext;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.skin.Icon;
 import org.apache.myfaces.trinidad.skin.Skin;
-
 import org.apache.myfaces.trinidad.skin.SkinAddition;
 import org.apache.myfaces.trinidad.skin.SkinVersion;
 import org.apache.myfaces.trinidadinternal.renderkit.core.CoreRenderingContext;
-import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.StyleSheetRenderer;
 import org.apache.myfaces.trinidadinternal.share.config.Configuration;
 import org.apache.myfaces.trinidadinternal.skin.icon.ReferenceIcon;
 import org.apache.myfaces.trinidadinternal.style.StyleContext;
@@ -273,6 +267,7 @@ abstract public class SkinImpl extends S
    * @param skinAddition The SkinAddition object to add to the Skin.
    * @throws NullPointerException if SkinAddition is null.
    */
+  @Override
   public void addSkinAddition (
     SkinAddition skinAddition
     )
@@ -294,6 +289,7 @@ abstract public class SkinImpl extends S
    * @return List an unmodifiable List of SkinAdditions.
    * @see #addSkinAddition(SkinAddition)
    */
+  @Override
   public List<SkinAddition> getSkinAdditions()
   {
     if (_skinAdditions == null)
@@ -338,6 +334,7 @@ abstract public class SkinImpl extends S
    * styles for this Skin, including any styles that are
    * contributed by skin-additions.
    */
+  @Override
   public StyleSheetDocument getStyleSheetDocument(StyleContext context)
   {
     // We synchronize here because technically speaking multiple
@@ -389,6 +386,7 @@ abstract public class SkinImpl extends S
    * @see #addSkinAddition(SkinAddition)
    * @deprecated Use addSkinAddition instead
    */
+  @Override
   public void registerStyleSheet(String styleSheetName)
   {
     //TODO Take out deprecated after sufficient amount of time has passed
@@ -398,21 +396,51 @@ abstract public class SkinImpl extends S
   }
   
   /**
-   * Check to see if this Skin has been marked dirty. 
+   * Check to see if this Skin has been marked dirty.
    * The only way to mark a Skin dirty is to call setDirty(true).
-   * @return true if the Skin is marked dirty. 
-   * 
+   * @return true if the Skin is marked dirty.
+   *
    */
   @Override
   public boolean isDirty()
   {
-    return _dirty;
+    return isDirty(false);
+  }
+
+
+  /**
+   * Check to see if this Skin is dirty with an optional check if any of its ancestor skins is dirty
+   * The only way to mark a Skin dirty is to call setDirty(true).
+   * @param checkAncestors, option to check if any ancestor skins are dirty
+   * @return true if the Skin is dirty, or optionally if any of its ancestor skins is dirty.
+   * @SuppressWarnings("deprecation")
+   */
+  @Override
+  public boolean isDirty(boolean checkAncestors)
+  {
+    // irrespective of the flag, if this skin is dirty then return true
+    if (_dirty)
+      return true;
+
+    // now we know that current skin is not dirty, so see if any parent is dirty only if the
+    // checkAncestors flag is set
+    if (checkAncestors)
+    {
+      Skin baseSkin = getBaseSkin();
+
+      if (baseSkin != null)
+      {
+        return baseSkin.isDirty(checkAncestors);
+      }
+    }
+
+    return false;
   }
 
   /**
-   * Sets the dirty flag of the Skin. Use this if you want to regenerate the skin. 
-   * During rendering, if isDirty is true, 
-   * the skin's css file will be reprocessed regardless of whether the css file has been modified 
+   * Sets the dirty flag of the Skin. Use this if you want to regenerate the skin.
+   * During rendering, if isDirty is true,
+   * the skin's css file will be reprocessed regardless of whether the css file has been modified
    * or if the CHECK_FILE_MODIFICATION flag was set. 
    * The Skinning Framework calls setDirty(false) after the skin has been reprocessed.
    */

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=1533115&r1=1533114&r2=1533115&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 Thu Oct 17 15:25:57 2013
@@ -31,14 +31,11 @@ import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
 
-import javax.el.ValueExpression;
-
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 
@@ -46,23 +43,16 @@ import org.apache.myfaces.trinidad.conte
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.resource.SkinResourceLoader;
 import org.apache.myfaces.trinidad.share.io.NameResolver;
+import org.apache.myfaces.trinidad.skin.CustomMetadata;
 import org.apache.myfaces.trinidad.skin.Icon;
 import org.apache.myfaces.trinidad.skin.Skin;
 import org.apache.myfaces.trinidad.skin.SkinAddition;
-import org.apache.myfaces.trinidad.skin.SkinFactory;
+import org.apache.myfaces.trinidad.skin.SkinFeatures;
+import org.apache.myfaces.trinidad.skin.SkinMetadata;
+import org.apache.myfaces.trinidad.skin.SkinProvider;
 import org.apache.myfaces.trinidad.skin.SkinVersion;
 import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
-import org.apache.myfaces.trinidadinternal.config.LazyValueExpression;
 import org.apache.myfaces.trinidadinternal.renderkit.core.CoreRenderingContext;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.CasablancaDesktopSkin;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.CasablancaPdaSkin;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.CasablancaPortletSkin;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.MinimalDesktopSkinExtension;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.MinimalPdaSkinExtension;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.MinimalPortletSkinExtension;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.SimpleDesktopSkin;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.SimplePdaSkin;
-import org.apache.myfaces.trinidadinternal.renderkit.core.skin.SimplePortletSkin;
 import org.apache.myfaces.trinidadinternal.share.xml.ClassParserFactory;
 import org.apache.myfaces.trinidadinternal.share.xml.ParseContextImpl;
 import org.apache.myfaces.trinidadinternal.share.xml.ParserFactory;
@@ -71,13 +61,9 @@ import org.apache.myfaces.trinidadintern
 import org.apache.myfaces.trinidadinternal.share.xml.XMLProvider;
 import org.apache.myfaces.trinidadinternal.share.xml.XMLUtils;
 import org.apache.myfaces.trinidadinternal.skin.icon.ReferenceIcon;
-import org.apache.myfaces.trinidadinternal.skin.parse.SkinAdditionNode;
-import org.apache.myfaces.trinidadinternal.skin.parse.SkinFeaturesNode;
-import org.apache.myfaces.trinidadinternal.skin.parse.SkinNode;
-import org.apache.myfaces.trinidadinternal.skin.parse.SkinVersionNode;
 import org.apache.myfaces.trinidadinternal.skin.parse.SkinsNode;
 import org.apache.myfaces.trinidadinternal.skin.parse.XMLConstants;
-
+import org.apache.myfaces.trinidadinternal.skin.provider.ExternalSkinProvider;
 import org.apache.myfaces.trinidadinternal.style.StyleContext;
 
 import org.xml.sax.InputSource;
@@ -91,131 +77,66 @@ import org.xml.sax.InputSource;
  */
 public class SkinUtils
 {
-
-  /**
-   * Register the base skins with the SkinFactory. (simple/minimal)
-   * Make sure the SkinFactory.getFactory() does not return null before
-   * calling this method.
-   */
-  static public void registerBaseSkins()
+  static public SkinProvider getSkinProvider(FacesContext context)
   {
+    if (context == null)
+      context = FacesContext.getCurrentInstance();
 
-    SkinFactory skinFactory = SkinFactory.getFactory();
-
-    // skinFactory should be non-null when this is called since it is
-    // initiated in the TrinidadFilterImpl, but in case it isn't do this
-    if (skinFactory == null)
-    {
-      SkinFactory.setFactory(new SkinFactoryImpl());
-      skinFactory = SkinFactory.getFactory();
-    }
+    if (context == null)
+      throw new NullPointerException("Cannot retrieve FacesContext. FacesContext is null.");
 
-    _registerTrinidadSkins(skinFactory);
+    return SkinProvider.getCurrentInstance(context.getExternalContext());
   }
 
-  /**
-   * 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)
+  static public SkinProvider getExternalSkinProvider(FacesContext context)
   {
-    boolean fine = _LOG.isFine();
-    if (fine) _LOG.fine("Begin registerSkinExtensions");
-    _registerSkinExtensionsAndAdditions(context, skinFactory);
-    if (fine) _LOG.fine("End registerSkinExtensions");
+    if (context == null)
+      context = FacesContext.getCurrentInstance();
+
+    if (context == null)
+      throw new NullPointerException("Cannot retrieve FacesContext. FacesContext is null.");
+
+    return ExternalSkinProvider.getCurrentInstance(context.getExternalContext());
   }
 
   /**
-   * 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
-   * calling this method.
-   * You should call registerBaseSkins() before calling this method.
-   * @param context ServletContext, used to get the trinidad-skins.xml file.
+   * Builds the SkinMetadata hierarchy from trinidad-skins.xml
+   * @return
    */
-  static public void registerSkinExtensions(
-    ExternalContext context)
+  static public List<SkinsNode> buildSkinsNodes(ExternalContext extCtxt)
   {
+    List<SkinsNode> metaInfSkinsNode = _getMetaInfSkinsNodeList();
+    SkinsNode webInfSkinsNode = _getWebInfSkinsNode(extCtxt);
+    List<SkinsNode> resourceLoaderSkinsNodes = _getSkinsNodesFromSkinResourceLoaderServices(extCtxt);
 
-    SkinFactory skinFactory = SkinFactory.getFactory();
+    List<SkinsNode> skinsNodes = new ArrayList<SkinsNode>(20);
 
-    // skinFactory should be non-null when this is called since it is
-    // initiated in the TrinidadFilterImpl, but in case it isn't do this
-    if (skinFactory == null)
-    {
-      SkinFactory.setFactory(new SkinFactoryImpl());
-      skinFactory = SkinFactory.getFactory();
-    }
-    
-    registerSkinExtensions(context, skinFactory);
+    if (metaInfSkinsNode != null)
+      skinsNodes.addAll(metaInfSkinsNode);
+
+    if (webInfSkinsNode != null)
+      skinsNodes.add(webInfSkinsNode);
+
+    if (resourceLoaderSkinsNodes != null)
+      skinsNodes.addAll(resourceLoaderSkinsNodes);
+
+    return skinsNodes;
   }
 
+
   /**
    * Returns the actual Icon referenced by the ReferenceIcon.
    * @param skin the Skin to use when resolving the ReferenceIcon
    * @param refIcon a ReferenceIcon instance
    * @return icon which is resolved. i.e., it is not a ReferenceIcon.
    */
-   static public Icon resolveReferenceIcon(
-     Skin          skin,
-     ReferenceIcon refIcon)
-   {
-     return _resolveReferenceIcon(skin, refIcon, null);
-   }
-
-  /**
-   * Helper for resolveReferenceIcon which uses a Stack of icon names
-   * to detect circular dependencies.
-   *
-   * @param skin the Skin to use when resolving the ReferenceIcon
-   * @param refIcon a ReferenceIcon instance
-   * @param referencedIconStack  The stack of reference icon names which have
-   *          already been visited.  Used to detect circular dependencies.
-   * @return icon which is resolved. i.e., it is not a ReferenceIcon.
-   */
-  static private Icon _resolveReferenceIcon(
-    Skin          skin,
-    ReferenceIcon refIcon,
-    Stack<String> referencedIconStack)
+  static public Icon resolveReferenceIcon(
+   Skin          skin,
+   ReferenceIcon refIcon)
   {
-    String refName = refIcon.getName();
-
-    // make sure we don't have a circular dependency
-    if ((referencedIconStack != null) && referencedIconStack.contains(refName))
-    {
-      if (_LOG.isWarning())
-        _LOG.warning("SKIN_CIRCULAR_INCLUDE_ERROR", refName);
-      return null;
-    }
-
-    if (referencedIconStack == null)
-    {
-      referencedIconStack = new Stack<String>();
-    }
-
-    referencedIconStack.push(refName);
-
-    Icon icon = skin.getIcon(refName, false);
-
-    if ((icon instanceof ReferenceIcon) && (icon != null))
-    {
-
-      return _resolveReferenceIcon(skin,
-                                  (ReferenceIcon)icon,
-                                  referencedIconStack);
-
-    }
-
-    return icon;
+   return _resolveReferenceIcon(skin, refIcon, null);
   }
-  
+
   public static String getSkinDebugInfo(Skin skin)
   {
     assert (null != skin);
@@ -288,6 +209,43 @@ public class SkinUtils
   }
 
   /**
+   * Get all the META-INF/trinidad-skins.xml files, parse them, and from each file we get
+   * a SkinsNode object -- the information inside the &lt;skins&gt; element -- each skin
+   * and each skin-addition.
+   * @return Each SkinsNode object we get from each META-INF/trinidad-skins.xml file,
+   * in a List<SkinsNode>.
+   */
+  private static List<SkinsNode> _getMetaInfSkinsNodeList()
+  {
+    List<SkinsNode> allSkinsNodes = new ArrayList<SkinsNode>();
+    ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+    try
+    {
+      Enumeration<URL> urls = loader.getResources(_META_INF_CONFIG_FILE);
+      Set<String> urlPaths = new HashSet<String>(16);
+
+      while (urls.hasMoreElements())
+      {
+        URL url = urls.nextElement();
+
+        // if url matches one we've already processed, skip it
+        boolean successfullyAdded = urlPaths.add(url.getPath());
+        // _processTrinidadSkinsURL logs the url we are processing
+        _processTrinidadSkinsURL(allSkinsNodes, url, successfullyAdded);
+      }
+    }
+    catch (IOException e)
+    {
+      _LOG.severe("ERR_LOADING_FILE", _META_INF_CONFIG_FILE);
+      _LOG.severe(e);
+    }
+
+    return allSkinsNodes;
+  }
+
+
+  /**
    * Create a SkinExtension off a generic SAX input source, using
    * a custom parsing manager.
    * <p>
@@ -310,14 +268,15 @@ public class SkinUtils
    * @param parserManager the ParserManager to use for parsing
    *                Must  be non-null.
    * @param configFile The name of the config file we are parsing.
-   * @return A SkinsNode object (contains a List of SkinNode and a List of SkinAdditionNode)
+   * @return A SkinsNode object (contains a List of SkinMetadata and a List of SkinAddition)
    */
   static private SkinsNode _getSkinsNodeFromInputStream(
     XMLProvider        provider,
     NameResolver       resolver,
     InputStream        inputStream,
     ParserManager      parserManager,
-    String             configFile
+    String             configFile,
+    boolean            isMetaInf
     )
   {
 
@@ -336,6 +295,11 @@ public class SkinUtils
 
       ParseContextImpl context = new ParseContextImpl();
 
+      // set a property on the parse context so that we can modify the stylesheet name
+      // while creating SkinMetadata or SkinAddition
+      if (isMetaInf)
+        context.setProperty(XMLConstants.SKIN_NAMESPACE, XMLConstants.META_INF, isMetaInf);
+
       // Set up the NameResolver if we have one
       if (resolver != null)
         XMLUtils.setResolver(context, resolver);
@@ -345,6 +309,8 @@ public class SkinUtils
                                             SkinsNode.class);
       skinsNode = ((SkinsNode)builder.parse(provider, input, context));
 
+      if (isMetaInf)
+        context.setProperty(XMLConstants.SKIN_NAMESPACE, XMLConstants.META_INF, null);
     }
     catch (Exception e)
     {
@@ -378,10 +344,12 @@ public class SkinUtils
      _registerFactory(manager, SkinsNode.class, "SkinsNode");
 
     // Register skin node factory and skin addition node factory
-    _registerFactory(manager, SkinNode.class, "SkinNode");
-    _registerFactory(manager, SkinAdditionNode.class, "SkinAdditionNode");
-    _registerFactory(manager, SkinVersionNode.class, "SkinVersionNode");
-    _registerFactory(manager, SkinFeaturesNode.class, "SkinFeaturesNode");
+    _registerFactory(manager, SkinMetadata.class, "SkinMetadata");
+    _registerFactory(manager, SkinAddition.class, "SkinAddition");
+    // TODO: change the parser names
+    _registerFactory(manager, SkinVersion.class, "SkinVersion");
+    _registerFactory(manager, SkinFeatures.class, "SkinFeatures");
+    _registerFactory(manager, CustomMetadata.class, "CustomMetadata");
 
     return manager;
   }
@@ -411,364 +379,6 @@ public class SkinUtils
   }
 
   /**
-   * register the Trinidad skins: simpleDesktopSkin, simplePdaSkin,
-   * and minimalDesktopSkin, minimalPdaSkin, casablancaSkin and portlet skins.
-   * @param skinFactory
-   */
-  private static void _registerTrinidadSkins(
-    SkinFactory skinFactory)
-  {
-    // SimpleDesktopSkin is the BASE skin for org.apache.myfaces.trinidad.desktop renderKit
-    // SimplePdaSkin is the BASE skin for org.apache.myfaces.trinidad.pda renderKit. By
-    // BASE skin, I mean, this is the skin that all SkinExtensions extend
-    // from.
-    SimpleDesktopSkin simpleDesktopSkin = new SimpleDesktopSkin();
-    skinFactory.addSkin(simpleDesktopSkin.getId(), simpleDesktopSkin);
-
-    SimplePdaSkin simplePdaSkin = new SimplePdaSkin();
-    skinFactory.addSkin(simplePdaSkin.getId(), simplePdaSkin);
-    //portlet skin maps most of our style classes to portlet style classes,
-    // so we output portlet style classes.
-    // It also clears out the portlet style class definitions.
-    SimplePortletSkin simplePortletSkin = new SimplePortletSkin();
-    skinFactory.addSkin(simplePortletSkin.getId(), simplePortletSkin);
-
-    MinimalDesktopSkinExtension minimalDesktopSkin =
-      new MinimalDesktopSkinExtension(simpleDesktopSkin);
-    skinFactory.addSkin(minimalDesktopSkin.getId(), minimalDesktopSkin);
-
-    MinimalPdaSkinExtension minimalPdaSkin =
-      new MinimalPdaSkinExtension(simplePdaSkin);
-    skinFactory.addSkin(minimalPdaSkin.getId(), minimalPdaSkin);
-
-    MinimalPortletSkinExtension minimalPortletSkin =
-      new MinimalPortletSkinExtension(simplePortletSkin);
-    skinFactory.addSkin(minimalPortletSkin.getId(), minimalPortletSkin);
-
-    CasablancaDesktopSkin casablancaDesktopSkin = new CasablancaDesktopSkin(simpleDesktopSkin);
-    skinFactory.addSkin(casablancaDesktopSkin.getId(), casablancaDesktopSkin);
-
-    CasablancaPdaSkin casablancaPdaSkin = new CasablancaPdaSkin(simplePdaSkin);
-    skinFactory.addSkin(casablancaPdaSkin.getId(), casablancaPdaSkin);
-
-    CasablancaPortletSkin casablancaPortletSkin = new CasablancaPortletSkin(simplePortletSkin);
-    skinFactory.addSkin(casablancaPortletSkin.getId(), casablancaPortletSkin);
-  }
-
-  /**
-   * Parse the trinidad-skins.xml file for SkinExtensions and SkinAdditionNodes and add each
-   * SkinExtension to the skinFactory and each SkinAddition to its skin.
-   * First find all the trinidad-skins.xml files that are in META-INF directory, and
-   * add those skins and skin additions.
-   * Then find the WEB-INF/trinidad-skins.xml file and add those skins and skin additions.
-   * The skins are ordered so that the 'extended' skins are registered before the skins that extend
-   * them.
-   * @param context
-   * @param skinFactory
-   */
-  private static void _registerSkinExtensionsAndAdditions(
-    ExternalContext context,
-    SkinFactory skinFactory)
-  {
-    if (context == null)
-      return;
-
-    // Add META-INF/trinidad-skins.xml skins to skin factory. (sorted first to make sure
-    // we register the most 'base' skins first)
-    if (_LOG.isFine()) _LOG.fine("Parse META-INF/trinidad-skins.xml files");
-    List<SkinsNode> metaInfSkinsNodeList = _getMetaInfSkinsNodeList();
-    // Go through each SkinsNode object
-    // (contains List of SkinNodes and List of SkinAdditionNodes)
-    // and return a List of the SkinNodes.
-    List<SkinNode> metaInfSkinNodes = new ArrayList<SkinNode>();
-    for (SkinsNode skinsNode : metaInfSkinsNodeList)
-    {
-      List<SkinNode> skinNodes = skinsNode.getSkinNodes();
-      if (skinNodes != null)
-        metaInfSkinNodes.addAll(skinNodes);
-    }
-
-    List<SkinNode> sortedMetaInfSkinNodes = _sortSkinNodes(skinFactory, metaInfSkinNodes);
-
-    for (SkinNode skinNode : sortedMetaInfSkinNodes)
-    {
-      _addSkinToFactory(skinFactory, skinNode, true);
-    }
-
-    // Add WEB-INF/trinidad-skins.xml skins to skin factory. (sorted first)
-    if (_LOG.isFine()) _LOG.fine("Parse WEB-INF/trinidad-skins.xml files");
-    SkinsNode webInfSkinsNode = _getWebInfSkinsNode(context);
-    if (webInfSkinsNode != null)
-    {
-      List<SkinNode> webInfSkinNodes = webInfSkinsNode.getSkinNodes();
-
-      List<SkinNode> sortedWebInfSkinNodes = _sortSkinNodes(skinFactory, webInfSkinNodes);
-
-      // register skins found in webInfSkinNodes
-      for (SkinNode skinNode : sortedWebInfSkinNodes)
-      {
-        _addSkinToFactory(skinFactory, skinNode, false);
-      }
-    }
-
-    // register all the skin additions from META-INF trinidad-skins.xml and WEB-INF
-    // trinidad-skins.xml that we have stored in the metaInfSkinsNodeList object and the
-    // webInfSkinsNode object
-    // skin-additions are additions to a skin, not extensions. They are used by
-    // custom component developers that want to add a stylesheet for their components
-    // to a particular skin, like the simple skin.
-    FacesContext fContext = FacesContext.getCurrentInstance();
-    // register skin-additions from META-INF/trinidad-skins.xml files
-    _registerMetaInfSkinAdditions(fContext, skinFactory, metaInfSkinsNodeList);
-
-    // register skin-additions from WEB-INF/trinidad-skins.xml file
-    if (webInfSkinsNode != null)
-    {
-      List<SkinAdditionNode> skinAdditionNodeList = webInfSkinsNode.getSkinAdditionNodes();
-      _registerSkinAdditions(fContext, skinFactory, skinAdditionNodeList, false);
-    }
-
-    _registerTrinidadSkinsFromSkinResourceLoaderServices(context, skinFactory);
-
-
-  }
-
-  // this finds the trinidad-skins.xml files by calling findResource on any SkinResourceLoader
-  // services. This is used by the DT to find trinidad-skins.xml files that are not in META-INF
-  // or WEB-INF. See TRINIDAD-1914
-  private static void _registerTrinidadSkinsFromSkinResourceLoaderServices(
-    ExternalContext context,
-    SkinFactory skinFactory)
-  {
-     if (_LOG.isFine()) _LOG.fine("Parse SkinResourceLoader trinidad-skins.xml");
-    // register skins found in DT using the META-INF/services
-    List<SkinResourceLoader> urlProviders = ClassLoaderUtils.getServices(
-                                      "org.apache.myfaces.trinidad.resource.SkinResourceLoader");
-    if (urlProviders != null && !urlProviders.isEmpty())
-    {
-      List<SkinsNode> additionalSkins = _getAdditionalTrinidadSkins(context, urlProviders);
-
-      // Go through each SkinsNode object
-      // (contains List of SkinNodes and List of SkinAdditionNodes)
-      // and return a List of the SkinNodes.
-      List<SkinNode> additionalSkinNodeList = new ArrayList<SkinNode>();
-      for (SkinsNode skinsNode : additionalSkins)
-      {
-        additionalSkinNodeList.addAll(skinsNode.getSkinNodes());
-      }
-
-      List<SkinNode> sortedAdditionalSkinNodes = _sortSkinNodes(skinFactory, additionalSkinNodeList);
-
-      for (SkinNode skinNode : sortedAdditionalSkinNodes)
-      {
-        if (_LOG.isFine()) _LOG.fine("Skin {0} with stylesheet {1}",
-                                     new Object[]{skinNode.getId(), skinNode.getStyleSheetName()});
-        _addSkinToFactory(skinFactory, skinNode, false);
-      }
-    }
-  }
-
-  /**
-   * Given the a List of SkinNodes, sort them so that the SkinNodes in such a way so that
-   * when we register the skins we make sure that the 'base' skins are registered before
-   * skins that extend them.
-   * @param skinFactory
-   * @param skinNodes
-   * @return sorted List of SkinNodes
-   */
-  private static List<SkinNode> _sortSkinNodes(
-    SkinFactory    skinFactory,
-    List<SkinNode> skinNodes)
-  {
-    List<SkinNode> sortedSkinNodes = new ArrayList<SkinNode>();
-    List<String>   skinNodesAdded = new ArrayList<String>();
-    List<String>   baseSkinIds = new ArrayList<String>();
-    for (Iterator<String> i = skinFactory.getSkinIds(); i.hasNext();)
-    {
-       baseSkinIds.add(i.next());
-    }
-
-    // first, the skins that don't extend anything
-    for (SkinNode skinNode : skinNodes)
-    {
-      String skinExtends = skinNode.getSkinExtends();
-
-      if (skinExtends == null)
-      {
-        sortedSkinNodes.add(skinNode);
-        skinNodesAdded.add(skinNode.getId());
-      }
-    }
-
-    // second, the skins that extend another skin
-    _sortSkinNodesWithExtensions(skinNodes, sortedSkinNodes, skinNodesAdded, baseSkinIds, 0);
-
-    return sortedSkinNodes;
-
-  }
-
-  /**
-   * This sorts SkinNodes that have their 'extends' value set, which means the skin
-   * extends another skin. The order of our skin nodes matters in this case. We want the
-   * base skin to be registered first.
-   * @param skinNodes
-   * @param sortedSkinNodes
-   * @param skinNodesAdded
-   * @param baseSkinIds
-   */
-  private static void _sortSkinNodesWithExtensions(
-    List<SkinNode> skinNodes,
-    List<SkinNode> sortedSkinNodes,
-    List<String>   skinNodesAdded,
-    List<String>   baseSkinIds,
-    int            originalLeftOverListSize)
-  {
-    List<SkinNode> leftOverList = new ArrayList<SkinNode>();
-
-    for (SkinNode skinNode : skinNodes)
-    {
-      String skinExtends = skinNode.getSkinExtends();
-
-      if (skinExtends != null)
-      {
-        if (skinNodesAdded.contains(skinExtends) ||
-            baseSkinIds.contains(skinExtends))
-        {
-          sortedSkinNodes.add(skinNode);
-          skinNodesAdded.add(skinNode.getId());
-        }
-        else
-        {
-          // left over, put in a left-over list
-          leftOverList.add(skinNode);
-        }
-      }
-    }
-    if ((originalLeftOverListSize > 0) &&
-         (leftOverList.size() == originalLeftOverListSize))
-    {
-      // Ok, we are left with skinNodes that cannot be registered because the skin they extend is
-      // not in the skinNodesAdded List. The skin they extend might not exist at all, or
-      // there is a circular dependency.
-      // So..., just add these to the list. When we register these, they will cause a severe error
-      // and the default base skin will be used.
-       StringBuffer buffer = new StringBuffer();
-       for (SkinNode leftOverNode : leftOverList)
-       {
-         buffer.append("Skin with id: " + leftOverNode.getId() +
-                      " extends skin with id: " + leftOverNode.getSkinExtends() + "\n");
-         sortedSkinNodes.add(leftOverNode);
-         skinNodesAdded.add(leftOverNode.getId());
-
-       }
-      _LOG.warning("The following skins extend each other in a circular " +
-                   "fashion or the skin they extend does not exist.\n" + buffer.toString());
-
-    }
-    else  if (leftOverList.size() > 0)
-    {
-      _sortSkinNodesWithExtensions(leftOverList, sortedSkinNodes,
-                                   skinNodesAdded, baseSkinIds, leftOverList.size());
-    }
-  }
-
-  /**
-   * Given a skinNode, create a Skin object and
-   * register the SkinExtension object with the skinFactory
-   * @param skinFactory
-   * @param skinNode
-   */
-  private static void _addSkinToFactory(
-      SkinFactory skinFactory,
-      SkinNode    skinNode,
-      boolean     isMetaInfFile)
-  {
-    //Moved to using a builder/director to avoid creating yet another overloaded constuctor
-    SkinExtensionDirector skinDirector = SkinUtils.createSkinExtensionDirector();
-    String renderKitId = skinNode.getRenderKitId();
-    skinDirector.setRenderKitIdPart(renderKitId);
-    skinDirector.setIdPart(skinNode.getId());
-    
-    skinDirector.setFamilyPart(skinNode.getFamily());
-    skinDirector.setStyleSheetNameAndIsMetaInf(skinNode.getStyleSheetName(), 
-                                              isMetaInfFile);
-    skinDirector.setResourceBundleNamePart(skinNode.getBundleName());
-    skinDirector.setTranslationSourcePart(skinNode.getTranslationSourceExpression());
-    SkinVersionNode skinVersionNode = skinNode.getSkinVersionNode();
-    if(skinVersionNode != null)
-    {
-     skinDirector.setSkinVersionPart(_createSkinVersion(skinVersionNode));
-    }
-    
-    SkinFeaturesNode featuresNode = skinNode.getSkinFeatures();
-    if(featuresNode!=null)
-    {
-     skinDirector.setSkinFeaturesPart(featuresNode.getSkinFeatures());
-    }
-    
-    String baseSkinName = skinNode.getSkinExtends(); 
-    Skin base = null;
-    if (baseSkinName != null)
-     base = skinFactory.getSkin(null, baseSkinName);
-    if (base == null)
-    {
-     base = _getDefaultBaseSkin(skinFactory, renderKitId);
-     
-     if (baseSkinName != null)
-     {
-       _LOG.severe("UNABLE_LOCATE_BASE_SKIN", 
-                   new String[]{baseSkinName, skinNode.getId(), 
-                                skinNode.getFamily(), renderKitId, 
-                                base.getId()});
-     }
-    }
-    skinDirector.setBaseSkinPart(base);
-    
-    // Put all the pieces together
-    Skin skin = skinDirector.produceSkinExtension();
-    
-    // Create a SkinExtension object and register skin with factory
-    skinFactory.addSkin(skin.getId(), skin);    
-  }
-       
-  private static SkinExtensionDirector createSkinExtensionDirector()
-  {
-    return new SkinExtensionDirector();
-  }
-         
-  private static ValueExpression
-  _createTranslationSourceValueExpression(
-    String translationSourceExpression)
-  {
-      if (translationSourceExpression != null)
-      {
-        translationSourceExpression = translationSourceExpression.trim();
-
-        return LazyValueExpression.createValueExpression(translationSourceExpression,
-                                                         Object.class);
-      }
-      else
-        return null;
-
-  }
-
-  // Create a SkinVersion object from the SkinVersionNode object.
-  private static SkinVersion _createSkinVersion(SkinVersionNode skinVersionNode)
-  {
-    if (skinVersionNode != null)
-    {
-      String name = skinVersionNode.getName();
-      boolean isDefault = skinVersionNode.isDefault();
-      if ("".equals(name) && !isDefault)
-         return SkinVersion.EMPTY_SKIN_VERSION;
-      else
-        return new SkinVersion(name, isDefault);
-    }
-    else
-      return SkinVersion.EMPTY_SKIN_VERSION;
-  }
-
-  /**
    * Get the WEB-INF/trinidad-skins.xml file, parse it, and return a List of SkinsNode objects.
    * @param context ServletContext used to getResourceAsStream
    * @return List of SkinNodes (skin elements) found in trinidad-skins.xml
@@ -780,15 +390,15 @@ public class SkinUtils
     if (in != null)
     {
       SkinsNode webInfSkinsNode =
-        _getSkinsNodeFromInputStream(null, null, in, _getDefaultManager(), _CONFIG_FILE);
+        _getSkinsNodeFromInputStream(null, null, in, _getDefaultManager(), _CONFIG_FILE, false);
       if (_LOG.isFine())
       {
-        for (SkinNode node : webInfSkinsNode.getSkinNodes())
+        for (SkinMetadata node : webInfSkinsNode.getSkinNodes())
         {
           _LOG.fine("Skin {0} with stylesheet {1}",
                     new Object[]{node.getId(), node.getStyleSheetName()});
         }
-        for (SkinAdditionNode node: webInfSkinsNode.getSkinAdditionNodes())
+        for (SkinAddition node: webInfSkinsNode.getSkinAdditionNodes())
         {
           _LOG.fine("SkinAddition {0} with stylesheet {1}",
                       new Object[]{node.getSkinId(), node.getStyleSheetName()});
@@ -804,174 +414,36 @@ public class SkinUtils
   }
 
   /**
-   * Get all the META-INF/trinidad-skins.xml files, parse them, and from each file we get
-   * a SkinsNode object -- the information inside the &lt;skins&gt; element -- each skin
-   * and each skin-addition.
-   * @return Each SkinsNode object we get from each META-INF/trinidad-skins.xml file,
-   * in a List<SkinsNode>.
+   * Looks for SPIs registered in META-INF/services folder with file
+   * name "org.apache.myfaces.trinidad.resource.SkinResourceLoader".
+   * Loads the trinidad-skins.xml exposed by these resource loades by calling findResource().
+   * Creates SkinsNodes and returns
+   *
+   * @param context
+   * @return list of SkinsNode representing trinidad-skins.xml loaded using SkinResourceLoader SPI
    */
-  private static List<SkinsNode> _getMetaInfSkinsNodeList()
-  {
-
-    List<SkinsNode> allSkinsNodes = new ArrayList<SkinsNode>();
-    ClassLoader loader = Thread.currentThread().getContextClassLoader();
-
-    try
-    {
-
-      Enumeration<URL> urls = loader.getResources(_META_INF_CONFIG_FILE);
-      Set<String> urlPaths = new HashSet<String>(16);
-
-      while (urls.hasMoreElements())
-      {
-        URL url = urls.nextElement();
-
-        // if url matches one we've already processed, skip it
-        boolean successfullyAdded = urlPaths.add(url.getPath());
-        // _processTrinidadSkinsURL logs the url we are processing
-        _processTrinidadSkinsURL(allSkinsNodes, url, successfullyAdded);
-
-
-      }
-    }
-    catch (IOException e)
-    {
-      _LOG.severe("ERR_LOADING_FILE", _META_INF_CONFIG_FILE);
-      _LOG.severe(e);
-    }
-
-    return allSkinsNodes;
-  }
-
-  private static Skin _getDefaultBaseSkin(
-    SkinFactory factory,
-    String      renderKitId)
-  {
-
-    String baseSkinId = (_RENDER_KIT_ID_PDA.equals(renderKitId)) ?
-                          _SIMPLE_PDA_SKIN_ID :
-                          _SIMPLE_DESKTOP_SKIN_ID;
-
-    Skin baseSkin = factory.getSkin(null, baseSkinId);
-
-    // It is an error if we were unable to find the base skin
-    if (baseSkin == null)
-      _LOG.severe(_UNKNOWN_BASE_SKIN_ERROR + baseSkinId);
-
-    return baseSkin;
-  }
-
-  // register the META-INF skin additions.
-  // It should not matter what order we process skin-additions since they should not
-  // depend upon one another.
-  // We sort them by style-sheet-name so the StyleSheetDocumentId will be the same regardless
-  // of order. Portals are using the styleSheetDocumentId to determine if the producer's skin
-  // matches the consumer's skin, and the order of the skin-additions should not change this.
-  private static void _registerMetaInfSkinAdditions(
-    FacesContext    fContext,
-    SkinFactory     skinFactory,
-    List<SkinsNode> metaInfSkinsNodeList)
+  private static List<SkinsNode> _getSkinsNodesFromSkinResourceLoaderServices(ExternalContext context)
   {
-    List<SkinAdditionNode> skinAdditionNodeList = new ArrayList<SkinAdditionNode>();
-
-    for (SkinsNode skinsNode : metaInfSkinsNodeList)
+     if (_LOG.isFine()) _LOG.fine("Parse SkinResourceLoader trinidad-skins.xml");
+    // register skins found in DT using the META-INF/services
+    List<SkinResourceLoader> urlProviders = ClassLoaderUtils.getServices(
+                                      "org.apache.myfaces.trinidad.resource.SkinResourceLoader");
+    if (urlProviders != null && !urlProviders.isEmpty())
     {
-      skinAdditionNodeList.addAll(skinsNode.getSkinAdditionNodes());
+      return _getResourceLoadedTrinidadSkins(context, urlProviders);
     }
 
-    Collections.sort(skinAdditionNodeList);
-    _registerSkinAdditions(fContext, skinFactory, skinAdditionNodeList, true);
-  }
-
-  /**
-   * Get the skin id and other information from each SkinAdditionNode and
-   * get the skin and register the SkinAddition with the skin
-   * @param fContext
-   * @param skinFactory
-   * @param skinAdditionNodeList
-   * @param isMetaInfFile true if the trinidad-skins.xml file is in the META-INF
-   * directory.
-   */
-  private static void _registerSkinAdditions(
-    FacesContext fContext,
-    SkinFactory  skinFactory,
-    List<SkinAdditionNode> skinAdditionNodeList,
-    boolean      isMetaInfFile
-    )
-  {
-    for (SkinAdditionNode skinAdditionNode : skinAdditionNodeList)
-    {
-      String skinId = skinAdditionNode.getSkinId();
-      String styleSheetName = skinAdditionNode.getStyleSheetName();
-      String resourceBundleName = skinAdditionNode.getResourceBundleName();
-      String translationSourceExpression = 
-        skinAdditionNode.getTranslationSourceExpression();
-      Map<String, String> features = skinAdditionNode.getSkinFeatures();
-      SkinAddition addition = null;
-      Skin skin = skinFactory.getSkin(fContext, skinId);
-      if (skin != null 
-          && ((styleSheetName != null) 
-              || (resourceBundleName != null)
-              || (translationSourceExpression != null)))
-      {
-        // If the styleSheetName is in the META-INF/trinidad-skins.xml file, then
-        // we prepend META-INF to the styleSheetName if it doesn't begin with '/'.
-        // This way we can find the file when we go to parse it later.
-        if (isMetaInfFile && (styleSheetName != null))
-            styleSheetName = _prependMetaInf(styleSheetName);
-
-        if (resourceBundleName != null)
-        {
-          // create SkinAddition with resourceBundleName 
-          addition = new SkinAddition(styleSheetName, resourceBundleName, features);
-        }
-        else
-        {
-          ValueExpression translationSourceVE = null;
-          if (translationSourceExpression != null)
-          {
-            translationSourceVE =
-              _createTranslationSourceValueExpression(translationSourceExpression);
-          }
-
-          if (translationSourceVE != null)
-          {
-            // Create a SkinAddition with translationSourceVE 
-            addition = new SkinAddition(styleSheetName, translationSourceVE, features);
-
-          }
-          else
-          {
-            // Create a SkinAddition with stylesheetName only 
-            addition = new SkinAddition(styleSheetName, features);
-
-          }
-        }
-      }
-      else if(features != null)
-      {
-        addition = new SkinAddition(features);
-      }
-      if(addition != null)
-        skin.addSkinAddition(addition);
-    }    
+    return Collections.emptyList();
   }
 
   /**
-   * Prepend META-INF to the styleSheetName if it doesn't begin with '/'.
-   * @param styleSheetName
-   * @return String styleSheetName or the styleSheetName prepended with META-INF/
+   * Given the list of SkinResourceLoaders, load the trindiad-skins
+   * This is used by DT to load trinidad-skins.xml not in META-INF or WEB-INF
+   * @param context
+   * @param providers
+   * @return
    */
-  private static String _prependMetaInf(String styleSheetName)
-  {
-    if (!(styleSheetName.startsWith("/")))
-      return _META_INF_DIR.concat(styleSheetName);
-    else
-      return styleSheetName;
-  }
-
-  // register skins found in DT using the META-INF/services
-  private static List<SkinsNode> _getAdditionalTrinidadSkins(
+  private static List<SkinsNode> _getResourceLoadedTrinidadSkins(
     ExternalContext context,
     List<SkinResourceLoader> providers)
   {
@@ -1030,6 +502,8 @@ public class SkinUtils
       if (_LOG.isFine()) _LOG.fine("Processing skin URL:{0}", url);
 
       URLConnection urlConnection = url.openConnection();
+      // the url here points to the trinidad-skins.xml, we do not expect this to change at run time
+      // so we can use caching for the URL in runtime.
       // prevent caching during DT where the source may change...
       if (Beans.isDesignTime())
       {
@@ -1045,17 +519,17 @@ public class SkinUtils
           SkinsNode metaInfSkinsNode =
             _getSkinsNodeFromInputStream(null, null, in,
                                          _getDefaultManager(),
-                                         url.toString());
+                                         url.toString(), true);
 
           if (metaInfSkinsNode != null)
           {
             // for debug only.
             if (_LOG.isFine())
             {
-              for (SkinNode node : metaInfSkinsNode.getSkinNodes())
+              for (SkinMetadata node : metaInfSkinsNode.getSkinNodes())
                 _LOG.fine("Skin {0} with stylesheet {1}",
                           new Object[]{node.getId(), node.getStyleSheetName()});
-              for (SkinAdditionNode node: metaInfSkinsNode.getSkinAdditionNodes())
+              for (SkinAddition node: metaInfSkinsNode.getSkinAdditionNodes())
                 _LOG.fine("SkinAddition {0} with stylesheet {1}",
                             new Object[]{node.getSkinId(), node.getStyleSheetName()});
             }
@@ -1080,6 +554,52 @@ public class SkinUtils
     }
   }
 
+  /**
+   * Helper for resolveReferenceIcon which uses a Stack of icon names
+   * to detect circular dependencies.
+   *
+   * @param skin the Skin to use when resolving the ReferenceIcon
+   * @param refIcon a ReferenceIcon instance
+   * @param referencedIconStack  The stack of reference icon names which have
+   *          already been visited.  Used to detect circular dependencies.
+   * @return icon which is resolved. i.e., it is not a ReferenceIcon.
+   */
+  static private Icon _resolveReferenceIcon(
+    Skin          skin,
+    ReferenceIcon refIcon,
+    Stack<String> referencedIconStack)
+  {
+    String refName = refIcon.getName();
+
+    // make sure we don't have a circular dependency
+    if ((referencedIconStack != null) && referencedIconStack.contains(refName))
+    {
+      if (_LOG.isWarning())
+        _LOG.warning("SKIN_CIRCULAR_INCLUDE_ERROR", refName);
+      return null;
+    }
+
+    if (referencedIconStack == null)
+    {
+      referencedIconStack = new Stack<String>();
+    }
+
+    referencedIconStack.push(refName);
+
+    Icon icon = skin.getIcon(refName, false);
+
+    if ((icon instanceof ReferenceIcon) && (icon != null))
+    {
+
+      return _resolveReferenceIcon(skin,
+                                  (ReferenceIcon)icon,
+                                  referencedIconStack);
+
+    }
+
+    return icon;
+  }
+
 
   private SkinUtils() {}
 
@@ -1096,129 +616,5 @@ public class SkinUtils
   static private final String _CONFIG_FILE = "/WEB-INF/trinidad-skins.xml";
   static private final String _META_INF_CONFIG_FILE = "META-INF/trinidad-skins.xml";
   static private final String _TRINIDAD_SKINS_XML = "trinidad-skins.xml";
-  static private final String _META_INF_DIR = "META-INF/";
   static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(SkinUtils.class);
-
-  // Error messages
-  private static final String _UNKNOWN_BASE_SKIN_ERROR =
-    "Unable to locate base skin: ";
-
-  static private final String _RENDER_KIT_ID_DESKTOP = "org.apache.myfaces.trinidad.desktop";
-  static private final String _RENDER_KIT_ID_PDA = "org.apache.myfaces.trinidad.pda";
-  static private final String _SIMPLE_PDA_SKIN_ID = "simple.pda";
-  static private final String _SIMPLE_DESKTOP_SKIN_ID = "simple.desktop";
-  
-  private static class SkinExtensionDirector
-  {
-  
-   public SkinExtension produceSkinExtension()
-   {
-     if (_baseSkin == null)
-       throw new NullPointerException("Null baseSkin");
-     if (_id == null)
-       throw new NullPointerException(_LOG.getMessage(
-         "NULL_SKIN_ID"));
-     if (_family == null)
-       throw new NullPointerException("Null family");
-     
-     if (_version == null)
-       _version = SkinVersion.EMPTY_SKIN_VERSION;
-     
-     if(_renderKitId == null)
-     {
-       _renderKitId = _RENDER_KIT_ID_DESKTOP;
-     }
-     
-     //bundle-name takes precedence over translation-source, parser prevents both from being set
-     if(_resourceBundleName != null && _translationSourceValueExpression != null)
-     {
-       _translationSourceValueExpression = null;
-     }
-     
-     return new SkinExtension(_baseSkin, _id, _family, _renderKitId, 
-                              _styleSheetName, _translationSourceValueExpression, 
-                              _version, _skinFeatures, _resourceBundleName);
-   }
-   
-   public void setBaseSkinPart(Skin baseSkin)
-   {
-     _baseSkin = baseSkin;
-   }
-   
-   public void setIdPart(String id)
-   {
-     _id = id; 
-   }
-   
-   public void setFamilyPart(String family)
-   {
-     _family = family;
-   }
-   
-   public void setRenderKitIdPart(String renderKitId)
-   {
-     _renderKitId = renderKitId;
-   }
-   
-   public void setStyleSheetNamePart(String styleSheetName)
-   {
-     setStyleSheetNameAndIsMetaInf(styleSheetName, false);
-   }
-   
-   public void setStyleSheetNameAndIsMetaInf(String styleSheetName, boolean isMetaInf)
-   {
-     // Set the style sheet
-     // If the styleSheetName is in the META-INF/trinidad-skins.xml file, then
-     // we prepend META-INF to the styleSheetName if it doesn't begin with '/'.
-     // This way we can find the file when we go to parse it later.
-     if (styleSheetName != null && isMetaInf)
-     {
-       styleSheetName = _prependMetaInf(styleSheetName);
-     }
-     // If bundleName and translationSourceExpression are both set, then we 
-     // only use the bundleName. An error was already logged during trinidad-skins
-     // parsing.
-     _styleSheetName = styleSheetName;
-     _styleSheetIsMetaInf = isMetaInf;
-   }
-   
-   public void setTranslationSourcePart(ValueExpression translationSourceVE)
-   {
-     _translationSourceValueExpression = translationSourceVE;
-   }
-   
-   public void setTranslationSourcePart(String expression)
-   {
-     if (expression != null)
-     {
-       setTranslationSourcePart(_createTranslationSourceValueExpression(expression));
-     }
-   }
-   
-   public void setSkinVersionPart(SkinVersion version)
-   {
-     _version = version;
-   }
-   
-   public void setSkinFeaturesPart(Map<String, String> features)
-   {
-     _skinFeatures = features;
-   }
-   
-   public void setResourceBundleNamePart(String resourceBundleName)
-   {
-     _resourceBundleName = resourceBundleName;
-   }
-   
-   private Skin _baseSkin;
-   private String _id;
-   private String _family;
-   private String _renderKitId;
-   private String _styleSheetName;
-   private boolean _styleSheetIsMetaInf;
-   private ValueExpression _translationSourceValueExpression;
-   private SkinVersion _version;
-   private Map<String, String> _skinFeatures;
-   private String _resourceBundleName; 
-  } //End private class SkinExtensionDirector
 }
\ No newline at end of file

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/StyleSheetEntry.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/StyleSheetEntry.java?rev=1533115&r1=1533114&r2=1533115&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/StyleSheetEntry.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/StyleSheetEntry.java Thu Oct 17 15:25:57 2013
@@ -578,46 +578,60 @@ class StyleSheetEntry
    *
    * @return a NameResolver instance that has been defined in META-INF\services\
    * org.apache.myfaces.trinidad.share.io.NameResolver
-  // In this file they will have a line like "org.mycompany.io.MyNameResolverImpl".
+   * In this file they will have a line like "org.mycompany.io.MyNameResolverImpl".
    * null if no NameResolver is found.
    */
   static private NameResolver _loadNameResolverFromServices(String name)
   {
-    // We don't want to check services every time, so instead store it on the applicationMap.
+    // first check if the cached NameResolver will serve the name requested
     FacesContext context = FacesContext.getCurrentInstance();
     Map<String, Object> appMap = context.getExternalContext().getApplicationMap();
 
-    // Is it stored on the application map already? If so, use it.
+    // Is it stored on the application map already? can it serve the current request? If so, use it.
     NameResolver savedResolver = (NameResolver)appMap.get(_SERVICES_RESOLVER_KEY);
     if (savedResolver != null)
-      return savedResolver;
+    {
+      try
+      {
+        savedResolver.getProvider(name);
+
+        // NameResolver has to throw IOException if unable to serve a name. It should not return null.
+        // therefore, if the line above did not throw an exception that means we can proceed with this resolver
+        return savedResolver;
+      }
+      catch (IOException ex)
+      {
+        // proceed with checking other registered NameResolvers, if the cached one does not serve the name requested
+        if (_LOG.isFine())
+          _LOG.fine(_SERVICES_RESOLVER_IOEXCEPTION_MSG);
+      }
+    }
 
-    List<NameResolver> resolvers = ClassLoaderUtils.getServices(
-                                      _NAME_RESOLVER_CLASS_NAME);
+    // Now, the cached resolver did not serve the name requested
+    // there fore, check other registered NameResolvers
+    List<NameResolver> resolvers = ClassLoaderUtils.getServices(_NAME_RESOLVER_CLASS_NAME);
 
     for (NameResolver customNameResolver : resolvers)
     {
-      InputStreamProvider provider = null;
       try
       {
-        provider = customNameResolver.getProvider(name);
+        customNameResolver.getProvider(name);
+
+        // NameResolver has to throw IOException if unable to serve a name. It should not return null.
+        // therefore, if the line above did not throw an exception that means we can proceed with this resolver
+        // cache the resolver and return
+        appMap.put(_SERVICES_RESOLVER_KEY, customNameResolver);
+        return customNameResolver;
       }
       catch (IOException e)
       {
         // Log fine message. Try the next factory to get a provider
         if (_LOG.isFine())
-          _LOG.fine(_SERVICES_RESOLVER_IOEXCEPTION_MSG);       
-      }
-      // Found a customNameResolver with a provider. So store it away and return it from the method.
-      if (provider != null)
-      {
-        appMap.put(_SERVICES_RESOLVER_KEY, customNameResolver);
-        return customNameResolver;
+          _LOG.fine(_SERVICES_RESOLVER_IOEXCEPTION_MSG);
       }
     }
-    
-    return null;
 
+    return null;
   }
 
   // A subclass of URLInputStreamProvider which never checks for
@@ -652,10 +666,10 @@ class StyleSheetEntry
     "Trying next nameResolver.";
 
   private static final String _SERVICES_RESOLVER_KEY =
-    "org.apache.myfaces.trinidadinternal.skin.SERVICES_RESOLVER_KEY";  
+    "org.apache.myfaces.trinidadinternal.skin.SERVICES_RESOLVER_KEY";
 
   private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(StyleSheetEntry.class);
-  
+
   private String              _name;
   private StyleSheetDocument  _document;