/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 * http://www.dspace.org/license/
 */
package org.dspace.utils.servlet;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.dspace.kernel.DSpaceKernel;
import org.dspace.kernel.DSpaceKernelManager;
import org.dspace.services.RequestService;


/**
 * This servlet filter will handle the hookup and setup for DSpace 
 * requests.  It should be applied to any webapp that is using the 
 * DSpace core.
 * <p>
 * It will also do anything necessary to the requests that are coming 
 * into a DSpace web application and the responses on their way out.
 * 
 * @author Aaron Zeckoski (azeckoski @ gmail.com)
 */
public final class DSpaceWebappServletFilter implements Filter {

    /* (non-Javadoc)
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        // ensure the kernel is running, if not then we have to die here
        try {
            getKernel();
        } catch (IllegalStateException e) {
            // no kernel so we die
            String message = "Could not start up DSpaceWebappServletFilter because the DSpace Kernel is unavailable or not running: " + e.getMessage();
            System.err.println(message);
            throw new ServletException(message, e);
        }
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
        // clean up the logger for this webapp
        // No longer using commons-logging (JCL), use slf4j instead
        //LogFactory.release(Thread.currentThread().getContextClassLoader());
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // now do some DSpace stuff
        //try {
            DSpaceKernel kernel = getKernel();

            // establish the request service startup
            RequestService requestService = kernel.getServiceManager().getServiceByName(RequestService.class.getName(), RequestService.class);
            if (requestService == null) {
                throw new IllegalStateException("Could not get the DSpace RequestService to start the request transaction");
            }

            // establish a request related to the current session
            requestService.startRequest(request, response); // will trigger the various request listeners
            try {
                // invoke the next filter
                chain.doFilter(request, response);

                // ensure we close out the request (happy request)
                requestService.endRequest(null);
            } catch (Exception e) {
                // failure occurred in the request so we destroy it
                requestService.endRequest(e);
                throw new ServletException(e); // rethrow the exception
            }
            /*
        } catch (Exception e) {
            String message = "Failure in the DSpaceWebappServletFilter: " + e.getMessage();
            System.err.println(message);
            if (res != null) {
                res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
            } else {
                throw new ServletException(message, e);
            }*/
        //}
    }

    /**
     * @return the current DSpace kernel or fail
     */
    public DSpaceKernel getKernel() {
        DSpaceKernel kernel = new DSpaceKernelManager().getKernel();
        if (! kernel.isRunning()) {
            throw new IllegalStateException("The DSpace kernel is not running: " + kernel);
        }
        return kernel;
    }

}
