/** * Abiquo community edition * cloud management application for hybrid clouds * Copyright (C) 2008-2010 - Abiquo Holdings S.L. * * This application is free software; you can redistribute it and/or * modify it under the terms of the GNU LESSER GENERAL PUBLIC * LICENSE as published by the Free Software Foundation under * version 3 of the License * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * LESSER GENERAL PUBLIC LICENSE v.3 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.abiquo.api.web.filters; import java.io.IOException; 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.HttpServletResponseWrapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.context.SecurityContextHolder; import com.abiquo.api.spring.security.AbiquoUserDetails; import com.abiquo.api.tracer.TracerContext; import com.abiquo.api.tracer.TracerContextHolder; /** * Traces Request, Response and Exception thrown by API Resources. * * @author eruiz */ public class TraceFilter implements Filter { /** The logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(TraceFilter.class); @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; // Encapsulate response to keep trace of status code StatusExposingServletResponse res = new StatusExposingServletResponse((HttpServletResponse) response); createTracerContext(request, res); traceRequest(req.getMethod(), req.getRequestURI(), req.getQueryString()); chain.doFilter(request, res); traceResponse(req.getMethod(), req.getRequestURI(), req.getQueryString(), res.getStatus()); destroyTracerContext(request, res); } /** * Logs the incoming API request in the log files and tracer. * * @param method Represents a HTTP Method (like GET) * @param path Request's URL * @param query Query string contained in request's URL */ private void traceRequest(final String method, final String path, final String query) { String message = String.format("Method: %s, Path: %s, Query: %s", method, path, query); LOGGER.trace("Incoming API request. " + message); } /** * Logs the outcoming API request in the log files and tracer. * * @param method Represents a HTTP Method (like GET) * @param path Request's URL * @param query Query string contained in request's URL * @param status The HTTP response code */ private void traceResponse(final String method, final String path, final String query, final int status) { String message = String.format("Method: %s, Path: %s, Query: %s, Status code: %d", method, path, query, status); LOGGER.trace("Outcoming API request. " + message); } @Override public void init(final FilterConfig config) throws ServletException { LOGGER.info("TraceFilter loaded"); } @Override public void destroy() { LOGGER.info("TraceFilter destroyed"); } private void createTracerContext(final ServletRequest request, final ServletResponse response) { HttpServletRequest req = (HttpServletRequest) request; // Get hierarchy information String resource = req.getRequestURI().replaceAll(req.getContextPath(), ""); // Get current user information AbiquoUserDetails userDetails = (AbiquoUserDetails) SecurityContextHolder.getContext().getAuthentication() .getPrincipal(); // Create the tracer context TracerContext context = new TracerContext(); context.setHierarchy(resource); context.setUserId(userDetails.getUserId()); context.setUsername(userDetails.getUsername()); context.setEnterpriseId(userDetails.getEnterpriseId()); context.setEnterpriseName(userDetails.getEnterpriseName()); // Publish the context the context TracerContextHolder.initialize(context); } private void destroyTracerContext(final ServletRequest request, final ServletResponse response) { TracerContextHolder.clearContext(); } /** * HttpServletResponseWrapper to encapsulate response to keep trace of status code. */ private static class StatusExposingServletResponse extends HttpServletResponseWrapper { private int httpStatus; public StatusExposingServletResponse(final HttpServletResponse response) { super(response); } @Override public void sendError(final int sc) throws IOException { httpStatus = sc; super.sendError(sc); } @Override public void sendError(final int sc, final String msg) throws IOException { httpStatus = sc; super.sendError(sc, msg); } @Override public void setStatus(final int sc) { httpStatus = sc; super.setStatus(sc); } public int getStatus() { return httpStatus; } } }