// $HeadURL$
// $Id$
//
// Copyright © 2006, 2010, 2011, 2012 by the President and Fellows of Harvard College.
//
// Screensaver is an open-source project developed by the ICCB-L and NSRB labs
// at Harvard Medical School. This software is distributed under the terms of
// the GNU General Public License.
package edu.harvard.med.screensaver.ui.arch.util.servlet;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* Servlet filter for Screensaver applications that
* <ul>
* <li>Filters out HTTP requests that are not for JSF-managed pages (e.g. static resources, such as images).
* <li>Handles exceptions by redirecting to a custom exception page.
* <li>Handles requests for termination of user sessions (session invalidation needs to be delayed until after JSF is done handling the request).
* <li>Generates "flanking" debug output around the handling of JSF requests.
* </ul>
*/
public class ScreensaverServletFilter extends OncePerRequestFilter
{
private static Logger log = Logger.getLogger(ScreensaverServletFilter.class);
public static final String DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory";
public static final String CLOSE_HTTP_SESSION = "closeHttpSession";
private static final String REPORT_EXCEPTION_URL = "/main/reportException.jsf";
private String sessionFactoryBeanName = DEFAULT_SESSION_FACTORY_BEAN_NAME;
@Override
protected void initFilterBean() throws ServletException
{
}
@Override
public void destroy()
{
log.info("destroying filter");
}
protected void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response,
final FilterChain filterChain)
throws ServletException, IOException
{
if (!isRequestForApplicationView(request) ||
request.getRemoteUser() == null) {
filterChain.doFilter(request, response);
return;
}
final HttpSession httpSession = request.getSession();
String httpSessionId = httpSession.getId();
log.info(">>>> Screensaver STARTING to process HTTP request for session " +
httpSessionId + " @ " + request.getRequestURI());
Throwable caughtException = null;
try {
filterChain.doFilter(request, response);
}
catch (Exception e) {
if (e instanceof ServletException) {
caughtException = ((ServletException) e).getRootCause();
}
else {
caughtException = e;
}
log.error("caught exception during invocation of servlet filter chain:", e);
caughtException.printStackTrace();
}
finally {
if (caughtException != null) {
httpSession.setAttribute("javax.servlet.error.exception", caughtException);
try {
response.sendRedirect(request.getContextPath() + REPORT_EXCEPTION_URL);
}
catch (IOException e) {
e.printStackTrace();
try {
response.sendError(500);
}
catch (IOException e1) {
// nothing more we can do!
e1.printStackTrace();
}
}
}
}
if (Boolean.TRUE.equals(httpSession.getAttribute(CLOSE_HTTP_SESSION))) {
httpSession.invalidate();
log.info("closed HTTP session " + httpSessionId);
}
log.info("<<<< Screensaver FINISHED processing HTTP request for session " +
httpSessionId + " @ " + request.getRequestURI());
}
/**
* Returns <code>true</code> iff the request is for a JSF view, and thus
* would make use of a Hibernate session.
*
* @motivation We use this to avoid performing Hibernate session management
* tasks for URLs of static resources (images, etc.).
*/
private boolean isRequestForApplicationView(HttpServletRequest request)
{
return request.getRequestURI().endsWith(".jsf");
}
}