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();
}
}
}