[gatein-commits] gatein SVN: r7695 - in portal/trunk/component: common/src/test/java/org/exoplatform/commons/cache/future and 11 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Mon Oct 10 04:29:58 EDT 2011


Author: trong.tran
Date: 2011-10-10 04:29:57 -0400 (Mon, 10 Oct 2011)
New Revision: 7695

Added:
   portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureMap.java
   portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/AbstractSkinServiceTest.java
   portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/MockResourceResolver.java
   portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinServiceInDevelopingMode.java
   portal/trunk/component/web/resources/src/test/resources/conf/resource-compressor-service-configuration.xml
   portal/trunk/component/web/resources/src/test/resources/conf/test-configuration.xml
   portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/FirstPortlet.css
   portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/SecondPortlet.css
Removed:
   portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java
   portal/trunk/component/web/resources/src/test/resources/conf/js-service-configuration.xml
   portal/trunk/component/web/resources/src/test/resources/conf/resource-compressor-service-configuration.xml
   portal/trunk/component/web/resources/src/test/resources/conf/skin-service-configuration.xml
   portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/portal/TestSkin/
   portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/portlet/
Modified:
   portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java
   portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/SimpleSkin.java
   portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java
   portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/compressor/ResourceCompressor.java
   portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/compressor/impl/ResourceCompressorService.java
   portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/tasks/PortalSkinTask.java
   portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/tasks/PortletSkinTask.java
   portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/xml/SkinConfigParser.java
   portal/trunk/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java
   portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/AbstractWebResourceTest.java
   portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinService.java
   portal/trunk/component/web/resources/src/test/resources/mockwebapp/gatein-resources.xml
Log:
GTNPORTAL-2157 Enhance SkinService implementation

Copied: portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureMap.java (from rev 7693, portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java)
===================================================================
--- portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureMap.java	                        (rev 0)
+++ portal/trunk/component/common/src/main/java/org/exoplatform/commons/cache/future/FutureMap.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.cache.future;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class FutureMap<K extends Serializable, V, C> extends FutureCache<K, V, C>
+{
+
+   /** . */
+   final Map<K, V> data;
+
+   public FutureMap(Loader<K, V, C> loader)
+   {
+      super(loader);
+
+      //
+      this.data = Collections.synchronizedMap(new HashMap<K, V>());
+   }
+
+   public void clear()
+   {
+      data.clear();
+   }
+
+   public void remove(K key)
+   {
+      data.remove(key);
+   }
+
+   @Override
+   protected V get(K key)
+   {
+      return data.get(key);
+   }
+
+   @Override
+   protected void put(K key, V value)
+   {
+      data.put(key, value);
+   }
+}
\ No newline at end of file

Deleted: portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java
===================================================================
--- portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/FutureMap.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2009 eXo Platform SAS.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.exoplatform.commons.cache.future;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
- * @version $Revision$
- */
-public class FutureMap<C> extends FutureCache<String, String, C>
-{
-
-   /** . */
-   final Map<String, String> data;
-
-   public FutureMap(Loader<String, String, C> loader)
-   {
-      super(loader);
-
-      //
-      this.data = Collections.synchronizedMap(new HashMap<String, String>());
-   }
-
-   @Override
-   protected String get(String key)
-   {
-      return data.get(key);
-   }
-
-   @Override
-   protected void put(String key, String value)
-   {
-      data.put(key, value);
-   }
-}

Modified: portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java
===================================================================
--- portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/common/src/test/java/org/exoplatform/commons/cache/future/GetTestCase.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -23,7 +23,6 @@
 import junit.framework.TestCase;
 
 import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
@@ -33,7 +32,7 @@
 {
    public void testGet()
    {
-      FutureMap<Callable<String>> futureCache = new FutureMap<Callable<String>>(new StringLoader());
+      FutureMap<String, String, Callable<String>> futureCache = new FutureMap<String, String, Callable<String>>(new StringLoader());
       Assert.assertEquals("foo_value", futureCache.get(new Callable<String>()
       {
          public String call() throws Exception
@@ -46,7 +45,7 @@
 
    public void testNullValue()
    {
-      FutureMap<Callable<String>> futureCache = new FutureMap<Callable<String>>(new StringLoader());
+      FutureMap<String, String, Callable<String>> futureCache = new FutureMap<String, String, Callable<String>>(new StringLoader());
       Assert.assertEquals(null, futureCache.get(new Callable<String>()
       {
          public String call() throws Exception
@@ -59,7 +58,7 @@
 
    public void testThrowException()
    {
-      FutureMap<Callable<String>> futureCache = new FutureMap<Callable<String>>(new StringLoader());
+      FutureMap<String, String, Callable<String>> futureCache = new FutureMap<String, String, Callable<String>>(new StringLoader());
       Assert.assertEquals(null, futureCache.get(new Callable<String>()
       {
          public String call() throws Exception
@@ -72,7 +71,7 @@
 
    public void testReentrancy()
    {
-      final FutureMap<Callable<String>> futureCache = new FutureMap<Callable<String>>(new StringLoader());
+      final FutureMap<String, String, Callable<String>> futureCache = new FutureMap<String, String, Callable<String>>(new StringLoader());
       String res = futureCache.get(new Callable<String>()
       {
          public String call() throws Exception

Modified: portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/SimpleSkin.java
===================================================================
--- portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/SimpleSkin.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/SimpleSkin.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -40,31 +40,26 @@
 
    private final String id_;
    
-   private final int cssPriority_;
+   private final int priority;
 
    public SimpleSkin(SkinService service, String module, String name, String cssPath)
    {
-      service_ = service;
-      module_ = module;
-      name_ = name;
-      cssPath_ = cssPath;
-      id_ = module.replace('/', '_');
-      cssPriority_ = -1;
+      this(service, module, name, cssPath, Integer.MAX_VALUE);
    }
 
-   public SimpleSkin(SkinService service, String module, String name, String cssPath, Integer cssPriority)
+   public SimpleSkin(SkinService service, String module, String name, String cssPath, int cssPriority)
    {
       service_ = service;
       module_ = module;
       name_ = name;
       cssPath_ = cssPath;
       id_ = module.replace('/', '_');
-      cssPriority_ = cssPriority != null ? cssPriority : -1;
+      priority = cssPriority;
    }
    
    public int getCSSPriority()
    {
-      return cssPriority_;
+      return priority;
    }
    
    public String getId()
@@ -89,7 +84,7 @@
 
    public String toString()
    {
-      return "SimpleSkin[id=" + id_ + ",module=" + module_ + ",name=" + name_ + ",cssPath=" + cssPath_ + "]";
+      return "SimpleSkin[id=" + id_ + ",module=" + module_ + ",name=" + name_ + ",cssPath=" + cssPath_ + ", priority=" + priority +"]";
    }
    
    public SkinURL createURL()

Modified: portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java
===================================================================
--- portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -19,7 +19,7 @@
 
 package org.exoplatform.portal.resource;
 
-import org.exoplatform.commons.cache.future.FutureExoCache;
+import org.exoplatform.commons.cache.future.FutureMap;
 import org.exoplatform.commons.cache.future.Loader;
 import org.exoplatform.commons.utils.BinaryOutput;
 import org.exoplatform.commons.utils.ByteArrayOutput;
@@ -36,7 +36,6 @@
 import org.exoplatform.management.rest.annotations.RESTEndpoint;
 import org.exoplatform.portal.resource.compressor.ResourceCompressor;
 import org.exoplatform.portal.resource.compressor.ResourceType;
-import org.exoplatform.services.cache.concurrent.ConcurrentFIFOExoCache;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.exoplatform.services.resources.Orientation;
@@ -46,13 +45,10 @@
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Date;
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -123,9 +119,9 @@
 
    private final HashSet<String> availableSkins_;
 
-   private final FutureExoCache<String, CachedStylesheet, Orientation> ltCache;
+   private final FutureMap<String, CachedStylesheet, Orientation> ltCache;
 
-   private final FutureExoCache<String, CachedStylesheet, Orientation> rtCache;
+   private final FutureMap<String, CachedStylesheet, Orientation> rtCache;
 
    private final Map<String, Set<String>> portletThemes_;
 
@@ -152,19 +148,25 @@
       {
          public CachedStylesheet retrieve(Orientation context, String key) throws Exception
          {
+            Resource skin = getCSSResource(key, key);
+            if (skin == null)
+            {
+               return null;
+            }
+            
             StringBuffer sb = new StringBuffer();
-            processCSS(sb, key, context, true);
-            String css;
+            processCSSRecursively(sb, true, skin, context);
+            String css = sb.toString();;
             try
             {
-               StringWriter output = new StringWriter();
-               SkinService.this.compressor.compress(new StringReader(sb.toString()), output, ResourceType.STYLESHEET);
-               css = output.toString();
+               if (SkinService.this.compressor.isSupported(ResourceType.STYLESHEET))
+               {
+                  css = SkinService.this.compressor.compress(css, ResourceType.STYLESHEET);
+               }
             }
             catch (Exception e)
             {
                log.warn("Error when compressing CSS " + key + " for orientation " + context + " will use normal CSS instead", e);
-               css = sb.toString();
             }
 
             return new CachedStylesheet(css);
@@ -176,8 +178,8 @@
       portalSkins_ = new LinkedHashMap<SkinKey, SkinConfig>();
       skinConfigs_ = new LinkedHashMap<SkinKey, SkinConfig>(20);
       availableSkins_ = new HashSet<String>(5);
-      ltCache = new FutureExoCache<String, CachedStylesheet, Orientation>(loader, new ConcurrentFIFOExoCache<String, CachedStylesheet>(200));
-      rtCache = new FutureExoCache<String, CachedStylesheet, Orientation>(loader, new ConcurrentFIFOExoCache<String, CachedStylesheet>(200));
+      ltCache = new FutureMap<String, CachedStylesheet, Orientation>(loader);
+      rtCache = new FutureMap<String, CachedStylesheet, Orientation>(loader);
       portletThemes_ = new HashMap<String, Set<String>>();
       portalContainerName = context.getPortalContainerName();
       mainResolver = new MainResourceResolver(portalContainerName, skinConfigs_);
@@ -186,97 +188,39 @@
    }
 
    /**
-    * add category into portletThemes_ if portletThemes does not contain one
-    * @param categoryName: category's name that wangt to add into portletThemes
+    * Add a new category for portlet themes if it does not exist
+    * 
+    * @param categoryName the category name
     */
    public void addCategoryTheme(String categoryName)
    {
       if (!portletThemes_.containsKey(categoryName))
+      {
          portletThemes_.put(categoryName, new HashSet<String>());
+      }
    }
 
    /**
-    * Register the stylesheet for a portal Skin. Do not replace any previous skin 
-    * 
-    * @param module
-    *           skin module identifier
-    * @param skinName
-    *           skin name
-    * @param cssPath
-    *           path uri to the css file. This is relative to the root context,
-    *           use leading '/'
-    * @param scontext
-    *           the webapp's {@link javax.servlet.ServletContext}
+    * @deprecated use {@link #addPortalSkin(String, String, String, int, boolean)} instead 
     */
+   @Deprecated
    public void addPortalSkin(String module, String skinName, String cssPath, ServletContext scontext)
    {
-      addPortalSkin(module, skinName, cssPath, scontext, false);
+      addPortalSkin(module, skinName, cssPath, Integer.MAX_VALUE, false);
    }
+   
 
    /**
-    * Register the stylesheet for a portal Skin.
-    * 
-    * @param module
-    *           skin module identifier
-    * @param skinName
-    *           skin name
-    * @param cssPath
-    *           path uri to the css file. This is relative to the root context,
-    *           use leading '/'
-    * @param scontext
-    *           the webapp's {@link javax.servlet.ServletContext}
-    * @param overwrite
-    *           if any previous skin should be replaced by that one
+    * @deprecated use {@link #addPortalSkin(String, String, String, int, boolean)} instead
     */
+   @Deprecated
    public void addPortalSkin(String module, String skinName, String cssPath, ServletContext scontext, boolean overwrite)
    {
-      availableSkins_.add(skinName);
-      SkinKey key = new SkinKey(module, skinName);
-      SkinConfig skinConfig = portalSkins_.get(key);
-      if (skinConfig == null || overwrite)
-      {
-         skinConfig = new SimpleSkin(this, module, skinName, cssPath);
-         portalSkins_.put(key, skinConfig);
-         
-         if (log.isDebugEnabled())
-         {
-            log.debug("Adding Portal skin : Bind " + key + " to " + skinConfig);
-         }
-      }
+      addPortalSkin(module, skinName, cssPath, Integer.MAX_VALUE, overwrite);
    }
-   
-   /**
-    * Register the stylesheet for a portal Skin.
-    * 
-    * @param module
-    *           skin module identifier
-    * @param skinName
-    *           skin name
-    * @param cssPath
-    *           path uri to the css file. This is relative to the root context,
-    *           use leading '/'
-    * @param cssData
-    *           the content of css
-    */
-   public void addPortalSkin(String module, String skinName, String cssPath, String cssData)
-   {
-      SkinKey key = new SkinKey(module, skinName);
-      SkinConfig skinConfig = portalSkins_.get(key);
-      if (skinConfig == null)
-      {
-         portalSkins_.put(key, new SimpleSkin(this, module, skinName, cssPath));
 
-         if (log.isDebugEnabled())
-         {
-            log.debug("Adding Portal skin : Bind " + key + " to " + skinConfig);
-         }
-      }
-      ltCache.remove(cssPath);
-      rtCache.remove(cssPath);
-   }
-
    /**
-    * Register the stylesheet for a portal Skin. Do not replace any previous skin. Support priority
+    * Register a portal skin
     * 
     * @param module
     *           skin module identifier
@@ -285,34 +229,12 @@
     * @param cssPath
     *           path uri to the css file. This is relative to the root context,
     *           use leading '/'
-    * @param scontext
-    *           the webapp's {@link javax.servlet.ServletContext}
-    * @param cssPriority          
-    *           priority to support sorting in skin list
-    */
-   public void addPortalSkin(String module, String skinName, String cssPath, ServletContext scontext, Integer cssPriority)
-   {
-      addPortalSkin(module, skinName, cssPath, scontext, false, cssPriority);
-   }
-   
-   /**
-    * Register the stylesheet for a portal Skin. Support priority
-    * 
-    * @param module
-    *           skin module identifier
-    * @param skinName
-    *           skin name
-    * @param cssPath
-    *           path uri to the css file. This is relative to the root context,
-    *           use leading '/'
-    * @param scontext
-    *           the webapp's {@link javax.servlet.ServletContext}
     * @param overwrite
     *           if any previous skin should be replaced by that one
     * @param cssPriority          
     *           priority to support sorting in skin list
     */
-   public void addPortalSkin(String module, String skinName, String cssPath, ServletContext scontext, boolean overwrite, Integer cssPrioriry)
+   public void addPortalSkin(String module, String skinName, String cssPath, int cssPrioriry, boolean overwrite)
    {
       availableSkins_.add(skinName);
       SkinKey key = new SkinKey(module, skinName);
@@ -330,8 +252,10 @@
    }
    
    /**
-    * Register the stylesheet for a portal Skin. Support priority
+    * Register a portal skin with the specific <code>cssData</code>
     * 
+    * @deprecated This method is not supported anymore.
+    *             The resource resolver pluggability mechanism should be used somehow
     * @param module
     *           skin module identifier
     * @param skinName
@@ -341,106 +265,33 @@
     *           use leading '/'
     * @param cssData
     *           the content of css
-    * @param cssPriority          
-    *           priority to support sorting in skin list
     */
-   public void addPortalSkin(String module, String skinName, String cssPath, String cssData, Integer cssPriority)
+   @Deprecated
+   public void addPortalSkin(String module, String skinName, String cssPath, String cssData)
    {
-      SkinKey key = new SkinKey(module, skinName);
-      SkinConfig skinConfig = portalSkins_.get(key);
-      if (skinConfig == null)
-      {
-         portalSkins_.put(key, new SimpleSkin(this, module, skinName, cssPath, cssPriority));
-
-         if (log.isDebugEnabled())
-         {
-            log.debug("Adding Portal skin : Bind " + key + " to " + skinConfig);
-         }
-      }
-      try
-      {
-         StringWriter output = new StringWriter();
-         compressor.compress(new StringReader(cssData), output, ResourceType.STYLESHEET);
-         cssData = output.toString();
-      }
-      catch (Exception e)
-      {
-         log.debug("Error when compressing CSS, will use normal CSS instead", e);
-      }
+      throw new UnsupportedOperationException("This method is not supported anymore.");
    }
    
    /**
-    * 
-    * Register the Skin for available portal Skins. Do not override previous skin 
-    * 
-    * @param module
-    *           skin module identifier
-    * @param skinName
-    *           skin name
-    * @param cssPath
-    *           path uri to the css file. This is relative to the root context,
-    *           use leading '/'
-    * @param scontext
-    *           the webapp's {@link javax.servlet.ServletContext}
+    * @deprecated use {@link #addSkin(String, String, String, int, boolean)} instead
     */
+   @Deprecated
    public void addSkin(String module, String skinName, String cssPath, ServletContext scontext)
    {
-      addSkin(module, skinName, cssPath, scontext, false);
+      addSkin(module, skinName, cssPath, Integer.MAX_VALUE, false);
    }
 
    /**
-    * Merge several skins into one single skin.
-    * 
-    * @param skins
-    *           the skins to merge
-    * @return the merged skin
+    * @deprecated use {@link #addSkin(String, String, String, int, boolean)} instead
     */
-   public Skin merge(Collection<SkinConfig> skins)
+   @Deprecated
+   public void addSkin(String module, String skinName, String cssPath, ServletContext scontext, boolean overwrite)
    {
-      return new CompositeSkin(this, skins);
+      addSkin(module, skinName, cssPath, Integer.MAX_VALUE, overwrite);
    }
 
    /**
-    * Add a resource resolver to plug external resolvers.
     * 
-    * @param resolver
-    *           a resolver to add
-    */
-   public void addResourceResolver(ResourceResolver resolver)
-   {
-      mainResolver.resolvers.addIfAbsent(resolver);
-   }
-
-   /**
-    * 
-    * Register the Skin for available portal Skins.
-    * 
-    * @param module
-    *           skin module identifier
-    * @param skinName
-    *           skin name
-    * @param cssPath
-    *           path uri to the css file. This is relative to the root context,
-    *           use leading '/'
-    * @param scontext
-    *           the webapp's {@link javax.servlet.ServletContext}
-    * @param overwrite
-    *           if any previous skin should be replaced by that one
-    */
-   public void addSkin(String module, String skinName, String cssPath, ServletContext scontext, boolean overwrite)
-   {
-      availableSkins_.add(skinName);
-      SkinKey key = new SkinKey(module, skinName);
-      SkinConfig skinConfig = skinConfigs_.get(key);
-      if (skinConfig == null || overwrite)
-      {
-         skinConfig = new SimpleSkin(this, module, skinName, cssPath);
-         skinConfigs_.put(key, skinConfig);
-      }
-   }
-   
-   /**
-    * 
     * Register the Skin for available portal Skins. Support priority
     * 
     * @param module
@@ -450,21 +301,19 @@
     * @param cssPath
     *           path uri to the css file. This is relative to the root context,
     *           use leading '/'
-    * @param scontext
-    *           the webapp's {@link javax.servlet.ServletContext}
     * @param overwrite
     *           if any previous skin should be replaced by that one
-    * @param cssPriority
+    * @param priority
     *           priority to support sorting in skin list
     */
-   public void addSkin(String module, String skinName, String cssPath, ServletContext scontext, boolean overwrite, Integer cssPriority)
+   public void addSkin(String module, String skinName, String cssPath, int priority, boolean overwrite)
    {
       availableSkins_.add(skinName);
       SkinKey key = new SkinKey(module, skinName);
       SkinConfig skinConfig = skinConfigs_.get(key);
       if (skinConfig == null || overwrite)
       {
-         skinConfig = new SimpleSkin(this, module, skinName, cssPath, cssPriority);
+         skinConfig = new SimpleSkin(this, module, skinName, cssPath, priority);
          skinConfigs_.put(key, skinConfig);
       }
    }
@@ -483,6 +332,7 @@
     * @param scontext
     *           the webapp's {@link javax.servlet.ServletContext}
     */
+   @Deprecated
    public void addSkin(String module, String skinName, String cssPath, String cssData)
    {
       availableSkins_.add(skinName);
@@ -495,8 +345,31 @@
       ltCache.remove(cssPath);
       rtCache.remove(cssPath);
    }
+   
+   /**
+    * Merge several skins into one single skin.
+    * 
+    * @param skins
+    *           the skins to merge
+    * @return the merged skin
+    */
+   public Skin merge(Collection<SkinConfig> skins)
+   {
+      return new CompositeSkin(this, skins);
+   }
 
    /**
+    * Add a resource resolver to plug external resolvers.
+    * 
+    * @param resolver
+    *           a resolver to add
+    */
+   public void addResourceResolver(ResourceResolver resolver)
+   {
+      mainResolver.resolvers.addIfAbsent(resolver);
+   }
+
+   /**
     * Registry theme category with its themes for portlet Theme
     * @param categoryName
     *             category name that will be registried
@@ -525,16 +398,16 @@
    /**
     * Return the CSS content of the file specified by the given URI.
     * 
-    * @param cssPath
+    * @param path
     *           path of the css to find
     * @return the css contet or null if not found.
     */
-   public String getCSS(String cssPath)
+   public String getCSS(String path)
    {
       try
       {
          final ByteArrayOutput output = new ByteArrayOutput();
-         renderCSS(new ResourceRenderer()
+         boolean success = renderCSS(new ResourceRenderer()
          {
             public BinaryOutput getOutput() throws IOException
             {
@@ -543,20 +416,29 @@
             public void setExpiration(long seconds)
             {
             }
-         }, cssPath);
-         return output.getString();
+         }, path);
+         
+         if (success)
+         {
+            return output.getString();
+         }
+         else
+         {
+            return null;
+         }
       }
       catch (IOException e)
       {
-         log.error("Error while rendering css " + cssPath, e);
+         log.error("Error while rendering css " + path, e);
          return null;
       }
       catch (RenderingException e)
       {
-         log.error("Error while rendering css " + cssPath, e);
+         log.error("Error while rendering css " + path, e);
          return null;
       }
    }
+
    /**
     * Render css content of the file specified by the given URI
     * @param renderer
@@ -565,8 +447,10 @@
     *          path uri to the css file
     * @throws RenderingException
     * @throws IOException
+    * @return <code>true</code> if the <code>CSS resource </code>is found and rendered;
+    *         <code>false</code> otherwise.
     */
-   public void renderCSS(ResourceRenderer renderer, String path) throws RenderingException, IOException
+   public boolean renderCSS(ResourceRenderer renderer, String path) throws RenderingException, IOException
    {
       Orientation orientation = Orientation.LT;
       if (path.endsWith("-lt.css"))
@@ -579,13 +463,30 @@
          orientation = Orientation.RT;
       }
 
-      // Try cache first
-      if (!PropertyManager.isDevelopping())
+      // Check if it is running under developing mode
+      if (PropertyManager.isDevelopping())
       {
+         StringBuffer sb = new StringBuffer();
+         Resource skin = getCSSResource(path, path);
+         if (skin == null)
+         {
+            return false;
+         }
+         processCSSRecursively(sb, false, skin, orientation);
+         byte[] bytes = sb.toString().getBytes("UTF-8");
+         renderer.getOutput().write(bytes);
+      }
+      else
+      {
          //
-         FutureExoCache<String, CachedStylesheet, Orientation> cache = orientation == Orientation.LT ? ltCache : rtCache;
+         FutureMap<String, CachedStylesheet, Orientation> cache = orientation == Orientation.LT ? ltCache : rtCache;
          CachedStylesheet cachedCss = cache.get(orientation, path);
-
+         
+         if (cachedCss == null)
+         {
+            return false;
+         }
+         
          if (path.startsWith("/" + portalContainerName + "/resource"))
          {
             renderer.setExpiration(ONE_MONTH);
@@ -597,29 +498,25 @@
          
          cachedCss.writeTo(renderer.getOutput());
       }
-      else
-      {
-         StringBuffer sb = new StringBuffer();
-         processCSS(sb, path, orientation, false);
-         byte[] bytes = sb.toString().getBytes("UTF-8");
-         renderer.getOutput().write(bytes);
-      }
+      return true;
    }
 
    /**
-    * get css content of URI file
-    * @param cssPath
+    * Return CSS data corresponding to the <code>path</code>
+    * 
+    * @param path
     *          path uri to the css file
     * @return css content of URI file or null if not found
     */
-   public String getMergedCSS(String cssPath)
+   @Deprecated
+   public String getMergedCSS(String path)
    {
-      CachedStylesheet stylesheet = ltCache.get(Orientation.LT, cssPath);
-      return stylesheet != null ? stylesheet.getText() : null;
+      return getCSS(path);
    }
 
    /**
-    * Get all SkinConfig of Portal Skin
+    * Return a collection of Portal Skins that its elements are ordered by CSS priority
+    * 
     * @param skinName
     *          name of Portal Skin
     * @return 
@@ -638,22 +535,16 @@
       {
          public int compare(SkinConfig o1, SkinConfig o2)
          {
-            if (o1.getCSSPriority() == o2.getCSSPriority())
-               return 1;//Can indicate others condition here
-            else if (o1.getCSSPriority() < 0)
-               return 1;
-            else if (o2.getCSSPriority() < 0)
-               return -1;
-            else
-               return o1.getCSSPriority() - o2.getCSSPriority();
+            return o1.getCSSPriority() - o2.getCSSPriority();
          }
       });
       return portalSkins;
    }
 
    /**
-    * Get all portlet's themes
-    * @return portlet's themes
+    * Return the map of portlet themes
+    * 
+    * @return the map of portlet themes
     */
    public Map<String, Set<String>> getPortletThemes()
    {
@@ -661,7 +552,8 @@
    }
 
    /**
-    * Get SkinConfig by module and skin name
+    * Return a SkinConfig mapping by the module and skin name
+    * 
     * @param module
     * @param skinName
     * @return SkinConfig by SkinKey(module, skinName), or SkinConfig by SkinKey(module, SkinService.DEFAULT_SKIN)
@@ -676,14 +568,30 @@
 
    /**
     * Remove SkinKey from SkinCache by portalName and skinName
+    * 
+    * @deprecated the method name is wrong to the behaviour it does.
+    *             Use {@link #removeSkin(String, String)} instead
+    * 
     * @param portalName
     * @param skinName
     */
+   @Deprecated
    public void invalidatePortalSkinCache(String portalName, String skinName)
    {
       SkinKey key = new SkinKey(portalName, skinName);
       skinConfigs_.remove(key);
    }
+   
+   /**
+    * Invalidate skin from the cache
+    * 
+    * @param path the key
+    */
+   public void invalidateCachedSkin(String path)
+   {
+      ltCache.remove(path);
+      rtCache.remove(path);
+   }
 
    /**
     * Return last modifed date of cached css
@@ -696,8 +604,13 @@
       {
          throw new IllegalArgumentException("path must not be null");
       }
+      
+      if (PropertyManager.isDevelopping())
+      {
+         return Long.MAX_VALUE;
+      }
 
-      FutureExoCache<String, CachedStylesheet, Orientation> cache = ltCache;
+      FutureMap<String, CachedStylesheet, Orientation> cache = ltCache;
       Orientation orientation = Orientation.LT;
       if (path.endsWith("-lt.css"))
       {
@@ -721,54 +634,102 @@
    }
 
    /**
-    * Remove SkinConfig from Portal Skin Configs  by module and skin name
+    * @deprecated The method name is not clear.
+    *             Using {@link #removeSkin(String, String)} instead
+    */
+   @Deprecated
+   public void remove(String module, String skinName)
+   {
+      removeSkin(module, skinName);
+   }
+   
+   /**
+    * Remove a Skin from the service as well as its cache
+    * 
     * @param module
     * @param skinName
-    * @throws Exception
     */
-   public void remove(String module, String skinName) throws Exception
+   public void removeSkin(String module, String skinName)
    {
       SkinKey key;
       if (skinName.length() == 0)
+      {
          key = new SkinKey(module, DEFAULT_SKIN);
+      }
       else
+      {
          key = new SkinKey(module, skinName);
-      skinConfigs_.remove(key);
+      }
+      
+      removeSkin(key);
    }
-
+   
    /**
-    * Remove Skin from Portal available Skin by skin name
-    * @param skinName
-    *          name of skin that will be removed
-    * @throws Exception
+    * Remove a Skin mapped to the <code>key</code>
+    * 
+    * @param key key whose mapping skin is to be removed from the service
     */
-   public void removeSupportedSkin(String skinName) throws Exception
+   public void removeSkin(SkinKey key)
    {
-      availableSkins_.remove(skinName);
+      if (key == null)
+      {
+         return;
+      }
+      
+      SkinConfig remove = skinConfigs_.remove(key);
+      
+      if (remove != null)
+      {
+         invalidateCachedSkin(remove.getCSSPath());
+      }
    }
-
+   
    /**
+    * @deprecated This is deprecated as its name was not clear.
+    *             Use {@link #removeSkins(List)} instead
+    */
+   @Deprecated
+   public void remove(List<SkinKey> keys) throws Exception
+   {
+      removeSkins(keys);
+   }
+   
+   /**
     * Remove SkinConfig from Portal Skin Config by SkinKey
     * @param keys
     *          SkinKey list these will be removed
     * @throws Exception
     */
-   public void remove(List<SkinKey> keys) throws Exception
+   public void removeSkins(List<SkinKey> keys) throws Exception
    {
       if (keys == null)
       {
          return;
       }
+      
       for (SkinKey key : keys)
       {
-         skinConfigs_.remove(key);
+         removeSkin(key);
       }
    }
 
+
    /**
-    * get quantity of Portal Skin Config
-    * @return
+    * Remove Skin from Portal available Skin by skin name
+    * @param skinName
+    *          name of skin that will be removed
+    * @throws Exception
     */
+   public void removeSupportedSkin(String skinName) throws Exception
+   {
+      availableSkins_.remove(skinName);
+   }
+
+   /**
+    * Return the number of skin config maintaining in this SkinService
+    * 
+    * @return the number of skin config maintaining in this SkinService
+    */
    public int size()
    {
       return skinConfigs_.size();
@@ -800,7 +761,7 @@
    private Resource getCSSResource(String cssPath, String outerCssFile)
    {
       Resource resource = mainResolver.resolve(cssPath);
-      if (resource == null)
+      if (resource == null && log.isErrorEnabled())
       {
          String logMessage;
          if (!cssPath.equals(outerCssFile))
@@ -821,22 +782,6 @@
       }
       return resource;
    }
-   
-   /**
-    * Apply CSS of skin
-    * @param appendable
-    * @param cssPath
-    * @param orientation
-    * @param merge
-    * @throws RenderingException
-    * @throws IOException
-    */
-   private void processCSS(Appendable appendable, String cssPath, Orientation orientation, boolean merge)
-      throws RenderingException, IOException
-   {
-      Resource skin = getCSSResource(cssPath, cssPath);      
-      processCSSRecursively(appendable, merge, skin, orientation);
-   }
 
    /**
     * Apply CSS for Skin <br/>
@@ -859,7 +804,6 @@
       String basePath = skin.getContextPath() + skin.getParentPath();
 
       //
-      String line = "";
       Reader tmp = skin.read();
       if (tmp == null)
       {
@@ -868,7 +812,8 @@
       BufferedReader reader = new SkipCommentReader(tmp, new CommentBlockHandler.OrientationCommentBlockHandler());
       try
       {
-         while ((line = reader.readLine()) != null)
+         String line = reader.readLine();
+         while (line != null)
          {            
             line = proccessOrientation(line, orientation);            
             line = proccessBackgroundUrl(line, basePath);                       
@@ -900,7 +845,11 @@
                matcher.appendReplacement((StringBuffer)appendable, str);
             }
             matcher.appendTail((StringBuffer)appendable);
-            appendable.append("\n");
+            
+            if ((line = reader.readLine()) != null)
+            {
+               appendable.append("\n");
+            }
          }         
       }
       finally

Modified: portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/compressor/ResourceCompressor.java
===================================================================
--- portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/compressor/ResourceCompressor.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/compressor/ResourceCompressor.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -31,8 +31,10 @@
 
 public interface ResourceCompressor
 {
-
+   public boolean isSupported(ResourceType resourceType);
+   
    public void compress(Reader input, Writer output, ResourceType resourceType) throws ResourceCompressorException,
          IOException;
 
+   public String compress(String input, ResourceType resourceType) throws ResourceCompressorException, IOException;
 }

Modified: portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/compressor/impl/ResourceCompressorService.java
===================================================================
--- portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/compressor/impl/ResourceCompressorService.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/compressor/impl/ResourceCompressorService.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -20,6 +20,8 @@
 
 import java.io.IOException;
 import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -50,16 +52,12 @@
 @NameTemplate({@Property(key = "service", value = "resource")})
 public class ResourceCompressorService implements ResourceCompressor, ManagementAware
 {
-
    /** . */
    private Log log = ExoLogger.getLogger(ResourceCompressorService.class);
 
    /** . */
    private Map<ResourceType, List<ResourceCompressorPlugin>> plugins;
 
-   /** . */
-   private ManagementContext managementContext;
-
    public ResourceCompressorService(InitParams params) throws Exception
    {
 
@@ -108,6 +106,13 @@
       return null;
    }
 
+   @Override
+   final public boolean isSupported(ResourceType resourceType)
+   {
+      return (getHighestPriorityCompressorPlugin(resourceType) != null);
+   }
+
+   @Override
    final public void compress(Reader input, Writer output, ResourceType resourceType)
       throws ResourceCompressorException, IOException
    {
@@ -121,6 +126,15 @@
          throw new ResourceCompressorException("There is no compressor for " + resourceType + " type");
       }
    }
+   
+   @Override
+   public String compress(String input, ResourceType resourceType) throws ResourceCompressorException, IOException
+   {
+      StringReader reader = new StringReader(input);
+      StringWriter writer = new StringWriter();
+      compress(reader, writer, resourceType);
+      return writer.toString();
+   }
 
    public ResourceCompressorPlugin getHighestPriorityCompressorPlugin(ResourceType resourceType)
    {
@@ -149,8 +163,10 @@
 
    public void setContext(ManagementContext context)
    {
-      this.managementContext = context;
-
+      if (context == null)
+      {
+         return;
+      }
       //
       for (Map.Entry<ResourceType, List<ResourceCompressorPlugin>> entry : plugins.entrySet())
       {

Modified: portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/tasks/PortalSkinTask.java
===================================================================
--- portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/tasks/PortalSkinTask.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/tasks/PortalSkinTask.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -76,14 +76,14 @@
       }
       String contextPath = scontext.getContextPath();
       String fullCSSPath = contextPath + cssPath;
-      Integer iCssPriority = null;
+      int priority;
       try
       {
-    	  iCssPriority = Integer.valueOf(cssPriority);
+         priority = Integer.valueOf(cssPriority);
       } catch (Exception e) {
-    	  //Don't set cssPriority when it is not a numarical
+         priority = Integer.MAX_VALUE;
       }
-      skinService.addPortalSkin(moduleName, skinName, fullCSSPath, scontext, overwrite, iCssPriority);
+      skinService.addPortalSkin(moduleName, skinName, fullCSSPath, priority, overwrite);
       updateSkinDependentManager(contextPath, moduleName, skinName);
    }
 

Modified: portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/tasks/PortletSkinTask.java
===================================================================
--- portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/tasks/PortletSkinTask.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/tasks/PortletSkinTask.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -93,14 +93,14 @@
       String moduleName = applicationName + "/" + portletName;
       String contextPath = scontext.getContextPath();
       String fullCSSPath = contextPath + cssPath;
-      Integer iCSSPriority = null;
+      int priority;
       try
       {
-    	  iCSSPriority = Integer.valueOf(cssPriority);
+         priority = Integer.valueOf(cssPriority);
       } catch (Exception e) {
-    	  //Don't set cssPriority when it is not a numarical
+         priority = Integer.MAX_VALUE;
       }
-      skinService.addSkin(moduleName, skinName, fullCSSPath, scontext, overwrite, iCSSPriority);
+      skinService.addSkin(moduleName, skinName, fullCSSPath, priority, overwrite);
       updateSkinDependentManager(contextPath, moduleName, skinName);
    }
 

Modified: portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/xml/SkinConfigParser.java
===================================================================
--- portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/xml/SkinConfigParser.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/main/java/org/exoplatform/portal/resource/config/xml/SkinConfigParser.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -152,7 +152,7 @@
       NodeList nodes = rootElement.getElementsByTagName(tagName);
       SkinConfigTask task;
 
-      for (int i = nodes.getLength() - 1; i >= 0; i--)
+      for (int i = 0; i < nodes.getLength(); i++)
       {
          task = (SkinConfigTask)elemtToTask(tagName);
          if (task != null)

Modified: portal/trunk/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java
===================================================================
--- portal/trunk/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -31,9 +31,6 @@
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -319,11 +316,8 @@
          // Minify
          try
          {
-            Reader input = new StringReader(s);
-            StringWriter output = new StringWriter();
-            compressor.compress(input, output, ResourceType.JAVASCRIPT);
-            
-            jsBytes = output.toString().getBytes();
+            String output = compressor.compress(s, ResourceType.JAVASCRIPT);
+            jsBytes = output.getBytes();
          }
          catch (Exception e)
          {

Copied: portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/AbstractSkinServiceTest.java (from rev 7650, portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinService.java)
===================================================================
--- portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/AbstractSkinServiceTest.java	                        (rev 0)
+++ portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/AbstractSkinServiceTest.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.portal.resource;
+
+import org.exoplatform.commons.utils.PropertyManager;
+import org.exoplatform.commons.xml.DocumentSource;
+import org.exoplatform.component.test.AbstractKernelTest;
+import org.exoplatform.component.test.ConfigurationUnit;
+import org.exoplatform.component.test.ConfiguredBy;
+import org.exoplatform.component.test.ContainerScope;
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.portal.resource.config.xml.SkinConfigParser;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.ServletContext;
+
+ at ConfiguredBy({@ConfigurationUnit(scope = ContainerScope.PORTAL, path = "conf/test-configuration.xml")})
+public abstract class AbstractSkinServiceTest extends AbstractKernelTest
+{
+   protected SkinService skinService;
+
+   private static ServletContext mockServletContext;
+
+   protected static MockResourceResolver resResolver;
+
+   abstract boolean isDevelopingMode();
+
+   abstract boolean setUpTestEnvironment();
+
+   abstract void touchSetUp();
+
+   @Override
+   protected void setUp() throws Exception
+   {
+      //Set running mode at starting up
+      PropertyManager.setProperty(PropertyManager.DEVELOPING, String.valueOf(isDevelopingMode()));
+
+      PortalContainer portalContainer = getContainer();
+
+      skinService = (SkinService)portalContainer.getComponentInstanceOfType(SkinService.class);
+
+      if (setUpTestEnvironment())
+      {
+         mockServletContext = new MockServletContext("mockwebapp", portalContainer.getPortalClassLoader());
+         skinService.registerContext(mockServletContext);
+
+         resResolver = new MockResourceResolver();
+         skinService.addResourceResolver(resResolver);
+
+         URL url = mockServletContext.getResource("/gatein-resources.xml");
+         SkinConfigParser.processConfigResource(DocumentSource.create(url), skinService, mockServletContext);
+
+         touchSetUp();
+      }
+   }
+
+   public void testInitializing()
+   {
+      assertEquals(1, skinService.getAvailableSkinNames().size());
+      assertTrue(skinService.getAvailableSkinNames().contains("TestSkin"));
+
+      String css = skinService.getCSS("/path/to/MockResourceResolver.css");
+      assertEquals(MockResourceResolver.class.getName(), css);
+   }
+
+   public void testPortalSkinAndPriority()
+   {
+      Collection<SkinConfig> portalSkinConfigs = skinService.getPortalSkins("TestSkin");
+      assertNotNull(portalSkinConfigs);
+      assertEquals(4, portalSkinConfigs.size());
+
+      SkinConfig[] array = new SkinConfig[4];
+      portalSkinConfigs.toArray(array);
+
+      SkinConfig portalSkin = array[0];
+      assertNotNull(portalSkin);
+      assertEquals("CoreSkin", portalSkin.getModule());
+      assertEquals(mockServletContext.getContextPath() + "/skin/core/Stylesheet.css", portalSkin.getCSSPath());
+
+      portalSkin = array[1];
+      assertNotNull(portalSkin);
+      assertEquals("Module2", portalSkin.getModule());
+      assertEquals(mockServletContext.getContextPath() + "/skin/module2/Stylesheet.css", portalSkin.getCSSPath());
+
+      portalSkin = array[2];
+      assertNotNull(portalSkin);
+      assertEquals("Module3", portalSkin.getModule());
+      assertEquals(mockServletContext.getContextPath() + "/skin/module3/Stylesheet.css", portalSkin.getCSSPath());
+
+      portalSkin = array[3];
+      assertNotNull(portalSkin);
+      assertEquals("Module1", portalSkin.getModule());
+      assertEquals(mockServletContext.getContextPath() + "/skin/module1/Stylesheet.css", portalSkin.getCSSPath());
+   }
+
+   public void testPortletSkin()
+   {
+      SkinConfig portletSkin = skinService.getSkin("mockwebapp/FirstPortlet", "TestSkin");
+      assertNotNull(portletSkin);
+      assertEquals(mockServletContext.getContextPath() + "/skin/FirstPortlet.css",
+         portletSkin.getCSSPath());
+      
+      portletSkin = skinService.getSkin("mockwebapp/SecondPortlet", "TestSkin");
+      assertNotNull(portletSkin);
+      assertEquals(mockServletContext.getContextPath() + "/skin/SecondPortlet.css",
+         portletSkin.getCSSPath());
+   }
+
+   public void testThemes()
+   {
+      Map<String, Set<String>> themeStyles = skinService.getPortletThemes();
+      Set<String> themes = themeStyles.get("Simple");
+      assertNotNull(themes);
+      assertTrue(themes.contains("SimpleBlue"));
+      assertTrue(themes.contains("SimpleViolet"));
+
+      assertNotNull(themeStyles.get("VistaStyle"));
+   }
+
+   public void testExistingCSS() throws Exception
+   {
+      String css = skinService.getCSS("/mockwebapp/skin/Stylesheet-lt.css");
+      assertTrue(css.length() > 0);
+
+      css = skinService.getCSS("/mockwebapp/skin/Stylesheet-rt.css");
+      assertTrue(css.length() > 0);
+   }
+
+   public void testNonExistingCSS()
+   {
+      String css = skinService.getCSS("/non/existing/file.css");
+      assertNull(css);
+      
+      css = skinService.getCSS("/non/existing/file-lt.css");
+      assertNull(css);
+   }
+
+   public void testProcessComment()
+   {
+      String path = "/process/comment/file.css";
+      String css =
+         "foo; /*background:url(bar.gif); Inline comment*/" +
+         "/* Block comment\n" +
+         "   background:url(bar.gif);\n" +
+         "   End of block comment */";
+      
+      resResolver.addResource(path, css);
+      
+      //TODO: It should only ignore the comment instead of removing it
+//      assertEquals(
+//         "foo; /*background:url(bar.gif); Inline comment*/" +
+//         "/* Block comment\n" +
+//         "   background:url(bar.gif);\n" +
+//         "   End of block comment */",
+//         skinService.getCSS(path));
+      assertEquals("foo;", skinService.getCSS(path));
+   }
+
+   public void testOrientation()
+   {
+      String path = "/orientation/file";
+      String css =
+         "aaa;/*orientation=lt*/bbb;/*orientation=rt*/\n" +
+         " aaa; /* orientation=lt */ bbb; /* orientation=rt */ \n" +
+         "{aaa;bbb;/*orientation=lt*/ccc;ddd;/*orientation=rt*/}\n" +
+         "{aaa;/*orientation=lt*/bbb;}{ccc;/*orientation=rt*/ddd;}";
+      
+      resResolver.addResource(path + ".css", css);
+
+      assertEquals(
+         "aaa;\n" +
+         "aaa;\n" +
+         "{aaa;bbb;/*orientation=lt*/ccc;}\n" +
+         "{aaa;/*orientation=lt*/bbb;}{ddd;}",
+         skinService.getCSS(path + "-lt.css"));
+      
+      assertEquals(
+         "bbb;/*orientation=rt*/\n" +
+         " bbb; /* orientation=rt */\n" +
+         "{aaa;ccc;ddd;/*orientation=rt*/}\n" +
+         "{bbb;}{ccc;/*orientation=rt*/ddd;}",
+         skinService.getCSS(path + "-rt.css"));
+   }
+
+   public void testBackgroundURL()
+   {
+      String path = "/background/url/file.css";
+      String css =
+         "background:url(images/foo.gif);\n" +
+         "background:url('/images/foo.gif');\n" +
+         "aaa; background: #fff url('images/foo.gif') no-repeat center -614px; ccc;";
+      
+      resResolver.addResource(path, css);
+      assertEquals(
+         "background:url(/background/url/images/foo.gif);\n" + 
+         "background:url('/images/foo.gif');\n" +
+         "aaa; background: #fff url('/background/url/images/foo.gif') no-repeat center -614px; ccc;",
+         skinService.getCSS(path));
+   }
+}

Modified: portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/AbstractWebResourceTest.java
===================================================================
--- portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/AbstractWebResourceTest.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/AbstractWebResourceTest.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -28,9 +28,8 @@
  * @date 7/5/11
  */
 @ConfiguredBy({
-   @ConfigurationUnit(scope = ContainerScope.PORTAL, path = "conf/resource-compressor-service-configuration.xml"),
-   @ConfigurationUnit(scope = ContainerScope.PORTAL, path = "conf/js-service-configuration.xml"),
-   @ConfigurationUnit(scope = ContainerScope.PORTAL, path = "conf/skin-service-configuration.xml")
+   @ConfigurationUnit(scope = ContainerScope.PORTAL, path = "conf/test-configuration.xml"),
+   @ConfigurationUnit(scope = ContainerScope.PORTAL, path = "conf/resource-compressor-service-configuration.xml")
 })
 public abstract class AbstractWebResourceTest extends AbstractKernelTest
 {

Added: portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/MockResourceResolver.java
===================================================================
--- portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/MockResourceResolver.java	                        (rev 0)
+++ portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/MockResourceResolver.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ * 
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.portal.resource;
+
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="trongtt at gmail.com">Trong Tran</a>
+ * @version $Revision$
+ */
+class MockResourceResolver implements ResourceResolver
+{
+   /** . */
+   private final Logger log = LoggerFactory.getLogger(MockResourceResolver.class);
+   
+   private Map<String, String> map = new HashMap<String, String>();
+
+   public MockResourceResolver()
+   {
+      addResource("/path/to/MockResourceResolver.css", this.getClass().getName());
+   }
+
+   public void addResource(String path, String value)
+   {
+      map.put(path, value);
+   }
+   
+   public String removeResource(String path)
+   {
+      return map.remove(path);
+   }
+
+   @Override
+   public Resource resolve(String path) throws NullPointerException
+   {
+      if (path == null)
+      {
+         throw new NullPointerException("No null path is accepted");
+      }
+
+      log.info("path to resolve : " + path);
+      
+      final String css = map.get(path);
+      if (css != null)
+      {
+         return new Resource(path)
+         {
+            @Override
+            public Reader read()
+            {
+               return new StringReader(css);
+            }
+         };
+      }
+      return null;
+   }
+}

Modified: portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinService.java
===================================================================
--- portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinService.java	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinService.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -18,207 +18,116 @@
  */
 package org.exoplatform.portal.resource;
 
-import org.exoplatform.commons.xml.DocumentSource;
-import org.exoplatform.component.test.AbstractKernelTest;
-import org.exoplatform.component.test.ConfigurationUnit;
-import org.exoplatform.component.test.ConfiguredBy;
-import org.exoplatform.component.test.ContainerScope;
-import org.exoplatform.container.PortalContainer;
-import org.exoplatform.portal.resource.config.xml.SkinConfigParser;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.net.URL;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import javax.servlet.ServletContext;
+import org.exoplatform.services.resources.Orientation;
 
+import java.util.Arrays;
+
 /**
- * @author <a href="hoang281283 at gmail.com">Minh Hoang TO</a>
- * @date 6/29/11
+ * @author <a href="trongtt at gmail.com">Trong Tran</a>
+ * @version $Revision$
  */
-public class TestSkinService extends AbstractWebResourceTest
+
+public class TestSkinService extends AbstractSkinServiceTest
 {
-   private PortalContainer portalContainer;
+   private static boolean isFirstStartup = true;
 
-   private SkinService skinService;
-
-   private ServletContext mockServletContext;
-
-   private volatile boolean initSkinService = true;
-
-   /** A cache of Method in SkinService, served for reflect invocation **/
-   private Map<String, Method> methodsOfSkinService = new HashMap<String, Method>();
-
-   @Override
-   protected void setUp() throws Exception
+   boolean isDevelopingMode()
    {
-      if(initSkinService)
-      {
-         initSkinService = false;
-
-         portalContainer = getContainer();
-         skinService = (SkinService)portalContainer.getComponentInstanceOfType(SkinService.class);
-         mockServletContext = new MockServletContext("mockwebapp", portalContainer.getPortalClassLoader());
-         skinService.registerContext(mockServletContext);
-
-         processSkinConfiguration("/gatein-resources.xml");
-      }
+      return false;
    }
 
-   private void processSkinConfiguration(String configResource) throws Exception
+   @Override
+   boolean setUpTestEnvironment()
    {
-      URL url = mockServletContext.getResource(configResource);
-      SkinConfigParser.processConfigResource(DocumentSource.create(url), skinService, mockServletContext);
+      return isFirstStartup;
    }
 
-   public void testInitService()
+   @Override
+   void touchSetUp()
    {
-      assertNotNull(portalContainer);
-      assertEquals("portal", portalContainer.getName());
-      assertNotNull(skinService);
+      isFirstStartup = false;
    }
 
-   public void testInitSkinModules()
+   public void testCompositeSkin()
    {
-      assertNotNull(skinService.getAvailableSkinNames());
-      assertTrue(skinService.getAvailableSkinNames().contains("TestSkin"));
-   }
+      SkinConfig fSkin = skinService.getSkin("mockwebapp/FirstPortlet", "TestSkin");
+      SkinConfig sSkin = skinService.getSkin("mockwebapp/SecondPortlet", "TestSkin");
+      assertNotNull(fSkin);
+      assertNotNull(sSkin);
 
-   public void testInitThemes()
-   {
+      Skin merged = skinService.merge(Arrays.asList(fSkin, sSkin));
+      SkinURL url = merged.createURL();
 
-   }
+      url.setOrientation(Orientation.LT);
+      assertEquals(
+         ".FirstPortlet {foo1 : bar1}\n" +
+         ".SecondPortlet {foo2 : bar2}",
+         skinService.getCSS(url.toString()));
 
-   public void testDeployedSkinModules()
-   {
-      assertNotNull(skinService.getAvailableSkinNames());
-      assertTrue(skinService.getAvailableSkinNames().contains("TestSkin"));
-
-      Collection<SkinConfig> skinConfigs = skinService.getPortalSkins("TestSkin");
-      assertNotNull(skinConfigs);
-
-      SkinConfig portalSkin = null;
-      for(SkinConfig config : skinConfigs)
-      {
-         if("TestSkin".equals(config.getName()))
-         {
-            portalSkin = config;
-            break;
-         }
-      }
-      assertNotNull(portalSkin);
-      assertEquals(mockServletContext.getContextPath() + "/skin/Stylesheet.css", portalSkin.getCSSPath());
-
-      SkinConfig firstPortletSkin = skinService.getSkin("mockwebapp/FirstPortlet", "TestSkin");
-      assertNotNull(firstPortletSkin);
-      assertEquals(mockServletContext.getContextPath() + "/skin/portlet/FirstPortlet/Stylesheet.css", firstPortletSkin.getCSSPath());
+      url.setOrientation(Orientation.RT);
+      assertEquals(
+         ".FirstPortlet {foo1 : bar1}\n" +
+         ".SecondPortlet {foo2 : bar2}",
+         skinService.getCSS(url.toString()));
    }
 
-   public void testDeployedThemes()
+   public void testCache()
    {
+      String path = "/path/to/test/caching.css";
 
-   }
+      resResolver.addResource(path, "foo");
+      assertEquals("foo", skinService.getCSS(path));
 
-   public void testRenderLT_CSS() throws Exception
-   {
-      ByteArrayOutputStream out = new ByteArrayOutputStream();
-      ResourceRenderer renderer = new MockResourceRenderer(out);
-
-      skinService.renderCSS(renderer, "/mockwebapp/skin/Stylesheet-lt.css");
-
-      //TODO: Check the array of bytes in out
+      resResolver.addResource(path, "bar");
+      assertEquals("foo", skinService.getCSS(path));
    }
-
-   public void testRenderRT_CSS() throws Exception
+   
+   public void testInvalidateCache()
    {
-      ByteArrayOutputStream out = new ByteArrayOutputStream();
-      ResourceRenderer renderer = new MockResourceRenderer(out);
+      String path = "/path/to/test/caching.css";
 
-      skinService.renderCSS(renderer, "/mockwebapp/skin/Stylesheet-rt.css");
+      resResolver.addResource(path, "foo");
+      assertEquals("foo", skinService.getCSS(path));
 
-      //TODO: Check the array of bytes in out
+      resResolver.addResource(path, "bar");
+      skinService.invalidateCachedSkin(path);
+      assertEquals("bar", skinService.getCSS(path));
    }
 
-   public void testBackground() throws Exception
+   public void testProcessImportCSS()
    {
-   }
+      String parent = "/process/import/css.css";
 
-   public void testServiceCache() throws Exception
-   {
-   }
+      resResolver.addResource(parent, "@import url(Portlet/Stylesheet.css); aaa;");
+      assertEquals(" aaa;", skinService.getCSS(parent));
+      skinService.invalidateCachedSkin(parent);
+      
+      resResolver.addResource(parent, "@import url('/Portlet/Stylesheet.css'); aaa;");
+      assertEquals(" aaa;", skinService.getCSS(parent));
+      skinService.invalidateCachedSkin(parent);
 
-   public void testSkinPriority() throws Exception
-   {
-   }
+      //parent file import child css file
+      resResolver.addResource(parent, "@import url(childCSS/child.css);  background:url(images/foo.gif);");
+      String child = "/process/import/childCSS/child.css";
+      resResolver.addResource(child, "background:url(bar.gif);");
 
-   public void testUndeploySkinConfig() throws Exception
-   {
-      //TODO: Fork the work of GateInSkinConfigRemoval here
+      /*
+       * Now test merge and process recursively (run in non-dev mode)
+       * We have folder /path/to/parent.css
+       *                                        /images/foo.gif
+       *                                        /childCSS/child.css
+       *                                                        /bar.gif
+       */
+      assertEquals("background:url(/process/import/childCSS/bar.gif);  background:url(/process/import/images/foo.gif);",
+         skinService.getCSS(parent));
    }
 
-   /**
-    * Designed to invoke reflectively private methods of SkinService. That facilitate
-    * writting JUnit tests
-    *
-    * @param methodName
-    * @param arguments
-    */
-   private void invokeMethodOfSkinService(String methodName, Object... arguments)
+   public void testLastModifiedSince()
    {
-      StringBuilder methodSignature = new StringBuilder(methodName);
-      Class<?>[] paramTypes = new Class<?>[arguments.length];
-      for(int i =0; i < arguments.length; i++)
-      {
-         paramTypes[i] = arguments[i].getClass();
-         methodSignature.append("_");
-         methodSignature.append(paramTypes[i].getName());
-      }
-      //First we look at the cache
-      Method method = methodsOfSkinService.get(methodSignature.toString());
+      String path = "/last/modify/since.css";
+      resResolver.addResource(path, "foo");
 
-      //Find method by reflection
-      if(method == null)
-      {
-         try
-         {
-            method = skinService.getClass().getDeclaredMethod(methodName, paramTypes);
-            if(method != null)
-            {
-               method.setAccessible(true);
-               methodsOfSkinService.put(methodSignature.toString(), method);
-            }
-            else
-            {
-               return;
-            }
-         }
-         catch (NoSuchMethodException ex)
-         {
-         }
-      }
-
-      try
-      {
-         if(Modifier.isStatic(method.getModifiers()))
-         {
-            method.invoke(null, arguments);
-         }
-         else
-         {
-            method.invoke(skinService, arguments);
-         }
-      }
-      catch(Exception ex)
-      {
-         ex.printStackTrace();
-      }
+      assertTrue(skinService.getCSS(path).length() > 0);
+      assertTrue(skinService.getLastModified(path) < System.currentTimeMillis());
    }
-
-   @Override
-   protected void tearDown() throws Exception
-   {
-   }
 }

Added: portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinServiceInDevelopingMode.java
===================================================================
--- portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinServiceInDevelopingMode.java	                        (rev 0)
+++ portal/trunk/component/web/resources/src/test/java/org/exoplatform/portal/resource/TestSkinServiceInDevelopingMode.java	2011-10-10 08:29:57 UTC (rev 7695)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.portal.resource;
+
+import org.exoplatform.services.resources.Orientation;
+
+import java.util.Arrays;
+
+
+/**
+ * @author <a href="trongtt at gmail.com">Trong Tran</a>
+ * @version $Revision$
+ */
+
+public class TestSkinServiceInDevelopingMode extends AbstractSkinServiceTest
+{
+   private static boolean isFirstStartup = true;
+   
+   boolean isDevelopingMode()
+   {
+      return true;
+   }
+
+   @Override
+   boolean setUpTestEnvironment()
+   {
+      return isFirstStartup;
+   }
+
+   @Override
+   void touchSetUp()
+   {
+      isFirstStartup = false;
+   }
+
+   public void testCompositeSkin()
+   {
+      SkinConfig fSkin = skinService.getSkin("mockwebapp/FirstPortlet", "TestSkin");
+      SkinConfig sSkin = skinService.getSkin("mockwebapp/SecondPortlet", "TestSkin");
+      assertNotNull(fSkin);
+      assertNotNull(sSkin);
+
+      Skin merged = skinService.merge(Arrays.asList(fSkin, sSkin));
+      SkinURL url = merged.createURL();
+
+      url.setOrientation(Orientation.LT);
+      assertEquals("@import url(/mockwebapp/skin/FirstPortlet-lt.css);\n"
+         + "@import url(/mockwebapp/skin/SecondPortlet-lt.css);", skinService.getCSS(url.toString()));
+
+      url.setOrientation(Orientation.RT);
+      assertEquals("@import url(/mockwebapp/skin/FirstPortlet-rt.css);\n"
+         + "@import url(/mockwebapp/skin/SecondPortlet-rt.css);", skinService.getCSS(url.toString()));
+   }
+
+   public void testCache()
+   {
+      String path = "/path/to/test/caching.css";
+
+      resResolver.addResource(path, "foo");
+      assertEquals("foo", skinService.getCSS(path));
+
+      resResolver.addResource(path, "bar");
+      assertEquals("bar", skinService.getCSS(path));
+   }
+   
+   public void testProcessImportCSS()
+   {
+      String parent = "/process/import/css.css";
+
+      resResolver.addResource(parent, "@import url(Portlet/Stylesheet.css); aaa;");
+      assertEquals("@import url(/process/import/Portlet/Stylesheet-lt.css); aaa;", skinService.getCSS(parent));
+      
+      resResolver.addResource(parent, "@import url('/Portlet/Stylesheet.css'); aaa;");
+      assertEquals("@import url('/Portlet/Stylesheet-lt.css'); aaa;", skinService.getCSS(parent));
+
+      //parent file import child css file
+      resResolver.addResource(parent, "@import url(childCSS/child.css);  background:url(images/foo.gif);");
+      String child = "/process/import/childCSS/child.css";
+      resResolver.addResource(child, "background:url(bar.gif);");
+
+      /*
+       * Now test merge and process recursively (run in non-dev mode)
+       * We have folder /process/import/css.css
+       *                                        /images/foo.gif
+       *                                        /childCSS/child.css
+       *                                                        /bar.gif
+       */
+      assertEquals("@import url(/process/import/childCSS/child-lt.css);  background:url(/process/import/images/foo.gif);",
+         skinService.getCSS(parent));
+   }
+
+   public void testLastModifiedSince()
+   {
+      String path = "/last/modify/since.css";
+      resResolver.addResource(path, "foo");
+
+      assertTrue(skinService.getCSS(path).length() > 0);
+      assertEquals(Long.MAX_VALUE, skinService.getLastModified(path));
+   }
+}

Deleted: portal/trunk/component/web/resources/src/test/resources/conf/js-service-configuration.xml
===================================================================
--- portal/trunk/component/web/resources/src/test/resources/conf/js-service-configuration.xml	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/test/resources/conf/js-service-configuration.xml	2011-10-10 08:29:57 UTC (rev 7695)
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-
-    Copyright (C) 2009 eXo Platform SAS.
-    
-    This is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as
-    published by the Free Software Foundation; either version 2.1 of
-    the License, or (at your option) any later version.
-    
-    This software is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-    
-    You should have received a copy of the GNU Lesser General Public
-    License along with this software; if not, write to the Free
-    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-    02110-1301 USA, or see the FSF site: http://www.fsf.org.
-
--->
-
-<configuration
-   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-   xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd"
-   xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
-   <component>
-		<key>org.exoplatform.web.application.javascript.JavascriptConfigService</key>
-		<type>org.exoplatform.web.application.javascript.JavascriptConfigService</type>
-	</component>
-</configuration>

Deleted: portal/trunk/component/web/resources/src/test/resources/conf/resource-compressor-service-configuration.xml
===================================================================
--- portal/trunk/component/web/resources/src/test/resources/conf/resource-compressor-service-configuration.xml	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/test/resources/conf/resource-compressor-service-configuration.xml	2011-10-10 08:29:57 UTC (rev 7695)
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-
-    Copyright (C) 2009 eXo Platform SAS.
-    
-    This is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as
-    published by the Free Software Foundation; either version 2.1 of
-    the License, or (at your option) any later version.
-    
-    This software is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-    
-    You should have received a copy of the GNU Lesser General Public
-    License along with this software; if not, write to the Free
-    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-    02110-1301 USA, or see the FSF site: http://www.fsf.org.
-
--->
-
-<configuration
-   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-   xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd"
-   xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
-
-   <component>
-      <key>org.exoplatform.portal.resource.compressor.ResourceCompressor</key>
-      <type>org.exoplatform.portal.resource.compressor.impl.ResourceCompressorService</type>
-      <component-plugins>
-         <component-plugin>
-            <name>MockCompressorPlugin</name>
-            <set-method>registerCompressorPlugin</set-method>
-            <type>org.exoplatform.portal.resource.compressor.MockCompressorPlugin</type>
-            <init-params>
-               <value-param>
-                  <name>plugin.priority</name>
-                  <value>5</value>
-               </value-param>
-            </init-params>
-         </component-plugin>
-         
-         <component-plugin>
-            <name>JSMinCompressorPlugin</name>
-            <set-method>registerCompressorPlugin</set-method>
-            <type>org.exoplatform.portal.resource.compressor.impl.JSMinCompressorPlugin</type>
-            <init-params>
-               <value-param>
-                  <name>plugin.priority</name>
-                  <value>9</value>
-               </value-param>
-            </init-params>
-         </component-plugin>
-         
-         <component-plugin>
-            <name>YUICSSCompressorPlugin</name>
-            <set-method>registerCompressorPlugin</set-method>
-            <type>org.exoplatform.portal.resource.compressor.css.YUICSSCompressorPlugin</type>
-            <init-params>
-               <value-param>
-                  <name>plugin.priority</name>
-                  <value>1</value>
-               </value-param>
-               <value-param>
-                  <name>line.break.position</name>
-                  <value>100</value>
-               </value-param>
-            </init-params>
-         </component-plugin>
-      </component-plugins>
-   </component>
-</configuration>

Added: portal/trunk/component/web/resources/src/test/resources/conf/resource-compressor-service-configuration.xml
===================================================================
--- portal/trunk/component/web/resources/src/test/resources/conf/resource-compressor-service-configuration.xml	                        (rev 0)
+++ portal/trunk/component/web/resources/src/test/resources/conf/resource-compressor-service-configuration.xml	2011-10-10 08:29:57 UTC (rev 7695)
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+    Copyright (C) 2009 eXo Platform SAS.
+    
+    This is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as
+    published by the Free Software Foundation; either version 2.1 of
+    the License, or (at your option) any later version.
+    
+    This software is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+    
+    You should have received a copy of the GNU Lesser General Public
+    License along with this software; if not, write to the Free
+    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+    02110-1301 USA, or see the FSF site: http://www.fsf.org.
+
+-->
+
+<configuration
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd"
+   xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
+   
+   <external-component-plugins>
+      <target-component>org.exoplatform.portal.resource.compressor.ResourceCompressor</target-component>
+      <component-plugin>
+         <name>MockCompressorPlugin</name>
+         <set-method>registerCompressorPlugin</set-method>
+         <type>org.exoplatform.portal.resource.compressor.MockCompressorPlugin</type>
+         <init-params>
+            <value-param>
+               <name>plugin.priority</name>
+               <value>5</value>
+            </value-param>
+         </init-params>
+      </component-plugin>
+
+      <component-plugin>
+         <name>JSMinCompressorPlugin</name>
+         <set-method>registerCompressorPlugin</set-method>
+         <type>org.exoplatform.portal.resource.compressor.impl.JSMinCompressorPlugin</type>
+         <init-params>
+            <value-param>
+               <name>plugin.priority</name>
+               <value>9</value>
+            </value-param>
+         </init-params>
+      </component-plugin>
+
+      <component-plugin>
+         <name>YUICSSCompressorPlugin</name>
+         <set-method>registerCompressorPlugin</set-method>
+         <type>org.exoplatform.portal.resource.compressor.css.YUICSSCompressorPlugin</type>
+         <init-params>
+            <value-param>
+               <name>plugin.priority</name>
+               <value>1</value>
+            </value-param>
+            <value-param>
+               <name>line.break.position</name>
+               <value>100</value>
+            </value-param>
+         </init-params>
+      </component-plugin>
+   </external-component-plugins>
+</configuration>

Deleted: portal/trunk/component/web/resources/src/test/resources/conf/skin-service-configuration.xml
===================================================================
--- portal/trunk/component/web/resources/src/test/resources/conf/skin-service-configuration.xml	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/test/resources/conf/skin-service-configuration.xml	2011-10-10 08:29:57 UTC (rev 7695)
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-
-    Copyright (C) 2009 eXo Platform SAS.
-    
-    This is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as
-    published by the Free Software Foundation; either version 2.1 of
-    the License, or (at your option) any later version.
-    
-    This software is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-    
-    You should have received a copy of the GNU Lesser General Public
-    License along with this software; if not, write to the Free
-    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-    02110-1301 USA, or see the FSF site: http://www.fsf.org.
-
--->
-
-<configuration
-   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-   xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd"
-   xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
-
-   <component>
-      <key>org.exoplatform.portal.resource.SkinService</key>
-      <type>org.exoplatform.portal.resource.SkinService</type>
-   </component>
-</configuration>

Added: portal/trunk/component/web/resources/src/test/resources/conf/test-configuration.xml
===================================================================
--- portal/trunk/component/web/resources/src/test/resources/conf/test-configuration.xml	                        (rev 0)
+++ portal/trunk/component/web/resources/src/test/resources/conf/test-configuration.xml	2011-10-10 08:29:57 UTC (rev 7695)
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+    Copyright (C) 2009 eXo Platform SAS.
+    
+    This is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as
+    published by the Free Software Foundation; either version 2.1 of
+    the License, or (at your option) any later version.
+    
+    This software is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+    
+    You should have received a copy of the GNU Lesser General Public
+    License along with this software; if not, write to the Free
+    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+    02110-1301 USA, or see the FSF site: http://www.fsf.org.
+
+-->
+
+<configuration
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd"
+   xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
+
+   <component>
+      <key>org.exoplatform.portal.resource.SkinService</key>
+      <type>org.exoplatform.portal.resource.SkinService</type>
+   </component>
+   
+   <component>
+      <key>org.exoplatform.web.application.javascript.JavascriptConfigService</key>
+      <type>org.exoplatform.web.application.javascript.JavascriptConfigService</type>
+   </component>
+
+   <component>
+      <key>org.exoplatform.portal.resource.compressor.ResourceCompressor</key>
+      <type>org.exoplatform.portal.resource.compressor.impl.ResourceCompressorService</type>
+   </component>
+</configuration>
\ No newline at end of file

Modified: portal/trunk/component/web/resources/src/test/resources/mockwebapp/gatein-resources.xml
===================================================================
--- portal/trunk/component/web/resources/src/test/resources/mockwebapp/gatein-resources.xml	2011-10-10 08:10:35 UTC (rev 7694)
+++ portal/trunk/component/web/resources/src/test/resources/mockwebapp/gatein-resources.xml	2011-10-10 08:29:57 UTC (rev 7695)
@@ -21,128 +21,93 @@
 -->
 <gatein-resources
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://www.gatein.org/xml/ns/gatein_resources_1_1 http://www.gatein.org/xml/ns/gatein_resources_1_1"
-    xmlns="http://www.gatein.org/xml/ns/gatein_resources_1_1">
+    xsi:schemaLocation="http://www.gatein.org/xml/ns/gatein_resources_1_2 http://www.gatein.org/xml/ns/gatein_resources_1_2"
+    xmlns="http://www.gatein.org/xml/ns/gatein_resources_1_2">
 
-	<portal-skin>
-		<skin-name>TestSkin</skin-name>
-		<css-path>/skin/Stylesheet.css</css-path>
-	</portal-skin>
+   <portal-skin>
+      <skin-name>TestSkin</skin-name>
+      <css-path>/skin/core/Stylesheet.css</css-path>
+      <css-priority>0</css-priority>
+   </portal-skin>
 
-  <portlet-skin>
-		<application-name>mockwebapp</application-name>
-		<portlet-name>FirstPortlet</portlet-name>
-		<skin-name>TestSkin</skin-name>
-		<css-path>/skin/portlet/FirstPortlet/Stylesheet.css</css-path>
-	</portlet-skin>
+   <portal-skin>
+      <skin-name>TestSkin</skin-name>
+      <skin-module>Module1</skin-module>
+      <css-path>/skin/module1/Stylesheet.css</css-path>
+   </portal-skin>
 
-	<!-- Simple window style -->
-	<window-style>
-		<style-name>Simple</style-name>
-		<style-theme>
-			<theme-name>SimpleBlue</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>SimpleViolet</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>SimpleOrange</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>SimplePink</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>SimpleGreen</theme-name>
-		</style-theme>
-	</window-style>
-	
-	<!-- RoundConer window style -->
-	<window-style>
-		<style-name>RoundConer</style-name>
-		<style-theme>
-			<theme-name>RoundConerBlue</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>RoundConerViolet</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>RoundConerOrange</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>RoundConerPink</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>RoundConerGreen</theme-name>
-		</style-theme>
-	</window-style>
-	
-	<!-- Shadow window style -->
-	<window-style>
-		<style-name>Shadow</style-name>
-		<style-theme>
-			<theme-name>ShadowBlue</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>ShadowViolet</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>ShadowOrange</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>ShadowPink</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>ShadowGreen</theme-name>
-		</style-theme>
-	</window-style>
-	
-	<!-- MacStyle window style -->
-	<window-style>
-		<style-name>MacStyle</style-name>
-		<style-theme>
-			<theme-name>MacTheme</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>MacGray</theme-name>
-		</style-theme>
-		<style-theme>
-			<theme-name>MacGreenSteel</theme-name>
-		</style-theme>
-	</window-style>
-	
-	<!-- VistaStyle window style -->
-	<window-style>
-		<style-name>VistaStyle</style-name>
-		<style-theme>
-			<theme-name>VistaTheme</theme-name>
-		</style-theme>
-	</window-style>
-	
-	<javascript>
-		<param>
-			<js-module>js.test1</js-module>
-			<js-path>/js/test1.js</js-path>	
-			<js-priority>-1</js-priority>		
-		</param>
-	</javascript>	
-	<javascript>
-		<param>
-			<js-module>js.test2</js-module>
-			<js-path>/js/test2.js</js-path>
-			<js-priority>1</js-priority>
-		</param>
-	</javascript>	
-	<javascript>
-		<param>
-			<js-module>js.test3</js-module>
-			<js-path>/js/test3.js</js-path>
-		</param>
-	</javascript>	
-	<javascript>
-		<param>
-			<js-module>js.test4</js-module>
-			<js-path>/js/test4.js</js-path>
-			<js-priority>2</js-priority>
-		</param>
-	</javascript>
+   <portal-skin>
+      <skin-name>TestSkin</skin-name>
+      <skin-module>Module2</skin-module>
+      <css-path>/skin/module2/Stylesheet.css</css-path>
+      <css-priority>1</css-priority>
+   </portal-skin>
+
+   <portal-skin>
+      <skin-name>TestSkin</skin-name>
+      <skin-module>Module3</skin-module>
+      <css-path>/skin/module3/Stylesheet.css</css-path>
+      <css-priority>1</css-priority>
+   </portal-skin>
+
+   <portlet-skin>
+      <application-name>mockwebapp</application-name>
+      <portlet-name>FirstPortlet</portlet-name>
+      <skin-name>TestSkin</skin-name>
+      <css-path>/skin/FirstPortlet.css</css-path>
+   </portlet-skin>
+
+   <portlet-skin>
+      <application-name>mockwebapp</application-name>
+      <portlet-name>SecondPortlet</portlet-name>
+      <skin-name>TestSkin</skin-name>
+      <css-path>/skin/SecondPortlet.css</css-path>
+   </portlet-skin>
+
+   <!-- Simple window style -->
+   <window-style>
+      <style-name>Simple</style-name>
+      <style-theme>
+         <theme-name>SimpleBlue</theme-name>
+      </style-theme>
+      <style-theme>
+         <theme-name>SimpleViolet</theme-name>
+      </style-theme>
+   </window-style>
+
+   <!-- VistaStyle window style -->
+   <window-style>
+      <style-name>VistaStyle</style-name>
+      <style-theme>
+         <theme-name>VistaTheme</theme-name>
+      </style-theme>
+   </window-style>
+
+   <javascript>
+      <param>
+         <js-module>js.test1</js-module>
+         <js-path>/js/test1.js</js-path>
+         <js-priority>-1</js-priority>
+      </param>
+   </javascript>
+   <javascript>
+      <param>
+         <js-module>js.test2</js-module>
+         <js-path>/js/test2.js</js-path>
+         <js-priority>1</js-priority>
+      </param>
+   </javascript>
+   <javascript>
+      <param>
+         <js-module>js.test3</js-module>
+         <js-path>/js/test3.js</js-path>
+      </param>
+   </javascript>
+   <javascript>
+      <param>
+         <js-module>js.test4</js-module>
+         <js-path>/js/test4.js</js-path>
+         <js-priority>2</js-priority>
+      </param>
+   </javascript>
 </gatein-resources>

Added: portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/FirstPortlet.css
===================================================================
--- portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/FirstPortlet.css	                        (rev 0)
+++ portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/FirstPortlet.css	2011-10-10 08:29:57 UTC (rev 7695)
@@ -0,0 +1 @@
+.FirstPortlet {foo1 : bar1}
\ No newline at end of file

Added: portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/SecondPortlet.css
===================================================================
--- portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/SecondPortlet.css	                        (rev 0)
+++ portal/trunk/component/web/resources/src/test/resources/mockwebapp/skin/SecondPortlet.css	2011-10-10 08:29:57 UTC (rev 7695)
@@ -0,0 +1 @@
+.SecondPortlet {foo2 : bar2}
\ No newline at end of file



More information about the gatein-commits mailing list