You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/06/23 23:05:35 UTC

svn commit: r1139073 - in /myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src: main/java/org/apache/myfaces/commons/resourcehandler/ main/java/org/apache/myfaces/commons/resourcehandler/config/ main/java/org/apache/myfaces/commons/reso...

Author: lu4242
Date: Thu Jun 23 21:05:34 2011
New Revision: 1139073

URL: http://svn.apache.org/viewvc?rev=1139073&view=rev
Log:
MFCOMMONS-33 Extended ResourceHandler implementation (myfaces-resources-config.xml parsing)

Added:
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceLoaderWrapper.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMeta.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMetaImpl.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/DefaultMyFacesResourceHandlerUrlProvider.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerConfigParser.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerUrlProvider.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/Library.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/MyFacesResourcesConfig.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/test/resources/test/
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/test/resources/test/myfaces-resources-config.xml
Modified:
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedDefaultResourceHandlerSupport.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceHandlerImpl.java
    myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceImpl.java

Modified: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedDefaultResourceHandlerSupport.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedDefaultResourceHandlerSupport.java?rev=1139073&r1=1139072&r2=1139073&view=diff
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedDefaultResourceHandlerSupport.java (original)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedDefaultResourceHandlerSupport.java Thu Jun 23 21:05:34 2011
@@ -29,6 +29,8 @@ import javax.faces.context.FacesContext;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 import org.apache.myfaces.commons.resourcehandler.application.FacesServletMapping;
+import org.apache.myfaces.commons.resourcehandler.config.MyFacesResourceHandlerConfigParser;
+import org.apache.myfaces.commons.resourcehandler.config.element.MyFacesResourcesConfig;
 import org.apache.myfaces.commons.resourcehandler.filter.ExtendedResourceHandlerFilter;
 import org.apache.myfaces.commons.resourcehandler.resource.BaseResourceHandlerSupport;
 import org.apache.myfaces.commons.resourcehandler.resource.ClassLoaderResourceLoader;
@@ -78,6 +80,8 @@ public class ExtendedDefaultResourceHand
     
     private final boolean _developmentStage;
     
+    private MyFacesResourcesConfig _config;
+    
     public ExtendedDefaultResourceHandlerSupport()
     {
         super();
@@ -91,6 +95,15 @@ public class ExtendedDefaultResourceHand
         _cacheDiskGzipResources = WebConfigParamUtils.getBooleanInitParameter(context.getExternalContext(), 
                 INIT_PARAM_CACHE_DISK_GZIP_RESOURCES, true);
         _developmentStage = context.isProjectStage(ProjectStage.Development);
+        
+        // parse the config
+        MyFacesResourceHandlerConfigParser configParser = new MyFacesResourceHandlerConfigParser();
+        _config = configParser.parse(FacesContext.getCurrentInstance());
+    }
+    
+    public MyFacesResourcesConfig getMyFacesResourcesConfig()
+    {
+        return _config;
     }
     
     public String[] getGzipResourcesSuffixes()
@@ -257,7 +270,9 @@ public class ExtendedDefaultResourceHand
         return mapping;
     }
 
-
+    /**
+     * Return the resource loaders used. Note this loaders should return ExtendedResourceMeta instances.
+     */
     public ResourceLoader[] getResourceLoaders()
     {
         if (_resourceLoaders == null)
@@ -269,15 +284,15 @@ public class ExtendedDefaultResourceHand
             if (!_developmentStage && isGzipResourcesEnabled() && isCacheDiskGzipResources())
             {
                 _resourceLoaders = new ResourceLoader[] {
-                        new GZIPResourceLoader(new ExternalContextResourceLoader("/resources"), this),
-                        new GZIPResourceLoader(new ClassLoaderResourceLoader("META-INF/resources"), this)
+                        new GZIPResourceLoader(new ExtendedResourceLoaderWrapper(new ExternalContextResourceLoader("/resources")), this),
+                        new GZIPResourceLoader(new ExtendedResourceLoaderWrapper(new ClassLoaderResourceLoader("META-INF/resources")), this)
                 };
             }
             else
             {
                 _resourceLoaders = new ResourceLoader[] {
-                        new ExternalContextResourceLoader("/resources"),
-                        new ClassLoaderResourceLoader("META-INF/resources")
+                        new ExtendedResourceLoaderWrapper(new ExternalContextResourceLoader("/resources")),
+                        new ExtendedResourceLoaderWrapper(new ClassLoaderResourceLoader("META-INF/resources"))
                 };
             }
         }

Modified: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceHandlerImpl.java?rev=1139073&r1=1139072&r2=1139073&view=diff
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceHandlerImpl.java (original)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceHandlerImpl.java Thu Jun 23 21:05:34 2011
@@ -39,8 +39,7 @@ import javax.faces.context.ExternalConte
 import javax.faces.context.FacesContext;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.myfaces.commons.resourcehandler.config.AdvancedResourceHandlerConfig;
-import org.apache.myfaces.commons.resourcehandler.config.AdvancedResourceHandlerConfigParser;
+import org.apache.myfaces.commons.resourcehandler.config.element.Library;
 import org.apache.myfaces.commons.resourcehandler.filter.ExtendedResourceHandlerFilter;
 import org.apache.myfaces.commons.resourcehandler.resource.ResourceHandlerCache;
 import org.apache.myfaces.commons.resourcehandler.resource.ResourceHandlerCache.ResourceValue;
@@ -74,18 +73,13 @@ public class ExtendedResourceHandlerImpl
     
     private ResourceHandler _delegate;
     
-    private AdvancedResourceHandlerConfig _config;
-    
     //private volatile Boolean filterOn;
 
     public ExtendedResourceHandlerImpl(ResourceHandler delegate)
     {
         this._delegate = delegate;
-        this._config = new AdvancedResourceHandlerConfig();
-        
-        // parse the config
-        AdvancedResourceHandlerConfigParser configParser = new AdvancedResourceHandlerConfigParser();
-        configParser.parse(_config);
+        //Eager initialization
+        _resourceHandlerSupport = new ExtendedDefaultResourceHandlerSupport();
     }
     
     /*
@@ -98,7 +92,7 @@ public class ExtendedResourceHandlerImpl
     @Override
     public Resource createResource(String resourceName, String libraryName)
     {
-        if (_config.isAdvancedLibrary(libraryName))
+        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
         {
             return createResource(resourceName, libraryName, null);
         }
@@ -112,7 +106,7 @@ public class ExtendedResourceHandlerImpl
     public Resource createResource(String resourceName, String libraryName,
             String contentType)
     {
-        if (_config.isAdvancedLibrary(libraryName))
+        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
         {
             return defaultCreateResource(resourceName, libraryName, contentType);
         }
@@ -122,7 +116,7 @@ public class ExtendedResourceHandlerImpl
         }
     }
     
-    private Resource defaultCreateResource(String resourceName, String libraryName,
+    private Resource defaultCreateResource(String resourceName, String expectedLibraryName,
             String contentType)
     {
         Resource resource = null;
@@ -141,31 +135,35 @@ public class ExtendedResourceHandlerImpl
         {
             localePrefix = getLocalePrefixForLocateResource();
         }
+        
+        //Calculate the real libraryName
+        String redirectedLibraryName = resolveLibraryName(expectedLibraryName);
 
         // check cache
-        if(getResourceLoaderCache().containsResource(resourceName, libraryName, contentType, localePrefix))
+        if(getResourceLoaderCache().containsResource(resourceName, redirectedLibraryName, contentType, localePrefix))
         {
             ResourceValue resourceValue = getResourceLoaderCache().getResource(
-                    resourceName, libraryName, contentType, localePrefix);
+                    resourceName, redirectedLibraryName, contentType, localePrefix);
             
             //resource = new ResourceImpl(resourceValue.getResourceMeta(), resourceValue.getResourceLoader(),
             //        getResourceHandlerSupport(), contentType);
-            resource = new ExtendedResourceImpl(resourceValue.getResourceMeta(), resourceValue.getResourceLoader(),
-                    getResourceHandlerSupport(), contentType, localePrefix);
+            resource = new ExtendedResourceImpl((ExtendedResourceMeta) resourceValue.getResourceMeta(), resourceValue.getResourceLoader(),
+                    getResourceHandlerSupport(), contentType, localePrefix, redirectedLibraryName.equals(expectedLibraryName) ? null : expectedLibraryName);
         }
         else
         {
             for (ResourceLoader loader : getResourceHandlerSupport().getResourceLoaders())
             {
-                ResourceMeta resourceMeta = deriveResourceMeta(loader, resourceName, libraryName, localePrefix);
+                ResourceMeta resourceMeta = deriveResourceMeta(loader, resourceName, redirectedLibraryName, localePrefix);
     
                 if (resourceMeta != null)
                 {
                     //resource = new ResourceImpl(resourceMeta, loader, getResourceHandlerSupport(), contentType);
-                    resource = new ExtendedResourceImpl(resourceMeta, loader, getResourceHandlerSupport(), contentType, localePrefix);
+                    resource = new ExtendedResourceImpl((ExtendedResourceMeta) resourceMeta, loader, getResourceHandlerSupport(), contentType, localePrefix,
+                            redirectedLibraryName.equals(expectedLibraryName) ? null : expectedLibraryName);
 
                     // cache it
-                    getResourceLoaderCache().putResource(resourceName, libraryName, contentType,
+                    getResourceLoaderCache().putResource(resourceName, redirectedLibraryName, contentType,
                             localePrefix, resourceMeta, loader);
                     break;
                 }
@@ -175,18 +173,43 @@ public class ExtendedResourceHandlerImpl
         return resource;
     }
 
+    public String resolveLibraryName(String libraryName)
+    {
+        String finalLibraryName = libraryName;
+        Library library = null;
+        boolean resolved = false;
+        do 
+        {
+            library = getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(finalLibraryName);
+            if (library != null)
+            {
+                if (library.getRedirectName() != null && library.getRedirectName().length() > 0)
+                {
+                    finalLibraryName = library.getRedirectName();
+                }
+                else
+                {
+                    //No redirect, so this is the real instance
+                    resolved = true;
+                }
+            }
+        } while (library != null && !resolved);
+        
+        return finalLibraryName;
+    }
+    
     /**
      * This method try to create a ResourceMeta for a specific resource
      * loader. If no library, or resource is found, just return null,
      * so the algorithm in createResource can continue checking with the 
      * next registered ResourceLoader. 
      */
-    protected ResourceMeta deriveResourceMeta(ResourceLoader resourceLoader,
+    protected ExtendedResourceMeta deriveResourceMeta(ResourceLoader resourceLoader,
             String resourceName, String libraryName, String localePrefix)
     {
         String resourceVersion = null;
         String libraryVersion = null;
-        ResourceMeta resourceId = null;
+        ExtendedResourceMeta resourceId = null;
         
         //1. Try to locate resource in a localized path
         if (localePrefix != null)
@@ -214,7 +237,7 @@ public class ExtendedResourceHandlerImpl
 
                 if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
                 {
-                    resourceId = resourceLoader.createResourceMeta(localePrefix, libraryName,
+                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(localePrefix, libraryName,
                             libraryVersion, resourceName, resourceVersion);
                 }
             }
@@ -224,7 +247,7 @@ public class ExtendedResourceHandlerImpl
                         .getResourceVersion(localePrefix + '/'+ resourceName);
                 if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
                 {               
-                    resourceId = resourceLoader.createResourceMeta(localePrefix, null, null,
+                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(localePrefix, null, null,
                             resourceName, resourceVersion);
                 }
             }
@@ -262,7 +285,7 @@ public class ExtendedResourceHandlerImpl
 
                 if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
                 {               
-                    resourceId = resourceLoader.createResourceMeta(null, libraryName,
+                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(null, libraryName,
                             libraryVersion, resourceName, resourceVersion);
                 }
             }
@@ -273,7 +296,7 @@ public class ExtendedResourceHandlerImpl
                 
                 if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
                 {               
-                    resourceId = resourceLoader.createResourceMeta(null, null, null,
+                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(null, null, null,
                             resourceName, resourceVersion);
                 }
             }
@@ -393,7 +416,7 @@ public class ExtendedResourceHandlerImpl
             {
                 super.handleResourceRequest(facesContext);
             }
-            else if (libraryName != null && !_config.isAdvancedLibrary(libraryName))
+            else if (libraryName != null && getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) == null)
             {
                 super.handleResourceRequest(facesContext);
             }
@@ -569,8 +592,11 @@ public class ExtendedResourceHandlerImpl
         }
         else
         {
-            //Default rules applies because resourceBasePath still starts with /javax.faces.resource, delegate to parent.
-            return super.isResourceRequest(facesContext);
+            //return super.isResourceRequest(facesContext);
+            //Since it is necessary to calculate the base path and we are in a filter request, it is not possible to delegate this call,
+            //because other ResourceHandler implementation assume this request comes from the servlet. Later, if the servlet is a target
+            //to this request, it will be processed there.
+            return false;
         }
     }
 
@@ -634,7 +660,7 @@ public class ExtendedResourceHandlerImpl
     @Override
     public boolean libraryExists(String libraryName)
     {
-        if (_config.isAdvancedLibrary(libraryName))
+        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
         {
             String localePrefix = getLocalePrefixForLocateResource();
     
@@ -688,10 +714,6 @@ public class ExtendedResourceHandlerImpl
      */
     protected ExtendedDefaultResourceHandlerSupport getResourceHandlerSupport()
     {
-        if (_resourceHandlerSupport == null)
-        {
-            _resourceHandlerSupport = new ExtendedDefaultResourceHandlerSupport();
-        }
         return _resourceHandlerSupport;
     }
 

Modified: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceImpl.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceImpl.java?rev=1139073&r1=1139072&r2=1139073&view=diff
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceImpl.java (original)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceImpl.java Thu Jun 23 21:05:34 2011
@@ -19,15 +19,21 @@
 package org.apache.myfaces.commons.resourcehandler;
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.ValueExpression;
+import javax.el.VariableMapper;
 import javax.faces.application.ResourceHandler;
 import javax.faces.context.FacesContext;
 
+import org.apache.myfaces.commons.resourcehandler.config.element.Library;
 import org.apache.myfaces.commons.resourcehandler.resource.ResourceImpl;
 import org.apache.myfaces.commons.resourcehandler.resource.ResourceLoader;
-import org.apache.myfaces.commons.resourcehandler.resource.ResourceMeta;
 
 /**
  * 
@@ -37,13 +43,23 @@ import org.apache.myfaces.commons.resour
 public class ExtendedResourceImpl extends ResourceImpl
 {
     private String _expectedLocalePrefix;
-
-    public ExtendedResourceImpl(ResourceMeta resourceMeta,
+    
+    private ExtendedResourceMeta _extendedResourceMeta;
+    
+    private ExtendedDefaultResourceHandlerSupport _extendedDefaultResourceHandlerSupport;
+    
+    public ExtendedResourceImpl(ExtendedResourceMeta resourceMeta,
             ResourceLoader resourceLoader, ExtendedDefaultResourceHandlerSupport support,
-            String contentType, String expectedLocalePrefix)
+            String contentType, String expectedLocalePrefix, String expectedLibraryName)
     {
         super(resourceMeta, resourceLoader, support, contentType);
+        _extendedResourceMeta = resourceMeta;
         _expectedLocalePrefix = expectedLocalePrefix;
+        _extendedDefaultResourceHandlerSupport = support;
+        if (expectedLibraryName != null)
+        {
+            setLibraryName(expectedLibraryName);
+        }
     }
 
     @Override
@@ -51,7 +67,50 @@ public class ExtendedResourceImpl extend
     {
         String mapping = getResourceHandlerSupport().getMapping() != null ?
                 getResourceHandlerSupport().getMapping() :
-                "" ; 
+                "" ;
+
+        Library library = getExtendedDefaultResourceHandlerSupport().getMyFacesResourcesConfig().
+            getLibrary(getLibraryName());
+            
+        if (library.getRequestPath() == null)
+        {
+            String localePrefix = getResourceMeta().getLocalePrefix() != null ?  
+                    getResourceMeta().getLocalePrefix() : _expectedLocalePrefix;
+            if (localePrefix == null)
+            {
+                // calculate current localePrefix (could be different from the one requested, e.g. on locale change)
+                localePrefix = getRequestLocalePrefix();
+            }
+            String path = null;
+            if (!getResourceHandlerSupport().isExtensionMapping())
+            {
+                path = mapping + ResourceHandler.RESOURCE_IDENTIFIER + "/$/" + 
+                                localePrefix + '/' + 
+                                getLibraryName() + '/' + 
+                                getResourceName();
+            }
+            else
+            {
+                path = ResourceHandler.RESOURCE_IDENTIFIER + "/$/" + 
+                localePrefix + '/' + 
+                getLibraryName() + '/' + 
+                getResourceName() + mapping;
+            }
+            
+            FacesContext facesContext = FacesContext.getCurrentInstance();
+            return facesContext.getApplication().getViewHandler().getResourceURL(facesContext, path);
+        }
+        else
+        {
+            //Redirect url assume prefix mapping.
+            FacesContext facesContext = FacesContext.getCurrentInstance();
+            return facesContext.getApplication().getViewHandler().getResourceURL(facesContext, 
+                    calculateRequestPath(facesContext, library.getRequestPath()));
+        }
+    }
+    
+    public String getLocalePrefix()
+    {
         String localePrefix = getResourceMeta().getLocalePrefix() != null ?  
                 getResourceMeta().getLocalePrefix() : _expectedLocalePrefix;
         if (localePrefix == null)
@@ -59,29 +118,30 @@ public class ExtendedResourceImpl extend
             // calculate current localePrefix (could be different from the one requested, e.g. on locale change)
             localePrefix = getRequestLocalePrefix();
         }
-        String path = null;
-        if (!getResourceHandlerSupport().isExtensionMapping())
-        {
-            path = mapping + ResourceHandler.RESOURCE_IDENTIFIER + "/$/" + 
-                            localePrefix + '/' + 
-                            getLibraryName() + '/' + 
-                            getResourceName();
-        }
-        else
+        return localePrefix;
+    }
+    
+    private String calculateRequestPath(FacesContext context, String expression)
+    {
+        ValueExpression requestPath = getExtendedResourceMeta().getRequestPathExpression(); 
+        if (requestPath == null)
         {
-            path = ResourceHandler.RESOURCE_IDENTIFIER + "/$/" + 
-            localePrefix + '/' + 
-            getLibraryName() + '/' + 
-            getResourceName() + mapping;
+            ELContext elContext = new ELContextWrapper(context.getELContext(), context, this);
+            requestPath = context.getApplication().getExpressionFactory().createValueExpression(
+                    elContext, expression, String.class);
+            getExtendedResourceMeta().setRequestPathExpression(requestPath);
         }
-        
-        FacesContext facesContext = FacesContext.getCurrentInstance();
-        return facesContext.getApplication().getViewHandler().getResourceURL(facesContext, path);
+        return (String) requestPath.getValue(context.getELContext());
     }
-
+    
+    protected ExtendedResourceMeta getExtendedResourceMeta()
+    {
+        return _extendedResourceMeta;
+    }
+    
     protected ExtendedDefaultResourceHandlerSupport getExtendedDefaultResourceHandlerSupport()
     {
-        return (ExtendedDefaultResourceHandlerSupport) getResourceHandlerSupport();
+        return _extendedDefaultResourceHandlerSupport;
     }
     
     @Override
@@ -137,5 +197,107 @@ public class ExtendedResourceImpl extend
             // de
             return language;
         }
-    }    
+    }
+    
+    private static class ELContextWrapper extends ELContext
+    {
+        private ELContext _delegate;
+        private VariableMapper _mapper;
+        
+        
+        private ELContextWrapper(ELContext delegate, FacesContext context, ExtendedResourceImpl resource)
+        {
+            this._delegate = delegate;
+            this._mapper = new VariableMapperWrapper(delegate.getVariableMapper(), context, resource);
+        }
+
+        public void setPropertyResolved(boolean resolved)
+        {
+            _delegate.setPropertyResolved(resolved);
+        }
+
+        public boolean isPropertyResolved()
+        {
+            return _delegate.isPropertyResolved();
+        }
+
+        public void putContext(Class key, Object contextObject)
+        {
+            _delegate.putContext(key, contextObject);
+        }
+
+        public Object getContext(Class key)
+        {
+            return _delegate.getContext(key);
+        }
+
+        public ELResolver getELResolver()
+        {
+            return _delegate.getELResolver();
+        }
+
+        public FunctionMapper getFunctionMapper()
+        {
+            return _delegate.getFunctionMapper();
+        }
+
+        public Locale getLocale()
+        {
+            return _delegate.getLocale();
+        }
+
+        public void setLocale(Locale locale)
+        {
+            _delegate.setLocale(locale);
+        }
+
+        public VariableMapper getVariableMapper()
+        {
+            return _mapper;
+        }
+    }
+    
+    private static class VariableMapperWrapper extends VariableMapper
+    {
+        private VariableMapper delegate;
+        
+        private Map<String, ValueExpression> map; 
+        
+        private VariableMapperWrapper(VariableMapper delegate, FacesContext context, ExtendedResourceImpl resource)
+        {
+            this.delegate = delegate;
+            map = new HashMap<String, ValueExpression>(4,1);
+            map.put("localePrefix", context.getApplication().getExpressionFactory().createValueExpression(resource.getLocalePrefix(), String.class));
+            map.put("libraryName", context.getApplication().getExpressionFactory().createValueExpression(resource.getLibraryName(), String.class));
+            map.put("resourceName", context.getApplication().getExpressionFactory().createValueExpression(resource.getResourceName(), String.class));
+            map.put("mapping", context.getApplication().getExpressionFactory().createValueExpression(
+                    resource.getExtendedDefaultResourceHandlerSupport().getMapping(), String.class));
+            map.put("extensionMapping", context.getApplication().getExpressionFactory().createValueExpression(
+                    resource.getExtendedDefaultResourceHandlerSupport().isExtensionMapping(), Boolean.class));
+        }
+
+        public ValueExpression resolveVariable(String variable)
+        {
+            ValueExpression value = map.get(variable);
+            if (value != null)
+            {
+                return value;
+            }
+            if (delegate != null)
+            {
+                return delegate.resolveVariable(variable);
+            }
+            return null;
+        }
+
+        public ValueExpression setVariable(String variable,
+                ValueExpression expression)
+        {
+            if (delegate != null)
+            {
+                return delegate.setVariable(variable, expression);
+            }
+            return null;
+        }
+    }
 }

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceLoaderWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceLoaderWrapper.java?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceLoaderWrapper.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceLoaderWrapper.java Thu Jun 23 21:05:34 2011
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.resourcehandler;
+
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceLoader;
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceLoaderWrapper;
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceMeta;
+
+/**
+ * Resource Loader that just wraps ResourceMetaImpl into ExtendedResourceMetaImpl,
+ * to allow cache request path expressions. 
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public class ExtendedResourceLoaderWrapper extends ResourceLoaderWrapper
+{
+    private ResourceLoader _delegate;
+    
+    public ExtendedResourceLoaderWrapper(ResourceLoader delegate)
+    {
+        this._delegate = delegate; 
+    }
+
+    @Override
+    public ResourceMeta createResourceMeta(String prefix, String libraryName,
+            String libraryVersion, String resourceName, String resourceVersion)
+    {
+        return new ExtendedResourceMetaImpl(
+                super.createResourceMeta(prefix, libraryName, libraryVersion, 
+                                         resourceName, resourceVersion));
+    }
+
+    public ResourceLoader getWrapped()
+    {
+        return _delegate;
+    }
+    
+}

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMeta.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMeta.java?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMeta.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMeta.java Thu Jun 23 21:05:34 2011
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.resourcehandler;
+
+import javax.el.ValueExpression;
+
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceMeta;
+
+/**
+ * This abstract class extends from default ResourceMeta to allow cache request path expressions on
+ * the resource cache and reuse it across requests.
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public abstract class ExtendedResourceMeta extends ResourceMeta
+{
+    public abstract ValueExpression getRequestPathExpression();
+    
+    public abstract void setRequestPathExpression(ValueExpression expression);
+}

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMetaImpl.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMetaImpl.java?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMetaImpl.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceMetaImpl.java Thu Jun 23 21:05:34 2011
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.resourcehandler;
+
+import javax.el.ValueExpression;
+import javax.faces.FacesWrapper;
+
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceMeta;
+
+/**
+ * This class extends from ExtendedResourceMeta to allow cache request path expressions on
+ * the resource cache and reuse it across requests.
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public class ExtendedResourceMetaImpl extends ExtendedResourceMeta implements FacesWrapper<ResourceMeta>
+{
+    private ResourceMeta _delegate;
+    private ValueExpression _requestPath;
+
+    public ExtendedResourceMetaImpl(ResourceMeta delegate)
+    {
+        _delegate = delegate;
+    }
+
+    public ValueExpression getRequestPathExpression()
+    {
+        return _requestPath;
+    }
+    
+    public void setRequestPathExpression(ValueExpression expression)
+    {
+        _requestPath = expression;
+    }
+
+    @Override
+    public String getLibraryName()
+    {
+        return getWrapped().getLibraryName();
+    }
+
+    @Override
+    public String getResourceName()
+    {
+        return getWrapped().getResourceName();
+    }
+
+    @Override
+    public String getLocalePrefix()
+    {
+        return getWrapped().getLocalePrefix();
+    }
+
+    @Override
+    public String getLibraryVersion()
+    {
+        return getWrapped().getLibraryVersion();
+    }
+
+    @Override
+    public String getResourceVersion()
+    {
+        return getWrapped().getResourceVersion();
+    }
+
+    @Override
+    public String getResourceIdentifier()
+    {
+        return getWrapped().getResourceIdentifier();
+    }
+
+    @Override
+    public boolean couldResourceContainValueExpressions()
+    {
+        return getWrapped().couldResourceContainValueExpressions();
+    }
+
+    public ResourceMeta getWrapped()
+    {
+        return _delegate;
+    }
+}

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/DefaultMyFacesResourceHandlerUrlProvider.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/DefaultMyFacesResourceHandlerUrlProvider.java?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/DefaultMyFacesResourceHandlerUrlProvider.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/DefaultMyFacesResourceHandlerUrlProvider.java Thu Jun 23 21:05:34 2011
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.resourcehandler.config;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+
+import org.apache.myfaces.commons.resourcehandler.AdvancedResourceHandler;
+import org.apache.myfaces.commons.util.ClassUtils;
+
+/**
+ * Default implementation used to load myfaces-resources-config.xml files
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public class DefaultMyFacesResourceHandlerUrlProvider extends MyFacesResourceHandlerUrlProvider
+{
+
+    public Collection<URL> getMetaInfConfigurationResources(ExternalContext context) throws IOException
+    {
+        ClassLoader contextClassLoader = ClassUtils.getContextClassLoader();
+        Enumeration<URL> metaInfConfigUrls = null;
+        List<URL> configUrls = new ArrayList<URL>(); 
+
+        try
+        {
+            // NOTE that there could be multiple config files (in different jar files)
+            metaInfConfigUrls = contextClassLoader.getResources(META_INF_CONFIG_FILE);
+        }
+        catch (IOException e)
+        {
+            throw new FacesException("Could not open " + AdvancedResourceHandler.CONFIG_FILE, e);
+        }
+
+        if (metaInfConfigUrls != null && metaInfConfigUrls.hasMoreElements())
+        {
+            while (metaInfConfigUrls.hasMoreElements())
+            {
+                URL url = metaInfConfigUrls.nextElement();
+                if (url != null)
+                {
+                    configUrls.add(url);
+                }
+            }
+        }
+
+        return configUrls;
+    }
+
+    public URL getWebInfConfigurationResource(ExternalContext context) throws IOException
+    {
+        return context.getResource(WEB_INF_CONFIG_FILE);
+    }
+}

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerConfigParser.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerConfigParser.java?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerConfigParser.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerConfigParser.java Thu Jun 23 21:05:34 2011
@@ -0,0 +1,302 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.resourcehandler.config;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.commons.resourcehandler.config.element.Library;
+import org.apache.myfaces.commons.resourcehandler.config.element.MyFacesResourcesConfig;
+import org.apache.myfaces.commons.util.ClassUtils;
+import org.apache.myfaces.commons.util.WebConfigParamUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * XML-parser for MyFacesResourcesConfig.
+ *
+ * @author Jakob Korherr
+ * @author Leonardo Uribe
+ */
+public class MyFacesResourceHandlerConfigParser
+{
+    
+    /**
+     * This param allow to override the default strategy to locate myfaces-resources-config.xml files, that will be parsed later. In this way
+     * it is possible to include new source locations or handle cases like OSGi specific setup.   
+     */
+    @JSFWebConfigParam
+    public static final String INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER = "org.apache.myfaces.commons.EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER";
+    public static final String INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER_DEFAULT = DefaultMyFacesResourceHandlerUrlProvider.class.getName();
+    
+    public MyFacesResourcesConfig parse(FacesContext facesContext)
+    {
+        String resourceHandlerUrlProviderClassName = WebConfigParamUtils.getStringInitParameter(facesContext.getExternalContext(),
+                INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER, INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER_DEFAULT);
+        
+        MyFacesResourceHandlerUrlProvider urlProvider = (MyFacesResourceHandlerUrlProvider) ClassUtils.newInstance(resourceHandlerUrlProviderClassName);
+        
+        List<URL> configUrls = new ArrayList<URL>(); 
+
+        try
+        {
+            configUrls.addAll(urlProvider.getMetaInfConfigurationResources(facesContext.getExternalContext()));
+        }
+        catch(IOException e)
+        {
+            throw new FacesException("Cannot get META-INF/myfaces-resources-config.xml urls", e);
+        }
+        
+        try
+        {
+            URL webInfConfig = urlProvider.getWebInfConfigurationResource(facesContext.getExternalContext());
+            if (webInfConfig != null)
+            {
+                configUrls.add(webInfConfig);
+            }
+        }
+        catch(IOException e)
+        {
+            throw new FacesException(e);
+        }
+        
+        List<MyFacesResourcesConfig> configList = new ArrayList<MyFacesResourcesConfig>();
+        // we have at least one config file and thus can start parsing
+        for (URL url : configUrls)
+        {
+            try
+            {
+                MyFacesResourcesConfig mrc = parseFile(url);
+                if (mrc != null)
+                {
+                    configList.add(mrc);
+                }
+            }
+            catch (IOException e) {
+                throw new FacesException("Cannot parse file "+url);
+            }
+        }
+        
+        MyFacesResourcesConfig finalConfig = new MyFacesResourcesConfig();
+        for (MyFacesResourcesConfig cfg : configList)
+        {
+            finalConfig.merge(cfg);
+        }
+        return finalConfig;
+    }
+    
+    private MyFacesResourcesConfig parseFile(URL configFileUrl) throws IOException
+    {
+        InputStream is = null;
+        URLConnection conn = null;
+        try
+        {
+            ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
+            boolean schemaValidating = false;
+
+            // parse file
+            LibraryHandler handler = new LibraryHandler(configFileUrl);
+            SAXParser parser = createSAXParser(handler, externalContext, schemaValidating);
+            conn = configFileUrl.openConnection();
+            conn.setUseCaches(false);
+            is = conn.getInputStream();
+            parser.parse(is, handler);
+            return handler.getMyFacesResourcesConfig();
+        }
+        catch (SAXException e)
+        {
+            IOException ioe = new IOException("Error parsing [" + configFileUrl + "]: ");
+            ioe.initCause(e);
+            throw ioe;
+        }
+        catch (ParserConfigurationException e)
+        {
+            IOException ioe = new IOException("Error parsing [" + configFileUrl + "]: ");
+            ioe.initCause(e);
+            throw ioe;
+        }
+        finally
+        {
+            if (is != null)
+                is.close();
+        }
+    }
+
+    private static final SAXParser createSAXParser(LibraryHandler handler, ExternalContext externalContext, boolean schemaValidating) throws SAXException,
+    ParserConfigurationException
+    {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        
+        //Just parse it and do not validate, because it is not necessary.
+        factory.setNamespaceAware(true);
+        factory.setFeature("http://xml.org/sax/features/validation", false);
+        factory.setValidating(false);
+        
+        SAXParser parser = factory.newSAXParser();
+        XMLReader reader = parser.getXMLReader();
+        reader.setErrorHandler(handler);
+        reader.setEntityResolver(handler);
+        return parser;
+    }
+    
+    private static class LibraryHandler extends DefaultHandler
+    {
+        private final URL source;
+
+        private final StringBuffer buffer;
+        
+        private Locator locator;
+        
+        private MyFacesResourcesConfig config;
+        
+        private String libraryName;
+        
+        private String redirectName;
+        
+        private String requestPath;
+        
+        public LibraryHandler(URL source)
+        {
+            this.source = source;
+            this.buffer = new StringBuffer(64);
+            this.config = null;
+        }
+        
+        public MyFacesResourcesConfig getMyFacesResourcesConfig()
+        {
+            return this.config;
+        }
+
+        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
+        {
+            this.buffer.setLength(0);
+            if ("myfaces-resources-config".equals(qName))
+            {
+                this.config = new MyFacesResourcesConfig();
+            }
+            else if ("library".equals(qName))
+            {
+                this.libraryName = null;
+                this.redirectName = null;
+                this.requestPath = null;
+            }
+        }
+        
+        public void endElement(String uri, String localName, String qName) throws SAXException
+        {
+            try
+            {
+                if (this.config == null)
+                {
+                    return;
+                }
+                
+                if ("library".equals(localName))
+                {
+                    Library l = new Library();
+                    l.setName(libraryName);
+                    l.setRedirectName(redirectName);
+                    l.setRequestPath(requestPath);
+                    config.addLibrary(l);
+                }
+                else if ("library-name".equals(localName))
+                {
+                    libraryName = captureBuffer();
+                }
+                else if ("redirect-name".equals(localName))
+                {
+                    redirectName = captureBuffer();
+                }
+                else if ("request-path".equals(localName))
+                {
+                    requestPath = captureBuffer();
+                }
+            }
+            catch (Exception e)
+            {
+                SAXException saxe = new SAXException("Error Handling [" + this.source + "@"
+                        + this.locator.getLineNumber() + "," + this.locator.getColumnNumber() + "] <" + qName + ">");
+                saxe.initCause(e);
+                throw saxe;
+            }
+        }
+
+        public void characters(char[] ch, int start, int length) throws SAXException
+        {
+            this.buffer.append(ch, start, length);
+        }
+        
+        private String captureBuffer() throws Exception
+        {
+            String s = this.buffer.toString().trim();
+            if (s.length() == 0)
+            {
+                throw new Exception("Value Cannot be Empty");
+            }
+            this.buffer.setLength(0);
+            return s;
+        }        
+        
+        public InputSource resolveEntity(String publicId, String systemId) throws SAXException
+        {
+            return null;
+        }
+
+        public void error(SAXParseException e) throws SAXException
+        {
+            SAXException saxe = new SAXException("Error Handling [" + this.source + "@" + e.getLineNumber() + ","
+                    + e.getColumnNumber() + "]");
+            saxe.initCause(e);
+            throw saxe;
+        }
+
+        public void setDocumentLocator(Locator locator)
+        {
+            this.locator = locator;
+        }
+
+        public void fatalError(SAXParseException e) throws SAXException
+        {
+            throw e;
+        }
+
+        public void warning(SAXParseException e) throws SAXException
+        {
+            throw e;
+        }
+    }
+
+}

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerUrlProvider.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerUrlProvider.java?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerUrlProvider.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/MyFacesResourceHandlerUrlProvider.java Thu Jun 23 21:05:34 2011
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.resourcehandler.config;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+
+import javax.faces.context.ExternalContext;
+
+/**
+ * Provides a way to lookup for myfaces-resources-config.xml urls
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public abstract class MyFacesResourceHandlerUrlProvider
+{
+    public static final String META_INF_CONFIG_FILE = "META-INF/myfaces-resources-config.xml";
+
+    public static final String WEB_INF_CONFIG_FILE = "/WEB-INF/myfaces-resources-config.xml";
+
+    public abstract Collection<URL> getMetaInfConfigurationResources(ExternalContext context) throws IOException;
+    
+    public abstract URL getWebInfConfigurationResource(ExternalContext context) throws IOException;
+}

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/Library.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/Library.java?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/Library.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/Library.java Thu Jun 23 21:05:34 2011
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.resourcehandler.config.element;
+
+/**
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public class Library
+{
+    private String _name;
+    private String _requestPath;
+    private String _redirectName;
+    
+    public String getName()
+    {
+        return _name;
+    }
+    public void setName(String name)
+    {
+        this._name = name;
+    }
+    public String getRequestPath()
+    {
+        return _requestPath;
+    }
+    public void setRequestPath(String requestPath)
+    {
+        this._requestPath = requestPath;
+    }
+    public String getRedirectName()
+    {
+        return _redirectName;
+    }
+    public void setRedirectName(String redirectName)
+    {
+        this._redirectName = redirectName;
+    }
+}

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/MyFacesResourcesConfig.java
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/MyFacesResourcesConfig.java?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/MyFacesResourcesConfig.java (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/config/element/MyFacesResourcesConfig.java Thu Jun 23 21:05:34 2011
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.commons.resourcehandler.config.element;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public class MyFacesResourcesConfig
+{
+    private Map<String, Library> libraries = new HashMap<String, Library>();
+    
+    private Map<String, Library> unmodifiableMap;
+
+    public void addLibrary(Library library)
+    {
+        libraries.put(library.getName(), library);
+        unmodifiableMap = null;
+    }
+    
+    public Library getLibrary(String name)
+    {
+        return libraries.get(name);
+    }
+    
+    public Map<String, Library> getLibraries()
+    {
+        if (unmodifiableMap == null)
+        {
+            unmodifiableMap = Collections.unmodifiableMap(libraries); 
+        }
+        return unmodifiableMap;
+    }
+    
+    public void merge(MyFacesResourcesConfig config)
+    {
+        for (Map.Entry<String, Library> entry : config.getLibraries().entrySet())
+        {
+            this.addLibrary(entry.getValue());
+        }
+    }
+}

Added: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/test/resources/test/myfaces-resources-config.xml
URL: http://svn.apache.org/viewvc/myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/test/resources/test/myfaces-resources-config.xml?rev=1139073&view=auto
==============================================================================
--- myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/test/resources/test/myfaces-resources-config.xml (added)
+++ myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/test/resources/test/myfaces-resources-config.xml Thu Jun 23 21:05:34 2011
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<myfaces-resources-config>
+    <!-- Mark this library to be handled by Extended Resource Handler -->
+    <library>
+        <library-name>libraryA</library-name>
+    </library>
+    
+    <!-- Indicate this library has another name, so if libraryC is used,
+    resources should be redirected to libraryC1 -->
+    <library>
+        <library-name>libraryC</library-name>
+        <redirect-name>libraryC1</redirect-name>
+    </library>
+    
+    <!-- Allow to customize the request path generated, to do things like
+    take library resources from a Content Delivery Network (CDN) or just
+    take it directly from an specified location. Note it is responsibility
+    of the developer to configure it properly, and the resources should
+    exists locally under the library name selected. -->
+    <library>
+        <library-name>libraryB</library-name>
+        <request-path>http://someaddress.com/alternatePath/#{resourceName}</request-path>
+    </library>
+</myfaces-resources-config>