be.bukkit.bungee.staffchat.BungeeMetricsLite.java Source code

Java tutorial

Introduction

Here is the source code for be.bukkit.bungee.staffchat.BungeeMetricsLite.java

Source

/*
 * BungeeMetrics
 * Copyright (c) 2014, Minecrell
 * MIT License: https://github.com/Minecrell/BungeeMetrics/blob/master/LICENSE
 * Adapted from Plugin-Metrics by Hidendra (Tyler Blair): https://github.com/Hidendra/Plugin-Metrics
 */

package be.bukkit.bungee.staffchat;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;

import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.scheduler.ScheduledTask;

import static com.google.common.base.StandardSystemProperty.*;
import static com.google.common.net.HttpHeaders.*;

public class BungeeMetricsLite {
    private final static Gson JSON = new Gson();

    private final static int REVISION = 7; // PluginMetrics revision
    private static final String BASE_URL = "http://report.mcstats.org";
    private static final String REPORT_URL = BASE_URL + "/plugin/";

    private final static int PING_INTERVAL = 15; // In minutes
    private final static TimeUnit PING_INTERVAL_UNIT = TimeUnit.MINUTES;

    private final Plugin plugin;
    private final String guid;

    private ScheduledTask task;

    public BungeeMetricsLite(Plugin plugin) {
        this.plugin = Preconditions.checkNotNull(plugin, "plugin");
        // Get UUID from the BungeeCord configuration
        this.guid = plugin.getProxy().getConfig().getUuid();
    }

    public void start() {
        // Check if UUID is not null --> Plugin statistics disabled
        if (task != null || guid == null || guid.isEmpty() || guid.equalsIgnoreCase("null"))
            return;

        this.task = plugin.getProxy().getScheduler().schedule(plugin, new Runnable() {
            private boolean ping;

            @Override
            public void run() {
                try {
                    postPlugin(ping);
                    this.ping = true; // Just ping now for the next times
                } catch (Exception e) {
                    Throwable cause = Throwables.getRootCause(e);
                    plugin.getLogger().log(Level.FINE, "Failed to submit plugin statistics: {0}: {1}",
                            new Object[] { cause.getClass().getName(), cause.getMessage() });
                }
            }
        }, 0, PING_INTERVAL, PING_INTERVAL_UNIT);
    }

    public void stop() {
        if (task != null) {
            task.cancel();
            task = null;
        }
    }

    private void postPlugin(final boolean ping) throws IOException {
        // Create data object
        JsonObject jsonData = new JsonObject();

        // Plugin and server information
        jsonData.addProperty("guid", guid);
        jsonData.addProperty("plugin_version", plugin.getDescription().getVersion());
        jsonData.addProperty("server_version",
                plugin.getProxy().getVersion() + " (MC: " + plugin.getProxy().getGameVersion() + ')');

        jsonData.addProperty("auth_mode", plugin.getProxy().getConfig().isOnlineMode() ? 1 : 0);
        jsonData.addProperty("players_online", plugin.getProxy().getOnlineCount());

        // New data as of R6, system information
        jsonData.addProperty("osname", OS_NAME.value());
        String osArch = OS_ARCH.value();
        jsonData.addProperty("osarch", osArch.equals("amd64") ? "x86_64" : osArch);
        jsonData.addProperty("osversion", OS_VERSION.value());
        jsonData.addProperty("cores", Runtime.getRuntime().availableProcessors());
        jsonData.addProperty("java_version", JAVA_VERSION.value());

        if (ping)
            jsonData.addProperty("ping", 1);

        // Get json output from GSON
        String json = JSON.toJson(jsonData);

        // Open URL connection
        URL url = new URL(REPORT_URL + URLEncoder.encode(plugin.getDescription().getName(), "UTF-8"));
        URLConnection con = url.openConnection();

        byte[] data = json.getBytes(Charsets.UTF_8);
        byte[] gzip = null;

        try { // Compress using GZIP
            gzip = gzip(data);
        } catch (Exception ignored) {
        }

        // Add request headers
        con.addRequestProperty(USER_AGENT, "MCStats/" + REVISION);
        con.addRequestProperty(CONTENT_TYPE, "application/json");
        if (gzip != null) {
            con.addRequestProperty(CONTENT_ENCODING, "gzip");
            data = gzip;
        }

        con.addRequestProperty(CONTENT_LENGTH, String.valueOf(data.length));
        con.addRequestProperty(ACCEPT, "application/json");
        con.addRequestProperty(CONNECTION, "close");

        con.setDoOutput(true);

        // Write json data to the opened stream
        try (OutputStream out = con.getOutputStream()) {
            out.write(data);
            out.flush();
        }

        String response; // Read the response
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
            response = reader.readLine();
        }

        // Check for error
        if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
            if (response == null)
                response = "null";
            else if (response.startsWith("7"))
                response = response.substring(response.startsWith("7,") ? 2 : 1);
            throw new IOException(response);
        }
    }

    private static byte[] gzip(byte[] data) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {
            gzip.write(data);
        }
        return out.toByteArray();
    }
}