ru.tehkode.permissions.bukkit.commands.UtilityCommands.java Source code

Java tutorial

Introduction

Here is the source code for ru.tehkode.permissions.bukkit.commands.UtilityCommands.java

Source

/*
 * PermissionsEx - Permissions plugin for Bukkit
 * Copyright (C) 2011 t3hk0d3 http://www.tehkode.ru
 *
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package ru.tehkode.permissions.bukkit.commands;

import com.google.common.collect.Iterables;
import com.mojang.api.profiles.HttpProfileRepository;
import com.mojang.api.profiles.Profile;
import com.mojang.api.profiles.ProfileRepository;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import ru.tehkode.permissions.PermissionsUserData;
import ru.tehkode.permissions.backends.PermissionBackend;
import ru.tehkode.permissions.PermissionManager;
import ru.tehkode.permissions.bukkit.ErrorReport;
import ru.tehkode.permissions.bukkit.PermissionsEx;
import ru.tehkode.permissions.commands.Command;
import ru.tehkode.permissions.commands.CommandsManager.CommandBinding;
import ru.tehkode.permissions.exceptions.PermissionBackendException;

import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;

public class UtilityCommands extends PermissionsCommand {

    @Command(name = "pex", syntax = "reload", permission = "permissions.manage.reload", description = "Reload environment")
    public void reload(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        try {
            plugin.getPermissionsManager().reset();
            sender.sendMessage(ChatColor.WHITE + "Permissions reloaded");
        } catch (PermissionBackendException e) {
            sender.sendMessage(ChatColor.RED + "Failed to reload permissions! Check configuration!\n"
                    + ChatColor.RED + "Error (see console for full): " + e.getMessage());
            plugin.getLogger().log(Level.WARNING,
                    "Failed to reload permissions when " + sender.getName() + " ran `pex reload`", e);
        }
    }

    @Command(name = "pex", syntax = "report", permission = "permissions.manage.reportbug", description = "Create an issue template to report an issue")
    public void report(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        ErrorReport report = ErrorReport.withException("User-requested report", new Exception().fillInStackTrace());
        sender.sendMessage("Fill in the information at " + report.getShortURL() + " to report an issue");
        sender.sendMessage(ChatColor.RED
                + "NOTE: A GitHub account is necessary to report issues. Create one at https://github.com/");
    }

    @Command(name = "pex", syntax = "config <node> [value]", permission = "permissions.manage.config", description = "Print or set <node> [value]")
    public void config(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {

        String nodeName = args.get("node");
        if (nodeName == null || nodeName.isEmpty()) {
            return;
        }

        FileConfiguration config = plugin.getConfig();

        if (args.get("value") != null) {
            config.set(nodeName, this.parseValue(args.get("value")));
            try {
                config.save(new File(plugin.getDataFolder(), "config.yml"));
            } catch (Throwable e) {
                sender.sendMessage(
                        ChatColor.RED + "[PermissionsEx] Failed to save configuration: " + e.getMessage());
            }
        }

        Object node = config.get(nodeName);
        if (node instanceof Map) {
            sender.sendMessage("Node \"" + nodeName + "\": ");
            for (Map.Entry<?, ?> entry : ((Map<?, ?>) node).entrySet()) {
                sender.sendMessage("  " + entry.getKey() + " = " + entry.getValue());
            }
        } else if (node instanceof List) {
            sender.sendMessage("Node \"" + nodeName + "\": ");
            for (Object item : ((List<?>) node)) {
                sender.sendMessage(" - " + item);
            }
        } else {
            sender.sendMessage("Node \"" + nodeName + "\" = \"" + node + "\"");
        }
    }

    @Command(name = "pex", syntax = "backend", permission = "permissions.manage.backend", description = "Print currently used backend")
    public void getBackend(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        sender.sendMessage("Current backend: " + plugin.getPermissionsManager().getBackend());
    }

    @Command(name = "pex", syntax = "backend <backend>", permission = "permissions.manage.backend", description = "Change permission backend on the fly (Use with caution!)")
    public void setBackend(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        if (args.get("backend") == null) {
            return;
        }

        try {
            plugin.getPermissionsManager().setBackend(args.get("backend"));
            sender.sendMessage(ChatColor.WHITE + "Permission backend changed!");
        } catch (RuntimeException e) {
            if (e.getCause() instanceof ClassNotFoundException) {
                sender.sendMessage(ChatColor.RED + "Specified backend not found.");
            } else {
                sender.sendMessage(ChatColor.RED + "Error during backend initialization.");
                e.printStackTrace();
            }
        } catch (PermissionBackendException e) {
            sender.sendMessage(ChatColor.RED + "Backend initialization failed! Fix your configuration!\n"
                    + ChatColor.RED + "Error (see console for more): " + e.getMessage());
            plugin.getLogger().log(Level.WARNING, "Backend initialization failed when " + sender.getName()
                    + " was initializing " + args.get("backend"), e);
        }
    }

    @Command(name = "pex", syntax = "hierarchy [world]", permission = "permissions.manage.users", description = "Print complete user/group hierarchy")
    public void printHierarchy(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        sender.sendMessage("User/Group inheritance hierarchy:");
        this.sendMessage(sender, this.printHierarchy(null, this.autoCompleteWorldName(args.get("world")), 0));
    }

    @Command(name = "pex", syntax = "convert uuid [force]", permission = "permissions.convert", description = "Bulk convert user data to UUID-based storage")
    public void convertUUID(final PermissionsEx plugin, final CommandSender sender, Map<String, String> args) {
        final PermissionBackend backend = plugin.getPermissionsManager().getBackend();
        if (!plugin.getServer().getOnlineMode() && !"force".equals(args.get("force"))) {
            sender.sendMessage(ChatColor.RED
                    + "This server is running in offline mode and UUIDs may not be stable. Please run '/pex convert uuid force' to perform conversion anyway, or switch to online mode.");
            return;
        }
        final ProfileRepository repo = new HttpProfileRepository("minecraft");
        final Collection<String> userIdentifiers = new HashSet<>(backend.getUserIdentifiers());
        for (Iterator<String> it = userIdentifiers.iterator(); it.hasNext();) {
            try {
                UUID.fromString(it.next());
                it.remove();
            } catch (IllegalArgumentException ex) {
            }
        }

        if (userIdentifiers.isEmpty()) {
            sender.sendMessage(ChatColor.RED + "No users to convert!");
            return;
        }

        sender.sendMessage("Beginning conversion to UUID in " + (int) Math.ceil(userIdentifiers.size() / 50000.0)
                + " batches of max 50k (1 batch is executed every 10 minutes)");
        backend.setPersistent(false);
        final Iterator<List<String>> splitIdentifiers = Iterables.partition(userIdentifiers, 50 * 1000).iterator(); // 50k users per 10 minutes
        final AtomicInteger batchNum = new AtomicInteger(1);

        plugin.getPermissionsManager().getExecutor().execute(new Runnable() {
            @Override
            public void run() {
                List<String> names = splitIdentifiers.next();
                try {
                    for (Profile profile : repo.findProfilesByNames(names.toArray(new String[names.size()]))) {
                        PermissionsUserData data = backend.getUserData(profile.getName());
                        data.setIdentifier(profile.getId().replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})",
                                "$1-$2-$3-$4-$5"));
                        data.setOption("name", profile.getName(), null);
                    }
                } catch (Exception e) {
                    ErrorReport.handleError("While converting batch " + batchNum.get() + " to UUID", e);
                    backend.setPersistent(true);
                    return;
                }
                if (splitIdentifiers.hasNext()) {
                    plugin.getPermissionsManager().getExecutor().schedule(this, 10, TimeUnit.MINUTES);
                    plugin.getLogger().info("Completed conversion batch " + batchNum.getAndIncrement() + " of "
                            + (int) Math.ceil(userIdentifiers.size() / 50000.0));
                } else {
                    plugin.getLogger().info("UUID conversion complete");
                    if (!(sender instanceof Player) || ((Player) sender).isOnline()) {
                        sender.sendMessage("UUID conversion complete");
                    }
                    backend.setPersistent(true);
                }
            }
        });
    }

    @Command(name = "pex", syntax = "import <backend>", permission = "permissions.dump", description = "Import data from <backend> as specified in the configuration")
    public void dumpData(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        try {
            PermissionManager mgr = plugin.getPermissionsManager();
            PermissionBackend backend = mgr.createBackend(args.get("backend"));
            mgr.getBackend().loadFrom(backend);

            sender.sendMessage(ChatColor.WHITE + "[PermissionsEx] Data from \"" + args.get("backend")
                    + "\" loaded into currently active backend");
        } catch (RuntimeException e) {
            if (e.getCause() instanceof ClassNotFoundException) {
                sender.sendMessage(ChatColor.RED + "Specified backend not found!");
            } else {
                sender.sendMessage(ChatColor.RED + "Error: " + e.getMessage());
                plugin.getLogger().severe("Error: " + e.getMessage());
                e.printStackTrace();
            }
        } catch (PermissionBackendException e) {
            sender.sendMessage(ChatColor.RED + "Backend " + args.get("backend")
                    + " was unable to load due to user configuration error. See console for details.");
            plugin.getLogger().log(Level.WARNING, "Import backend unable to load", e);
        }
    }

    @Command(name = "pex", syntax = "toggle debug", permission = "permissions.debug", description = "Enable/disable debug mode")
    public void toggleFeature(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        PermissionManager manager = plugin.getPermissionsManager();

        manager.setDebug(!manager.isDebug());
        String debugStatusMessage = "Debug mode " + (manager.isDebug() ? "enabled" : "disabled");
        if (sender instanceof Player) {
            sender.sendMessage(debugStatusMessage);
        }
        plugin.getLogger().warning(debugStatusMessage);
    }

    private static int tryGetInt(CommandSender sender, Map<String, String> args, String key, int def) {
        if (!args.containsKey(key)) {
            return def;
        }

        try {
            return Integer.parseInt(args.get(key));
        } catch (NumberFormatException e) {
            sender.sendMessage(ChatColor.RED + "Invalid " + key + " entered; must be an integer but was '"
                    + args.get(key) + "'");
            return Integer.MIN_VALUE;
        }
    }

    @Command(name = "pex", syntax = "help [page] [count]", permission = "permissions.manage", description = "PermissionsEx commands help")
    public void showHelp(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        List<CommandBinding> commands = this.manager.getCommands();

        int count = tryGetInt(sender, args, "count", 4);
        int page = tryGetInt(sender, args, "page", 1);

        if (page == Integer.MIN_VALUE || count == Integer.MIN_VALUE) {
            return; // method already prints error message
        }

        if (page < 1) {
            sender.sendMessage(ChatColor.RED + "Page couldn't be lower than 1");
            return;
        }

        int totalPages = (int) Math.ceil(commands.size() / count);

        sender.sendMessage(ChatColor.BLUE + "PermissionsEx" + ChatColor.WHITE + " commands (page " + ChatColor.GOLD
                + page + "/" + totalPages + ChatColor.WHITE + "): ");

        int base = count * (page - 1);

        for (int i = base; i < base + count; i++) {
            if (i >= commands.size()) {
                break;
            }

            Command command = commands.get(i).getMethodAnnotation();
            String commandName = String.format("/%s %s", command.name(), command.syntax())
                    .replace("<", ChatColor.BOLD.toString() + ChatColor.RED + "<")
                    .replace(">", ">" + ChatColor.RESET + ChatColor.GOLD.toString())
                    .replace("[", ChatColor.BOLD.toString() + ChatColor.BLUE + "[")
                    .replace("]", "]" + ChatColor.RESET + ChatColor.GOLD.toString());

            sender.sendMessage(ChatColor.GOLD + commandName);
            sender.sendMessage(ChatColor.AQUA + "    " + command.description());
        }
    }

    @Command(name = "pex", syntax = "version", permission = "permissions.manage", description = "Display version of PermissionsEx")
    public void showVersion(PermissionsEx plugin, CommandSender sender, Map<String, String> args) {
        if (sender instanceof Player) {
            sender.sendMessage("[" + ChatColor.RED + "PermissionsEx" + ChatColor.WHITE + "] version ["
                    + ChatColor.BLUE + plugin.getDescription().getVersion() + ChatColor.WHITE + "]");
        } else {
            sender.sendMessage("[PermissionsEx] version [" + plugin.getDescription().getVersion() + "]");
        }
    }
}