All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.guizhanss.guizhanlib.updater.UpdaterTask Maven / Gradle / Ivy

There is a newer version: 1.8.1
Show newest version
package net.guizhanss.guizhanlib.updater;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.guizhanss.guizhanlib.utils.JsonUtil;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Auto update task.
 *
 * @author ybw0014
 */
class UpdaterTask implements Runnable {
    private static boolean DEBUG = false;

    private final AbstractGuizhanBuildsUpdater updater;

    private String workingDirectory;
    private JsonObject repoInfo = null;
    private JsonObject updateInfo = null;

    UpdaterTask(AbstractGuizhanBuildsUpdater updater) {
        this.updater = updater;
    }

    @Override
    public void run() {
        getRepoInfo();

        String format = getVersionFormat();
        if (format == null) {
            updater.log(Level.SEVERE, Locales.INVALID_VERSION);
            return;
        }
        if (!checkVersion(format)) {
            updater.log(Level.WARNING, Locales.INVALID_FILE_VERSION);
            return;
        }
        if (hasUpdate()) {
            if (updater.getConfig().checkOnly()) {
                sendUpdateNotification();
            } else {
                update();
            }
        }
    }

    /**
     * Get repository information.
     */
    private void getRepoInfo() {
        try {
            URL repos = new URL(updater.getReposFileURL());
            JsonObject reposJson = (JsonObject) JsonUtil.parse(fetch(repos));

            String key = updater.getRepoKey();
            // direct find
            JsonElement currentRepoInfo = JsonUtil.getFromPath(reposJson, key);

            if (currentRepoInfo == null) {
                // find by alias
                JsonArray reposArray = JsonUtil.getFromPath(reposJson, "repos").getAsJsonArray();
                for (JsonElement repo : reposArray) {
                    JsonObject repoObj = repo.getAsJsonObject();
                    if (!repoObj.has("alias")) {
                        continue;
                    }
                    for (JsonElement alias : repoObj.get("alias").getAsJsonArray()) {
                        String aliasPrimitive = alias.getAsJsonPrimitive().getAsString();
                        if (aliasPrimitive.equals(key)) {
                            currentRepoInfo = repoObj;
                            break;
                        }
                    }
                    if (currentRepoInfo != null) {
                        break;
                    }
                }
            }

            if (currentRepoInfo == null) {
                throw new IllegalStateException("Repository information is not found");
            }

            repoInfo = (JsonObject) currentRepoInfo;

            // Get working directory
            workingDirectory = MessageFormat.format(
                "{0}/{1}/{2}",
                updater.getUser(),
                updater.getRepo(),
                updater.getBranch()
            );
        } catch (MalformedURLException | IllegalStateException | IllegalArgumentException | NullPointerException ex) {
            updater.log(Level.SEVERE, Locales.CANNOT_FIND_REPO);
            if (DEBUG) {
                updater.log(Level.SEVERE, ex, ex.getMessage());
            }
        }
    }

    /**
     * Get the version format.
     *
     * @return the version format, {@code null} if failed
     */
    @Nullable
    private String getVersionFormat() {
        try {
            return JsonUtil.getFromPath(repoInfo, "buildOptions.version").getAsString();
        } catch (IllegalStateException | IllegalArgumentException | NullPointerException ex) {
            if (DEBUG) {
                updater.log(Level.SEVERE, ex, ex.getMessage());
            }
            return null;
        }
    }

    /**
     * Check if version format matches.
     *
     * @param format The version format.
     *
     * @return Whether the version format matches.
     */
    private boolean checkVersion(String format) {
        if (!updater.getConfig().checkVersionFormat()) {
            return true;
        }
        String regex = format.replace("(", "\\(")
            .replace(")", "\\)")
            .replace("{version}", "\\d{1,6}")
            .replace("{git_commit}", "([a-z0-9]{7})")
            .replace("{Year}", "\\d{4}")
            .replace("{year}", "\\d{2}")
            .replace("{Month}", "\\d{2}")
            .replace("{month}", "\\d{1,2}")
            .replace("{Date}", "\\d{2}")
            .replace("{date}", "\\d{1,2}");
        Pattern pattern = Pattern.compile(regex);
        Matcher m = pattern.matcher(updater.getPlugin().getDescription().getVersion());
        return m.matches();
    }

    /**
     * Check if there is new build.
     *
     * @return Whether new build exists.
     */
    private boolean hasUpdate() {
        try {
            // Retrieve builds info
            URL buildsUrl = new URL(updater.getBuildsInfo(workingDirectory));
            JsonObject buildsJson = (JsonObject) JsonUtil.parse(fetch(buildsUrl));
            JsonArray builds = (JsonArray) JsonUtil.getFromPath(buildsJson, "builds");

            JsonObject build = null;
            for (int i = builds.size() - 1; i >= 0; i--) {
                build = (JsonObject) builds.get(i);
                if (build.get("success").getAsBoolean()) break;
                build = null;
            }
            if (build == null) {
                updater.log(Level.SEVERE, Locales.CANNOT_FIND_BUILDS);
                return false;
            }

            String pluginName = JsonUtil.getFromPath(repoInfo, "buildOptions.name").getAsString();
            boolean needUpdate = !MessageFormat.format("{0}-{1}.jar", pluginName, updater.getPlugin().getDescription().getVersion()).equals(build.get("target").getAsString());
            if (!needUpdate) {
                updater.log(Level.INFO, Locales.UP_TO_DATE, updater.getPlugin().getName());
                return false;
            }
            updateInfo = build;
            return true;
        } catch (MalformedURLException | IllegalArgumentException | IllegalStateException | NullPointerException ex) {
            updater.log(Level.SEVERE, Locales.CANNOT_FETCH_INFO);
            if (DEBUG) {
                updater.log(Level.SEVERE, ex, ex.getMessage());
            }
            return false;
        }
    }

    /**
     * Send update notification.
     */
    private void sendUpdateNotification() {
        updater.log(Level.INFO, Locales.NEED_UPDATE, updater.getPlugin().getName());
        updater.log(Level.INFO, Locales.DOWNLOAD_NOTIFICATION, updater.getPlugin().getName());
    }

    /**
     * Download and install the latest version
     */
    private void update() {
        String targetFilename = updateInfo.get("target").getAsString();
        updater.log(Level.INFO, Locales.NEED_UPDATE, updater.getPlugin().getName());
        updater.log(Level.INFO, Locales.DOWNLOADING, updater.getPlugin().getName(), updateInfo.get("id").getAsString());

        try {
            BufferedInputStream input = new BufferedInputStream(new URL(updater.getTargetUrl(workingDirectory, targetFilename)).openStream());
            FileOutputStream output = new FileOutputStream(new File("plugins/" + updater.getPlugin().getServer().getUpdateFolder(), updater.getFile().getName()));
            byte[] data = new byte[1024];
            int read;

            while ((read = input.read(data, 0, 1024)) != -1) {
                output.write(data, 0, read);
            }

            input.close();
            output.close();
        } catch (Exception ex) {
            updater.log(Level.SEVERE, Locales.DOWNLOAD_FAIL, updater.getPlugin().getName());
            if (DEBUG) {
                updater.log(Level.SEVERE, ex, ex.getMessage());
            }
            return;
        }

        updater.log(Level.INFO, " ");
        updater.log(Level.INFO, Locales.UPDATE_INFO_0);
        updater.log(Level.INFO, Locales.UPDATE_INFO_1, updater.getPlugin().getName(), updateInfo.get("id").getAsString());
        updater.log(Level.INFO, Locales.UPDATE_INFO_2);
        updater.log(Level.INFO, " ");
    }

    /**
     * Fetch information from {@link URL}.
     *
     * @param url The {@link URL} of resource.
     *
     * @return The content {@link String}.
     */
    @Nullable
    private String fetch(@Nonnull URL url) {
        try {
            StringBuilder content = new StringBuilder();

            URLConnection connection = url.openConnection();
            connection.setConnectTimeout(10_000);
            connection.addRequestProperty("User-Agent", "Guizhan Updater");
            connection.setDoOutput(true);

            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
            String line = reader.readLine();
            while (line != null) {
                content.append(line);
                line = reader.readLine();
            }

            return content.toString();
        } catch (IOException | NullPointerException ex) {
            updater.log(Level.WARNING, Locales.CANNOT_FETCH_INFO);
            if (DEBUG) {
                updater.log(Level.SEVERE, ex, ex.getMessage());
            }
            return null;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy