package org.nextprot.api.web; import java.io.IOException; import java.util.UUID; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.filter.OncePerRequestFilter; import com.brsanthu.googleanalytics.GoogleAnalytics; import com.brsanthu.googleanalytics.GoogleAnalyticsRequest; import com.brsanthu.googleanalytics.PageViewHit; import com.google.common.base.Optional; public class GoogleAnalyticsFilter extends OncePerRequestFilter { private GoogleAnalytics ga = null; private final Log Logger = LogFactory.getLog(GoogleAnalyticsFilter.class); private String gaTrackingID = null; private static final String GA_TRACKING_ID_SYS_PROP = "GATrackingId"; @Override public void initFilterBean() { if(System.getProperty(GA_TRACKING_ID_SYS_PROP) != null){ gaTrackingID = System.getProperty(GA_TRACKING_ID_SYS_PROP); } if(gaTrackingID != null){ ga = new GoogleAnalytics(gaTrackingID); Logger.info("Google Analytics filter initialized with " + gaTrackingID); }else { Logger.info("Google Analytics not initialized because -D" + GA_TRACKING_ID_SYS_PROP + "=UA-17852148-* system property was not found. Place it in the start.ini of the jetty application."); } } private GoogleAnalyticsRequest<?> generateHit(HttpServletRequest request) { PageViewHit hit = new PageViewHit(request.getRequestURL().toString(), request.getPathInfo()); Logger.debug("Sending hit: " + request.getRequestURL().toString()); hit.clientId(getClientId(request).toString()); // Overriding IP if present from the client Optional<String> ip = getClientIP(request); if (ip.isPresent()) { hit.userIp(ip.get()); } return hit; } private void sendToGoogleAnalytics(HttpServletRequest request) { try { ga.postAsync(generateHit(request)); } catch (Exception e) { Logger.error("Failed to send to GA" + e.getMessage()); } } @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws ServletException, IOException { if ((ga != null) && (!"OPTIONS".equals(req.getMethod()))) { sendToGoogleAnalytics(req); } chain.doFilter(req, resp); } public UUID getClientId(HttpServletRequest request) { // Keeping just IP + agent method, because some methods may require // authentication and others not. And therefore different UUID would be // generated. UUID id = getClientUniqueIdentifier(request); // Logger.debug("Found UUID " + id + " based on custom headers"); return id; } /** * Get a client unique identifier created using the headers * * @param request * @return */ public UUID getClientUniqueIdentifier(HttpServletRequest request) { StringBuilder sb = new StringBuilder(); sb.append(request.getHeader("origin") + "; "); sb.append(request.getHeader("user-agent") + "; "); sb.append(request.getHeader("hostname") + "; "); sb.append(request.getHeader("x-forwarded-for") + "; "); sb.append(request.getRemoteHost() + "; "); sb.append(request.getRemoteUser() + "; "); sb.append(request.getRemoteAddr() + "; "); Logger.debug("Building Client ID based on string " + sb.toString()); return UUID.nameUUIDFromBytes(sb.toString().getBytes()); } /** * Gets the IP of the real client * * @param request * @return */ public Optional<String> getClientIP(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); // May differ from // implementations if (ip != null) { return Optional.of(ip); } else { return Optional.absent(); } } }