
package de.ivu.elect.jee.faces;

import java.io.IOException;

import javax.faces.application.ResourceHandler;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import de.ivu.elect.jee.log.ElectMDC;
import de.ivu.elect.jee.session.SessionIdFilter;

/**
 * Filter, der UTF-8 als Character-Encoding setzt. Ohne diesen Filter würden Umlaute bei Formularen fehlerhaft
 * ausgewertet
 * 
 * Quelle: http://stackoverflow.com/questions/2006826/jsf-form-and-german-umlauts
 */
public class UTF8Filter implements Filter {

  private static final Logger LOG = LoggerFactory.getLogger(UTF8Filter.class);

  private static final boolean LOG_FILTER_EXCEPTIONS = "true".equalsIgnoreCase(System.getProperty("LOG_FILTER_EXCEPTIONS"));

  @Override
  public void destroy() {
    // nothing 
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
      ServletException {
    if (request.getCharacterEncoding() == null) {
      request.setCharacterEncoding("UTF-8");
    }

    // ELECT-12533
    setLoggingParameter(request);

    disableCache(request, response); // ELECT-1127
    try {
      chain.doFilter(request, response);
    } catch (Throwable e) {
      if (isFilterException(e)) {
        LOG.warn("Filtered Exception: " + e.getMessage());
      } else {
        if (LOG_FILTER_EXCEPTIONS) {
          LOG.warn(e.getMessage(), e);
        }
        throw e;
      }
    } finally {
      clearLogginParameter();
    }
  }

  private void clearLogginParameter() {
    try {
      MDC.clear();
    } catch (Exception e) {
      LOG.warn("Fehler beim Loeschen des Logging-Parameters: " + e.getMessage());
    }
  }

  private void setLoggingParameter(ServletRequest request) {
    try {
      MDC.put(ElectMDC.SESSION_PARAMETER, bestimmeSessionId(request));
    } catch (Exception e) {
      LOG.warn("Fehler beim Setzen des Logging-Parameters: " + e.getMessage());
    }
  }

  private String bestimmeSessionId(ServletRequest request) {
    HttpSession session = ((HttpServletRequest) request).getSession(false);
    if (session == null) {
      return ElectMDC.SESSION_NO_VALUE;
    }
    return SessionIdFilter.maskiere(session.getId());
  }

  private boolean isFilterException(Throwable e) {
    return isBrokenPipe(e);
  }

  private boolean isBrokenPipe(Throwable e) {
    return e != null && e.getMessage() != null && e.getMessage().contains("broken pipe");
  }

  private void disableCache(ServletRequest request, ServletResponse response) {
    HttpServletRequest httpReq = (HttpServletRequest) request;
    HttpServletResponse httpRes = (HttpServletResponse) response;

    if (!httpReq.getRequestURI().startsWith(httpReq.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
      httpRes.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
      httpRes.setHeader("Pragma", "no-cache"); // HTTP 1.0.
      httpRes.setDateHeader("Expires", 0); // Proxies.
    }
  }

  @Override
  public void init(FilterConfig arg0) throws ServletException {
    // nothing 

  }

}
