package com.nitorcreations.puggly;

import com.nitorcreations.puggly.domain.LoggedExchange;
import com.nitorcreations.puggly.domain.LoggedRequest;
import com.nitorcreations.puggly.domain.LoggedResponse;
import com.nitorcreations.puggly.domain.tranforms.ExchangeCondition;
import com.nitorcreations.puggly.domain.tranforms.ExchangeTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoggingFilter implements Filter {

    private Logger logger = LoggerFactory.getLogger(LoggingFilter.class);

    private ChainedExchangeTransformer transformer = new ChainedExchangeTransformer();
    private ChainedExchangeSkipper skipper = new ChainedExchangeSkipper();

    @Override
    public void init(FilterConfig config) throws ServletException {
        // NOOP.
    }

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

            ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
            ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper((HttpServletResponse) response);

            try {
                chain.doFilter(requestWrapper, responseWrapper);
            } finally {
                final byte[] body = responseWrapper.getContentAsByteArray();

                LoggedRequest loggedRequest = new LoggedRequest(requestWrapper, new String(requestWrapper.getContentAsByteArray(), requestWrapper.getCharacterEncoding()));
                LoggedResponse loggedResponse = new LoggedResponse(responseWrapper, new String(body, responseWrapper.getCharacterEncoding()));
                LoggedExchange loggedExchange = new LoggedExchange(loggedRequest, loggedResponse);

                HttpServletResponse rawResponse = (HttpServletResponse) responseWrapper.getResponse();

                if (body.length > 0) {
                    rawResponse.setContentLength(body.length);
                    StreamUtils.copy(body, rawResponse.getOutputStream());
                }

                if (!skipper.test(loggedExchange)) {
                    logger.debug("{}", transformer.apply(loggedExchange));
                }
            }
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        // NOOP.
    }

    public void registerSkipCondition(ExchangeCondition condition) {
        skipper.registerSkipCondition(condition);
    }

    public void registerTransform(ExchangeCondition condition, ExchangeTransform transform) {
        transformer.registerTransform(condition, transform);
    }

}
@@ -436,16 +436,76 @@
 mUtils;%0A
+import org.springframework.web.filter.OncePerRequestFilter;%0A
 import o
@@ -655,9 +655,58 @@
 let.
-*
+FilterChain;%0Aimport javax.servlet.ServletException
 ;%0Aim
@@ -856,19 +856,30 @@
 ter 
-implement
+extend
 s 
+OncePerRequest
 Filt
@@ -1145,119 +1145,16 @@
    p
-ublic void init(FilterConfig config) throws ServletException %7B%0A        // NOOP.%0A    %7D%0A%0A    @Override%0A    public
+rotected
  voi
@@ -1163,17 +1163,29 @@
 doFilter
-(
+Internal(Http
 ServletR
@@ -1200,16 +1200,20 @@
 equest, 
+Http
 ServletR
@@ -1292,195 +1292,8 @@
 n %7B%0A
-        if (request instanceof HttpServletRequest) %7B%0A            if (response.getCharacterEncoding() == null) %7B%0A                response.setCharacterEncoding(%22UTF-8%22);%0A            %7D%0A%0A    
     
@@ -1379,29 +1379,8 @@
 per(
-(HttpServletRequest) 
 requ
@@ -1385,20 +1385,16 @@
 quest);%0A
-    
         
@@ -1475,38 +1475,16 @@
 Wrapper(
-(HttpServletResponse) 
 response
@@ -1499,22 +1499,14 @@
     
-    
 try %7B%0A
-    
     
@@ -1570,20 +1570,16 @@
         
-    
 %7D finall
@@ -1594,20 +1594,16 @@
         
-    
 final by
@@ -1652,28 +1652,24 @@
 teArray();%0A%0A
-    
             
@@ -1828,36 +1828,32 @@
 ));%0A            
-    
 LoggedResponse l
@@ -1971,28 +1971,24 @@
             
-    
 LoggedExchan
@@ -2071,20 +2071,16 @@
         
-    
 HttpServ
@@ -2167,28 +2167,24 @@
             
-    
 if (body.len
@@ -2190,28 +2190,24 @@
 ngth %3E 0) %7B%0A
-    
             
@@ -2269,20 +2269,16 @@
         
-    
 StreamUt
@@ -2320,28 +2320,24 @@
 tStream());%0A
-    
             
@@ -2347,28 +2347,24 @@
             
-    
 if (!skipper
@@ -2384,28 +2384,24 @@
 xchange)) %7B%0A
-    
             
@@ -2463,36 +2463,32 @@
 ));%0A            
-    
 %7D%0A            %7D%0A
@@ -2485,153 +2485,9 @@
     
-    %7D%0A        %7D else %7B%0A            chain.doFilter(request, response);%0A        %7D%0A    %7D%0A%0A    @Override%0A    public void destroy() %7B%0A        // NOOP.
+%7D
 %0A   

extend Spring's OncePerRequestFilter for more configurability