net.amigocraft.mpt.command.InstallCommand.java Source code

Java tutorial

Introduction

Here is the source code for net.amigocraft.mpt.command.InstallCommand.java

Source

/*
 * MPT (Map Packaging Tool)
 *
 * Copyright (c) 2014-2015 Maxim Roncac <mproncace@lapis.blue>
 *
 * The MIT License (MIT)
 *
 *     Permission is hereby granted, free of charge, to any person obtaining a copy
 *     of this software and associated documentation files (the "Software"), to deal
 *     in the Software without restriction, including without limitation the rights
 *     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *     copies of the Software, and to permit persons to whom the Software is
 *     furnished to do so, subject to the following conditions:
 *
 *     The above copyright notice and this permission notice shall be included in all
 *     copies or substantial portions of the Software.
 *
 *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *     SOFTWARE.
 */
package net.amigocraft.mpt.command;

import static net.amigocraft.mpt.util.Config.*;
import static net.amigocraft.mpt.util.MiscUtil.*;

import net.amigocraft.mpt.Main;
import net.amigocraft.mpt.util.Config;
import net.amigocraft.mpt.util.MPTException;
import net.amigocraft.mpt.util.MiscUtil;

import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipFile;

public class InstallCommand extends SubcommandManager {

    public InstallCommand(CommandSender sender, String[] args) {
        super(sender, args);
    }

    @Override
    public void handle() {
        if (!checkPerms())
            return;
        if (args.length > 1) {
            Bukkit.getScheduler().runTaskAsynchronously(Main.plugin, new Runnable() {
                public void run() {
                    try {
                        for (int i = 1; i < args.length; i++) {
                            String id = args[i].toLowerCase();
                            threadSafeSendMessage(sender,
                                    INFO_COLOR + "[MPT] Downloading package " + ID_COLOR + id + INFO_COLOR + "...");
                            downloadPackage(id);
                            threadSafeSendMessage(sender,
                                    INFO_COLOR + "[MPT] Successfully downloaded content! " + "Installing...");
                            installPackage(id);
                            threadSafeSendMessage(sender,
                                    INFO_COLOR + "[MPT] Successfully installed " + ID_COLOR + id);
                        }
                    } catch (MPTException ex) {
                        threadSafeSendMessage(sender, ERROR_COLOR + "[MPT] " + ex.getMessage());
                    }
                }
            });
        } else
            sender.sendMessage(ERROR_COLOR + "[MPT] Too few arguments! Type " + COMMAND_COLOR + "/mpt help"
                    + ERROR_COLOR + " for help.");
    }

    @SuppressWarnings("unchecked")
    public static void downloadPackage(String id) throws MPTException {
        JSONObject packages = (JSONObject) Main.packageStore.get("packages");
        if (packages != null) {
            JSONObject pack = (JSONObject) packages.get(id);
            if (pack != null) {
                if (pack.containsKey("name") && pack.containsKey("version") && pack.containsKey("url")) {
                    if (pack.containsKey("sha1") || !Config.ENFORCE_CHECKSUM) {
                        String name = pack.get("name").toString();
                        String version = pack.get("version").toString();
                        String fullName = name + " v" + version;
                        String url = pack.get("url").toString();
                        String sha1 = pack.containsKey("sha1") ? pack.get("sha1").toString() : "";
                        if (pack.containsKey("installed")) { //TODO: compare versions
                            throw new MPTException(ID_COLOR + name + ERROR_COLOR + " is already installed");
                        }
                        try {
                            URLConnection conn = new URL(url).openConnection();
                            conn.connect();
                            ReadableByteChannel rbc = Channels.newChannel(conn.getInputStream());
                            File file = new File(Main.plugin.getDataFolder(),
                                    "cache" + File.separator + id + ".zip");
                            file.setReadable(true, false);
                            file.setWritable(true, false);
                            file.getParentFile().mkdirs();
                            file.createNewFile();
                            FileOutputStream os = new FileOutputStream(file);
                            os.getChannel().transferFrom(rbc, 0, MiscUtil.getFileSize(new URL(url)));
                            os.close();
                            if (!sha1.isEmpty() && !sha1(file.getAbsolutePath()).equals(sha1)) {
                                file.delete();
                                throw new MPTException(ERROR_COLOR + "Failed to install package " + ID_COLOR
                                        + fullName + ERROR_COLOR + ": checksum mismatch!");
                            }
                        } catch (IOException ex) {
                            throw new MPTException(
                                    ERROR_COLOR + "Failed to download package " + ID_COLOR + fullName);
                        }
                    } else
                        throw new MPTException(ERROR_COLOR + "Package " + ID_COLOR + id + ERROR_COLOR
                                + " is missing SHA-1 checksum! Aborting...");
                } else
                    throw new MPTException(ERROR_COLOR + "Package " + ID_COLOR + id + ERROR_COLOR
                            + " is missing required elements!");
            } else
                throw new MPTException(ERROR_COLOR + "Cannot find package with id " + ID_COLOR + id);
        } else {
            throw new MPTException(ERROR_COLOR + "Package store is malformed!");
        }
    }

    public static void installPackage(String id) throws MPTException {
        if (Thread.currentThread().getId() == Main.mainThreadId)
            throw new MPTException(ERROR_COLOR + "Packages may not be installed from the main thread!");
        id = id.toLowerCase();
        try {
            File file = new File(Main.plugin.getDataFolder(), "cache" + File.separator + id + ".zip");
            if (!file.exists())
                downloadPackage(id);
            if (!Main.packageStore.containsKey("packages")
                    && ((JSONObject) Main.packageStore.get("packages")).containsKey(id))
                throw new MPTException(
                        ERROR_COLOR + "Cannot find package by id " + ID_COLOR + id + ERROR_COLOR + "!");
            JSONObject pack = (JSONObject) ((JSONObject) Main.packageStore.get("packages")).get(id);
            List<String> files = new ArrayList<>();
            lockStores();
            boolean success = MiscUtil.unzip(new ZipFile(file), Bukkit.getWorldContainer(), files);
            if (!KEEP_ARCHIVES)
                file.delete();
            pack.put("installed", pack.get("version").toString());
            JSONArray fileArray = new JSONArray();
            for (String str : files)
                fileArray.add(str);
            pack.put("files", fileArray);
            try {
                writePackageStore();
            } catch (IOException ex) {
                ex.printStackTrace();
                unlockStores();
                throw new MPTException(ERROR_COLOR + "Failed to write package store to disk!");
            }
            unlockStores();
            if (!success)
                throw new MPTException(
                        ERROR_COLOR + "Some files were not extracted. Use verbose logging for details.");
        } catch (IOException ex) {
            throw new MPTException(ERROR_COLOR + "Failed to access archive!");
        }
    }
}