package net.kencochrane.raven.ext;

import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.json.simple.JSONObject;

import net.kencochrane.raven.spi.JSONProcessor;
import net.kencochrane.raven.spi.RavenMDC;

/**
 * Add HTTP request information to logs when logs are created on HTTP request
 * threads.
 *
 * @author vvasabi
 * @since 1.0
 */
public class ServletJSONProcessor implements JSONProcessor {

    public static final String MDC_REQUEST
            = ServletJSONProcessor.class.getName() + ".httpServletRequest";
    private static final String HTTP_INTERFACE = "sentry.interfaces.Http";

    @Override
    @SuppressWarnings("unchecked")
    public void process(JSONObject json) {
        RavenMDC mdc = RavenMDC.getInstance();
        HttpServletRequest request = (HttpServletRequest)mdc.get(MDC_REQUEST);
        if (request == null) {
            // no request available; do nothing
            return;
        }

        json.put(HTTP_INTERFACE, buildHttpObject(request));
    }

    @SuppressWarnings("unchecked")
    private JSONObject buildHttpObject(HttpServletRequest request) {
        JSONObject http = new JSONObject();
        http.put("url", getUrl(request));
        http.put("method", request.getMethod());
        http.put("data", getData(request));
        http.put("query_string", request.getQueryString());
        http.put("headers", getHeaders(request));
        http.put("env", getEnvironmentVariables(request));
        return http;
    }

    private String getUrl(HttpServletRequest request) {
        StringBuffer sb = request.getRequestURL();
        String query = request.getQueryString();
        if (query != null) {
            sb.append("?").append(query);
        }
        return sb.toString();
    }

    @SuppressWarnings("unchecked")
    private JSONObject getData(HttpServletRequest request) {
        if ("GET".equals(request.getMethod())) {
            return null;
        }

        JSONObject data = new JSONObject();
        Map<String, String[]> params = request.getParameterMap();
        for (Entry<String, String[]> entry : params.entrySet()) {
            data.put(entry.getKey(), entry.getValue()[0]);
        }
        return data;
    }

    @SuppressWarnings("unchecked")
    private JSONObject getHeaders(HttpServletRequest request) {
        JSONObject headers = new JSONObject();
        Enumeration<String> headersEnum = request.getHeaderNames();
        while (headersEnum.hasMoreElements()) {
            String name = headersEnum.nextElement();
            headers.put(capitalize(name), request.getHeader(name));
        }
        return headers;
    }

    @SuppressWarnings("unchecked")
    private JSONObject getEnvironmentVariables(HttpServletRequest request) {
        JSONObject env = new JSONObject();
        env.put("REMOTE_ADDR", request.getRemoteAddr());
        env.put("SERVER_NAME", request.getServerName());
        env.put("SERVER_PORT", request.getServerPort());
        env.put("SERVER_PROTOCOL", request.getProtocol());
        return env;
    }

    /**
     * Capitalize the first letter of each part of a header name. This is
     * necessary because Sentry currently expects header names to be formatted
     * this way.
     *
     * @param headerName header name to capitalize
     * @return capitalized header name
     */
    private static String capitalize(String headerName) {
        String[] tokens = headerName.split("-");
        for (int i = 0; i < tokens.length; i ++) {
            tokens[i] = StringUtils.capitalize(tokens[i]);
        }
        return StringUtils.join(tokens, "-");
    }

}

@@ -110,16 +110,50 @@
 Entry;%0A%0A
+import javax.servlet.http.Cookie;%0A
 import j
@@ -190,16 +190,16 @@
 equest;%0A
-
 %0Aimport 
@@ -1188,32 +1188,39 @@
 d%22)%0A    private 
+static 
 JSONObject build
@@ -1495,24 +1495,74 @@
 yString());%0A
+        http.put(%22cookies%22, getCookies(request));%0A
         http
@@ -1698,16 +1698,23 @@
 private 
+static 
 String g
@@ -2006,32 +2006,39 @@
 d%22)%0A    private 
+static 
 JSONObject getDa
@@ -2086,11 +2086,13 @@
 if (
-%22GE
+!%22POS
 T%22.e
@@ -2469,32 +2469,349 @@
 d%22)%0A    private 
+static JSONObject getCookies(HttpServletRequest request) %7B%0A        JSONObject cookiesMap = new JSONObject();%0A      for (Cookie cookie : request.getCookies()) %7B%0A          cookiesMap.put(cookie.getName(), cookie.getValue());%0A      %7D%0A      return cookiesMap;%0A    %7D%0A%0A    @SuppressWarnings(%22unchecked%22)%0A    private static 
 JSONObject getHe
@@ -3198,32 +3198,32 @@
 gs(%22unchecked%22)%0A
-
     private JSON
@@ -3218,16 +3218,23 @@
 private 
+static 
 JSONObje

Include cookies. Append data only when request is POST.