org.ajax4jsf.resource.InternetResourceService.java Source code

Java tutorial

Introduction

Here is the source code for org.ajax4jsf.resource.InternetResourceService.java

Source

/**
 * License Agreement.
 *
 * Rich Faces - Natural Ajax for Java Server Faces (JSF)
 *
 * Copyright (C) 2007 Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

package org.ajax4jsf.resource;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.ajax4jsf.Messages;
import org.ajax4jsf.cache.Cache;
import org.ajax4jsf.cache.CacheConfigurationLoader;
import org.ajax4jsf.cache.CacheException;
import org.ajax4jsf.cache.CacheFactory;
import org.ajax4jsf.cache.CacheLoader;
import org.ajax4jsf.cache.CacheManager;
import org.ajax4jsf.cache.ServletContextInitMap;
import org.ajax4jsf.resource.util.URLToStreamHelper;
import org.ajax4jsf.webapp.BaseFilter;
import org.ajax4jsf.webapp.CacheContent;
import org.ajax4jsf.webapp.WebXml;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class InternetResourceService implements CacheLoader, CacheConfigurationLoader {
    private static final Log log = LogFactory.getLog(InternetResourceService.class);

    static final String ENABLE_CACHING_PARAMETER = "enable-cache";

    private static final String RESOURCE_LIFECYCLE_PARAMETER = "org.ajax4jsf.RESOURCE_LIFECYCLE";

    private FilterConfig filterConfig;

    private boolean cacheEnabled = true;

    private Cache cache = null;

    // private ServletCacheAdministrator cacheAdmin;

    private FacesContextFactory contextFactory;

    // private RenderKitFactory renderKitFactory;
    private String lifecycleClass;

    private ResourceLifecycle lifecycle;

    private InternetResourceBuilder resourceBuilder;

    private WebXml webXml;

    public InternetResourceService() {
    }

    public void setCacheEnabled(boolean b) {
        cacheEnabled = b;
    }

    public void init(FilterConfig config) throws ServletException {
        filterConfig = config;
        ServletContext servletContext = config.getServletContext();
        if ("false".equalsIgnoreCase(config.getInitParameter(ENABLE_CACHING_PARAMETER))) {
            setCacheEnabled(false);
            // this.cacheEnabled = false;
            // this.cacheAdmin = null;
        } else {
            // this.cacheAdmin = ServletCacheAdministrator.getInstance(
            // servletContext, cacheProperties);
            try {
                CacheManager cacheManager = CacheManager.getInstance();
                Map<String, String> env = new ServletContextInitMap(servletContext);
                CacheFactory cacheFactory = cacheManager.getCacheFactory(env);
                this.cache = cacheFactory.createCache(env, this, this);
            } catch (CacheException e) {
                throw new FacesException(e.getMessage(), e);
            }
        }
        // Create Resource-specific Faces Lifecycle instance.
        lifecycleClass = servletContext.getInitParameter(RESOURCE_LIFECYCLE_PARAMETER);
        if (lifecycleClass != null) {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            try {
                Class<?> clazz = classLoader.loadClass(lifecycleClass);
                lifecycle = (ResourceLifecycle) clazz.newInstance();
            } catch (Exception e) {
                throw new FacesException("Error create instance of resource Lifecycle " + lifecycleClass, e);
            }
        } else {
            lifecycle = new ResourceLifecycle();
        }
        webXml = new WebXml();
        webXml.init(servletContext, filterConfig.getFilterName());
        if (log.isDebugEnabled()) {
            log.debug("Resources service initialized");
        }
    }

    public boolean serviceResource(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws ServletException, IOException {
        String resourceKey = webXml.getFacesResourceKey(httpServletRequest);
        if (null != resourceKey) {
            serviceResource(resourceKey, httpServletRequest, httpServletResponse);
            return true;
        }
        return false;
    }

    public void serviceResource(String resourceKey, HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        InternetResource resource;// getInternetResource(request);
        try {
            resource = getResourceBuilder().getResourceForKey(resourceKey);
        } catch (ResourceNotFoundException e) {
            throw new ServletException(e);
        }
        Object resourceDataForKey = getResourceBuilder().getResourceDataForKey(resourceKey);

        ResourceContext resourceContext = getResourceContext(resource, request, response);
        resourceContext.setResourceData(resourceDataForKey);
        try {

            if (resource.isCacheable(resourceContext) && this.cacheEnabled) {
                // Test for client request modification time.
                try {
                    long ifModifiedSince = request.getDateHeader("If-Modified-Since");
                    if (ifModifiedSince >= 0) {
                        // Test for modification. 1000 ms due to round
                        // modification
                        // time to seconds.
                        long lastModified = resource.getLastModified(resourceContext).getTime() - 1000;
                        if (lastModified <= ifModifiedSince) {
                            response.setStatus(304);
                            return;
                        }
                    }
                } catch (IllegalArgumentException e) {
                    log.warn(Messages.getMessage(Messages.PARSING_IF_MODIFIED_SINCE_WARNING), e);
                }
                String cacheKey = resourceKey;
                CachedResourceContext cachedResourceContext = new CachedResourceContext(resourceContext);

                CacheContext cacheLoaderContext = new CacheContext(cachedResourceContext, resource);

                try {
                    CacheContent content = (CacheContent) cache.get(cacheKey, cacheLoaderContext);
                    if (log.isDebugEnabled()) {
                        log.debug(Messages.getMessage(Messages.GET_CONTENT_FROM_CACHE_INFO, cacheKey));
                    }
                    content.sendHeaders(response);
                    // Correct expires date for resource.
                    long expired = resource.getExpired(resourceContext);
                    if (expired < 0) {
                        expired = InternetResource.DEFAULT_EXPIRE;
                    }
                    response.setDateHeader("Expires", System.currentTimeMillis() + expired);
                    //                  response.addHeader("Cache-control", "max-age="
                    //                        + (expired / 1000L));
                    if (!request.getMethod().equals("HEAD")) {
                        content.send(response);
                    }
                    content.flush(response);
                } catch (CacheException e) {
                    log.error(Messages.getMessage(Messages.SEND_RESOURCE_ERROR), e);
                    throw new ServletException(Messages.getMessage(Messages.SEND_RESOURCE_ERROR_2, e.getMessage()),
                            e);
                }
            } else {
                getLifecycle().send(resourceContext, resource);
                // sendResource(resource, request, response,
                // resourceDataForKey);
            }

        } finally {
            resourceContext.release();
        }
    }

    /**
     * @param resource
     * @param request
     * @param response
     * @return
     * @throws ServletException
     * @throws FacesException
     */
    protected ResourceContext getResourceContext(InternetResource resource, HttpServletRequest request,
            HttpServletResponse response) throws FacesException {
        FacesContext facesContext = null;
        ResourceContext resourceContext;
        if (resource.requireFacesContext()) {
            facesContext = getFacesContext(request, response);
            resourceContext = new FacesResourceContext(facesContext);
        } else {
            resourceContext = new ServletResourceContext(getServletContext(), request, response);
        }
        return resourceContext;
    }

    /**
     * Get properties file from classpath
     * 
     * @param name
     * @return
     */
    protected Properties getProperties(String name) {
        Properties properties = new Properties();
        InputStream props = URLToStreamHelper.urlToStreamSafe(BaseFilter.class.getResource(name));
        if (null != props) {
            try {
                properties.load(props);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                log.warn(Messages.getMessage(Messages.READING_PROPERTIES_ERROR, name), e);
            } finally {
                try {
                    props.close();
                } catch (IOException e) {
                    // Can be ignored
                }
            }
        }
        return properties;

    }

    /**
     * @return Returns the servletContext.
     */
    protected ServletContext getServletContext() {
        return filterConfig.getServletContext();
    }

    /**
     * @return the lifecycle
     * @throws ServletException
     */
    protected ResourceLifecycle getLifecycle() throws FacesException {
        return lifecycle;
    }

    /**
     * @return the contextFactory
     */
    protected synchronized FacesContextFactory getContextFactory() {
        if (contextFactory == null) {
            contextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
        }

        return contextFactory;
    }

    protected FacesContext getFacesContext(ServletRequest request, ServletResponse response) throws FacesException {
        return getContextFactory().getFacesContext(getServletContext(), request, response, getLifecycle());
    }

    /**
     * @return the resourceBuilder
     */
    protected InternetResourceBuilder getResourceBuilder() {
        if (resourceBuilder == null) {
            // Create resource builder for this filter.
            resourceBuilder = InternetResourceBuilder.getInstance();
        }
        return resourceBuilder;
    }

    public Object load(Object key, Object context) throws CacheException {
        CacheContext cacheKey = (CacheContext) context;
        CachedResourceContext resourceContext = cacheKey.getResourceContext();
        try {
            getLifecycle().send(resourceContext, cacheKey.getResource());
        } catch (IOException e) {
            throw new CacheException(e.getMessage(), e);
        }
        // TODO - set refresh interval ?
        // cache.put(cacheKey, resourceContext.getContent());
        return resourceContext.getContent();
    }

    public Properties loadProperties(String name) {
        return getProperties(name);
    }

}