io.mapzone.arena.tracker.GoogleAnalyticsTracker.java Source code

Java tutorial

Introduction

Here is the source code for io.mapzone.arena.tracker.GoogleAnalyticsTracker.java

Source

/*
 * polymap.org Copyright (C) 2016, the @authors. All rights reserved.
 *
 * This 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; either version 3.0 of the License, or (at your option) any later
 * version.
 *
 * 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 for more details.
 */
package io.mapzone.arena.tracker;

import java.util.EventObject;
import java.util.List;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.ServletRequestEvent;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.google.common.collect.Lists;

import org.polymap.core.runtime.event.Event.Scope;
import org.polymap.core.runtime.event.EventHandler;
import org.polymap.core.runtime.event.EventManager;

/**
 * This tracker, tracks servlet requests to mapzone into the configured tracker id.
 *
 * @author Steffen Stundzig
 */
public class GoogleAnalyticsTracker implements AutoCloseable {

    private static final Log log = LogFactory.getLog(GoogleAnalyticsTracker.class);

    private final String trackerId;

    private CloseableHttpClient httpClient;

    public GoogleAnalyticsTracker(final String trackerId) {
        this.trackerId = trackerId;
    }

    public void start() {
        EventManager.instance().subscribe(this, ev -> ev instanceof ServletRequestEvent);
    }

    @Override
    public void close() {
        EventManager.instance().unsubscribe(this);
    }

    @EventHandler(delay = 100, scope = Scope.JVM)
    public void track(List<ServletRequestEvent> events) {
        // delay ensures that we run in an async background job
        List<NameValuePair> params = Lists.newArrayList();
        for (EventObject event : events) {
            // add more types here
            if (event instanceof ServletRequestEvent) {
                extractParams(params, (ServletRequestEvent) event);
            }
            send(params);
            params.clear();
        }
    }

    private void extractParams(List<NameValuePair> params, ServletRequestEvent event) {
        params.add(new BasicNameValuePair("t", "event"));
        params.add(new BasicNameValuePair("ec", "externalRequest"));
        HttpServletRequest request = (HttpServletRequest) event.getServletRequest();
        if (request != null) {
            try {
                // TODO, add user or session or something else here authToken
                String clientId = "anonymous";
                String authToken = request.getParameter("authToken");
                if (!StringUtils.isBlank(authToken)) {
                    clientId = authToken;
                }
                addEncoded(params, "cid", clientId);

                // request.get
                String context = request.getServletPath();
                int index = context.lastIndexOf("/");
                if (index != -1) {
                    context = context.substring(index + 1);
                }
                addEncoded(params, "ea", context);
                if (!StringUtils.isBlank(request.getContentType())) {
                    index = request.getContentType().toLowerCase().lastIndexOf("charset=");
                    if (index != -1) {
                        addEncoded(params, "de", request.getContentType().substring(index + 8));
                    }
                }
                addEncoded(params, "dl", request.getServletPath() + "?" + request.getQueryString());
                addEncoded(params, "el", request.getQueryString());
                addEncoded(params, "dr", request.getHeader("Referer"));
                addEncoded(params, "ua", request.getHeader("User-Agent"));
                addEncoded(params, "uip", request.getRemoteAddr());
            } catch (UnsupportedEncodingException e) {
                // do nothing
                log.error(e);
            }

        }
    }

    private void addEncoded(List<NameValuePair> params, String key, String value)
            throws UnsupportedEncodingException {
        if (!StringUtils.isBlank(value)) {
            params.add(new BasicNameValuePair(key, URLEncoder.encode(value, "utf-8")));
        }
    }

    private void send(List<NameValuePair> params) {
        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost("https://www.google-analytics.com/collect");
            params.add(new BasicNameValuePair("v", "1"));
            params.add(new BasicNameValuePair("tid", trackerId));
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            response = httpClient().execute(httpPost);
            EntityUtils.consume(response.getEntity());
        } catch (IOException e) {
            // do nothing
            log.error(e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
    }

    private CloseableHttpClient httpClient() {
        if (httpClient == null) {
            httpClient = HttpClients.createDefault();
        }
        return httpClient;
    }
}