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

svn commit: r1632268 [1/2] - in /myfaces/trinidad/trunk: trinidad-api/src/test/java/org/apache/myfaces/trinidadbuild/test/ trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/ trinidad-impl/src/main/java/org/apache/myfaces/tri...

Author: andys
Date: Thu Oct 16 10:31:25 2014
New Revision: 1632268

URL: http://svn.apache.org/r1632268
Log:
Setting el-style to native for new files from previous commit.

Modified:
    myfaces/trinidad/trunk/trinidad-api/src/test/java/org/apache/myfaces/trinidadbuild/test/ConcurrentMapTestCase.java   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/BaseSkinProvider.java   (contents, props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/SkinProviderRegistry.java   (contents, props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/TrinidadSkinProvider.java   (contents, props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/CopyOnWriteArrayMap.java   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/custom/CustomSkinProvider1.java   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/custom/CustomSkinProvider2.java   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/provider/SkinProviderTest.java   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/util/CopyOnWriteArrayMapTest.java   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/util/LRUCopyOnWriteArrayMapTest.java   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/META-INF/services/org.apache.myfaces.trinidad.skin.SkinProvider   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/META-INF/trinidad-skins.xml   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/beach/CustomStyles.css   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/beach/beach.css   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/purple/purpleBigFontSkin.css   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/purple/purpleBigFontSkinFour.css   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/purple/purpleBigFontSkinThree.css   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/purple/purpleBigFontSkinTwo.css   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/purple/purpleSkin.css   (props changed)
    myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/suede/suede.css   (props changed)

Propchange: myfaces/trinidad/trunk/trinidad-api/src/test/java/org/apache/myfaces/trinidadbuild/test/ConcurrentMapTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/BaseSkinProvider.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/BaseSkinProvider.java?rev=1632268&r1=1632267&r2=1632268&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/BaseSkinProvider.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/BaseSkinProvider.java Thu Oct 16 10:31:25 2014
@@ -1,480 +1,480 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.trinidadinternal.skin.provider;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.faces.context.ExternalContext;
-
-import org.apache.myfaces.trinidad.logging.TrinidadLogger;
-import org.apache.myfaces.trinidad.skin.Skin;
-import org.apache.myfaces.trinidad.skin.SkinMetadata;
-import org.apache.myfaces.trinidad.skin.SkinProvider;
-import org.apache.myfaces.trinidad.skin.SkinVersion;
-
-/**
- * This is the common base class for Trinidad SkinProviders. This class abstracts out some common
- * code that is useful across Trinidad internal SkinProviders. One such example worth mentioning is
- * the code to finding a Skin match for a given SkinMetadata search criteria.
- *
- * @See TrinidadBaseSkinProvider
- * @See TrinidadSkinProvider
- * @See ExternalSkinProvider
- */
-abstract class BaseSkinProvider extends SkinProvider
-{
-  public BaseSkinProvider()
-  {
-    initSkins();
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public Skin getSkin(ExternalContext context, SkinMetadata skinMetadata)
-  {
-    synchronized (this)
-    {
-      return _getMatchingSkin(context, skinMetadata);
-    }
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public Collection<SkinMetadata> getSkinMetadata(ExternalContext context)
-  {
-    synchronized (this)
-    {
-      return Collections.unmodifiableCollection(_skins.keySet());
-    }
-  }
-
-  /**
-   * add method used to register a skin with the provider.
-   *
-   * @param metadata
-   * @param skin
-   * @return Any previously registered skins existing with the same metadata
-   */
-  public Skin addSkin(SkinMetadata metadata, Skin skin)
-  {
-    if (metadata == null || skin == null)
-    {
-      _LOG.warning("CANNOT_ADD_SKIN");
-      return null;
-    }
-
-    if (_LOG.isFine())
-      _LOG.fine("Adding skin to cache [metadata: {0}, skin: {1}]", new Object[] {metadata, skin});
-
-    synchronized (this)
-    {
-      return _skins.put(metadata, skin);
-    }
-  }
-
-  /**
-   * template method to be implemented by subclasses with logic to load a skin that base class knows
-   * as available with the current skin provider being asked to load the skin
-   *
-   * @param context
-   * @param skinMetadata
-   */
-  protected abstract Skin loadAvailableSkin(ExternalContext context, SkinMetadata skinMetadata);
-
-  /**
-   * getter for the skins, only used by ExternalSkinProvider.reload to cache and restore the skins
-   * if reload fails
-   *
-   * @return
-   */
-  protected Map<SkinMetadata, Skin> getSkins()
-  {
-    synchronized (this)
-    {
-      return _skins;
-    }
-  }
-
-  /**
-   * setter for the skins, only used by ExternalSkinProvider.reload to cache and restore the skins
-   * if reload fails
-   *
-   * @param skins
-   */
-  protected void setSkins(Map<SkinMetadata, Skin> skins)
-  {
-    synchronized (this)
-    {
-      // do not allow a null to be set.
-      if (skins == null)
-        skins = new HashMap<SkinMetadata, Skin>();
-
-      _skins = skins;
-    }
-  }
-
-  /**
-   * initialize a new HashMap for the skins, used by constructor and ExternalSkinProvider.reload
-   */
-  protected void initSkins()
-  {
-    synchronized (this)
-    {
-      _skins = new HashMap<SkinMetadata, Skin>();
-    }
-  }
-
-  /**
-   * Hook to do any kind of initialization before loading a skin or skin metadata sub classes can
-   * choose to implement
-   *
-   * @param context
-   */
-  protected void initialize(ExternalContext context)
-  {
-  }
-
-  /**
-   * one point method for searching skins
-   *
-   * @param context
-   * @param searchMetadata to search for
-   * @return matching skin
-   */
-  private final Skin _getMatchingSkin(ExternalContext context, SkinMetadata searchMetadata)
-  {
-    if (searchMetadata == null)
-      throw new NullPointerException("SkinMetadata passed for search is null");
-
-    // find a skin that is already loaded using the exact search metadata passed.
-    Skin availableSkin = _skins.get(searchMetadata);
-    if (availableSkin != null)
-      return availableSkin;
-
-    // there is no skin already available, so find a skin which matches the search criteria
-    // verify that either id or family is set for the search
-    if (null == searchMetadata.getId() && null == searchMetadata.getFamily())
-    {
-      if (_LOG.isWarning())
-        _LOG.warning("SP_CANNOT_FIND_SKIN_WITHOUT_FAMILY_OR_ID");
-
-      throw new NullPointerException(_LOG.getMessage("SP_CANNOT_FIND_SKIN_WITHOUT_FAMILY_OR_ID"));
-    }
-
-    initialize(context);
-
-    if (_LOG.isFine())
-      _LOG.fine("SP_FINDING_SKIN_FOR", new Object[]{searchMetadata.toString()});
-
-    // first check if a skin matching the requirement is present in this provider
-
-    SkinMetadata availableMetadata = _findSkinMetadata(context, searchMetadata);
-    if (availableMetadata == null)
-    {
-      if (_LOG.isFine())
-        _LOG.fine(this + " Cannot find skin in this provider: " + searchMetadata);
-
-      return null;
-    }
-
-    // find a skin that is already loaded
-    // this is different from doing it at the beginning of the method
-    // because the metadata with which the skin is added into _skins
-    // may not have matched completely, since searchMetadata can provide
-    // only certain conditions.
-    availableSkin = _skins.get(availableMetadata);
-    if (availableSkin != null)
-      return availableSkin;
-
-    // now we know that there is a skin available but not loaded
-    // so load the skin
-    availableSkin = loadAvailableSkin(context, availableMetadata);
-    assert (availableSkin != null);
-
-    _skins.put(availableMetadata, availableSkin);
-
-    return availableSkin;
-  }
-
-  /**
-   * find if there is a skin with the search condition supported by the current SkinProvider
-   *
-   * @param search
-   * @return
-   */
-  private SkinMetadata _findSkinMetadata(ExternalContext context, SkinMetadata search)
-  {
-    SkinMetadata matchingSkinMetadata = null;
-    String skinId = search.getId();
-
-    Collection<SkinMetadata> skinMetadata = getSkinMetadata(context);
-
-    if (skinMetadata == null || skinMetadata.isEmpty())
-      return null;
-
-    // search is with either id or (family, renderkit, version)
-    // we have ensure that either id or family is passed in the search
-    if (skinId != null)
-    {
-      // Id is available then search using ID
-      for (SkinMetadata m : skinMetadata)
-        if (skinId.equals(m.getId()))
-        {
-          matchingSkinMetadata = m;
-        }
-
-      if (matchingSkinMetadata == null)
-      {
-        if (_LOG.isFine())
-        {
-          _LOG.fine("SP_CANNOT_FIND_MATCHING_SKIN_ID", new Object[]{skinId});
-        }
-      }
-    }
-    else
-    {
-      // search using family, renderkit, version
-      String family = search.getFamily();
-
-      // we need at least the family to go on with the search
-      if (family == null)
-        return null;
-
-      // renderkit id cannot be null, we initialize it to APACHE_TRINIDAD_DESKTOP
-      String renderKit = search.getRenderKitId();
-
-      // version cannot be null as we initialize it to SkinVersion.EMPTY_SKIN_VERSION
-      SkinVersion version = search.getVersion();
-
-      List<SkinMetadata> familyRenderKitMatches = new ArrayList<SkinMetadata>(2);
-
-      // search using family and renderkit id
-      for (SkinMetadata m : skinMetadata)
-        if (family.equalsIgnoreCase(m.getFamily()) &&
-              renderKit.equalsIgnoreCase(m.getRenderKitId()))
-          familyRenderKitMatches.add(m);
-
-      if (familyRenderKitMatches.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.isFine())
-        {
-          _LOG.fine("SP_CANNOT_FIND_MATCHING_SKIN", new Object[]{family, renderKit});
-        }
-
-        return null;
-      }
-
-      // at this point we know we have something in the familyRenderKitMatches
-      // which is a list of matching family and renderKitId skins. Now match the version
-      // to find the best matched skin.
-      String versionName = version.getName();
-      boolean versionIsDefault = version.isDefault();
-      boolean foundMatchingSkin = false;
-
-      // if the user didn't ask for the 'default' version, then look for the exact match
-      if (!versionIsDefault)
-      {
-        matchingSkinMetadata = _findSkinMetadataForVersionName(familyRenderKitMatches, version);
-      }
-
-      // matchingSkinMetadata will be null if an exact version match (family+renderKitId+version)
-      // was not found;
-      // or if user was asking for a default version
-      // we can have an exact version match if the user asks for null version,
-      // and we find a skin with no
-      // version set.
-      if (matchingSkinMetadata == null || versionIsDefault)
-      {
-        // at this point either user is looking for default skin
-        // or did not find the exact version match specified
-        // so we find the default skin
-        matchingSkinMetadata = _findSkinMetadataWithDefaultVersion(familyRenderKitMatches);
-
-        if (matchingSkinMetadata == null)
-        {
-          // if we fail to find a default skin then
-          // get the latest skin in the matchingSkinList if there is no skin marked default.
-          if (_LOG.isFine())
-            _LOG.fine(this + " did not find default / version skinMetadata. so getting leaf skin");
-
-          matchingSkinMetadata = _findLeafSkinMetadata(familyRenderKitMatches);
-        }
-        else if ((matchingSkinMetadata != null) && versionIsDefault)
-        {
-          // found the default skin the user wanted
-          if (_LOG.isFine())
-            _LOG.fine(this + " found default skinMetadata");
-
-          foundMatchingSkin = true;
-        }
-      }
-
-      // log messages
-      if (foundMatchingSkin)
-      {
-        if (_LOG.isFine())
-          _LOG.fine("GET_SKIN_FOUND_SKIN_VERSION",
-                    new Object[]{family, version, matchingSkinMetadata.getId()});
-      }
-      else if (matchingSkinMetadata != null)
-      {
-        if (_LOG.isFine())
-        {
-          if ("".equals(versionName))
-          {
-            _LOG.fine("GET_SKIN_CANNOT_FIND_NO_VERSION",
-                      new Object[]{family, matchingSkinMetadata.getId()});
-          }
-          else
-          {
-            _LOG.fine("GET_SKIN_CANNOT_FIND_SKIN_VERSION",
-                      new Object[]{family, version, matchingSkinMetadata.getId()});
-          }
-        }
-      }
-
-      if (matchingSkinMetadata == null)
-      {
-        matchingSkinMetadata = familyRenderKitMatches.get(familyRenderKitMatches.size() - 1);
-      }
-    }
-
-
-    if (matchingSkinMetadata != null)
-      if (_LOG.isFine())
-        _LOG.fine(this + " found matching metadata: " + matchingSkinMetadata);
-
-    return matchingSkinMetadata;
-  }
-
-  /**
-   * find a skin with version passed
-   *
-   * @param skins
-   * @param version
-   * @return
-   */
-  private SkinMetadata _findSkinMetadataForVersionName(Collection<SkinMetadata> skins,
-                                                       SkinVersion version)
-  {
-    if (version == null)
-      throw new IllegalArgumentException("skin version cannot be null");
-
-    if (version.getName() == null || version.getName().isEmpty())
-      return null;
-
-    for (SkinMetadata metadata : skins)
-    {
-      // metadata cannot be null and also version inside it cannot be null
-      if (version.getName().equals(metadata.getVersion().getName()))
-      {
-        if (_LOG.isFine())
-          _LOG.fine("Found version match skinMetadata: " + metadata);
-
-        return metadata;
-      }
-    }
-
-    return null;
-  }
-
-  /**
-   * Latest skin is the one which is last in the family hierarchy eg: fusion-v1 -> fusion-v2 ->
-   * fusion-v3 Among this fusion-v3 is the latest. So we look for a skin that is not extended by any
-   * other skin in the family.
-   *
-   * @param skins
-   * @return
-   */
-  private SkinMetadata _findLeafSkinMetadata(Collection<SkinMetadata> skins)
-  {
-    List<SkinMetadata> leafSkinMetadata = new ArrayList<SkinMetadata>();
-    List<String> parentIds = new ArrayList<String>();
-
-    // collect parents skins among the list
-    for (SkinMetadata metadata : skins)
-    {
-      String parentId = metadata.getBaseSkinId();
-      if (parentId != null)
-        parentIds.add(metadata.getBaseSkinId());
-    }
-
-    // find leaf skins, which is not in parent list
-    for (SkinMetadata metadata : skins)
-    {
-      String skinId = metadata.getId();
-      if (skinId != null && !parentIds.contains(skinId))
-      {
-        leafSkinMetadata.add(metadata);
-      }
-    }
-
-    // if there are no leaves, return null
-    // this is a rare case, almost impossible since there will be
-    // at least one skin which is not parent of another
-    // but let us cover the corner case if any
-    if (leafSkinMetadata.isEmpty())
-      return null;
-
-    // if there is one leaf skin return that
-    // if there are many, return the last one among the leaves
-    return leafSkinMetadata.get(leafSkinMetadata.size() - 1);
-  }
-
-  /**
-   * find a skin 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.
-   */
-  private SkinMetadata _findSkinMetadataWithDefaultVersion(
-    Collection<SkinMetadata> matchingSkinList)
-  {
-    for (SkinMetadata metadata : matchingSkinList)
-    {
-      SkinVersion skinVersion = metadata.getVersion();
-
-      if (skinVersion != null && skinVersion.isDefault())
-      {
-        if (_LOG.isFine())
-          _LOG.fine("Found default skinMetadata: " + metadata);
-
-        return metadata;
-      }
-    }
-
-    return null;
-  }
-
-  private Map<SkinMetadata, Skin> _skins;
-  private final static TrinidadLogger _LOG =
-    TrinidadLogger.createTrinidadLogger(BaseSkinProvider.class);
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.trinidadinternal.skin.provider;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.context.ExternalContext;
+
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.skin.Skin;
+import org.apache.myfaces.trinidad.skin.SkinMetadata;
+import org.apache.myfaces.trinidad.skin.SkinProvider;
+import org.apache.myfaces.trinidad.skin.SkinVersion;
+
+/**
+ * This is the common base class for Trinidad SkinProviders. This class abstracts out some common
+ * code that is useful across Trinidad internal SkinProviders. One such example worth mentioning is
+ * the code to finding a Skin match for a given SkinMetadata search criteria.
+ *
+ * @See TrinidadBaseSkinProvider
+ * @See TrinidadSkinProvider
+ * @See ExternalSkinProvider
+ */
+abstract class BaseSkinProvider extends SkinProvider
+{
+  public BaseSkinProvider()
+  {
+    initSkins();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Skin getSkin(ExternalContext context, SkinMetadata skinMetadata)
+  {
+    synchronized (this)
+    {
+      return _getMatchingSkin(context, skinMetadata);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Collection<SkinMetadata> getSkinMetadata(ExternalContext context)
+  {
+    synchronized (this)
+    {
+      return Collections.unmodifiableCollection(_skins.keySet());
+    }
+  }
+
+  /**
+   * add method used to register a skin with the provider.
+   *
+   * @param metadata
+   * @param skin
+   * @return Any previously registered skins existing with the same metadata
+   */
+  public Skin addSkin(SkinMetadata metadata, Skin skin)
+  {
+    if (metadata == null || skin == null)
+    {
+      _LOG.warning("CANNOT_ADD_SKIN");
+      return null;
+    }
+
+    if (_LOG.isFine())
+      _LOG.fine("Adding skin to cache [metadata: {0}, skin: {1}]", new Object[] {metadata, skin});
+
+    synchronized (this)
+    {
+      return _skins.put(metadata, skin);
+    }
+  }
+
+  /**
+   * template method to be implemented by subclasses with logic to load a skin that base class knows
+   * as available with the current skin provider being asked to load the skin
+   *
+   * @param context
+   * @param skinMetadata
+   */
+  protected abstract Skin loadAvailableSkin(ExternalContext context, SkinMetadata skinMetadata);
+
+  /**
+   * getter for the skins, only used by ExternalSkinProvider.reload to cache and restore the skins
+   * if reload fails
+   *
+   * @return
+   */
+  protected Map<SkinMetadata, Skin> getSkins()
+  {
+    synchronized (this)
+    {
+      return _skins;
+    }
+  }
+
+  /**
+   * setter for the skins, only used by ExternalSkinProvider.reload to cache and restore the skins
+   * if reload fails
+   *
+   * @param skins
+   */
+  protected void setSkins(Map<SkinMetadata, Skin> skins)
+  {
+    synchronized (this)
+    {
+      // do not allow a null to be set.
+      if (skins == null)
+        skins = new HashMap<SkinMetadata, Skin>();
+
+      _skins = skins;
+    }
+  }
+
+  /**
+   * initialize a new HashMap for the skins, used by constructor and ExternalSkinProvider.reload
+   */
+  protected void initSkins()
+  {
+    synchronized (this)
+    {
+      _skins = new HashMap<SkinMetadata, Skin>();
+    }
+  }
+
+  /**
+   * Hook to do any kind of initialization before loading a skin or skin metadata sub classes can
+   * choose to implement
+   *
+   * @param context
+   */
+  protected void initialize(ExternalContext context)
+  {
+  }
+
+  /**
+   * one point method for searching skins
+   *
+   * @param context
+   * @param searchMetadata to search for
+   * @return matching skin
+   */
+  private final Skin _getMatchingSkin(ExternalContext context, SkinMetadata searchMetadata)
+  {
+    if (searchMetadata == null)
+      throw new NullPointerException("SkinMetadata passed for search is null");
+
+    // find a skin that is already loaded using the exact search metadata passed.
+    Skin availableSkin = _skins.get(searchMetadata);
+    if (availableSkin != null)
+      return availableSkin;
+
+    // there is no skin already available, so find a skin which matches the search criteria
+    // verify that either id or family is set for the search
+    if (null == searchMetadata.getId() && null == searchMetadata.getFamily())
+    {
+      if (_LOG.isWarning())
+        _LOG.warning("SP_CANNOT_FIND_SKIN_WITHOUT_FAMILY_OR_ID");
+
+      throw new NullPointerException(_LOG.getMessage("SP_CANNOT_FIND_SKIN_WITHOUT_FAMILY_OR_ID"));
+    }
+
+    initialize(context);
+
+    if (_LOG.isFine())
+      _LOG.fine("SP_FINDING_SKIN_FOR", new Object[]{searchMetadata.toString()});
+
+    // first check if a skin matching the requirement is present in this provider
+
+    SkinMetadata availableMetadata = _findSkinMetadata(context, searchMetadata);
+    if (availableMetadata == null)
+    {
+      if (_LOG.isFine())
+        _LOG.fine(this + " Cannot find skin in this provider: " + searchMetadata);
+
+      return null;
+    }
+
+    // find a skin that is already loaded
+    // this is different from doing it at the beginning of the method
+    // because the metadata with which the skin is added into _skins
+    // may not have matched completely, since searchMetadata can provide
+    // only certain conditions.
+    availableSkin = _skins.get(availableMetadata);
+    if (availableSkin != null)
+      return availableSkin;
+
+    // now we know that there is a skin available but not loaded
+    // so load the skin
+    availableSkin = loadAvailableSkin(context, availableMetadata);
+    assert (availableSkin != null);
+
+    _skins.put(availableMetadata, availableSkin);
+
+    return availableSkin;
+  }
+
+  /**
+   * find if there is a skin with the search condition supported by the current SkinProvider
+   *
+   * @param search
+   * @return
+   */
+  private SkinMetadata _findSkinMetadata(ExternalContext context, SkinMetadata search)
+  {
+    SkinMetadata matchingSkinMetadata = null;
+    String skinId = search.getId();
+
+    Collection<SkinMetadata> skinMetadata = getSkinMetadata(context);
+
+    if (skinMetadata == null || skinMetadata.isEmpty())
+      return null;
+
+    // search is with either id or (family, renderkit, version)
+    // we have ensure that either id or family is passed in the search
+    if (skinId != null)
+    {
+      // Id is available then search using ID
+      for (SkinMetadata m : skinMetadata)
+        if (skinId.equals(m.getId()))
+        {
+          matchingSkinMetadata = m;
+        }
+
+      if (matchingSkinMetadata == null)
+      {
+        if (_LOG.isFine())
+        {
+          _LOG.fine("SP_CANNOT_FIND_MATCHING_SKIN_ID", new Object[]{skinId});
+        }
+      }
+    }
+    else
+    {
+      // search using family, renderkit, version
+      String family = search.getFamily();
+
+      // we need at least the family to go on with the search
+      if (family == null)
+        return null;
+
+      // renderkit id cannot be null, we initialize it to APACHE_TRINIDAD_DESKTOP
+      String renderKit = search.getRenderKitId();
+
+      // version cannot be null as we initialize it to SkinVersion.EMPTY_SKIN_VERSION
+      SkinVersion version = search.getVersion();
+
+      List<SkinMetadata> familyRenderKitMatches = new ArrayList<SkinMetadata>(2);
+
+      // search using family and renderkit id
+      for (SkinMetadata m : skinMetadata)
+        if (family.equalsIgnoreCase(m.getFamily()) &&
+              renderKit.equalsIgnoreCase(m.getRenderKitId()))
+          familyRenderKitMatches.add(m);
+
+      if (familyRenderKitMatches.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.isFine())
+        {
+          _LOG.fine("SP_CANNOT_FIND_MATCHING_SKIN", new Object[]{family, renderKit});
+        }
+
+        return null;
+      }
+
+      // at this point we know we have something in the familyRenderKitMatches
+      // which is a list of matching family and renderKitId skins. Now match the version
+      // to find the best matched skin.
+      String versionName = version.getName();
+      boolean versionIsDefault = version.isDefault();
+      boolean foundMatchingSkin = false;
+
+      // if the user didn't ask for the 'default' version, then look for the exact match
+      if (!versionIsDefault)
+      {
+        matchingSkinMetadata = _findSkinMetadataForVersionName(familyRenderKitMatches, version);
+      }
+
+      // matchingSkinMetadata will be null if an exact version match (family+renderKitId+version)
+      // was not found;
+      // or if user was asking for a default version
+      // we can have an exact version match if the user asks for null version,
+      // and we find a skin with no
+      // version set.
+      if (matchingSkinMetadata == null || versionIsDefault)
+      {
+        // at this point either user is looking for default skin
+        // or did not find the exact version match specified
+        // so we find the default skin
+        matchingSkinMetadata = _findSkinMetadataWithDefaultVersion(familyRenderKitMatches);
+
+        if (matchingSkinMetadata == null)
+        {
+          // if we fail to find a default skin then
+          // get the latest skin in the matchingSkinList if there is no skin marked default.
+          if (_LOG.isFine())
+            _LOG.fine(this + " did not find default / version skinMetadata. so getting leaf skin");
+
+          matchingSkinMetadata = _findLeafSkinMetadata(familyRenderKitMatches);
+        }
+        else if ((matchingSkinMetadata != null) && versionIsDefault)
+        {
+          // found the default skin the user wanted
+          if (_LOG.isFine())
+            _LOG.fine(this + " found default skinMetadata");
+
+          foundMatchingSkin = true;
+        }
+      }
+
+      // log messages
+      if (foundMatchingSkin)
+      {
+        if (_LOG.isFine())
+          _LOG.fine("GET_SKIN_FOUND_SKIN_VERSION",
+                    new Object[]{family, version, matchingSkinMetadata.getId()});
+      }
+      else if (matchingSkinMetadata != null)
+      {
+        if (_LOG.isFine())
+        {
+          if ("".equals(versionName))
+          {
+            _LOG.fine("GET_SKIN_CANNOT_FIND_NO_VERSION",
+                      new Object[]{family, matchingSkinMetadata.getId()});
+          }
+          else
+          {
+            _LOG.fine("GET_SKIN_CANNOT_FIND_SKIN_VERSION",
+                      new Object[]{family, version, matchingSkinMetadata.getId()});
+          }
+        }
+      }
+
+      if (matchingSkinMetadata == null)
+      {
+        matchingSkinMetadata = familyRenderKitMatches.get(familyRenderKitMatches.size() - 1);
+      }
+    }
+
+
+    if (matchingSkinMetadata != null)
+      if (_LOG.isFine())
+        _LOG.fine(this + " found matching metadata: " + matchingSkinMetadata);
+
+    return matchingSkinMetadata;
+  }
+
+  /**
+   * find a skin with version passed
+   *
+   * @param skins
+   * @param version
+   * @return
+   */
+  private SkinMetadata _findSkinMetadataForVersionName(Collection<SkinMetadata> skins,
+                                                       SkinVersion version)
+  {
+    if (version == null)
+      throw new IllegalArgumentException("skin version cannot be null");
+
+    if (version.getName() == null || version.getName().isEmpty())
+      return null;
+
+    for (SkinMetadata metadata : skins)
+    {
+      // metadata cannot be null and also version inside it cannot be null
+      if (version.getName().equals(metadata.getVersion().getName()))
+      {
+        if (_LOG.isFine())
+          _LOG.fine("Found version match skinMetadata: " + metadata);
+
+        return metadata;
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Latest skin is the one which is last in the family hierarchy eg: fusion-v1 -> fusion-v2 ->
+   * fusion-v3 Among this fusion-v3 is the latest. So we look for a skin that is not extended by any
+   * other skin in the family.
+   *
+   * @param skins
+   * @return
+   */
+  private SkinMetadata _findLeafSkinMetadata(Collection<SkinMetadata> skins)
+  {
+    List<SkinMetadata> leafSkinMetadata = new ArrayList<SkinMetadata>();
+    List<String> parentIds = new ArrayList<String>();
+
+    // collect parents skins among the list
+    for (SkinMetadata metadata : skins)
+    {
+      String parentId = metadata.getBaseSkinId();
+      if (parentId != null)
+        parentIds.add(metadata.getBaseSkinId());
+    }
+
+    // find leaf skins, which is not in parent list
+    for (SkinMetadata metadata : skins)
+    {
+      String skinId = metadata.getId();
+      if (skinId != null && !parentIds.contains(skinId))
+      {
+        leafSkinMetadata.add(metadata);
+      }
+    }
+
+    // if there are no leaves, return null
+    // this is a rare case, almost impossible since there will be
+    // at least one skin which is not parent of another
+    // but let us cover the corner case if any
+    if (leafSkinMetadata.isEmpty())
+      return null;
+
+    // if there is one leaf skin return that
+    // if there are many, return the last one among the leaves
+    return leafSkinMetadata.get(leafSkinMetadata.size() - 1);
+  }
+
+  /**
+   * find a skin 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.
+   */
+  private SkinMetadata _findSkinMetadataWithDefaultVersion(
+    Collection<SkinMetadata> matchingSkinList)
+  {
+    for (SkinMetadata metadata : matchingSkinList)
+    {
+      SkinVersion skinVersion = metadata.getVersion();
+
+      if (skinVersion != null && skinVersion.isDefault())
+      {
+        if (_LOG.isFine())
+          _LOG.fine("Found default skinMetadata: " + metadata);
+
+        return metadata;
+      }
+    }
+
+    return null;
+  }
+
+  private Map<SkinMetadata, Skin> _skins;
+  private final static TrinidadLogger _LOG =
+    TrinidadLogger.createTrinidadLogger(BaseSkinProvider.class);
 }
\ No newline at end of file

Propchange: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/BaseSkinProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/SkinProviderRegistry.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/SkinProviderRegistry.java?rev=1632268&r1=1632267&r2=1632268&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/SkinProviderRegistry.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/SkinProviderRegistry.java Thu Oct 16 10:31:25 2014
@@ -1,547 +1,547 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.trinidadinternal.skin.provider;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-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.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.skin.SkinUtils;
-
-/**
- * Internal implementation of SkinProvider which is exposed using SkinProvider.getCurrentInstance()
- * This class collates all SkinProvider SPIs, Trinidad SkinProviders and SkinFactory to return the
- * best match for a Skin requested This class reads all registered SPIs using
- * org.apache.myfaces.trinidad.skin.SkinProvider
- * <p/>
- * Instance of this class is created and put into the ExternalContext during bootstrap in
- * GlobalConfiguratorImpl and retrieved in the static factory inside SkinProvider
- * <p/>
- */
-public class SkinProviderRegistry extends SkinProvider
-{
-
-  public SkinProviderRegistry()
-  {
-    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
-    List<SkinProvider> services = ClassLoaderUtils.getServices(SkinProvider.class.getName());
-
-    if (_LOG.isFine())
-      _LOG.fine("Adding providers from registered SPIs... " + services.size());
-
-    List<SkinProvider> providers = new ArrayList<SkinProvider>(services.size() + 2);
-    providers.addAll(services);
-
-    // add internal skin providers at the end
-    // this is to give the other SPIs a chance before the internal skin providers
-    if (_LOG.isFine())
-      _LOG.fine("Adding TrinidadSkinProvider... ");
-
-    providers.add(TrinidadSkinProvider.getCurrentInstance(externalContext));
-
-    if (_LOG.isFine())
-      _LOG.fine("Adding TrinidadBaseSkinProvider... ");
-
-    // this provider serves static base skins, so we can create a new instance here
-    providers.add(new TrinidadBaseSkinProvider());
-
-    if (_LOG.isFine())
-      _LOG.fine("Adding ExternalSkinProvider... ");
-
-    providers.add(ExternalSkinProvider.getCurrentInstance(externalContext));
-
-    _providers = Collections.unmodifiableList(providers);
-  }
-
-  @Override
-  public Collection<SkinMetadata> getSkinMetadata(ExternalContext externalContext)
-  {
-    Collection<SkinMetadata> metadata = new ArrayList<SkinMetadata>();
-
-    for (SkinProvider provider : _providers)
-      metadata.addAll(provider.getSkinMetadata(externalContext));
-
-    return Collections.unmodifiableCollection(metadata);
-  }
-
-  /**
-   * @param externalContext
-   * @param skinMetadata search criteria object containing the information of skin to be queried id,
-   *                     family, renderKit, version are the information used from skin metadata to
-   *                     perform search for the skin requested. Other fields do not participate in
-   *                     the search.
-   * @return matching skin for the search criteria passed, if none found, return the simple skin for
-   * the renderKit in search criteria if renderKit not specified in search criteria, skinMetadata
-   * automatically assumes it as SkinMetadata.RenderKitId.DESKTOP
-   */
-  @Override
-  public Skin getSkin(ExternalContext externalContext, SkinMetadata skinMetadata)
-  {
-    _handleCircularDependency(skinMetadata);
-
-    List<Skin> matchingSkins = new ArrayList<Skin>();
-    Skin matchingSkin = null;
-
-    if (_LOG.isFine())
-      _LOG.fine("Skin request for metadata: " + skinMetadata);
-
-    for (SkinProvider provider : _providers)
-    {
-      matchingSkin = provider.getSkin(externalContext, skinMetadata);
-
-      if (matchingSkin != null)
-      {
-        // log which provider got skin etc
-        if (_LOG.isFine())
-          _LOG.fine("Skin obtained for metadata: " + skinMetadata + " from provider: " + provider);
-
-        matchingSkins.add(matchingSkin);
-      }
-    }
-
-    if (_LOG.isFine())
-      _LOG.fine("Matches obtained for " + skinMetadata + ": " + matchingSkins.size());
-
-    // now we are done with asking all skin providers
-    // ensure that the matching skins returned are indeed matching the search criteria
-    // onus is on SkinProviderRegistry to serve the skin requested, even if a SkinProvider
-    // returns a wrong skin.
-
-    // filter the results obtained from skin providers based on id, family and renderKit
-    // filtering on version is more complicated and taken up subsequently
-    matchingSkins = _filterSkins(matchingSkins, skinMetadata);
-
-    if (matchingSkins.isEmpty())
-    {
-      if (_LOG.isFine())
-        _LOG.fine("NO MATCH. Will return a simple skin or null for skin metadata: " + skinMetadata);
-
-      assert (skinMetadata.getRenderKitId() != null);
-
-      // if renderKit is available return the simple skin for that renderKit
-      // skinMetadata.getRenderKitId() can never be null, default renderKit will always be DESKTOP
-      matchingSkin = SkinUtils.getDefaultSkinForRenderKitId(this,
-                                                            externalContext,
-                                                            skinMetadata.getRenderKitId());
-      _processSkinForReturn(skinMetadata, matchingSkin);
-      return matchingSkin;
-    }
-
-
-    // we have at least one match now
-    // if we have only one match
-    // return that skin
-    if (matchingSkins.size() == 1)
-    {
-      if (_LOG.isFine())
-        _LOG.fine("returning ONLY match for skin metadata: " + skinMetadata);
-
-
-      matchingSkin = matchingSkins.get(0);
-      _processSkinForReturn(skinMetadata, matchingSkin);
-      return matchingSkin;
-    }
-
-    // at this point we have more than one matches for the search criteria passed
-    // so, extract the best match based on version
-    return _versionFilter(skinMetadata, matchingSkins);
-  }
-
-  /**
-   * exposing providers for testability
-   * @return
-   */
-  List<SkinProvider> getProviders()
-  {
-    return _providers;
-  }
-
-  /**
-   * ensure sanity in the list of matches received by filtering the skins based on id, family and
-   * renderKit
-   *
-   * @param skins
-   * @param metadata
-   * @return
-   */
-  private List<Skin> _filterSkins(List<Skin> skins, SkinMetadata metadata)
-  {
-    if (skins == null || skins.isEmpty() || metadata == null)
-      return Collections.emptyList();
-
-    List<Skin> filterList = _idFilter(skins, metadata.getId());
-
-    // if the id based filtering resulted in only match then return that
-    // provided id was mentioned in search criteria
-    if (filterList.size() == 1 && metadata.getId() != null)
-    {
-      return filterList;
-    }
-
-    // if more than one match for id or if id is not specified, then filter by family
-    filterList = _familyFilter(filterList, metadata.getFamily());
-
-    // if the family based filtering resulted in only match then return that
-    // provided family was mentioned in search criteria
-    if (filterList.size() == 1 && metadata.getFamily() != null)
-    {
-      return filterList;
-    }
-
-    // if family based filtering resulted in multiple matches, or if family and id are not
-    // specified,
-    // proceed with renderKit based filtering.
-    filterList = _renderKitFilter(filterList, metadata.getRenderKitId());
-
-    return filterList;
-  }
-
-  /**
-   * filter based on skin id, if mentioned. Otherwise return the list as is
-   *
-   * @param skins
-   * @param id
-   * @return
-   */
-  private List<Skin> _idFilter(List<Skin> skins, String id)
-  {
-    if (id == null || id.isEmpty())
-      return skins;
-
-    List<Skin> filterList = new ArrayList<Skin>(skins.size());
-
-    for (Skin skin : skins)
-      if (id.equals(skin.getId()))
-        filterList.add(skin);
-
-    return filterList;
-  }
-
-  /**
-   * filter based on skin family, if mentioned. Otherwise return the list as is
-   *
-   * @param skins
-   * @param family
-   * @return
-   */
-  private List<Skin> _familyFilter(List<Skin> skins, String family)
-  {
-    if (family == null || family.isEmpty())
-      return skins;
-
-    List<Skin> filterList = new ArrayList<Skin>(skins.size());
-
-    for (Skin skin : skins)
-      if (family.equalsIgnoreCase(skin.getFamily()))
-        filterList.add(skin);
-
-    return filterList;
-  }
-
-  /**
-   * filter based on skin renderkit id, if mentioned. Otherwise return the list as is
-   *
-   * @param skins
-   * @param renderKitId
-   * @return
-   */
-  private List<Skin> _renderKitFilter(List<Skin> skins, String renderKitId)
-  {
-    if (renderKitId == null || renderKitId.isEmpty())
-      return skins;
-
-    List<Skin> filterList = new ArrayList<Skin>(skins.size());
-
-    for (Skin skin : skins)
-      if (renderKitId.equalsIgnoreCase(skin.getRenderKitId()))
-        filterList.add(skin);
-
-    return filterList;
-  }
-
-  /**
-   * filter based on version if version is mentioned try to return exact match else if version is
-   * not mentioned or version is default try to return default skin else try to return leaf skin
-   * else return first match
-   *
-   * @param searchCriteria
-   * @param matchingSkins
-   * @return
-   */
-  private Skin _versionFilter(SkinMetadata searchCriteria,
-                              List<Skin> matchingSkins)
-  {
-    SkinVersion version = searchCriteria.getVersion();
-    Skin matchingSkin;
-    // we can now find the best match based on version
-    // now that there is a version mentioned and skins matching is > 1
-    // look for exact name match
-    matchingSkin = _findSkinForVersionName(matchingSkins, version);
-
-    // if we found exact match in version, return it.
-    if (matchingSkin != null)
-    {
-      if (_LOG.isFine())
-        _LOG.fine("returning exact version match.");
-
-      _processSkinForReturn(searchCriteria, matchingSkin);
-      return matchingSkin;
-    }
-
-    // either user is looking for default version or did not find the version requested
-    // try to find a default skin
-    matchingSkin = _findSkinWithDefaultVersion(matchingSkins);
-
-    // if we found the default version skin, return it.
-    if (matchingSkin != null)
-    {
-      if (_LOG.isFine())
-        _LOG.fine("returning DEFAULT version match.");
-      _processSkinForReturn(searchCriteria, matchingSkin);
-      return matchingSkin;
-    }
-
-    // the version that user asked for is not available
-    // so find leaf skin
-    matchingSkin = _findLeafSkin(matchingSkins);
-
-    // if we found a leaf skin return that
-    if (matchingSkin != null)
-    {
-      if (_LOG.isFine())
-        _LOG.fine("return LEAF skin or one of the matches.");
-
-      _processSkinForReturn(searchCriteria, matchingSkin);
-      return matchingSkin;
-    }
-
-    // we failed to find any better result for the given version, so return first match
-    if (_LOG.isFine())
-      _LOG.fine("nothing worked so return first match.");
-
-    matchingSkin = matchingSkins.get(0);
-    _processSkinForReturn(searchCriteria, matchingSkins.get(0));
-    return matchingSkin;
-  }
-
-  /**
-   * This method processes a skin that is being returned from the provider.
-   * 1. remove the skin from the context tracking
-   * 2. add any missing skin additions to the skin
-   * @param skinMetadata
-   * @return
-   */
-  private void _processSkinForReturn(SkinMetadata skinMetadata,
-                                     Skin skin)
-  {
-    FacesContext context = FacesContext.getCurrentInstance();
-    _clearReturningSkinContext(context, skinMetadata);
-
-    // before returning the skin, ensure that all skin additions defined in trinidad-skins.xml
-    // are added.
-    TrinidadSkinProvider.getCurrentInstance(context.getExternalContext()).ensureSkinAdditions(skin);
-  }
-
-  /**
-   * We track the skin being requested to build the hierarchy so that we can identify circular
-   * dependencies. This method clears the information for the present Skin that is being returned.
-   * @param context
-   * @param skinMetadata
-   */
-  private void _clearReturningSkinContext(FacesContext context, SkinMetadata skinMetadata)
-  {
-    Map attrMap = context.getAttributes();
-    Object o = attrMap.get(_SKIN_PROVIDER_CONTEXT);
-    List<SkinMetadata> requesters;
-
-    if (o != null)
-    {
-      requesters = (List) o;
-      // remove the skinMetadata
-      requesters.remove(skinMetadata);
-
-      if (_LOG.isFiner())
-      {
-        _LOG.finer("Removing " + skinMetadata + " from context");
-        _LOG.finer("Context now is " + requesters);
-      }
-    }
-  }
-
-  /**
-   * find a skin with version passed
-   *
-   * @param skins
-   * @param version
-   * @return
-   */
-  private Skin _findSkinForVersionName(Collection<Skin> skins, SkinVersion version)
-  {
-    if (version == null)
-      throw new IllegalArgumentException("skin version cannot be null");
-
-    if (version.getName() == null || version.getName().isEmpty())
-      return null;
-
-    for (Skin skin : skins)
-    {
-      // metadata cannot be null and also version inside it cannot be null
-      if (version.getName().equals(skin.getVersion().getName()))
-      {
-        if (_LOG.isFine())
-          _LOG.fine("Found version match skin: " + skin);
-
-        return skin;
-      }
-    }
-
-    return null;
-  }
-
-  /**
-   * Latest skin is the one which is last in the family hierarchy eg: fusion-v1 -> fusion-v2 ->
-   * fusion-v3 Among this fusion-v3 is the latest. So we look for a skin that is not extended by any
-   * other skin in the family.
-   *
-   * @param skins
-   * @return
-   */
-  private Skin _findLeafSkin(Collection<Skin> skins)
-  {
-    List<Skin> leafSkins = new ArrayList<Skin>();
-    List<String> parentIds = new ArrayList<String>();
-
-    // collect parents skins among the list
-    for (Skin metadata : skins)
-    {
-      Skin baseSkin = metadata.getBaseSkin();
-      if (baseSkin != null)
-      {
-        String parentId = baseSkin.getId();
-        if (parentId != null)
-          parentIds.add(parentId);
-      }
-    }
-
-    // find leaf skins, which is not in parent list
-    for (Skin skin : skins)
-    {
-      String skinId = skin.getId();
-      if (skinId != null && !parentIds.contains(skinId))
-      {
-        leafSkins.add(skin);
-      }
-    }
-
-    // if there are no leaves, return null
-    // this is a rare case, almost impossible since there will be
-    // at least one skin which is not parent of another
-    // but let us cover the corner case if any
-    if (leafSkins.isEmpty())
-      return null;
-
-    // if there is one leaf skin return that
-    // if there are many, return the last one among the leaves
-    return leafSkins.get(leafSkins.size() - 1);
-  }
-
-  /**
-   * find a skin 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.
-   */
-  private Skin _findSkinWithDefaultVersion(Collection<Skin> matchingSkinList)
-  {
-    for (Skin skin : matchingSkinList)
-    {
-      SkinVersion skinVersion = skin.getVersion();
-
-      if (skinVersion != null && skinVersion.isDefault())
-      {
-        if (_LOG.isFine())
-          _LOG.fine("Found default skin: " + skin);
-
-        return skin;
-      }
-    }
-
-    return null;
-  }
-
-  /**
-   * We track the skin being requested to build the hierarchy so that we can identify circular
-   * dependencies. This method adds the currently requested skin into the context. If a skin is
-   * re-requested, then an exception will be thrown
-   * @param skinMetadata
-   * @throws IllegalStateException if a circular dependency is detected
-   */
-  private void _handleCircularDependency(SkinMetadata skinMetadata)
-  {
-    FacesContext context = FacesContext.getCurrentInstance();
-    Map attrMap = context.getAttributes();
-    Object o = attrMap.get(_SKIN_PROVIDER_CONTEXT);
-    List<SkinMetadata> requesters = null;
-
-    if (o == null)
-    {
-      requesters = new ArrayList<SkinMetadata>();
-      attrMap.put(_SKIN_PROVIDER_CONTEXT, requesters);
-    }
-    else
-      requesters = (List) o;
-
-    if (requesters.contains(skinMetadata))
-    {
-      String message = "Circular dependency detected while loading skin: " + skinMetadata
-                         + ". Requesters are: " + requesters;
-      if (_LOG.isSevere())
-        _LOG.severe(message);
-
-      throw new IllegalStateException(message);
-    }
-
-    // add the currently requested metadata into list
-    requesters.add(skinMetadata);
-
-    if (_LOG.isFiner())
-    {
-      _LOG.finer("Adding " + skinMetadata + " to context");
-      _LOG.finer("Context now is " + requesters);
-    }
-  }
-
-  private final List<SkinProvider> _providers;
-
-  private static final String         _SKIN_PROVIDER_CONTEXT =
-    "org.apache.myfaces.trinidadinternal.skin.provider.SkinProviderRegistry.Context";
-  private static final TrinidadLogger _LOG                   =
-    TrinidadLogger.createTrinidadLogger(SkinProviderRegistry.class);
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.trinidadinternal.skin.provider;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+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.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.skin.SkinUtils;
+
+/**
+ * Internal implementation of SkinProvider which is exposed using SkinProvider.getCurrentInstance()
+ * This class collates all SkinProvider SPIs, Trinidad SkinProviders and SkinFactory to return the
+ * best match for a Skin requested This class reads all registered SPIs using
+ * org.apache.myfaces.trinidad.skin.SkinProvider
+ * <p/>
+ * Instance of this class is created and put into the ExternalContext during bootstrap in
+ * GlobalConfiguratorImpl and retrieved in the static factory inside SkinProvider
+ * <p/>
+ */
+public class SkinProviderRegistry extends SkinProvider
+{
+
+  public SkinProviderRegistry()
+  {
+    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
+    List<SkinProvider> services = ClassLoaderUtils.getServices(SkinProvider.class.getName());
+
+    if (_LOG.isFine())
+      _LOG.fine("Adding providers from registered SPIs... " + services.size());
+
+    List<SkinProvider> providers = new ArrayList<SkinProvider>(services.size() + 2);
+    providers.addAll(services);
+
+    // add internal skin providers at the end
+    // this is to give the other SPIs a chance before the internal skin providers
+    if (_LOG.isFine())
+      _LOG.fine("Adding TrinidadSkinProvider... ");
+
+    providers.add(TrinidadSkinProvider.getCurrentInstance(externalContext));
+
+    if (_LOG.isFine())
+      _LOG.fine("Adding TrinidadBaseSkinProvider... ");
+
+    // this provider serves static base skins, so we can create a new instance here
+    providers.add(new TrinidadBaseSkinProvider());
+
+    if (_LOG.isFine())
+      _LOG.fine("Adding ExternalSkinProvider... ");
+
+    providers.add(ExternalSkinProvider.getCurrentInstance(externalContext));
+
+    _providers = Collections.unmodifiableList(providers);
+  }
+
+  @Override
+  public Collection<SkinMetadata> getSkinMetadata(ExternalContext externalContext)
+  {
+    Collection<SkinMetadata> metadata = new ArrayList<SkinMetadata>();
+
+    for (SkinProvider provider : _providers)
+      metadata.addAll(provider.getSkinMetadata(externalContext));
+
+    return Collections.unmodifiableCollection(metadata);
+  }
+
+  /**
+   * @param externalContext
+   * @param skinMetadata search criteria object containing the information of skin to be queried id,
+   *                     family, renderKit, version are the information used from skin metadata to
+   *                     perform search for the skin requested. Other fields do not participate in
+   *                     the search.
+   * @return matching skin for the search criteria passed, if none found, return the simple skin for
+   * the renderKit in search criteria if renderKit not specified in search criteria, skinMetadata
+   * automatically assumes it as SkinMetadata.RenderKitId.DESKTOP
+   */
+  @Override
+  public Skin getSkin(ExternalContext externalContext, SkinMetadata skinMetadata)
+  {
+    _handleCircularDependency(skinMetadata);
+
+    List<Skin> matchingSkins = new ArrayList<Skin>();
+    Skin matchingSkin = null;
+
+    if (_LOG.isFine())
+      _LOG.fine("Skin request for metadata: " + skinMetadata);
+
+    for (SkinProvider provider : _providers)
+    {
+      matchingSkin = provider.getSkin(externalContext, skinMetadata);
+
+      if (matchingSkin != null)
+      {
+        // log which provider got skin etc
+        if (_LOG.isFine())
+          _LOG.fine("Skin obtained for metadata: " + skinMetadata + " from provider: " + provider);
+
+        matchingSkins.add(matchingSkin);
+      }
+    }
+
+    if (_LOG.isFine())
+      _LOG.fine("Matches obtained for " + skinMetadata + ": " + matchingSkins.size());
+
+    // now we are done with asking all skin providers
+    // ensure that the matching skins returned are indeed matching the search criteria
+    // onus is on SkinProviderRegistry to serve the skin requested, even if a SkinProvider
+    // returns a wrong skin.
+
+    // filter the results obtained from skin providers based on id, family and renderKit
+    // filtering on version is more complicated and taken up subsequently
+    matchingSkins = _filterSkins(matchingSkins, skinMetadata);
+
+    if (matchingSkins.isEmpty())
+    {
+      if (_LOG.isFine())
+        _LOG.fine("NO MATCH. Will return a simple skin or null for skin metadata: " + skinMetadata);
+
+      assert (skinMetadata.getRenderKitId() != null);
+
+      // if renderKit is available return the simple skin for that renderKit
+      // skinMetadata.getRenderKitId() can never be null, default renderKit will always be DESKTOP
+      matchingSkin = SkinUtils.getDefaultSkinForRenderKitId(this,
+                                                            externalContext,
+                                                            skinMetadata.getRenderKitId());
+      _processSkinForReturn(skinMetadata, matchingSkin);
+      return matchingSkin;
+    }
+
+
+    // we have at least one match now
+    // if we have only one match
+    // return that skin
+    if (matchingSkins.size() == 1)
+    {
+      if (_LOG.isFine())
+        _LOG.fine("returning ONLY match for skin metadata: " + skinMetadata);
+
+
+      matchingSkin = matchingSkins.get(0);
+      _processSkinForReturn(skinMetadata, matchingSkin);
+      return matchingSkin;
+    }
+
+    // at this point we have more than one matches for the search criteria passed
+    // so, extract the best match based on version
+    return _versionFilter(skinMetadata, matchingSkins);
+  }
+
+  /**
+   * exposing providers for testability
+   * @return
+   */
+  List<SkinProvider> getProviders()
+  {
+    return _providers;
+  }
+
+  /**
+   * ensure sanity in the list of matches received by filtering the skins based on id, family and
+   * renderKit
+   *
+   * @param skins
+   * @param metadata
+   * @return
+   */
+  private List<Skin> _filterSkins(List<Skin> skins, SkinMetadata metadata)
+  {
+    if (skins == null || skins.isEmpty() || metadata == null)
+      return Collections.emptyList();
+
+    List<Skin> filterList = _idFilter(skins, metadata.getId());
+
+    // if the id based filtering resulted in only match then return that
+    // provided id was mentioned in search criteria
+    if (filterList.size() == 1 && metadata.getId() != null)
+    {
+      return filterList;
+    }
+
+    // if more than one match for id or if id is not specified, then filter by family
+    filterList = _familyFilter(filterList, metadata.getFamily());
+
+    // if the family based filtering resulted in only match then return that
+    // provided family was mentioned in search criteria
+    if (filterList.size() == 1 && metadata.getFamily() != null)
+    {
+      return filterList;
+    }
+
+    // if family based filtering resulted in multiple matches, or if family and id are not
+    // specified,
+    // proceed with renderKit based filtering.
+    filterList = _renderKitFilter(filterList, metadata.getRenderKitId());
+
+    return filterList;
+  }
+
+  /**
+   * filter based on skin id, if mentioned. Otherwise return the list as is
+   *
+   * @param skins
+   * @param id
+   * @return
+   */
+  private List<Skin> _idFilter(List<Skin> skins, String id)
+  {
+    if (id == null || id.isEmpty())
+      return skins;
+
+    List<Skin> filterList = new ArrayList<Skin>(skins.size());
+
+    for (Skin skin : skins)
+      if (id.equals(skin.getId()))
+        filterList.add(skin);
+
+    return filterList;
+  }
+
+  /**
+   * filter based on skin family, if mentioned. Otherwise return the list as is
+   *
+   * @param skins
+   * @param family
+   * @return
+   */
+  private List<Skin> _familyFilter(List<Skin> skins, String family)
+  {
+    if (family == null || family.isEmpty())
+      return skins;
+
+    List<Skin> filterList = new ArrayList<Skin>(skins.size());
+
+    for (Skin skin : skins)
+      if (family.equalsIgnoreCase(skin.getFamily()))
+        filterList.add(skin);
+
+    return filterList;
+  }
+
+  /**
+   * filter based on skin renderkit id, if mentioned. Otherwise return the list as is
+   *
+   * @param skins
+   * @param renderKitId
+   * @return
+   */
+  private List<Skin> _renderKitFilter(List<Skin> skins, String renderKitId)
+  {
+    if (renderKitId == null || renderKitId.isEmpty())
+      return skins;
+
+    List<Skin> filterList = new ArrayList<Skin>(skins.size());
+
+    for (Skin skin : skins)
+      if (renderKitId.equalsIgnoreCase(skin.getRenderKitId()))
+        filterList.add(skin);
+
+    return filterList;
+  }
+
+  /**
+   * filter based on version if version is mentioned try to return exact match else if version is
+   * not mentioned or version is default try to return default skin else try to return leaf skin
+   * else return first match
+   *
+   * @param searchCriteria
+   * @param matchingSkins
+   * @return
+   */
+  private Skin _versionFilter(SkinMetadata searchCriteria,
+                              List<Skin> matchingSkins)
+  {
+    SkinVersion version = searchCriteria.getVersion();
+    Skin matchingSkin;
+    // we can now find the best match based on version
+    // now that there is a version mentioned and skins matching is > 1
+    // look for exact name match
+    matchingSkin = _findSkinForVersionName(matchingSkins, version);
+
+    // if we found exact match in version, return it.
+    if (matchingSkin != null)
+    {
+      if (_LOG.isFine())
+        _LOG.fine("returning exact version match.");
+
+      _processSkinForReturn(searchCriteria, matchingSkin);
+      return matchingSkin;
+    }
+
+    // either user is looking for default version or did not find the version requested
+    // try to find a default skin
+    matchingSkin = _findSkinWithDefaultVersion(matchingSkins);
+
+    // if we found the default version skin, return it.
+    if (matchingSkin != null)
+    {
+      if (_LOG.isFine())
+        _LOG.fine("returning DEFAULT version match.");
+      _processSkinForReturn(searchCriteria, matchingSkin);
+      return matchingSkin;
+    }
+
+    // the version that user asked for is not available
+    // so find leaf skin
+    matchingSkin = _findLeafSkin(matchingSkins);
+
+    // if we found a leaf skin return that
+    if (matchingSkin != null)
+    {
+      if (_LOG.isFine())
+        _LOG.fine("return LEAF skin or one of the matches.");
+
+      _processSkinForReturn(searchCriteria, matchingSkin);
+      return matchingSkin;
+    }
+
+    // we failed to find any better result for the given version, so return first match
+    if (_LOG.isFine())
+      _LOG.fine("nothing worked so return first match.");
+
+    matchingSkin = matchingSkins.get(0);
+    _processSkinForReturn(searchCriteria, matchingSkins.get(0));
+    return matchingSkin;
+  }
+
+  /**
+   * This method processes a skin that is being returned from the provider.
+   * 1. remove the skin from the context tracking
+   * 2. add any missing skin additions to the skin
+   * @param skinMetadata
+   * @return
+   */
+  private void _processSkinForReturn(SkinMetadata skinMetadata,
+                                     Skin skin)
+  {
+    FacesContext context = FacesContext.getCurrentInstance();
+    _clearReturningSkinContext(context, skinMetadata);
+
+    // before returning the skin, ensure that all skin additions defined in trinidad-skins.xml
+    // are added.
+    TrinidadSkinProvider.getCurrentInstance(context.getExternalContext()).ensureSkinAdditions(skin);
+  }
+
+  /**
+   * We track the skin being requested to build the hierarchy so that we can identify circular
+   * dependencies. This method clears the information for the present Skin that is being returned.
+   * @param context
+   * @param skinMetadata
+   */
+  private void _clearReturningSkinContext(FacesContext context, SkinMetadata skinMetadata)
+  {
+    Map attrMap = context.getAttributes();
+    Object o = attrMap.get(_SKIN_PROVIDER_CONTEXT);
+    List<SkinMetadata> requesters;
+
+    if (o != null)
+    {
+      requesters = (List) o;
+      // remove the skinMetadata
+      requesters.remove(skinMetadata);
+
+      if (_LOG.isFiner())
+      {
+        _LOG.finer("Removing " + skinMetadata + " from context");
+        _LOG.finer("Context now is " + requesters);
+      }
+    }
+  }
+
+  /**
+   * find a skin with version passed
+   *
+   * @param skins
+   * @param version
+   * @return
+   */
+  private Skin _findSkinForVersionName(Collection<Skin> skins, SkinVersion version)
+  {
+    if (version == null)
+      throw new IllegalArgumentException("skin version cannot be null");
+
+    if (version.getName() == null || version.getName().isEmpty())
+      return null;
+
+    for (Skin skin : skins)
+    {
+      // metadata cannot be null and also version inside it cannot be null
+      if (version.getName().equals(skin.getVersion().getName()))
+      {
+        if (_LOG.isFine())
+          _LOG.fine("Found version match skin: " + skin);
+
+        return skin;
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Latest skin is the one which is last in the family hierarchy eg: fusion-v1 -> fusion-v2 ->
+   * fusion-v3 Among this fusion-v3 is the latest. So we look for a skin that is not extended by any
+   * other skin in the family.
+   *
+   * @param skins
+   * @return
+   */
+  private Skin _findLeafSkin(Collection<Skin> skins)
+  {
+    List<Skin> leafSkins = new ArrayList<Skin>();
+    List<String> parentIds = new ArrayList<String>();
+
+    // collect parents skins among the list
+    for (Skin metadata : skins)
+    {
+      Skin baseSkin = metadata.getBaseSkin();
+      if (baseSkin != null)
+      {
+        String parentId = baseSkin.getId();
+        if (parentId != null)
+          parentIds.add(parentId);
+      }
+    }
+
+    // find leaf skins, which is not in parent list
+    for (Skin skin : skins)
+    {
+      String skinId = skin.getId();
+      if (skinId != null && !parentIds.contains(skinId))
+      {
+        leafSkins.add(skin);
+      }
+    }
+
+    // if there are no leaves, return null
+    // this is a rare case, almost impossible since there will be
+    // at least one skin which is not parent of another
+    // but let us cover the corner case if any
+    if (leafSkins.isEmpty())
+      return null;
+
+    // if there is one leaf skin return that
+    // if there are many, return the last one among the leaves
+    return leafSkins.get(leafSkins.size() - 1);
+  }
+
+  /**
+   * find a skin 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.
+   */
+  private Skin _findSkinWithDefaultVersion(Collection<Skin> matchingSkinList)
+  {
+    for (Skin skin : matchingSkinList)
+    {
+      SkinVersion skinVersion = skin.getVersion();
+
+      if (skinVersion != null && skinVersion.isDefault())
+      {
+        if (_LOG.isFine())
+          _LOG.fine("Found default skin: " + skin);
+
+        return skin;
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * We track the skin being requested to build the hierarchy so that we can identify circular
+   * dependencies. This method adds the currently requested skin into the context. If a skin is
+   * re-requested, then an exception will be thrown
+   * @param skinMetadata
+   * @throws IllegalStateException if a circular dependency is detected
+   */
+  private void _handleCircularDependency(SkinMetadata skinMetadata)
+  {
+    FacesContext context = FacesContext.getCurrentInstance();
+    Map attrMap = context.getAttributes();
+    Object o = attrMap.get(_SKIN_PROVIDER_CONTEXT);
+    List<SkinMetadata> requesters = null;
+
+    if (o == null)
+    {
+      requesters = new ArrayList<SkinMetadata>();
+      attrMap.put(_SKIN_PROVIDER_CONTEXT, requesters);
+    }
+    else
+      requesters = (List) o;
+
+    if (requesters.contains(skinMetadata))
+    {
+      String message = "Circular dependency detected while loading skin: " + skinMetadata
+                         + ". Requesters are: " + requesters;
+      if (_LOG.isSevere())
+        _LOG.severe(message);
+
+      throw new IllegalStateException(message);
+    }
+
+    // add the currently requested metadata into list
+    requesters.add(skinMetadata);
+
+    if (_LOG.isFiner())
+    {
+      _LOG.finer("Adding " + skinMetadata + " to context");
+      _LOG.finer("Context now is " + requesters);
+    }
+  }
+
+  private final List<SkinProvider> _providers;
+
+  private static final String         _SKIN_PROVIDER_CONTEXT =
+    "org.apache.myfaces.trinidadinternal.skin.provider.SkinProviderRegistry.Context";
+  private static final TrinidadLogger _LOG                   =
+    TrinidadLogger.createTrinidadLogger(SkinProviderRegistry.class);
 }
\ No newline at end of file

Propchange: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/SkinProviderRegistry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/TrinidadSkinProvider.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/TrinidadSkinProvider.java?rev=1632268&r1=1632267&r2=1632268&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/TrinidadSkinProvider.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/TrinidadSkinProvider.java Thu Oct 16 10:31:25 2014
@@ -1,217 +1,217 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.trinidadinternal.skin.provider;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import javax.faces.context.ExternalContext;
-
-import org.apache.myfaces.trinidad.logging.TrinidadLogger;
-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.SkinProvider;
-import org.apache.myfaces.trinidadinternal.skin.SkinExtension;
-import org.apache.myfaces.trinidadinternal.skin.SkinUtils;
-import org.apache.myfaces.trinidadinternal.skin.parse.SkinsNode;
-
-/**
- * This is the Trinidad's SkinProvider for loading skins from trinidad-skins.xml. This provider
- * reads and caches trinidad-skins.xml from various sources like META-INF, WEB-INF and
- * SkinResourceLoader API during its initialization. Subsequently the Skin objects are created
- * lazily using the cached metadata, only when it is first requested for.
- */
-public final class TrinidadSkinProvider extends BaseSkinProvider
-{
-  /**
-   * Key for the TrinidadSkinProvider stored in ExternalContext
-   */
-  public static final String TRINDIAD_SKIN_PROVIDER_KEY =
-    "org.apache.myfaces.trinidad.skin.TRINIDAD_SKIN_PROVIDER_INSTANCE";
-
-  /**
-   * static factory method to get hold of a TrinidadSkinProvider object This can be used for easy
-   * creation of Skin object without having to implement the abstract class
-   *
-   * @param ec
-   * @return
-   */
-  public static TrinidadSkinProvider getCurrentInstance(ExternalContext ec)
-  {
-    if (ec == null)
-      throw new NullPointerException("ExternalContext is passed as null");
-
-    TrinidadSkinProvider trinidadSkinProvider =
-      (TrinidadSkinProvider) ec.getApplicationMap().get(TRINDIAD_SKIN_PROVIDER_KEY);
-    return trinidadSkinProvider;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public Collection<SkinMetadata> getSkinMetadata(ExternalContext context)
-  {
-    initialize(context);
-    return _skinMetadata;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected Skin loadAvailableSkin(ExternalContext context, SkinMetadata skinMetadata)
-  {
-    SkinMetadata matchingNode = null;
-
-    for (SkinMetadata node : _skinMetadata)
-    {
-      if (skinMetadata.getId().equals(node.getId()))
-      {
-        matchingNode = node;
-        break;
-      }
-    }
-
-    if (matchingNode == null)
-    {
-      // This cannot happen because base class checks for availability before it calls for the
-      // skin to be loaded
-      String message = _LOG.getMessage("SP_LOADING_UNKNOWN_SKIN", skinMetadata.getId());
-      _LOG.severe(message);
-      throw new IllegalArgumentException(message);
-    }
-
-    String id = matchingNode.getId();
-    String family = matchingNode.getFamily();
-    String renderKitId = matchingNode.getRenderKitId();
-    Skin baseSkin = null;
-    String baseSkinId = matchingNode.getBaseSkinId();
-    SkinProvider provider = SkinProvider.getCurrentInstance(context);
-
-    if (provider != null && baseSkinId != null)
-      baseSkin = provider.getSkin(context, new SkinMetadata.Builder().id(baseSkinId).build());
-
-    // if there is no base skin then use the default base skin for the renderKit
-    if (baseSkin == null)
-    {
-      baseSkin = SkinUtils.getDefaultSkinForRenderKitId(provider, context, renderKitId);
-    }
-
-    if (id == null)
-      throw new NullPointerException(_LOG.getMessage("NULL_SKIN_ID"));
-
-    if (family == null)
-      throw new NullPointerException("Null family");
-
-    _LOG.fine("Creating skin extension for skin metadata {0}", skinMetadata);
-    return new SkinExtension(baseSkin, matchingNode, true);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected void initialize(ExternalContext extCtxt)
-  {
-    if (extCtxt == null)
-    {
-      throw new NullPointerException("ExternalContext is passed as null");
-    }
-
-    if (_skinMetadata == null)
-    {
-      if (_LOG.isFine())
-        _LOG.fine("init provider.");
-
-      // only now do initialization
-      List<SkinsNode> skinsNodes = SkinUtils.buildSkinsNodes(extCtxt);
-      List<SkinMetadata> skinNodes = new ArrayList<SkinMetadata>();
-      List<SkinAddition> skinAdditionNodes = new ArrayList<SkinAddition>();
-
-      for (SkinsNode node : skinsNodes)
-      {
-        if (node != null)
-        {
-          skinNodes.addAll(node.getSkinNodes());
-          skinAdditionNodes.addAll(node.getSkinAdditionNodes());
-        }
-      }
-
-      if (skinNodes.isEmpty())
-        _skinMetadata = Collections.emptyList();
-      else
-        _skinMetadata = Collections.unmodifiableList(skinNodes);
-
-      if (skinAdditionNodes.isEmpty())
-        _skinAdditionNodes = Collections.emptyList();
-      else
-        _skinAdditionNodes = Collections.unmodifiableList(skinAdditionNodes);
-
-      if (_LOG.isFine())
-      {
-        _LOG.fine("Number of skin metadata loaded from trinidad-skins.xml: {0}", _skinMetadata.size());
-        _LOG.fine("Number of skin additions loaded from trinidad-skins.xml: {0}", _skinAdditionNodes.size());
-      }
-    }
-  }
-
-  /**
-   * used to ensure that the skin and its base skin additions are added correctly
-   * This is called at the exit point of SkinProviderRegistry
-   * @param skin
-   */
-  void ensureSkinAdditions(Skin skin)
-  {
-    if (_skinAdditionNodes == null || _skinAdditionNodes.isEmpty())
-      return;
-
-    for (SkinAddition addition : _skinAdditionNodes)
-    {
-      // skin additions in _skinAdditionNodes will not be null
-      _checkAndAddInHierarchy(skin, addition);
-    }
-  }
-
-  private void _checkAndAddInHierarchy(Skin skin, SkinAddition addition)
-  {
-    // exit condition for the recursive call
-    if (skin == null)
-      return;
-
-    String skinId = addition.getSkinId();
-
-    if (skinId != null && skinId.equals(skin.getId()))
-    {
-      skin.addSkinAddition(addition);
-    }
-
-    _checkAndAddInHierarchy(skin.getBaseSkin(), addition);
-  }
-
-  private List<SkinMetadata> _skinMetadata;
-  private List<SkinAddition> _skinAdditionNodes;
-
-  private final static TrinidadLogger _LOG =
-    TrinidadLogger.createTrinidadLogger(TrinidadSkinProvider.class);
-}
-
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.trinidadinternal.skin.provider;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.faces.context.ExternalContext;
+
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+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.SkinProvider;
+import org.apache.myfaces.trinidadinternal.skin.SkinExtension;
+import org.apache.myfaces.trinidadinternal.skin.SkinUtils;
+import org.apache.myfaces.trinidadinternal.skin.parse.SkinsNode;
+
+/**
+ * This is the Trinidad's SkinProvider for loading skins from trinidad-skins.xml. This provider
+ * reads and caches trinidad-skins.xml from various sources like META-INF, WEB-INF and
+ * SkinResourceLoader API during its initialization. Subsequently the Skin objects are created
+ * lazily using the cached metadata, only when it is first requested for.
+ */
+public final class TrinidadSkinProvider extends BaseSkinProvider
+{
+  /**
+   * Key for the TrinidadSkinProvider stored in ExternalContext
+   */
+  public static final String TRINDIAD_SKIN_PROVIDER_KEY =
+    "org.apache.myfaces.trinidad.skin.TRINIDAD_SKIN_PROVIDER_INSTANCE";
+
+  /**
+   * static factory method to get hold of a TrinidadSkinProvider object This can be used for easy
+   * creation of Skin object without having to implement the abstract class
+   *
+   * @param ec
+   * @return
+   */
+  public static TrinidadSkinProvider getCurrentInstance(ExternalContext ec)
+  {
+    if (ec == null)
+      throw new NullPointerException("ExternalContext is passed as null");
+
+    TrinidadSkinProvider trinidadSkinProvider =
+      (TrinidadSkinProvider) ec.getApplicationMap().get(TRINDIAD_SKIN_PROVIDER_KEY);
+    return trinidadSkinProvider;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Collection<SkinMetadata> getSkinMetadata(ExternalContext context)
+  {
+    initialize(context);
+    return _skinMetadata;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Skin loadAvailableSkin(ExternalContext context, SkinMetadata skinMetadata)
+  {
+    SkinMetadata matchingNode = null;
+
+    for (SkinMetadata node : _skinMetadata)
+    {
+      if (skinMetadata.getId().equals(node.getId()))
+      {
+        matchingNode = node;
+        break;
+      }
+    }
+
+    if (matchingNode == null)
+    {
+      // This cannot happen because base class checks for availability before it calls for the
+      // skin to be loaded
+      String message = _LOG.getMessage("SP_LOADING_UNKNOWN_SKIN", skinMetadata.getId());
+      _LOG.severe(message);
+      throw new IllegalArgumentException(message);
+    }
+
+    String id = matchingNode.getId();
+    String family = matchingNode.getFamily();
+    String renderKitId = matchingNode.getRenderKitId();
+    Skin baseSkin = null;
+    String baseSkinId = matchingNode.getBaseSkinId();
+    SkinProvider provider = SkinProvider.getCurrentInstance(context);
+
+    if (provider != null && baseSkinId != null)
+      baseSkin = provider.getSkin(context, new SkinMetadata.Builder().id(baseSkinId).build());
+
+    // if there is no base skin then use the default base skin for the renderKit
+    if (baseSkin == null)
+    {
+      baseSkin = SkinUtils.getDefaultSkinForRenderKitId(provider, context, renderKitId);
+    }
+
+    if (id == null)
+      throw new NullPointerException(_LOG.getMessage("NULL_SKIN_ID"));
+
+    if (family == null)
+      throw new NullPointerException("Null family");
+
+    _LOG.fine("Creating skin extension for skin metadata {0}", skinMetadata);
+    return new SkinExtension(baseSkin, matchingNode, true);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected void initialize(ExternalContext extCtxt)
+  {
+    if (extCtxt == null)
+    {
+      throw new NullPointerException("ExternalContext is passed as null");
+    }
+
+    if (_skinMetadata == null)
+    {
+      if (_LOG.isFine())
+        _LOG.fine("init provider.");
+
+      // only now do initialization
+      List<SkinsNode> skinsNodes = SkinUtils.buildSkinsNodes(extCtxt);
+      List<SkinMetadata> skinNodes = new ArrayList<SkinMetadata>();
+      List<SkinAddition> skinAdditionNodes = new ArrayList<SkinAddition>();
+
+      for (SkinsNode node : skinsNodes)
+      {
+        if (node != null)
+        {
+          skinNodes.addAll(node.getSkinNodes());
+          skinAdditionNodes.addAll(node.getSkinAdditionNodes());
+        }
+      }
+
+      if (skinNodes.isEmpty())
+        _skinMetadata = Collections.emptyList();
+      else
+        _skinMetadata = Collections.unmodifiableList(skinNodes);
+
+      if (skinAdditionNodes.isEmpty())
+        _skinAdditionNodes = Collections.emptyList();
+      else
+        _skinAdditionNodes = Collections.unmodifiableList(skinAdditionNodes);
+
+      if (_LOG.isFine())
+      {
+        _LOG.fine("Number of skin metadata loaded from trinidad-skins.xml: {0}", _skinMetadata.size());
+        _LOG.fine("Number of skin additions loaded from trinidad-skins.xml: {0}", _skinAdditionNodes.size());
+      }
+    }
+  }
+
+  /**
+   * used to ensure that the skin and its base skin additions are added correctly
+   * This is called at the exit point of SkinProviderRegistry
+   * @param skin
+   */
+  void ensureSkinAdditions(Skin skin)
+  {
+    if (_skinAdditionNodes == null || _skinAdditionNodes.isEmpty())
+      return;
+
+    for (SkinAddition addition : _skinAdditionNodes)
+    {
+      // skin additions in _skinAdditionNodes will not be null
+      _checkAndAddInHierarchy(skin, addition);
+    }
+  }
+
+  private void _checkAndAddInHierarchy(Skin skin, SkinAddition addition)
+  {
+    // exit condition for the recursive call
+    if (skin == null)
+      return;
+
+    String skinId = addition.getSkinId();
+
+    if (skinId != null && skinId.equals(skin.getId()))
+    {
+      skin.addSkinAddition(addition);
+    }
+
+    _checkAndAddInHierarchy(skin.getBaseSkin(), addition);
+  }
+
+  private List<SkinMetadata> _skinMetadata;
+  private List<SkinAddition> _skinAdditionNodes;
+
+  private final static TrinidadLogger _LOG =
+    TrinidadLogger.createTrinidadLogger(TrinidadSkinProvider.class);
+}
+

Propchange: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/provider/TrinidadSkinProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/CopyOnWriteArrayMap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/custom/CustomSkinProvider1.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/custom/CustomSkinProvider2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/provider/SkinProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/util/CopyOnWriteArrayMapTest.java
------------------------------------------------------------------------------
    svn:eol-style = native