net.ae97.totalpermissions.update.UpdateChecker.java Source code

Java tutorial

Introduction

Here is the source code for net.ae97.totalpermissions.update.UpdateChecker.java

Source

/*
 * Copyright (C) 2014 AE97
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.ae97.totalpermissions.update;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.ae97.totalpermissions.TotalPermissions;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;

/**
 * @author Lord_Ralex
 */
public class UpdateChecker extends Thread {

    private boolean download;
    private String apikey;
    private boolean disabled;
    private Logger pluginLogger;
    private File pluginFile;
    private String pluginName, pluginVersion;

    public UpdateChecker() {

    }

    @Override
    public void start() {
        throw new UnsupportedOperationException("Cannot run an update on an unknown plugin");
    }

    public void start(TotalPermissions plugin) {
        pluginLogger = plugin.getLogger();
        pluginFile = plugin.getFile();
        pluginName = plugin.getName();
        pluginVersion = plugin.getDescription().getVersion();
        YamlConfiguration config = new YamlConfiguration();
        config.options().header(
                "This configuration file affects all plugins using the Updater system (version 2+ - http://forums.bukkit.org/threads/96681/ )"
                        + '\n'
                        + "If you wish to use your API key, read http://wiki.bukkit.org/ServerMods_API and place it below."
                        + '\n'
                        + "Some updating systems will not adhere to the disabled value, but these may be turned off in their plugin's configuration.");
        config.addDefault("api-key", "PUT_API_KEY_HERE");
        config.addDefault("disable", false);

        File updaterFolder = new File(plugin.getDataFolder().getParentFile(), "Updater");
        File updaterConfigFile = new File(updaterFolder, "config.yml");

        updaterFolder.mkdirs();
        String tempKey = null;
        boolean tempDisabled = false;
        if (!updaterConfigFile.exists()) {
            config.options().copyDefaults(true);
            try {
                config.save(updaterConfigFile);
                config.load(updaterConfigFile);
            } catch (IOException e) {
                pluginLogger.log(Level.SEVERE, "Error saving default Updater config", e);
                tempKey = null;
                tempDisabled = true;
            } catch (InvalidConfigurationException e) {
                pluginLogger.log(Level.SEVERE, "Error loading default Updater config", e);
                tempKey = null;
                tempDisabled = true;
            }
        }
        apikey = tempKey == null ? config.getString("api-key", null) : null;
        disabled = tempDisabled || config.getBoolean("disable", false)
                || !plugin.getConfig().getBoolean("update.check", true);
        download = !disabled && plugin.getConfig().getBoolean("update.download", true);
        super.start();
    }

    @Override
    public void run() {
        if (disabled) {
            return;
        }
        try {
            URL url = new URL("https://api.curseforge.com/servermods/files?projectIds=54850");
            URLConnection conn = url.openConnection();
            conn.setConnectTimeout(5000);
            if (apikey != null && !apikey.isEmpty() && !apikey.equals("PUT_API_KEY_HERE")) {
                conn.addRequestProperty("X-API-Key", apikey);
            }
            conn.addRequestProperty("User-Agent", "Updater - TotalPermissions-v" + pluginVersion);
            conn.setDoOutput(true);

            BufferedReader reader = null;
            JsonElement details = null;
            try {
                reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String json = reader.readLine();
                JsonArray array = new JsonParser().parse(json).getAsJsonArray();
                details = array.get(array.size() - 1);
            } catch (IOException e) {
                if (e.getMessage().contains("HTTP response code: 403")) {
                    throw new IOException("CurseAPI rejected API-KEY", e);
                }
                throw e;
            } finally {
                if (reader != null) {
                    reader.close();
                }
            }

            if (details == null) {
                return;
            }

            String onlineVersion = details.getAsJsonObject().get("name").getAsString();

            if (!checkForUpdate(pluginVersion, onlineVersion)) {
                return;
            }

            pluginLogger.log(Level.INFO, "Update found! Current: {0} Latest: {1}",
                    new String[] { StringUtils.join(getVersionInts(pluginVersion), "."),
                            StringUtils.join(getVersionInts(onlineVersion), ".") });

            if (!download) {
                return;
            }

            String downloadLink = details.getAsJsonObject().get("downloadUrl").getAsString();

            String pluginFileName = pluginFile.getName();

            if (!pluginFileName.equalsIgnoreCase(pluginName + ".jar")) {
                pluginLogger.log(Level.WARNING, "FILE NAME IS NOT {0}.jar! Forcing rename", pluginName);
                pluginFile.deleteOnExit();
            }

            File output = new File(Bukkit.getUpdateFolderFile(), pluginName + ".jar");
            download(downloadLink, output);

        } catch (MalformedURLException ex) {
            pluginLogger.log(Level.SEVERE, "URL could not be created", ex);
        } catch (IOException ex) {
            pluginLogger.log(Level.SEVERE, "Error occurred on checking for update for " + pluginName, ex);
        }
    }

    private boolean checkForUpdate(String current, String online) {
        if (current.equals(online)) {
            return false;
        }

        return checkUpdate(getVersionInts(current), getVersionInts(online));
    }

    private boolean checkUpdate(Integer[] current, Integer[] online) {
        if (current.length > online.length) {
            Integer[] newOnline = new Integer[current.length];
            System.arraycopy(online, 0, newOnline, 0, online.length);
            for (int i = online.length; i < newOnline.length; i++) {
                newOnline[i] = 0;
            }
            online = newOnline;
        } else if (online.length > current.length) {
            Integer[] newCurrent = new Integer[online.length];
            System.arraycopy(current, 0, newCurrent, 0, current.length);
            for (int i = current.length; i < newCurrent.length; i++) {
                newCurrent[i] = 0;
            }
            current = newCurrent;
        }
        for (int i = 0; i < current.length; i++) {
            if (online[i] > current[i]) {
                return true;
            }
        }
        return false;
    }

    private Integer[] getVersionInts(String versionString) {
        String bits;
        if (versionString.split("\\-v").length == 2) {
            bits = versionString.split("\\-v")[1];
        } else if (versionString.split(" v").length == 2) {
            bits = versionString.split(" v")[1];
        } else if (versionString.split(" ").length == 2) {
            bits = versionString.split(" ")[1];
        } else {
            bits = versionString;
        }

        Integer[] versionMapping = new Integer[bits.split("\\.").length];
        String[] nums = bits.split("\\.");
        for (int i = 0; i < nums.length; i++) {
            try {
                versionMapping[i] = Integer.parseInt(nums[i]);
            } catch (NumberFormatException e) {
                versionMapping[i] = 0;
            }
        }

        return versionMapping;
    }

    private boolean download(String link, File output) {
        InputStream in = null;
        FileOutputStream out = null;
        try {
            URL url = new URL(link);
            in = url.openStream();
            out = new FileOutputStream(output);
            byte[] buffer = new byte[1024];
            while (in.read(buffer) != -1) {
                out.write(buffer);
            }
            pluginLogger.info("Download complete, restart server to apply");
            return true;
        } catch (IOException e) {
            return false;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ex) {
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException ex) {
                }
            }
        }
    }
}