Package org.apache.myfaces.commons.resourcehandler

Source Code of org.apache.myfaces.commons.resourcehandler.ExtendedDefaultResourceHandlerSupport

/*
* 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.util.Map;

import javax.faces.application.ProjectStage;
import javax.faces.application.Resource;
import javax.faces.application.ResourceHandler;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.webapp.FacesServlet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.resource.BaseResourceHandlerSupport;
import org.apache.myfaces.commons.resourcehandler.resource.ClassLoaderResourceLoader;
import org.apache.myfaces.commons.resourcehandler.resource.ExternalContextResourceLoader;
import org.apache.myfaces.commons.resourcehandler.resource.ResourceLoader;
import org.apache.myfaces.commons.resourcehandler.resource.ResourceMeta;
import org.apache.myfaces.commons.resourcehandler.webapp.config.WebConfigProvider;
import org.apache.myfaces.commons.resourcehandler.webapp.config.WebConfigProviderFactory;
import org.apache.myfaces.commons.resourcehandler.webapp.config.WebRegistration;
import org.apache.myfaces.commons.resourcehandler.webapp.config.element.ServletRegistration;
import org.apache.myfaces.commons.util.ClassUtils;
import org.apache.myfaces.commons.util.StringUtils;
import org.apache.myfaces.commons.util.WebConfigParamUtils;

public class ExtendedDefaultResourceHandlerSupport extends BaseResourceHandlerSupport
{
    protected static final String CACHED_SERVLET_MAPPING =
        ExtendedDefaultResourceHandlerSupport.class.getName() + ".CACHED_SERVLET_MAPPING";
   
    /**
     * Enable or disable gzip compressions for resources served by this extended resource handler. By default is disabled (false).
     */
    @JSFWebConfigParam(defaultValue="false")
    public static final String INIT_PARAM_GZIP_RESOURCES_ENABLED = "org.apache.myfaces.commons.GZIP_RESOURCES_ENABLED";
   
    /**
     * Indicate the suffix used to recognize resources that should be compressed. By default is ".css .js".
     */
    @JSFWebConfigParam(defaultValue=".css, .js")
    public static final String INIT_PARAM_GZIP_RESOURCES_SUFFIX = "org.apache.myfaces.commons.GZIP_RESOURCES_SUFFIX";
    public static final String INIT_PARAM_GZIP_RESOURCES_EXTENSIONS_DEFAULT = ".css .js";
   
    /**
     * Indicate if gzipped files are stored on a temporal directory to serve them later. By default is true. If this is
     * disable, the files are compressed when they are served.
     */
    @JSFWebConfigParam(defaultValue="true")
    public static final String INIT_PARAM_CACHE_DISK_GZIP_RESOURCES = "org.apache.myfaces.commons.CACHE_DISK_GZIP_RESOURCES";
   
    /**
     * Indicate the prefix that is added to each resource path that is used later to check if the request is a resource request.
     *
     * By default is /javax.faces.resource
     */
    @JSFWebConfigParam(defaultValue="/javax.faces.resource")
    public static final String INIT_PARAM_EXTENDED_RESOURCE_IDENTIFIER = "org.apache.myfaces.commons.EXTENDED_RESOURCE_IDENTIFIER";
   
    private static final String INIT_PARAM_DELEGATE_FACES_SERVLET = "org.apache.myfaces.DELEGATE_FACES_SERVLET";
   
    private static Class DELEGATE_FACES_SERVLET_INTERFACE_CLASS = null;
   
    static
    {
        try
        {
            DELEGATE_FACES_SERVLET_INTERFACE_CLASS = ClassUtils.classForName("org.apache.myfaces.shared_impl.webapp.webxml.DelegatedFacesServlet");
        }
        catch (ClassNotFoundException e)
        {
        }
    }
   
    /**
     * Accept-Encoding HTTP header field.
     */
    private static final String ACCEPT_ENCODING_HEADER = "Accept-Encoding";
   
    private ResourceLoader[] _resourceLoaders;
   
    private final boolean _gzipResourcesEnabled;
   
    private final String[] _gzipResourcesSuffix;
   
    private final boolean _cacheDiskGzipResources;
   
    private final boolean _developmentStage;
   
    private MyFacesResourcesConfig _config;
   
    private WebConfigProvider _webConfigProvider;
   
    private String _resourceIdentifier;
   
    public ExtendedDefaultResourceHandlerSupport()
    {
        super();
        FacesContext context = FacesContext.getCurrentInstance();
       
        _gzipResourcesEnabled = WebConfigParamUtils.getBooleanInitParameter(context.getExternalContext(),
                INIT_PARAM_GZIP_RESOURCES_ENABLED, false);
        _gzipResourcesSuffix = StringUtils.splitShortString(
                WebConfigParamUtils.getStringInitParameter(context.getExternalContext(),
                        INIT_PARAM_GZIP_RESOURCES_SUFFIX, INIT_PARAM_GZIP_RESOURCES_EXTENSIONS_DEFAULT), ' ');
        _cacheDiskGzipResources = WebConfigParamUtils.getBooleanInitParameter(context.getExternalContext(),
                INIT_PARAM_CACHE_DISK_GZIP_RESOURCES, true);
        _developmentStage = context.isProjectStage(ProjectStage.Development);
       
        _resourceIdentifier = WebConfigParamUtils.getStringInitParameter(context.getExternalContext(),
                INIT_PARAM_EXTENDED_RESOURCE_IDENTIFIER, ResourceHandler.RESOURCE_IDENTIFIER);
       
        // parse the config
        MyFacesResourceHandlerConfigParser configParser = new MyFacesResourceHandlerConfigParser();
        _config = configParser.parse(FacesContext.getCurrentInstance());

        _webConfigProvider = WebConfigProviderFactory.getFacesConfigResourceProviderFactory(context).
            createWebConfigProvider(context);
       
        _webConfigProvider.init(context);
       
        // GZIPResourceLoader does some file operations to clear the cache, so this call must be done
        // to ensure only one thread is cleaning it up (at setup time)
        getResourceLoaders();
    }
   
    public MyFacesResourcesConfig getMyFacesResourcesConfig()
    {
        return _config;
    }
   
    public String[] getGzipResourcesSuffixes()
    {
        return _gzipResourcesSuffix;
    }
   
    public boolean isGzipResourcesEnabled()
    {
        return _gzipResourcesEnabled;
    }
   
    public boolean isCacheDiskGzipResources()
    {
        return _cacheDiskGzipResources;
    }
   
    public boolean isCompressable(ResourceMeta resourceMeta)
    {
        if (getGzipResourcesSuffixes() != null)
        {
            boolean compressable = false;           
            for (int i = 0; i < getGzipResourcesSuffixes().length; i++)
            {
                if (getGzipResourcesSuffixes()[i] != null &&
                    getGzipResourcesSuffixes()[i].length() > 0 &&
                    resourceMeta.getResourceName().endsWith(getGzipResourcesSuffixes()[i]))
                {
                    compressable = true;
                    break;
                }
            }
            return compressable;
        }
        else
        {
            return true;
        }
    }
   
    public boolean isCompressable(Resource resource)
    {
        if (getGzipResourcesSuffixes() != null)
        {
            boolean compressable = false;           
            for (int i = 0; i < getGzipResourcesSuffixes().length; i++)
            {
                if (getGzipResourcesSuffixes()[i] != null &&
                    getGzipResourcesSuffixes()[i].length() > 0 &&
                    resource.getResourceName().endsWith(getGzipResourcesSuffixes()[i]))
                {
                    compressable = true;
                    break;
                }
            }
            return compressable;
        }
        else
        {
            return true;
        }
    }

    public boolean userAgentSupportsCompression(FacesContext facesContext)
    {
        String acceptEncodingHeader = facesContext.getExternalContext()
                .getRequestHeaderMap().get(ACCEPT_ENCODING_HEADER);

        return ResourceUtils.isGZIPEncodingAccepted(acceptEncodingHeader);
    }

    public String calculateResourceBasePath(FacesContext facesContext)
    {       
        ExternalContext externalContext = facesContext.getExternalContext();     
        String resourceBasePath = null;
       
        //Calculate the mapping from the current request information
        FacesServletMapping mapping = calculateFacesServletMapping(
                externalContext.getRequestServletPath(),
                externalContext.getRequestPathInfo());
        //FacesServletMapping mapping = getFacesServletMapping(facesContext);
       
        if (mapping != null)
        {
            if (mapping.isExtensionMapping())
            {
                // Mapping using a suffix. In this case we have to strip
                // the suffix. If we have a url like:
                // http://localhost:8080/testjsf20/javax.faces.resource/imagen.jpg.jsf?ln=dojo
                //
                // The servlet path is /javax.faces.resource/imagen.jpg.jsf
                //
                // For obtain the resource name we have to remove the .jsf suffix and
                // the prefix ResourceHandler.RESOURCE_IDENTIFIER
                resourceBasePath = externalContext.getRequestServletPath();
                int stripPoint = resourceBasePath.lastIndexOf('.');
                if (stripPoint > 0)
                {
                    resourceBasePath = resourceBasePath.substring(0, stripPoint);
                }
            }
            else
            {
                // Mapping using prefix. In this case we have to strip
                // the prefix used for mapping. If we have a url like:
                // http://localhost:8080/testjsf20/faces/javax.faces.resource/imagen.jpg?ln=dojo
                //
                // The servlet path is /faces
                // and the path info is /javax.faces.resource/imagen.jpg
                //
                // For obtain the resource name we have to remove the /faces prefix and
                // then the prefix ResourceHandler.RESOURCE_IDENTIFIER
                resourceBasePath = externalContext.getRequestPathInfo();
            }
            return resourceBasePath;
        }
        else
        {
            //If no mapping is detected, just return the
            //information follows the servlet path but before
            //the query string
            return externalContext.getRequestPathInfo();
        }
    }
   
    protected FacesServletMapping getFacesServletMapping(FacesContext context)
    {
        Map<Object, Object> attributes = context.getAttributes();

        // Has the mapping already been determined during this request?
        FacesServletMapping mapping = (FacesServletMapping) attributes.get(CACHED_SERVLET_MAPPING);
        if (mapping == null)
        {
            ExternalContext externalContext = context.getExternalContext();
           
            FacesServletMapping calculatedMapping = calculateFacesServletMapping(
                    externalContext.getRequestServletPath(),
                    externalContext.getRequestPathInfo());
           
            if (!calculatedMapping.isPrefixMapping())
            {
                // Scan the current configuration if there is a FacesServlet and if that so,
                // retrieve the first prefix mapping and use it.
                getWebConfigProvider().update(context);
               
                WebRegistration webRegistration = getWebConfigProvider().getWebRegistration(context);
               
                String prefix = getFacesServletPrefixMapping(context, webRegistration);
               
                if (prefix != null)
                {
                    mapping = FacesServletMapping.createPrefixMapping(prefix);
                }
                else
                {
                    mapping = calculatedMapping;
                }
            }
            else
            {
                mapping = calculatedMapping;
            }

            attributes.put(CACHED_SERVLET_MAPPING, mapping);
        }
        return mapping;
    }
   
    private String getFacesServletPrefixMapping(FacesContext context, WebRegistration webRegistration)
    {
        String prefix = null;
       
        String delegateFacesServlet = WebConfigParamUtils.getStringInitParameter(context.getExternalContext(),
                INIT_PARAM_DELEGATE_FACES_SERVLET);
       
        for (Map.Entry<String, ? extends ServletRegistration> entry : webRegistration.getServletRegistrations().entrySet())
        {
            ServletRegistration registration = entry.getValue();
            boolean facesServlet = false;
            if (FacesServlet.class.getName().equals(registration.getClassName()))
            {
                facesServlet = true;
            }
            else if (delegateFacesServlet != null && delegateFacesServlet.equals(registration.getClassName()))
            {
                facesServlet = true;
            }
            else
            {
                if (DELEGATE_FACES_SERVLET_INTERFACE_CLASS != null)
                {
                    try
                    {
                        Class servletClass = ClassUtils.classForName(registration.getClassName());
                        if (DELEGATE_FACES_SERVLET_INTERFACE_CLASS.isAssignableFrom(servletClass));
                        {
                            facesServlet = true;
                        }
                    }
                    catch (ClassNotFoundException e)
                    {
                        Log log = LogFactory.getLog(ExtendedDefaultResourceHandlerSupport.class);
                        if (log.isTraceEnabled())
                        {
                            log.trace("cannot load servlet class to detect if is a FacesServlet or DelegateFacesServlet", e);
                        }
                    }
                }
            }
            if (facesServlet)
            {
                for (String urlPattern : registration.getMappings())
                {
                    String extension = urlPattern != null && urlPattern.startsWith("*.") ? urlPattern.substring(urlPattern
                            .indexOf('.')) : null;
                    if (extension == null)
                    {
                        int index = urlPattern.indexOf("/*");
                        if (index != -1)
                        {
                            prefix = urlPattern.substring(0, urlPattern.indexOf("/*"));
                        }
                        else
                        {
                            prefix = urlPattern;
                        }
                    }
                    else
                    {
                        prefix = null;
                    }
                   
                    if (prefix != null)
                    {
                        return prefix;
                    }
                }
            }
        }
        return prefix;
    }

    /**
     * Return the resource loaders used. Note this loaders should return ExtendedResourceMeta instances.
     */
    public ResourceLoader[] getResourceLoaders()
    {
        if (_resourceLoaders == null)
        {
            // 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
            if (/*!_developmentStage && */isGzipResourcesEnabled() && isCacheDiskGzipResources())
            {
                _resourceLoaders = new ResourceLoader[] {
                        new GZIPResourceLoader(new ExtendedResourceLoaderWrapper(new ExternalContextResourceLoader("/resources")), this),
                        new GZIPResourceLoader(new ExtendedResourceLoaderWrapper(new ClassLoaderResourceLoader("META-INF/resources")), this)
                };
            }
            else
            {
                _resourceLoaders = new ResourceLoader[] {
                        new ExtendedResourceLoaderWrapper(new ExternalContextResourceLoader("/resources")),
                        new ExtendedResourceLoaderWrapper(new ClassLoaderResourceLoader("META-INF/resources"))
                };
            }
        }
        return _resourceLoaders;
    }
   
    public WebConfigProvider getWebConfigProvider()
    {
        return _webConfigProvider;
    }
   
    @Override
    public String getResourceIdentifier()
    {
        return _resourceIdentifier;
    }

}
TOP

Related Classes of org.apache.myfaces.commons.resourcehandler.ExtendedDefaultResourceHandlerSupport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.