Package com.dianping.cat.servlet

Source Code of com.dianping.cat.servlet.CatFilter$RequestWrapper

package com.dianping.cat.servlet;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.unidal.helper.Joiners;
import org.unidal.helper.Joiners.IBuilder;

import com.dianping.cat.Cat;
import com.dianping.cat.CatConstants;
import com.dianping.cat.configuration.NetworkInterfaceManager;
import com.dianping.cat.configuration.client.entity.Server;
import com.dianping.cat.message.Event;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.MessageProducer;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.internal.DefaultMessageManager;
import com.dianping.cat.message.internal.DefaultTransaction;
import com.dianping.cat.message.spi.MessageTree;

public class CatFilter implements Filter {
  private static Map<MessageFormat, String> s_patterns = new LinkedHashMap<MessageFormat, String>();

  private List<Handler> m_handlers = new ArrayList<Handler>();

  @Override
  public void destroy() {
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
        ServletException {
    Context ctx = new Context(new RequestWrapper((HttpServletRequest) request), new ResponseWrapper(
          (HttpServletResponse) response), chain, m_handlers);

    ctx.handle();
  }

  protected String getOriginalUrl(ServletRequest request) {
    return ((HttpServletRequest) request).getRequestURI();
  }

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    String pattern = filterConfig.getInitParameter("pattern");

    if (pattern != null) {
      try {
        String[] patterns = pattern.split(";");

        for (String temp : patterns) {
          String[] temps = temp.split(":");

          s_patterns.put(new MessageFormat(temps[0].trim()), temps[1].trim());
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    m_handlers.add(CatHandler.ENVIRONMENT);
    m_handlers.add(CatHandler.ID_SETUP);
    m_handlers.add(CatHandler.LOG_SPAN);
    m_handlers.add(CatHandler.LOG_CLIENT_PAYLOAD);
  }

  private static enum CatHandler implements Handler {
    ENVIRONMENT {
      protected int detectMode(HttpServletRequest req) {
        String source = req.getHeader("X-CAT-SOURCE");
        String id = req.getHeader("X-CAT-ID");

        Cat.setup(null);

        if ("container".equals(source)) {
          return 2;
        } else if (id != null && id.length() > 0) {
          return 1;
        } else {
          return 0;
        }
      }

      @Override
      public void handle(Context ctx) throws IOException, ServletException {
        HttpServletRequest req = ctx.getRequest();
        boolean top = !Cat.getManager().hasContext();

        ctx.setTop(top);

        if (top) {
          ctx.setMode(detectMode(req));
          ctx.setType(CatConstants.TYPE_URL);

          setTraceMode(req);
        } else {
          ctx.setType(CatConstants.TYPE_URL_FORWARD);
        }

        try {
          ctx.handle();
        } finally {
          if (top) {
            Cat.reset();
          }
        }
      }

      protected void setTraceMode(HttpServletRequest req) {
        String traceMode = "X-CAT-TRACE-MODE";
        String headMode = req.getHeader(traceMode);

        if ("true".equals(headMode)) {
          Cat.getManager().setTraceMode(true);
        }
      }
    },

    ID_SETUP {
      private String m_servers;

      private String getCatServer() {
        if (m_servers == null) {
          DefaultMessageManager manager = (DefaultMessageManager) Cat.getManager();
          List<Server> servers = manager.getConfigManager().getServers();

          m_servers = Joiners.by(',').join(servers, new IBuilder<Server>() {
            @Override
            public String asString(Server server) {
              String ip = server.getIp();
              Integer httpPort = server.getHttpPort();

              if ("127.0.0.1".equals(ip)) {
                ip = NetworkInterfaceManager.INSTANCE.getLocalHostAddress();
              }

              return ip + ":" + httpPort;
            }
          });
        }

        return m_servers;
      }

      @Override
      public void handle(Context ctx) throws IOException, ServletException {
        boolean isTraceMode = Cat.getManager().isTraceMode();

        HttpServletRequest req = ctx.getRequest();
        HttpServletResponse res = ctx.getResponse();
        MessageProducer producer = Cat.getProducer();
        int mode = ctx.getMode();

        switch (mode) {
        case 0:
          ctx.setId(producer.createMessageId());
          break;
        case 1:
          ctx.setRootId(req.getHeader("X-CAT-ROOT-ID"));
          ctx.setParentId(req.getHeader("X-CAT-PARENT-ID"));
          ctx.setId(req.getHeader("X-CAT-ID"));
          break;
        case 2:
          ctx.setRootId(producer.createMessageId());
          ctx.setParentId(ctx.getRootId());
          ctx.setId(producer.createMessageId());
          break;
        default:
          throw new RuntimeException(String.format("Internal Error: unsupported mode(%s)!", mode));
        }

        if (isTraceMode) {
          MessageTree tree = Cat.getManager().getThreadLocalMessageTree();

          tree.setMessageId(ctx.getId());
          tree.setParentMessageId(ctx.getParentId());
          tree.setRootMessageId(ctx.getRootId());

          res.setHeader("X-CAT-SERVER", getCatServer());

          switch (mode) {
          case 0:
            res.setHeader("X-CAT-ROOT-ID", ctx.getId());
            break;
          case 1:
            res.setHeader("X-CAT-ROOT-ID", ctx.getRootId());
            res.setHeader("X-CAT-PARENT-ID", ctx.getParentId());
            res.setHeader("X-CAT-ID", ctx.getId());
            break;
          case 2:
            res.setHeader("X-CAT-ROOT-ID", ctx.getRootId());
            res.setHeader("X-CAT-PARENT-ID", ctx.getParentId());
            res.setHeader("X-CAT-ID", ctx.getId());
            break;
          }
        }

        ctx.handle();
      }
    },

    LOG_CLIENT_PAYLOAD {
      @Override
      public void handle(Context ctx) throws IOException, ServletException {
        HttpServletRequest req = ctx.getRequest();
        String type = ctx.getType();

        if (ctx.isTop()) {
          logRequestClientInfo(req, type);
          logRequestPayload(req, type);
        } else {
          logRequestPayload(req, type);
        }

        ctx.handle();
      }

      protected void logRequestClientInfo(HttpServletRequest req, String type) {
        StringBuilder sb = new StringBuilder(1024);
        String ip = "";
        String ipForwarded = req.getHeader("x-forwarded-for");

        if (ipForwarded == null) {
          ip = req.getRemoteAddr();
        } else {
          ip = ipForwarded;
        }

        sb.append("IPS=").append(ip);
        sb.append("&VirtualIP=").append(req.getRemoteAddr());
        sb.append("&Server=").append(req.getServerName());
        sb.append("&Referer=").append(req.getHeader("referer"));
        sb.append("&Agent=").append(req.getHeader("user-agent"));

        Cat.logEvent(type, type + ".Server", Message.SUCCESS, sb.toString());
      }

      protected void logRequestPayload(HttpServletRequest req, String type) {
        StringBuilder sb = new StringBuilder(256);

        sb.append(req.getScheme().toUpperCase()).append('/');
        sb.append(req.getMethod()).append(' ').append(req.getRequestURI());

        String qs = req.getQueryString();

        if (qs != null) {
          sb.append('?').append(qs);
        }

        Cat.logEvent(type, type + ".Method", Message.SUCCESS, sb.toString());
      }
    },

    LOG_SPAN {

      private void customizeStatus(Transaction t, HttpServletRequest req) {
        Object catStatus = req.getAttribute(CatConstants.CAT_STATE);
       
        if (catStatus != null) {
          t.setStatus(catStatus.toString());
        } else {
          t.setStatus(Message.SUCCESS);
        }
      }

      private void customizeUri(Transaction t, HttpServletRequest req) {
        Object catPageUri = req.getAttribute(CatConstants.CAT_PAGE_URI);
       
        if (t instanceof DefaultTransaction && catPageUri instanceof String) {
          ((DefaultTransaction) t).setName(catPageUri.toString());
        }
      }

      private String getRequestURI(HttpServletRequest req) {
        String requestURI = req.getRequestURI();

        if (s_patterns.size() == 0) {
          return requestURI;
        } else {
          for (Entry<MessageFormat, String> entry : s_patterns.entrySet()) {
            MessageFormat format = entry.getKey();

            try {
              format.parse(requestURI);

              return entry.getValue();
            } catch (Exception e) {
              // ignore
            }
          }
          return requestURI;
        }
      }

      @Override
      public void handle(Context ctx) throws IOException, ServletException {
        HttpServletRequest req = ctx.getRequest();
        Transaction t = Cat.newTransaction(ctx.getType(), getRequestURI(req));

        try {
          ctx.handle();
          customizeStatus(t, req);
        } catch (ServletException e) {
          Cat.logError(e);
          t.setStatus(e);
          throw e;
        } catch (IOException e) {
          Cat.logError(e);
          t.setStatus(e);
          throw e;
        } catch (RuntimeException e) {
          Cat.logError(e);
          t.setStatus(e);
          throw e;
        } catch (Error e) {
          Cat.logError(e);
          t.setStatus(e);
          throw e;
        } finally {
          customizeUri(t, req);
          t.complete();
        }
      }
    };
  }

  protected static class Context {
    private FilterChain m_chain;

    private List<Handler> m_handlers;

    private int m_index;

    private int m_mode;

    private String m_rootId;

    private String m_parentId;

    private String m_id;

    private HttpServletRequest m_request;

    private HttpServletResponse m_response;

    private boolean m_top;

    private String m_type;

    public Context(HttpServletRequest request, HttpServletResponse response, FilterChain chain, List<Handler> handlers) {
      m_request = request;
      m_response = response;
      m_chain = chain;
      m_handlers = handlers;
    }

    public String getId() {
      return m_id;
    }

    public int getMode() {
      return m_mode;
    }

    public String getParentId() {
      return m_parentId;
    }

    public HttpServletRequest getRequest() {
      return m_request;
    }

    public HttpServletResponse getResponse() {
      return m_response;
    }

    public String getRootId() {
      return m_rootId;
    }

    public String getType() {
      return m_type;
    }

    public void handle() throws IOException, ServletException {
      if (m_index < m_handlers.size()) {
        Handler handler = m_handlers.get(m_index++);

        handler.handle(this);
      } else {
        m_chain.doFilter(m_request, m_response);
      }
    }

    public boolean isTop() {
      return m_top;
    }

    public void setId(String id) {
      m_id = id;
    }

    public void setMode(int mode) {
      m_mode = mode;
    }

    public void setParentId(String parentId) {
      m_parentId = parentId;
    }

    public void setRootId(String rootId) {
      m_rootId = rootId;
    }

    public void setTop(boolean top) {
      m_top = top;
    }

    public void setType(String type) {
      m_type = type;
    }
  }

  public static class CookieWrapper extends Cookie {
    private Cookie m_cookie;

    public CookieWrapper(Cookie cookie) {
      super(cookie.getName(), cookie.getValue());
      m_cookie = cookie;
    }

    public CookieWrapper(String name, String value) {
      super(name, value);
    }

    public Object clone() {
      return m_cookie.clone();
    }

    public boolean equals(Object obj) {
      return m_cookie.equals(obj);
    }

    public String getComment() {
      return m_cookie.getComment();
    }

    public String getDomain() {
      return m_cookie.getDomain();
    }

    public int getMaxAge() {
      return m_cookie.getMaxAge();
    }

    public String getName() {
      return m_cookie.getName();
    }

    public String getPath() {
      return m_cookie.getPath();
    }

    public boolean getSecure() {
      return m_cookie.getSecure();
    }

    public String getValue() {
      Event event = Cat.newEvent(Cat.getManager().getDomain() + ":ReadCookie", m_cookie.getName());

      event.setStatus(Event.SUCCESS);
      event.complete();
      return m_cookie.getValue();
    }

    public int getVersion() {
      return m_cookie.getVersion();
    }

    public int hashCode() {
      return m_cookie.hashCode();
    }

    public void setComment(String purpose) {
      m_cookie.setComment(purpose);
    }

    public void setDomain(String pattern) {
      m_cookie.setDomain(pattern);
    }

    public void setMaxAge(int expiry) {
      m_cookie.setMaxAge(expiry);
    }

    public void setPath(String uri) {
      m_cookie.setPath(uri);
    }

    public void setSecure(boolean flag) {
      m_cookie.setSecure(flag);
    }

    public void setValue(String newValue) {
      m_cookie.setValue(newValue);
    }

    public void setVersion(int v) {
      m_cookie.setVersion(v);
    }

    public String toString() {
      return m_cookie.toString();
    }
  }

  protected static interface Handler {
    public void handle(Context ctx) throws IOException, ServletException;
  }

  public static class RequestWrapper extends HttpServletRequestWrapper {

    private HttpServletRequest m_request;

    public RequestWrapper(HttpServletRequest request) {
      super(request);
      m_request = request;
    }

    @Override
    public Cookie[] getCookies() {
      Cookie[] cookies = m_request.getCookies();

      if (cookies != null) {
        int length = cookies.length;
        CookieWrapper[] wappers = new CookieWrapper[length];

        for (int i = 0; i < length; i++) {
          wappers[i] = new CookieWrapper(cookies[i]);
        }
        return wappers;
      } else {
        return null;
      }
    }

  }

  public static class ResponseWrapper extends HttpServletResponseWrapper {

    public ResponseWrapper(HttpServletResponse response) {
      super(response);
    }

    @Override
    public void addCookie(Cookie cookie) {
      Event event = Cat.newEvent(Cat.getManager().getDomain() + ":SetCookie", cookie.getName());

      event.setStatus(Event.SUCCESS);
      event.addData("domain", cookie.getDomain());
      event.addData("path", cookie.getPath());
      event.addData("maxAge", cookie.getMaxAge());
      event.complete();
      super.addCookie(cookie);
    }

    @Override
    public void addHeader(String name, String value) {
      Event event = Cat.newEvent(Cat.getManager().getDomain() + ":SetHead", name);

      event.setStatus(Event.SUCCESS);
      event.addData("value", value);
      event.complete();
      super.addHeader(name, value);
    }
  }
}
TOP

Related Classes of com.dianping.cat.servlet.CatFilter$RequestWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.