package org.xcolab.view.auth.tracking;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;

import org.xcolab.client.members.pojo.Member;
import org.xcolab.commons.http.servlet.RequestUtil;
import org.xcolab.view.auth.AuthenticationContext;

import java.io.IOException;
import java.util.stream.Stream;

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;

public class UserTrackingFilter implements Filter {

    private static final Logger log = LoggerFactory.getLogger(UserTrackingFilter.class);

    private final UserTrackingService userTrackingService;

    public UserTrackingFilter(UserTrackingService userTrackingService) {
        this.userTrackingService = userTrackingService;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("Filter initialized.");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (!(request instanceof HttpServletRequest && response instanceof HttpServletResponse)) {
            throw new UnsupportedOperationException("This filter can only handle HttpServletRequests");
        }
        final HttpServletRequest httpRequest = (HttpServletRequest) request;
        final HttpServletResponse httpResponse = (HttpServletResponse) response;
        final String originalUri = RequestUtil.getOriginalUri(httpRequest);

        if (Stream.of("/js", "/vendor", "/images", "/css", "/widgets", "/image", "/notificationMessage")
                .anyMatch(originalUri::startsWith)) {
            chain.doFilter(request, response);
            return;
        }

        final Member realMemberOrNull = new AuthenticationContext().getRealMemberOrNull();
        userTrackingService.trackVisitor(httpRequest, httpResponse, realMemberOrNull,
                originalUri
                , httpRequest.getHeader(HttpHeaders.REFERER));
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}

@@ -134,16 +134,76 @@
 Headers;
+%0Aimport org.springframework.web.filter.OncePerRequestFilter;
 %0A%0Aimport
@@ -411,37 +411,8 @@
 m;%0A%0A
-import javax.servlet.Filter;%0A
 impo
@@ -445,43 +445,8 @@
 in;%0A
-import javax.servlet.FilterConfig;%0A
 impo
@@ -484,83 +484,8 @@
 on;%0A
-import javax.servlet.ServletRequest;%0Aimport javax.servlet.ServletResponse;%0A
 impo
@@ -610,19 +610,30 @@
 ter 
-implement
+extend
 s 
+OncePerRequest
 Filt
@@ -947,654 +947,173 @@
    p
-ublic void init(FilterConfig filterConfig) throws ServletException %7B%0A        log.info(%22Filter initialized.%22);%0A    %7D%0A%0A    @Override%0A    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)%0A            throws IOException, ServletException %7B%0A        if (!(request instanceof HttpServletRequest && response instanceof HttpServletResponse)) %7B%0A            throw new UnsupportedOperationException(%22This filter can only handle HttpServletRequests%22);
+rotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
 %0A      
-  %7D%0A
       
-  final HttpServletRequest httpRequest = (HttpServletRequest) request;%0A        final HttpServletResponse httpResponse = (HttpServletResponse) response;
+FilterChain filterChain) throws ServletException, IOException %7B%0A
 %0A   
@@ -1171,21 +1171,17 @@
 inalUri(
-httpR
+r
 equest);
@@ -1208,16 +1208,17 @@
 .of(%22/js
+/
 %22, %22/ven
@@ -1220,16 +1220,17 @@
 %22/vendor
+/
 %22, %22/ima
@@ -1236,16 +1236,17 @@
 ages
+/
 %22, %22/css
 %22, %22
@@ -1241,16 +1241,17 @@
 %22, %22/css
+/
 %22, %22/wid
@@ -1254,16 +1254,17 @@
 /widgets
+/
 %22, %22/ima
@@ -1265,18 +1265,35 @@
  %22/image
+/
 %22,
+%0A               
  %22/notif
@@ -1308,33 +1308,16 @@
 essage%22)
-%0A                
 .anyMatc
@@ -1350,33 +1350,39 @@
 ) %7B%0A            
-c
+filterC
 hain.doFilter(re
@@ -1566,21 +1566,17 @@
 tor(
-httpR
+r
 equest, 
 http
@@ -1571,21 +1571,17 @@
 equest, 
-httpR
+r
 esponse,
@@ -1598,32 +1598,16 @@
 rOrNull,
-%0A               
  origina
@@ -1610,16 +1610,17 @@
 ginalUri
+,
 %0A       
@@ -1632,15 +1632,9 @@
     
-, httpR
+r
 eque
@@ -1677,17 +1677,23 @@
         
-c
+filterC
 hain.doF
@@ -1727,57 +1727,7 @@
    %7D
-%0A%0A    @Override%0A    public void destroy() %7B%0A%0A    %7D
 %0A%7D%0A

Make tracking filter run only once