You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by st...@apache.org on 2011/10/20 12:49:36 UTC

svn commit: r1186730 [12/22] - in /myfaces/commons/branches/jsf_20: examples/ examples/myfaces-commons-examples/src/main/java/org/apache/myfaces/commons/examples/ examples/myfaces-commons-examples/src/main/java/org/apache/myfaces/commons/examples/acces...

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=1186730&r1=1186729&r2=1186730&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 Oct 20 10:49:18 2011
@@ -1,766 +1,766 @@
-/*
- * 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 java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Locale;
-import java.util.Map;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.zip.GZIPOutputStream;
-
-import javax.faces.FacesException;
-import javax.faces.application.ProjectStage;
-import javax.faces.application.Resource;
-import javax.faces.application.ResourceHandler;
-import javax.faces.application.ResourceHandlerWrapper;
-import javax.faces.application.ResourceWrapper;
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.myfaces.commons.resourcehandler.config.element.Library;
-import org.apache.myfaces.commons.resourcehandler.resource.ResourceHandlerCache;
-import org.apache.myfaces.commons.resourcehandler.resource.ResourceHandlerCache.ResourceValue;
-import org.apache.myfaces.commons.resourcehandler.resource.ResourceLoader;
-import org.apache.myfaces.commons.resourcehandler.resource.ResourceMeta;
-import org.apache.myfaces.commons.util.ClassUtils;
-import org.apache.myfaces.commons.util.ExternalContextUtils;
-import org.apache.myfaces.commons.util.RequestType;
-import org.apache.myfaces.commons.util.StringUtils;
-
-/**
- * 
- * @author Leonardo Uribe
- *
- */
-public class ExtendedResourceHandlerImpl extends ResourceHandlerWrapper
-{
-    private static final String IS_RESOURCE_REQUEST = "org.apache.myfaces.commons.IS_RESOURCE_REQUEST";
-    
-    private static final String RESOURCE_LOCALE = "org.apache.myfaces.commons.RESOURCE_LOCALE";
-
-    private ExtendedDefaultResourceHandlerSupport _resourceHandlerSupport;
-
-    private ResourceHandlerCache _resourceHandlerCache;
-
-    //private static final Log log = LogFactory.getLog(ResourceHandlerImpl.class);
-    private static final Logger log = Logger.getLogger(ExtendedResourceHandlerImpl.class.getName());
-
-    private static final int _BUFFER_SIZE = 2048;
-    
-    private ResourceHandler _delegate;
-    
-    //private volatile Boolean filterOn;
-
-    public ExtendedResourceHandlerImpl(ResourceHandler delegate)
-    {
-        this._delegate = delegate;
-        //Eager initialization
-        _resourceHandlerSupport = new ExtendedDefaultResourceHandlerSupport();
-    }
-    
-    /*
-    @Override
-    public Resource createResource(String resourceName)
-    {
-        return createResource(resourceName, null);
-    }*/
-    
-    @Override
-    public Resource createResource(String resourceName, String libraryName)
-    {
-        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
-        {
-            return createResource(resourceName, libraryName, null);
-        }
-        else
-        {
-            return super.createResource(resourceName, libraryName);
-        }
-    }
-
-    @Override
-    public Resource createResource(String resourceName, String libraryName,
-            String contentType)
-    {
-        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
-        {
-            return defaultCreateResource(resourceName, libraryName, contentType);
-        }
-        else
-        {
-            return super.createResource(resourceName, libraryName, contentType);
-        }
-    }
-    
-    private Resource defaultCreateResource(String resourceName, String expectedLibraryName,
-            String contentType)
-    {
-        Resource resource = null;
-
-        FacesContext facesContext = FacesContext.getCurrentInstance();
-
-        if (contentType == null)
-        {
-            //Resolve contentType using ExternalContext.getMimeType
-            contentType = facesContext.getExternalContext().getMimeType(resourceName);
-        }
-        
-        String localePrefix = (String) facesContext.getAttributes().get(RESOURCE_LOCALE);
-        
-        if (localePrefix == null)
-        {
-            localePrefix = getLocalePrefixForLocateResource();
-        }
-        
-        //Calculate the real libraryName
-        String redirectedLibraryName = resolveLibraryName(expectedLibraryName);
-
-        // check cache
-        if(getResourceLoaderCache().containsResource(resourceName, redirectedLibraryName, contentType, localePrefix))
-        {
-            ResourceValue resourceValue = getResourceLoaderCache().getResource(
-                    resourceName, redirectedLibraryName, contentType, localePrefix);
-            
-            //resource = new ResourceImpl(resourceValue.getResourceMeta(), resourceValue.getResourceLoader(),
-            //        getResourceHandlerSupport(), contentType);
-            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, redirectedLibraryName, localePrefix);
-    
-                if (resourceMeta != null)
-                {
-                    //resource = new ResourceImpl(resourceMeta, loader, getResourceHandlerSupport(), contentType);
-                    resource = new ExtendedResourceImpl((ExtendedResourceMeta) resourceMeta, loader, getResourceHandlerSupport(), contentType, localePrefix,
-                            redirectedLibraryName.equals(expectedLibraryName) ? null : expectedLibraryName);
-
-                    // cache it
-                    getResourceLoaderCache().putResource(resourceName, redirectedLibraryName, contentType,
-                            localePrefix, resourceMeta, loader);
-                    break;
-                }
-            }
-        }
-        
-        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 ExtendedResourceMeta deriveResourceMeta(ResourceLoader resourceLoader,
-            String resourceName, String libraryName, String localePrefix)
-    {
-        String resourceVersion = null;
-        String libraryVersion = null;
-        ExtendedResourceMeta resourceId = null;
-        
-        //1. Try to locate resource in a localized path
-        if (localePrefix != null)
-        {
-            if (null != libraryName)
-            {
-                String pathToLib = localePrefix + '/' + libraryName;
-                libraryVersion = resourceLoader.getLibraryVersion(pathToLib);
-
-                if (null != libraryVersion)
-                {
-                    String pathToResource = localePrefix + '/'
-                            + libraryName + '/' + libraryVersion + '/'
-                            + resourceName;
-                    resourceVersion = resourceLoader
-                            .getResourceVersion(pathToResource);
-                }
-                else
-                {
-                    String pathToResource = localePrefix + '/'
-                            + libraryName + '/' + resourceName;
-                    resourceVersion = resourceLoader
-                            .getResourceVersion(pathToResource);
-                }
-
-                if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
-                {
-                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(localePrefix, libraryName,
-                            libraryVersion, resourceName, resourceVersion);
-                }
-            }
-            else
-            {
-                resourceVersion = resourceLoader
-                        .getResourceVersion(localePrefix + '/'+ resourceName);
-                if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
-                {               
-                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(localePrefix, null, null,
-                            resourceName, resourceVersion);
-                }
-            }
-
-            if (resourceId != null)
-            {
-                if (!resourceLoader.resourceExists(resourceId))
-                {
-                    resourceId = null;
-                }
-            }            
-        }
-        
-        //2. Try to localize resource in a non localized path
-        if (resourceId == null)
-        {
-            if (null != libraryName)
-            {
-                libraryVersion = resourceLoader.getLibraryVersion(libraryName);
-
-                if (null != libraryVersion)
-                {
-                    String pathToResource = (libraryName + '/' + libraryVersion
-                            + '/' + resourceName);
-                    resourceVersion = resourceLoader
-                            .getResourceVersion(pathToResource);
-                }
-                else
-                {
-                    String pathToResource = (libraryName + '/'
-                            + resourceName);
-                    resourceVersion = resourceLoader
-                            .getResourceVersion(pathToResource);
-                }
-
-                if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
-                {               
-                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(null, libraryName,
-                            libraryVersion, resourceName, resourceVersion);
-                }
-            }
-            else
-            {
-                resourceVersion = resourceLoader
-                        .getResourceVersion(resourceName);
-                
-                if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
-                {               
-                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(null, null, null,
-                            resourceName, resourceVersion);
-                }
-            }
-
-            if (resourceId != null)
-            {
-                if (!resourceLoader.resourceExists(resourceId))
-                {
-                    resourceId = null;
-                }
-            }            
-        }
-        
-        return resourceId;
-    }
-
-    /**
-     *  Handle the resource request, writing in the output. 
-     *  
-     *  This method implements an algorithm semantically identical to 
-     *  the one described on the javadoc of ResourceHandler.handleResourceRequest 
-     */
-    @Override
-    public void handleResourceRequest(FacesContext facesContext) throws IOException
-    {
-        // Only if filter is on
-        //if (!isFilterOn())
-        //{
-        //    super.handleResourceRequest(facesContext);
-        //}
-        
-        // And this is a request handled from the filter first! 
-        //if (!facesContext.getAttributes().containsKey(ResourceHandlerFilter.RESOURCE_HANDLER_FILTER_REQUEST))
-        //{
-        //    super.handleResourceRequest(facesContext);
-        //}
-        
-        try
-        {
-            String resourceBasePath = getResourceHandlerSupport()
-                    .calculateResourceBasePath(facesContext);
-    
-            if (resourceBasePath == null)
-            {
-                // No base name could be calculated, so no further
-                //advance could be done here. HttpServletResponse.SC_NOT_FOUND
-                //cannot be returned since we cannot extract the 
-                //resource base name
-                super.handleResourceRequest(facesContext);
-                return;
-            }
-    
-            // We neet to get an instance of HttpServletResponse, but sometimes
-            // the response object is wrapped by several instances of 
-            // ServletResponseWrapper (like ResponseSwitch).
-            // Since we are handling a resource, we can expect to get an 
-            // HttpServletResponse.
-            if (!RequestType.SERVLET.equals(ExternalContextUtils.getRequestType(facesContext.getExternalContext())))
-            {
-                throw new IllegalStateException("Could not obtain an instance of HttpServletResponse.");
-            }
-            Object response = facesContext.getExternalContext().getResponse();
-            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
-            if (httpServletResponse == null)
-            {
-                throw new IllegalStateException("Could not obtain an instance of HttpServletResponse.");
-            }
-    
-            if (isResourceIdentifierExcluded(facesContext, resourceBasePath))
-            {
-                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
-                return;
-            }
-
-            String resourceName = null;
-            String libraryName = null;
-            String requestedLocalePrefix = null;
-            if (resourceBasePath.startsWith(getResourceHandlerSupport().getResourceIdentifier()))
-            {
-                //resourceName = resourceBasePath
-                //        .substring(ResourceHandler.RESOURCE_IDENTIFIER.length() + 1);
-                resourceName = resourceBasePath
-                        .substring(getResourceHandlerSupport().getResourceIdentifier().length());
-                
-                if (resourceName.startsWith("/$"))
-                {
-                    //Extract locale prefix, libraryName and resourceName
-                    int from = 3;
-                    int to = resourceName.indexOf('/',3);
-                    requestedLocalePrefix = resourceName.substring(from,to);
-                    from = to+1;
-                    to = resourceName.indexOf('/', from);
-                    libraryName = resourceName.substring(from, to);
-                    resourceName = resourceName.substring(to+1);
-                }
-                else
-                {
-                    //No special identifier used, delegate to default algorithm
-                    resourceName = null;
-                    //Try to get the library name using the standard form
-                    //libraryName = facesContext.getExternalContext()
-                    //    .getRequestParameterMap().get("ln");
-                }
-            }
-            else
-            {
-                //Does not have the conditions for be a resource call, let the base one
-                //return not found
-                super.handleResourceRequest(facesContext);
-                return;
-            }
-            
-            //Only resources with resourceName and advanced libraryName are handled by this handler
-            if (resourceName == null)
-            {
-                super.handleResourceRequest(facesContext);
-                return;
-            }
-            else if (libraryName == null)
-            {
-                super.handleResourceRequest(facesContext);
-                return;
-            }
-            else if (libraryName != null && getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) == null)
-            {
-                super.handleResourceRequest(facesContext);
-                return;
-            }
-    
-            if (requestedLocalePrefix != null)
-            {
-                facesContext.getAttributes().put(RESOURCE_LOCALE, requestedLocalePrefix);
-            }
-            
-            Resource resource = null;
-            //if (libraryName != null)
-            //{
-                //log.info("libraryName=" + libraryName);
-                resource = facesContext.getApplication().getResourceHandler().createResource(resourceName, libraryName);
-            //}
-            //else
-            //{
-            //    resource = facesContext.getApplication().getResourceHandler().createResource(resourceName);
-            //}
-    
-            if (resource == null)
-            {
-                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
-                return;
-            }
-    
-            if (!resource.userAgentNeedsUpdate(facesContext))
-            {
-                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
-                return;
-            }
-    
-            httpServletResponse.setContentType(_getContentType(resource, facesContext.getExternalContext()));
-    
-            Map<String, String> headers = resource.getResponseHeaders();
-    
-            for (Map.Entry<String, String> entry : headers.entrySet())
-            {
-                httpServletResponse.setHeader(entry.getKey(), entry.getValue());
-            }
-            
-            //serve up the bytes (taken from trinidad ResourceServlet)
-            try
-            {
-                // we should serve a compressed version of the resource, if
-                //   - ProjectStage != Development
-                //   - a compressed version is available (created in constructor)
-                //   - the user agent supports compresssion
-                // and if there is no caching on disk, do compression here!
-                if (!facesContext.isProjectStage(ProjectStage.Development) &&
-                    getResourceHandlerSupport().isGzipResourcesEnabled() && 
-                    !getResourceHandlerSupport().isCacheDiskGzipResources() && 
-                    getResourceHandlerSupport().userAgentSupportsCompression(facesContext) && 
-                    getResourceHandlerSupport().isCompressable(resource))
-                {
-                    InputStream in = resource.getInputStream();
-                    OutputStream out = new GZIPOutputStream(httpServletResponse.getOutputStream(), _BUFFER_SIZE);
-                    byte[] buffer = new byte[_BUFFER_SIZE];
-        
-                    try
-                    {
-                        int count = pipeBytes(in, out, buffer);
-                        //set the content lenght
-                        httpServletResponse.setContentLength(count);
-                    }
-                    finally
-                    {
-                        try
-                        {
-                            in.close();
-                        }
-                        finally
-                        {
-                            out.close();
-                        }
-                    }
-                }
-                else
-                {
-                    InputStream in = resource.getInputStream();
-                    OutputStream out = httpServletResponse.getOutputStream();
-                    byte[] buffer = new byte[_BUFFER_SIZE];
-        
-                    try
-                    {
-                        int count = pipeBytes(in, out, buffer);
-                        //set the content lenght
-                        httpServletResponse.setContentLength(count);
-                    }
-                    finally
-                    {
-                        try
-                        {
-                            in.close();
-                        }
-                        finally
-                        {
-                            out.close();
-                        }
-                    }
-                }
-            }
-            catch (IOException e)
-            {
-                //TODO: Log using a localized message (which one?)
-                if (log.isLoggable(Level.SEVERE))
-                    log.severe("Error trying to load resource " + resourceName
-                            + " with library " + libraryName + " :"
-                            + e.getMessage());
-                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
-            }
-        }
-        catch (Throwable ex)
-        {
-            // handle the Throwable accordingly. Maybe generate an error page.
-            // FIXME we are creating a html error page for a non html request here
-            // shouln't we do something better? -=Jakob Korherr=-
-            throw new FacesException(ex);
-            //ErrorPageWriter.handleThrowable(facesContext, ex);
-        }
-    }
-
-    /**
-     * Reads the specified input stream into the provided byte array storage and
-     * writes it to the output stream.
-     */
-    private static int pipeBytes(InputStream in, OutputStream out, byte[] buffer)
-            throws IOException
-    {
-        int count = 0;
-        int length;
-
-        while ((length = (in.read(buffer))) >= 0)
-        {
-            out.write(buffer, 0, length);
-            count += length;
-        }
-        return count;
-    }
-
-    @Override
-    public boolean isResourceRequest(FacesContext facesContext)
-    {
-        // Since this method could be called many times we save it
-        //on request map so the first time is calculated it remains
-        //alive until the end of the request
-        Boolean value = (Boolean) facesContext.getAttributes().get(IS_RESOURCE_REQUEST);
-
-        if (value != null && value)
-        {
-            //return the saved value
-            return value;
-        }
-        else
-        {
-            String resourceBasePath = getResourceHandlerSupport()
-                    .calculateResourceBasePath(facesContext);
-
-            if (resourceBasePath != null
-                    && resourceBasePath.startsWith(getResourceHandlerSupport().getResourceIdentifier()))
-            {
-                facesContext.getAttributes().put(IS_RESOURCE_REQUEST, Boolean.TRUE);
-                return true;
-            }
-            else
-            {
-                value = super.isResourceRequest(facesContext); 
-                facesContext.getAttributes().put(IS_RESOURCE_REQUEST, value);
-                return value;
-            }
-        }
-    }
-
-    protected String getLocalePrefixForLocateResource()
-    {
-        String localePrefix = null;
-        FacesContext context = FacesContext.getCurrentInstance();
-
-        String bundleName = context.getApplication().getMessageBundle();
-
-        if (null != bundleName)
-        {
-            Locale locale = context.getApplication().getViewHandler()
-                    .calculateLocale(context);
-
-            ResourceBundle bundle = ResourceBundle
-                    .getBundle(bundleName, locale, ClassUtils.getContextClassLoader());
-
-            if (bundle != null)
-            {
-                try
-                {
-                    localePrefix = bundle.getString(ResourceHandler.LOCALE_PREFIX);
-                }
-                catch (MissingResourceException e)
-                {
-                    // Ignore it and return null
-                }
-            }
-        }
-        return localePrefix;
-    }
-
-    protected boolean isResourceIdentifierExcluded(FacesContext context,
-            String resourceIdentifier)
-    {
-        String value = context.getExternalContext().getInitParameter(
-                RESOURCE_EXCLUDES_PARAM_NAME);
-        if (value == null)
-        {
-            value = RESOURCE_EXCLUDES_DEFAULT_VALUE;
-        }
-        //TODO: optimize this code
-        String[] extensions = StringUtils.splitShortString(value, ' ');
-        for (int i = 0; i < extensions.length; i++)
-        {
-            if (resourceIdentifier.endsWith(extensions[i]))
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Check if a library exists or not. This is done delegating
-     * to each ResourceLoader used, because each one has a different
-     * prefix and way to load resources.
-     * 
-     */
-    @Override
-    public boolean libraryExists(String libraryName)
-    {
-        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
-        {
-            String localePrefix = getLocalePrefixForLocateResource();
-    
-            String pathToLib = null;
-            
-            if (localePrefix != null)
-            {
-                //Check with locale
-                pathToLib = localePrefix + '/' + libraryName;
-                
-                for (ResourceLoader loader : getResourceHandlerSupport()
-                        .getResourceLoaders())
-                {
-                    if (loader.libraryExists(pathToLib))
-                    {
-                        return true;
-                    }
-                }            
-            }
-    
-            //Check without locale
-            for (ResourceLoader loader : getResourceHandlerSupport()
-                    .getResourceLoaders())
-            {
-                if (loader.libraryExists(libraryName))
-                {
-                    return true;
-                }
-            }
-        }
-        else
-        {
-            super.libraryExists(libraryName);
-        }
-
-        return false;
-    }
-
-    /**
-     * @param resourceHandlerSupport
-     *            the resourceHandlerSupport to set
-     */
-    public void setResourceHandlerSupport(
-            ExtendedDefaultResourceHandlerSupport resourceHandlerSupport)
-    {
-        _resourceHandlerSupport = resourceHandlerSupport;
-    }
-
-    /**
-     * @return the resourceHandlerSupport
-     */
-    protected ExtendedDefaultResourceHandlerSupport getResourceHandlerSupport()
-    {
-        return _resourceHandlerSupport;
-    }
-
-    private ResourceHandlerCache getResourceLoaderCache()
-    {
-        if (_resourceHandlerCache == null)
-            _resourceHandlerCache = new ResourceHandlerCache();
-        return _resourceHandlerCache;
-    }
-
-    private String _getContentType(Resource resource, ExternalContext externalContext)
-    {
-        String contentType = resource.getContentType();
-
-        // the resource does not provide a content-type --> determine it via mime-type
-        if (contentType == null || contentType.length() == 0)
-        {
-            String resourceName = getWrappedResourceName(resource);
-
-            if (resourceName != null)
-            {
-                contentType = externalContext.getMimeType(resourceName);
-            }
-        }
-
-        return contentType;
-    }
-
-    /**
-     * Recursively unwarp the resource until we find the real resourceName
-     * This is needed because the JSF2 specced ResourceWrapper doesn't override
-     * the getResourceName() method :(
-     * @param resource
-     * @return the first non-null resourceName or <code>null</code> if none set
-     */
-    private String getWrappedResourceName(Resource resource)
-    {
-        String resourceName = resource.getResourceName();
-        if (resourceName != null)
-        {
-            return resourceName;
-        }
-
-        if (resource instanceof ResourceWrapper)
-        {
-            return getWrappedResourceName(((ResourceWrapper) resource).getWrapped());
-        }
-
-        return null;
-    }
-
-    @Override
-    public ResourceHandler getWrapped()
-    {
-        return _delegate;
-    }
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.GZIPOutputStream;
+
+import javax.faces.FacesException;
+import javax.faces.application.ProjectStage;
+import javax.faces.application.Resource;
+import javax.faces.application.ResourceHandler;
+import javax.faces.application.ResourceHandlerWrapper;
+import javax.faces.application.ResourceWrapper;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.myfaces.commons.resourcehandler.config.element.Library;
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceHandlerCache;
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceHandlerCache.ResourceValue;
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceLoader;
+import org.apache.myfaces.commons.resourcehandler.resource.ResourceMeta;
+import org.apache.myfaces.commons.util.ClassUtils;
+import org.apache.myfaces.commons.util.ExternalContextUtils;
+import org.apache.myfaces.commons.util.RequestType;
+import org.apache.myfaces.commons.util.StringUtils;
+
+/**
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public class ExtendedResourceHandlerImpl extends ResourceHandlerWrapper
+{
+    private static final String IS_RESOURCE_REQUEST = "org.apache.myfaces.commons.IS_RESOURCE_REQUEST";
+    
+    private static final String RESOURCE_LOCALE = "org.apache.myfaces.commons.RESOURCE_LOCALE";
+
+    private ExtendedDefaultResourceHandlerSupport _resourceHandlerSupport;
+
+    private ResourceHandlerCache _resourceHandlerCache;
+
+    //private static final Log log = LogFactory.getLog(ResourceHandlerImpl.class);
+    private static final Logger log = Logger.getLogger(ExtendedResourceHandlerImpl.class.getName());
+
+    private static final int _BUFFER_SIZE = 2048;
+    
+    private ResourceHandler _delegate;
+    
+    //private volatile Boolean filterOn;
+
+    public ExtendedResourceHandlerImpl(ResourceHandler delegate)
+    {
+        this._delegate = delegate;
+        //Eager initialization
+        _resourceHandlerSupport = new ExtendedDefaultResourceHandlerSupport();
+    }
+    
+    /*
+    @Override
+    public Resource createResource(String resourceName)
+    {
+        return createResource(resourceName, null);
+    }*/
+    
+    @Override
+    public Resource createResource(String resourceName, String libraryName)
+    {
+        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
+        {
+            return createResource(resourceName, libraryName, null);
+        }
+        else
+        {
+            return super.createResource(resourceName, libraryName);
+        }
+    }
+
+    @Override
+    public Resource createResource(String resourceName, String libraryName,
+            String contentType)
+    {
+        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
+        {
+            return defaultCreateResource(resourceName, libraryName, contentType);
+        }
+        else
+        {
+            return super.createResource(resourceName, libraryName, contentType);
+        }
+    }
+    
+    private Resource defaultCreateResource(String resourceName, String expectedLibraryName,
+            String contentType)
+    {
+        Resource resource = null;
+
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+
+        if (contentType == null)
+        {
+            //Resolve contentType using ExternalContext.getMimeType
+            contentType = facesContext.getExternalContext().getMimeType(resourceName);
+        }
+        
+        String localePrefix = (String) facesContext.getAttributes().get(RESOURCE_LOCALE);
+        
+        if (localePrefix == null)
+        {
+            localePrefix = getLocalePrefixForLocateResource();
+        }
+        
+        //Calculate the real libraryName
+        String redirectedLibraryName = resolveLibraryName(expectedLibraryName);
+
+        // check cache
+        if(getResourceLoaderCache().containsResource(resourceName, redirectedLibraryName, contentType, localePrefix))
+        {
+            ResourceValue resourceValue = getResourceLoaderCache().getResource(
+                    resourceName, redirectedLibraryName, contentType, localePrefix);
+            
+            //resource = new ResourceImpl(resourceValue.getResourceMeta(), resourceValue.getResourceLoader(),
+            //        getResourceHandlerSupport(), contentType);
+            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, redirectedLibraryName, localePrefix);
+    
+                if (resourceMeta != null)
+                {
+                    //resource = new ResourceImpl(resourceMeta, loader, getResourceHandlerSupport(), contentType);
+                    resource = new ExtendedResourceImpl((ExtendedResourceMeta) resourceMeta, loader, getResourceHandlerSupport(), contentType, localePrefix,
+                            redirectedLibraryName.equals(expectedLibraryName) ? null : expectedLibraryName);
+
+                    // cache it
+                    getResourceLoaderCache().putResource(resourceName, redirectedLibraryName, contentType,
+                            localePrefix, resourceMeta, loader);
+                    break;
+                }
+            }
+        }
+        
+        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 ExtendedResourceMeta deriveResourceMeta(ResourceLoader resourceLoader,
+            String resourceName, String libraryName, String localePrefix)
+    {
+        String resourceVersion = null;
+        String libraryVersion = null;
+        ExtendedResourceMeta resourceId = null;
+        
+        //1. Try to locate resource in a localized path
+        if (localePrefix != null)
+        {
+            if (null != libraryName)
+            {
+                String pathToLib = localePrefix + '/' + libraryName;
+                libraryVersion = resourceLoader.getLibraryVersion(pathToLib);
+
+                if (null != libraryVersion)
+                {
+                    String pathToResource = localePrefix + '/'
+                            + libraryName + '/' + libraryVersion + '/'
+                            + resourceName;
+                    resourceVersion = resourceLoader
+                            .getResourceVersion(pathToResource);
+                }
+                else
+                {
+                    String pathToResource = localePrefix + '/'
+                            + libraryName + '/' + resourceName;
+                    resourceVersion = resourceLoader
+                            .getResourceVersion(pathToResource);
+                }
+
+                if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
+                {
+                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(localePrefix, libraryName,
+                            libraryVersion, resourceName, resourceVersion);
+                }
+            }
+            else
+            {
+                resourceVersion = resourceLoader
+                        .getResourceVersion(localePrefix + '/'+ resourceName);
+                if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
+                {               
+                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(localePrefix, null, null,
+                            resourceName, resourceVersion);
+                }
+            }
+
+            if (resourceId != null)
+            {
+                if (!resourceLoader.resourceExists(resourceId))
+                {
+                    resourceId = null;
+                }
+            }            
+        }
+        
+        //2. Try to localize resource in a non localized path
+        if (resourceId == null)
+        {
+            if (null != libraryName)
+            {
+                libraryVersion = resourceLoader.getLibraryVersion(libraryName);
+
+                if (null != libraryVersion)
+                {
+                    String pathToResource = (libraryName + '/' + libraryVersion
+                            + '/' + resourceName);
+                    resourceVersion = resourceLoader
+                            .getResourceVersion(pathToResource);
+                }
+                else
+                {
+                    String pathToResource = (libraryName + '/'
+                            + resourceName);
+                    resourceVersion = resourceLoader
+                            .getResourceVersion(pathToResource);
+                }
+
+                if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
+                {               
+                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(null, libraryName,
+                            libraryVersion, resourceName, resourceVersion);
+                }
+            }
+            else
+            {
+                resourceVersion = resourceLoader
+                        .getResourceVersion(resourceName);
+                
+                if (!(resourceVersion != null && ResourceLoader.VERSION_INVALID.equals(resourceVersion)))
+                {               
+                    resourceId = (ExtendedResourceMeta) resourceLoader.createResourceMeta(null, null, null,
+                            resourceName, resourceVersion);
+                }
+            }
+
+            if (resourceId != null)
+            {
+                if (!resourceLoader.resourceExists(resourceId))
+                {
+                    resourceId = null;
+                }
+            }            
+        }
+        
+        return resourceId;
+    }
+
+    /**
+     *  Handle the resource request, writing in the output. 
+     *  
+     *  This method implements an algorithm semantically identical to 
+     *  the one described on the javadoc of ResourceHandler.handleResourceRequest 
+     */
+    @Override
+    public void handleResourceRequest(FacesContext facesContext) throws IOException
+    {
+        // Only if filter is on
+        //if (!isFilterOn())
+        //{
+        //    super.handleResourceRequest(facesContext);
+        //}
+        
+        // And this is a request handled from the filter first! 
+        //if (!facesContext.getAttributes().containsKey(ResourceHandlerFilter.RESOURCE_HANDLER_FILTER_REQUEST))
+        //{
+        //    super.handleResourceRequest(facesContext);
+        //}
+        
+        try
+        {
+            String resourceBasePath = getResourceHandlerSupport()
+                    .calculateResourceBasePath(facesContext);
+    
+            if (resourceBasePath == null)
+            {
+                // No base name could be calculated, so no further
+                //advance could be done here. HttpServletResponse.SC_NOT_FOUND
+                //cannot be returned since we cannot extract the 
+                //resource base name
+                super.handleResourceRequest(facesContext);
+                return;
+            }
+    
+            // We neet to get an instance of HttpServletResponse, but sometimes
+            // the response object is wrapped by several instances of 
+            // ServletResponseWrapper (like ResponseSwitch).
+            // Since we are handling a resource, we can expect to get an 
+            // HttpServletResponse.
+            if (!RequestType.SERVLET.equals(ExternalContextUtils.getRequestType(facesContext.getExternalContext())))
+            {
+                throw new IllegalStateException("Could not obtain an instance of HttpServletResponse.");
+            }
+            Object response = facesContext.getExternalContext().getResponse();
+            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+            if (httpServletResponse == null)
+            {
+                throw new IllegalStateException("Could not obtain an instance of HttpServletResponse.");
+            }
+    
+            if (isResourceIdentifierExcluded(facesContext, resourceBasePath))
+            {
+                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
+                return;
+            }
+
+            String resourceName = null;
+            String libraryName = null;
+            String requestedLocalePrefix = null;
+            if (resourceBasePath.startsWith(getResourceHandlerSupport().getResourceIdentifier()))
+            {
+                //resourceName = resourceBasePath
+                //        .substring(ResourceHandler.RESOURCE_IDENTIFIER.length() + 1);
+                resourceName = resourceBasePath
+                        .substring(getResourceHandlerSupport().getResourceIdentifier().length());
+                
+                if (resourceName.startsWith("/$"))
+                {
+                    //Extract locale prefix, libraryName and resourceName
+                    int from = 3;
+                    int to = resourceName.indexOf('/',3);
+                    requestedLocalePrefix = resourceName.substring(from,to);
+                    from = to+1;
+                    to = resourceName.indexOf('/', from);
+                    libraryName = resourceName.substring(from, to);
+                    resourceName = resourceName.substring(to+1);
+                }
+                else
+                {
+                    //No special identifier used, delegate to default algorithm
+                    resourceName = null;
+                    //Try to get the library name using the standard form
+                    //libraryName = facesContext.getExternalContext()
+                    //    .getRequestParameterMap().get("ln");
+                }
+            }
+            else
+            {
+                //Does not have the conditions for be a resource call, let the base one
+                //return not found
+                super.handleResourceRequest(facesContext);
+                return;
+            }
+            
+            //Only resources with resourceName and advanced libraryName are handled by this handler
+            if (resourceName == null)
+            {
+                super.handleResourceRequest(facesContext);
+                return;
+            }
+            else if (libraryName == null)
+            {
+                super.handleResourceRequest(facesContext);
+                return;
+            }
+            else if (libraryName != null && getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) == null)
+            {
+                super.handleResourceRequest(facesContext);
+                return;
+            }
+    
+            if (requestedLocalePrefix != null)
+            {
+                facesContext.getAttributes().put(RESOURCE_LOCALE, requestedLocalePrefix);
+            }
+            
+            Resource resource = null;
+            //if (libraryName != null)
+            //{
+                //log.info("libraryName=" + libraryName);
+                resource = facesContext.getApplication().getResourceHandler().createResource(resourceName, libraryName);
+            //}
+            //else
+            //{
+            //    resource = facesContext.getApplication().getResourceHandler().createResource(resourceName);
+            //}
+    
+            if (resource == null)
+            {
+                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
+                return;
+            }
+    
+            if (!resource.userAgentNeedsUpdate(facesContext))
+            {
+                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+                return;
+            }
+    
+            httpServletResponse.setContentType(_getContentType(resource, facesContext.getExternalContext()));
+    
+            Map<String, String> headers = resource.getResponseHeaders();
+    
+            for (Map.Entry<String, String> entry : headers.entrySet())
+            {
+                httpServletResponse.setHeader(entry.getKey(), entry.getValue());
+            }
+            
+            //serve up the bytes (taken from trinidad ResourceServlet)
+            try
+            {
+                // we should serve a compressed version of the resource, if
+                //   - ProjectStage != Development
+                //   - a compressed version is available (created in constructor)
+                //   - the user agent supports compresssion
+                // and if there is no caching on disk, do compression here!
+                if (!facesContext.isProjectStage(ProjectStage.Development) &&
+                    getResourceHandlerSupport().isGzipResourcesEnabled() && 
+                    !getResourceHandlerSupport().isCacheDiskGzipResources() && 
+                    getResourceHandlerSupport().userAgentSupportsCompression(facesContext) && 
+                    getResourceHandlerSupport().isCompressable(resource))
+                {
+                    InputStream in = resource.getInputStream();
+                    OutputStream out = new GZIPOutputStream(httpServletResponse.getOutputStream(), _BUFFER_SIZE);
+                    byte[] buffer = new byte[_BUFFER_SIZE];
+        
+                    try
+                    {
+                        int count = pipeBytes(in, out, buffer);
+                        //set the content lenght
+                        httpServletResponse.setContentLength(count);
+                    }
+                    finally
+                    {
+                        try
+                        {
+                            in.close();
+                        }
+                        finally
+                        {
+                            out.close();
+                        }
+                    }
+                }
+                else
+                {
+                    InputStream in = resource.getInputStream();
+                    OutputStream out = httpServletResponse.getOutputStream();
+                    byte[] buffer = new byte[_BUFFER_SIZE];
+        
+                    try
+                    {
+                        int count = pipeBytes(in, out, buffer);
+                        //set the content lenght
+                        httpServletResponse.setContentLength(count);
+                    }
+                    finally
+                    {
+                        try
+                        {
+                            in.close();
+                        }
+                        finally
+                        {
+                            out.close();
+                        }
+                    }
+                }
+            }
+            catch (IOException e)
+            {
+                //TODO: Log using a localized message (which one?)
+                if (log.isLoggable(Level.SEVERE))
+                    log.severe("Error trying to load resource " + resourceName
+                            + " with library " + libraryName + " :"
+                            + e.getMessage());
+                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
+            }
+        }
+        catch (Throwable ex)
+        {
+            // handle the Throwable accordingly. Maybe generate an error page.
+            // FIXME we are creating a html error page for a non html request here
+            // shouln't we do something better? -=Jakob Korherr=-
+            throw new FacesException(ex);
+            //ErrorPageWriter.handleThrowable(facesContext, ex);
+        }
+    }
+
+    /**
+     * Reads the specified input stream into the provided byte array storage and
+     * writes it to the output stream.
+     */
+    private static int pipeBytes(InputStream in, OutputStream out, byte[] buffer)
+            throws IOException
+    {
+        int count = 0;
+        int length;
+
+        while ((length = (in.read(buffer))) >= 0)
+        {
+            out.write(buffer, 0, length);
+            count += length;
+        }
+        return count;
+    }
+
+    @Override
+    public boolean isResourceRequest(FacesContext facesContext)
+    {
+        // Since this method could be called many times we save it
+        //on request map so the first time is calculated it remains
+        //alive until the end of the request
+        Boolean value = (Boolean) facesContext.getAttributes().get(IS_RESOURCE_REQUEST);
+
+        if (value != null && value)
+        {
+            //return the saved value
+            return value;
+        }
+        else
+        {
+            String resourceBasePath = getResourceHandlerSupport()
+                    .calculateResourceBasePath(facesContext);
+
+            if (resourceBasePath != null
+                    && resourceBasePath.startsWith(getResourceHandlerSupport().getResourceIdentifier()))
+            {
+                facesContext.getAttributes().put(IS_RESOURCE_REQUEST, Boolean.TRUE);
+                return true;
+            }
+            else
+            {
+                value = super.isResourceRequest(facesContext); 
+                facesContext.getAttributes().put(IS_RESOURCE_REQUEST, value);
+                return value;
+            }
+        }
+    }
+
+    protected String getLocalePrefixForLocateResource()
+    {
+        String localePrefix = null;
+        FacesContext context = FacesContext.getCurrentInstance();
+
+        String bundleName = context.getApplication().getMessageBundle();
+
+        if (null != bundleName)
+        {
+            Locale locale = context.getApplication().getViewHandler()
+                    .calculateLocale(context);
+
+            ResourceBundle bundle = ResourceBundle
+                    .getBundle(bundleName, locale, ClassUtils.getContextClassLoader());
+
+            if (bundle != null)
+            {
+                try
+                {
+                    localePrefix = bundle.getString(ResourceHandler.LOCALE_PREFIX);
+                }
+                catch (MissingResourceException e)
+                {
+                    // Ignore it and return null
+                }
+            }
+        }
+        return localePrefix;
+    }
+
+    protected boolean isResourceIdentifierExcluded(FacesContext context,
+            String resourceIdentifier)
+    {
+        String value = context.getExternalContext().getInitParameter(
+                RESOURCE_EXCLUDES_PARAM_NAME);
+        if (value == null)
+        {
+            value = RESOURCE_EXCLUDES_DEFAULT_VALUE;
+        }
+        //TODO: optimize this code
+        String[] extensions = StringUtils.splitShortString(value, ' ');
+        for (int i = 0; i < extensions.length; i++)
+        {
+            if (resourceIdentifier.endsWith(extensions[i]))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check if a library exists or not. This is done delegating
+     * to each ResourceLoader used, because each one has a different
+     * prefix and way to load resources.
+     * 
+     */
+    @Override
+    public boolean libraryExists(String libraryName)
+    {
+        if (getResourceHandlerSupport().getMyFacesResourcesConfig().getLibrary(libraryName) != null)
+        {
+            String localePrefix = getLocalePrefixForLocateResource();
+    
+            String pathToLib = null;
+            
+            if (localePrefix != null)
+            {
+                //Check with locale
+                pathToLib = localePrefix + '/' + libraryName;
+                
+                for (ResourceLoader loader : getResourceHandlerSupport()
+                        .getResourceLoaders())
+                {
+                    if (loader.libraryExists(pathToLib))
+                    {
+                        return true;
+                    }
+                }            
+            }
+    
+            //Check without locale
+            for (ResourceLoader loader : getResourceHandlerSupport()
+                    .getResourceLoaders())
+            {
+                if (loader.libraryExists(libraryName))
+                {
+                    return true;
+                }
+            }
+        }
+        else
+        {
+            super.libraryExists(libraryName);
+        }
+
+        return false;
+    }
+
+    /**
+     * @param resourceHandlerSupport
+     *            the resourceHandlerSupport to set
+     */
+    public void setResourceHandlerSupport(
+            ExtendedDefaultResourceHandlerSupport resourceHandlerSupport)
+    {
+        _resourceHandlerSupport = resourceHandlerSupport;
+    }
+
+    /**
+     * @return the resourceHandlerSupport
+     */
+    protected ExtendedDefaultResourceHandlerSupport getResourceHandlerSupport()
+    {
+        return _resourceHandlerSupport;
+    }
+
+    private ResourceHandlerCache getResourceLoaderCache()
+    {
+        if (_resourceHandlerCache == null)
+            _resourceHandlerCache = new ResourceHandlerCache();
+        return _resourceHandlerCache;
+    }
+
+    private String _getContentType(Resource resource, ExternalContext externalContext)
+    {
+        String contentType = resource.getContentType();
+
+        // the resource does not provide a content-type --> determine it via mime-type
+        if (contentType == null || contentType.length() == 0)
+        {
+            String resourceName = getWrappedResourceName(resource);
+
+            if (resourceName != null)
+            {
+                contentType = externalContext.getMimeType(resourceName);
+            }
+        }
+
+        return contentType;
+    }
+
+    /**
+     * Recursively unwarp the resource until we find the real resourceName
+     * This is needed because the JSF2 specced ResourceWrapper doesn't override
+     * the getResourceName() method :(
+     * @param resource
+     * @return the first non-null resourceName or <code>null</code> if none set
+     */
+    private String getWrappedResourceName(Resource resource)
+    {
+        String resourceName = resource.getResourceName();
+        if (resourceName != null)
+        {
+            return resourceName;
+        }
+
+        if (resource instanceof ResourceWrapper)
+        {
+            return getWrappedResourceName(((ResourceWrapper) resource).getWrapped());
+        }
+
+        return null;
+    }
+
+    @Override
+    public ResourceHandler getWrapped()
+    {
+        return _delegate;
+    }
 }
\ No newline at end of file

Propchange: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceHandlerImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=1186730&r1=1186729&r2=1186730&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 Oct 20 10:49:18 2011
@@ -1,323 +1,323 @@
-/*
- * 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 java.io.IOException;
-import java.io.InputStream;
-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.ValueExpressionFilterInputStream;
-
-/**
- * 
- * @author Leonardo Uribe
- *
- */
-public class ExtendedResourceImpl extends ResourceImpl
-{
-    private String _expectedLocalePrefix;
-    
-    private ExtendedResourceMeta _extendedResourceMeta;
-    
-    private ExtendedDefaultResourceHandlerSupport _extendedDefaultResourceHandlerSupport;
-    
-    public ExtendedResourceImpl(ExtendedResourceMeta resourceMeta,
-            ResourceLoader resourceLoader, ExtendedDefaultResourceHandlerSupport support,
-            String contentType, String expectedLocalePrefix, String expectedLibraryName)
-    {
-        super(resourceMeta, resourceLoader, support, contentType);
-        _extendedResourceMeta = resourceMeta;
-        _expectedLocalePrefix = expectedLocalePrefix;
-        _extendedDefaultResourceHandlerSupport = support;
-        if (expectedLibraryName != null)
-        {
-            setLibraryName(expectedLibraryName);
-        }
-    }
-    
-    @Override
-    public InputStream getInputStream() throws IOException
-    {
-        if ( getExtendedDefaultResourceHandlerSupport().isGzipResourcesEnabled() &&
-             getExtendedDefaultResourceHandlerSupport().isCacheDiskGzipResources() &&
-             getExtendedDefaultResourceHandlerSupport().isCompressable(this) &&
-             getExtendedDefaultResourceHandlerSupport().userAgentSupportsCompression(FacesContext.getCurrentInstance()))
-        {
-            //GZIPResourceLoader will take care of resources containing ValueExpressions 
-            return getResourceLoader().getResourceInputStream(getResourceMeta());
-        }
-        else
-        {
-            return super.getInputStream();
-        }
-    }
-
-    @Override
-    public String getRequestPath()
-    {
-        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 + getResourceHandlerSupport().getResourceIdentifier() + "/$/" + 
-                                localePrefix + '/' + 
-                                getLibraryName() + '/' + 
-                                getResourceName();
-            }
-            else
-            {
-                path = getResourceHandlerSupport().getResourceIdentifier() + "/$/" + 
-                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)
-        {
-            // calculate current localePrefix (could be different from the one requested, e.g. on locale change)
-            localePrefix = getRequestLocalePrefix();
-        }
-        return localePrefix;
-    }
-    
-    private String calculateRequestPath(FacesContext context, String expression)
-    {
-        ValueExpression requestPath = getExtendedResourceMeta().getRequestPathExpression(); 
-        if (requestPath == null)
-        {
-            ELContext elContext = new ELContextWrapper(context.getELContext(), context, this);
-            requestPath = context.getApplication().getExpressionFactory().createValueExpression(
-                    elContext, expression, String.class);
-            getExtendedResourceMeta().setRequestPathExpression(requestPath);
-        }
-        return (String) requestPath.getValue(context.getELContext());
-    }
-    
-    protected ExtendedResourceMeta getExtendedResourceMeta()
-    {
-        return _extendedResourceMeta;
-    }
-    
-    protected ExtendedDefaultResourceHandlerSupport getExtendedDefaultResourceHandlerSupport()
-    {
-        return _extendedDefaultResourceHandlerSupport;
-    }
-    
-    @Override
-    public Map<String, String> getResponseHeaders()
-    {
-        FacesContext facesContext = FacesContext.getCurrentInstance();
-        
-        if (facesContext.getApplication().getResourceHandler().isResourceRequest(facesContext))
-        {
-            Map<String, String> headers = super.getResponseHeaders();
-            
-            if (getExtendedDefaultResourceHandlerSupport().isGzipResourcesEnabled() && 
-                getExtendedDefaultResourceHandlerSupport().userAgentSupportsCompression(facesContext) && 
-                getExtendedDefaultResourceHandlerSupport().isCompressable(this))
-                {
-                    headers.put("Content-Encoding", "gzip");
-                }
-            
-            return headers; 
-        }
-        else
-        {
-            //No need to return headers 
-            return Collections.emptyMap();
-        }
-    }
-    
-    /**
-     * Returns the String representation of the current locale for the use in the request path.
-     *
-     * @return
-     */
-    private static String getRequestLocalePrefix()
-    {
-        FacesContext facesContext = FacesContext.getCurrentInstance();
-        Locale locale = facesContext.getViewRoot().getLocale();
-        if (locale == null)
-        {
-            // fallback to default locale
-            locale = Locale.getDefault();
-        }
-        
-        String language = locale.getLanguage();
-        String country = locale.getCountry();
-        
-        if (country != null)
-        {
-            // de_AT
-            return language + "_" + country;
-        }
-        else
-        {
-            // 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;
-        }
-    }
-}
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+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.ValueExpressionFilterInputStream;
+
+/**
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public class ExtendedResourceImpl extends ResourceImpl
+{
+    private String _expectedLocalePrefix;
+    
+    private ExtendedResourceMeta _extendedResourceMeta;
+    
+    private ExtendedDefaultResourceHandlerSupport _extendedDefaultResourceHandlerSupport;
+    
+    public ExtendedResourceImpl(ExtendedResourceMeta resourceMeta,
+            ResourceLoader resourceLoader, ExtendedDefaultResourceHandlerSupport support,
+            String contentType, String expectedLocalePrefix, String expectedLibraryName)
+    {
+        super(resourceMeta, resourceLoader, support, contentType);
+        _extendedResourceMeta = resourceMeta;
+        _expectedLocalePrefix = expectedLocalePrefix;
+        _extendedDefaultResourceHandlerSupport = support;
+        if (expectedLibraryName != null)
+        {
+            setLibraryName(expectedLibraryName);
+        }
+    }
+    
+    @Override
+    public InputStream getInputStream() throws IOException
+    {
+        if ( getExtendedDefaultResourceHandlerSupport().isGzipResourcesEnabled() &&
+             getExtendedDefaultResourceHandlerSupport().isCacheDiskGzipResources() &&
+             getExtendedDefaultResourceHandlerSupport().isCompressable(this) &&
+             getExtendedDefaultResourceHandlerSupport().userAgentSupportsCompression(FacesContext.getCurrentInstance()))
+        {
+            //GZIPResourceLoader will take care of resources containing ValueExpressions 
+            return getResourceLoader().getResourceInputStream(getResourceMeta());
+        }
+        else
+        {
+            return super.getInputStream();
+        }
+    }
+
+    @Override
+    public String getRequestPath()
+    {
+        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 + getResourceHandlerSupport().getResourceIdentifier() + "/$/" + 
+                                localePrefix + '/' + 
+                                getLibraryName() + '/' + 
+                                getResourceName();
+            }
+            else
+            {
+                path = getResourceHandlerSupport().getResourceIdentifier() + "/$/" + 
+                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)
+        {
+            // calculate current localePrefix (could be different from the one requested, e.g. on locale change)
+            localePrefix = getRequestLocalePrefix();
+        }
+        return localePrefix;
+    }
+    
+    private String calculateRequestPath(FacesContext context, String expression)
+    {
+        ValueExpression requestPath = getExtendedResourceMeta().getRequestPathExpression(); 
+        if (requestPath == null)
+        {
+            ELContext elContext = new ELContextWrapper(context.getELContext(), context, this);
+            requestPath = context.getApplication().getExpressionFactory().createValueExpression(
+                    elContext, expression, String.class);
+            getExtendedResourceMeta().setRequestPathExpression(requestPath);
+        }
+        return (String) requestPath.getValue(context.getELContext());
+    }
+    
+    protected ExtendedResourceMeta getExtendedResourceMeta()
+    {
+        return _extendedResourceMeta;
+    }
+    
+    protected ExtendedDefaultResourceHandlerSupport getExtendedDefaultResourceHandlerSupport()
+    {
+        return _extendedDefaultResourceHandlerSupport;
+    }
+    
+    @Override
+    public Map<String, String> getResponseHeaders()
+    {
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        
+        if (facesContext.getApplication().getResourceHandler().isResourceRequest(facesContext))
+        {
+            Map<String, String> headers = super.getResponseHeaders();
+            
+            if (getExtendedDefaultResourceHandlerSupport().isGzipResourcesEnabled() && 
+                getExtendedDefaultResourceHandlerSupport().userAgentSupportsCompression(facesContext) && 
+                getExtendedDefaultResourceHandlerSupport().isCompressable(this))
+                {
+                    headers.put("Content-Encoding", "gzip");
+                }
+            
+            return headers; 
+        }
+        else
+        {
+            //No need to return headers 
+            return Collections.emptyMap();
+        }
+    }
+    
+    /**
+     * Returns the String representation of the current locale for the use in the request path.
+     *
+     * @return
+     */
+    private static String getRequestLocalePrefix()
+    {
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        Locale locale = facesContext.getViewRoot().getLocale();
+        if (locale == null)
+        {
+            // fallback to default locale
+            locale = Locale.getDefault();
+        }
+        
+        String language = locale.getLanguage();
+        String country = locale.getCountry();
+        
+        if (country != null)
+        {
+            // de_AT
+            return language + "_" + country;
+        }
+        else
+        {
+            // 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;
+        }
+    }
+}

Propchange: myfaces/commons/branches/jsf_20/myfaces-commons-resourcehandler/src/main/java/org/apache/myfaces/commons/resourcehandler/ExtendedResourceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native