mirror of
https://github.com/TotalFreedomMC/OpenInv.git
synced 2025-07-30 17:31:57 +00:00
New updater.
This commit is contained in:
parent
56752df92e
commit
91f1f4b3e7
6 changed files with 416 additions and 624 deletions
|
@ -41,42 +41,39 @@ import com.lishid.openinv.utils.UpdateManager;
|
|||
*
|
||||
* @author lishid
|
||||
*/
|
||||
public class OpenInv extends JavaPlugin
|
||||
{
|
||||
public class OpenInv extends JavaPlugin {
|
||||
public static final Logger logger = Logger.getLogger("Minecraft.OpenInv");
|
||||
|
||||
|
||||
public static HashMap<String, ISpecialPlayerInventory> inventories = new HashMap<String, ISpecialPlayerInventory>();
|
||||
public static HashMap<String, ISpecialEnderChest> enderChests = new HashMap<String, ISpecialEnderChest>();
|
||||
private static Metrics metrics;
|
||||
|
||||
|
||||
private UpdateManager updater = new UpdateManager();
|
||||
|
||||
|
||||
public static OpenInv mainPlugin;
|
||||
|
||||
public static IPlayerDataManager playerLoader;
|
||||
public static IInventoryAccess inventoryAccess;
|
||||
public static IAnySilentChest anySilentChest;
|
||||
|
||||
public void onEnable()
|
||||
{
|
||||
|
||||
public void onEnable() {
|
||||
// Get plugin manager
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
|
||||
|
||||
// Version check
|
||||
boolean success = InternalAccessor.Initialize(this.getServer());
|
||||
|
||||
if(!success)
|
||||
{
|
||||
|
||||
if (!success) {
|
||||
OpenInv.log("Your version of CraftBukkit is not supported.");
|
||||
OpenInv.log("Please look for an updated version of OpenInv.");
|
||||
pm.disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
playerLoader = InternalAccessor.Instance.newPlayerDataManager();
|
||||
inventoryAccess = InternalAccessor.Instance.newInventoryAccess();
|
||||
anySilentChest = InternalAccessor.Instance.newAnySilentChest();
|
||||
|
||||
|
||||
mainPlugin = this;
|
||||
FileConfiguration config = getConfig();
|
||||
config.set("CheckForUpdates", config.getBoolean("CheckForUpdates", true));
|
||||
|
@ -89,128 +86,108 @@ public class OpenInv extends JavaPlugin
|
|||
config.addDefault("NotifyAnyChest", true);
|
||||
config.options().copyDefaults(true);
|
||||
saveConfig();
|
||||
|
||||
|
||||
pm.registerEvents(new OpenInvPlayerListener(), this);
|
||||
pm.registerEvents(new OpenInvEntityListener(), this);
|
||||
pm.registerEvents(new OpenInvInventoryListener(), this);
|
||||
|
||||
|
||||
getCommand("openinv").setExecutor(new OpenInvPluginCommand(this));
|
||||
getCommand("searchinv").setExecutor(new SearchInvPluginCommand());
|
||||
getCommand("toggleopeninv").setExecutor(new ToggleOpenInvPluginCommand());
|
||||
getCommand("silentchest").setExecutor(new SilentChestPluginCommand(this));
|
||||
getCommand("anychest").setExecutor(new AnyChestPluginCommand(this));
|
||||
getCommand("openender").setExecutor(new OpenEnderPluginCommand(this));
|
||||
|
||||
|
||||
updater.Initialize(this, getFile());
|
||||
|
||||
|
||||
// Metrics
|
||||
try
|
||||
{
|
||||
try {
|
||||
metrics = new Metrics(this);
|
||||
metrics.start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
catch (Exception e) {
|
||||
OpenInv.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean NotifySilentChest()
|
||||
{
|
||||
|
||||
public static boolean NotifySilentChest() {
|
||||
return mainPlugin.getConfig().getBoolean("NotifySilentChest", true);
|
||||
}
|
||||
|
||||
public static boolean NotifyAnyChest()
|
||||
{
|
||||
|
||||
public static boolean NotifyAnyChest() {
|
||||
return mainPlugin.getConfig().getBoolean("NotifyAnyChest", true);
|
||||
}
|
||||
|
||||
public static boolean GetCheckForUpdates()
|
||||
{
|
||||
|
||||
public static boolean GetCheckForUpdates() {
|
||||
return mainPlugin.getConfig().getBoolean("CheckForUpdates", true);
|
||||
}
|
||||
|
||||
public static boolean GetPlayerItemOpenInvStatus(String name)
|
||||
{
|
||||
|
||||
public static boolean GetPlayerItemOpenInvStatus(String name) {
|
||||
return mainPlugin.getConfig().getBoolean("ItemOpenInv." + name.toLowerCase() + ".toggle", false);
|
||||
}
|
||||
|
||||
public static void SetPlayerItemOpenInvStatus(String name, boolean status)
|
||||
{
|
||||
|
||||
public static void SetPlayerItemOpenInvStatus(String name, boolean status) {
|
||||
mainPlugin.getConfig().set("ItemOpenInv." + name.toLowerCase() + ".toggle", status);
|
||||
mainPlugin.saveConfig();
|
||||
}
|
||||
|
||||
public static boolean GetPlayerSilentChestStatus(String name)
|
||||
{
|
||||
|
||||
public static boolean GetPlayerSilentChestStatus(String name) {
|
||||
return mainPlugin.getConfig().getBoolean("SilentChest." + name.toLowerCase() + ".toggle", false);
|
||||
}
|
||||
|
||||
public static void SetPlayerSilentChestStatus(String name, boolean status)
|
||||
{
|
||||
|
||||
public static void SetPlayerSilentChestStatus(String name, boolean status) {
|
||||
mainPlugin.getConfig().set("SilentChest." + name.toLowerCase() + ".toggle", status);
|
||||
mainPlugin.saveConfig();
|
||||
}
|
||||
|
||||
public static boolean GetPlayerAnyChestStatus(String name)
|
||||
{
|
||||
|
||||
public static boolean GetPlayerAnyChestStatus(String name) {
|
||||
return mainPlugin.getConfig().getBoolean("AnyChest." + name.toLowerCase() + ".toggle", true);
|
||||
}
|
||||
|
||||
public static void SetPlayerAnyChestStatus(String name, boolean status)
|
||||
{
|
||||
|
||||
public static void SetPlayerAnyChestStatus(String name, boolean status) {
|
||||
mainPlugin.getConfig().set("AnyChest." + name.toLowerCase() + ".toggle", status);
|
||||
mainPlugin.saveConfig();
|
||||
}
|
||||
|
||||
public static int GetItemOpenInvItem()
|
||||
{
|
||||
if (mainPlugin.getConfig().get("ItemOpenInvItemID") == null)
|
||||
{
|
||||
|
||||
public static int GetItemOpenInvItem() {
|
||||
if (mainPlugin.getConfig().get("ItemOpenInvItemID") == null) {
|
||||
SaveToConfig("ItemOpenInvItemID", 280);
|
||||
}
|
||||
return mainPlugin.getConfig().getInt("ItemOpenInvItemID", 280);
|
||||
}
|
||||
|
||||
public static Object GetFromConfig(String data, Object defaultValue)
|
||||
{
|
||||
|
||||
public static Object GetFromConfig(String data, Object defaultValue) {
|
||||
Object val = mainPlugin.getConfig().get(data);
|
||||
if (val == null)
|
||||
{
|
||||
if (val == null) {
|
||||
mainPlugin.getConfig().set(data, defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveToConfig(String data, Object value)
|
||||
{
|
||||
|
||||
public static void SaveToConfig(String data, Object value) {
|
||||
mainPlugin.getConfig().set(data, value);
|
||||
mainPlugin.saveConfig();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log an information
|
||||
*/
|
||||
public static void log(String text)
|
||||
{
|
||||
public static void log(String text) {
|
||||
logger.info("[OpenInv] " + text);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log an error
|
||||
*/
|
||||
public static void log(Throwable e)
|
||||
{
|
||||
public static void log(Throwable e) {
|
||||
logger.severe("[OpenInv] " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
public static void ShowHelp(Player player)
|
||||
{
|
||||
|
||||
public static void ShowHelp(Player player) {
|
||||
player.sendMessage(ChatColor.GREEN + "/openinv <Player> - Open a player's inventory");
|
||||
player.sendMessage(ChatColor.GREEN + " (aliases: oi, inv, open)");
|
||||
player.sendMessage(ChatColor.GREEN + "/openender <Player> - Open a player's enderchest");
|
||||
|
@ -225,12 +202,12 @@ public class OpenInv extends JavaPlugin
|
|||
player.sendMessage(ChatColor.GREEN + "/silentchest - Toggle silent chest function");
|
||||
player.sendMessage(ChatColor.GREEN + " (aliases: sc, silent)");
|
||||
}
|
||||
|
||||
|
||||
public static boolean hasPermission(Permissible player, String permission) {
|
||||
String[] parts = permission.split("\\.");
|
||||
String perm = "";
|
||||
for(int i = 0; i < parts.length; i++) {
|
||||
if(player.hasPermission(perm + "*")) {
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
if (player.hasPermission(perm + "*")) {
|
||||
return true;
|
||||
}
|
||||
perm += parts[i] + ".";
|
||||
|
|
|
@ -21,16 +21,13 @@ import org.bukkit.event.EventPriority;
|
|||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
|
||||
public class OpenInvInventoryListener implements Listener
|
||||
{
|
||||
public class OpenInvInventoryListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onInventoryClick(InventoryClickEvent event)
|
||||
{
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
// If this is the top inventory
|
||||
// if (event.getView().convertSlot(event.getRawSlot()) == event.getRawSlot())
|
||||
// {
|
||||
if (!OpenInv.inventoryAccess.check(event.getInventory(), event.getWhoClicked()))
|
||||
{
|
||||
if (!OpenInv.inventoryAccess.check(event.getInventory(), event.getWhoClicked())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
// }
|
||||
|
|
|
@ -32,120 +32,96 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
|||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
|
||||
public class OpenInvPlayerListener implements Listener
|
||||
{
|
||||
public class OpenInvPlayerListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerJoin(PlayerJoinEvent event)
|
||||
{
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
ISpecialPlayerInventory inventory = OpenInv.inventories.get(event.getPlayer().getName().toLowerCase());
|
||||
|
||||
if (inventory != null)
|
||||
{
|
||||
|
||||
if (inventory != null) {
|
||||
inventory.PlayerGoOnline(event.getPlayer());
|
||||
}
|
||||
|
||||
|
||||
ISpecialEnderChest chest = OpenInv.enderChests.get(event.getPlayer().getName().toLowerCase());
|
||||
|
||||
if (chest != null)
|
||||
{
|
||||
|
||||
if (chest != null) {
|
||||
chest.PlayerGoOnline(event.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerQuit(PlayerQuitEvent event)
|
||||
{
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
ISpecialPlayerInventory inventory = OpenInv.inventories.get(event.getPlayer().getName().toLowerCase());
|
||||
if (inventory != null)
|
||||
{
|
||||
if (inventory != null) {
|
||||
inventory.PlayerGoOffline();
|
||||
}
|
||||
ISpecialEnderChest chest = OpenInv.enderChests.get(event.getPlayer().getName().toLowerCase());
|
||||
if (chest != null)
|
||||
{
|
||||
if (chest != null) {
|
||||
chest.PlayerGoOffline();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerInteract(PlayerInteractEvent event)
|
||||
{
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.useInteractedBlock() == Result.DENY)
|
||||
return;
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getType() == org.bukkit.Material.ENDER_CHEST)
|
||||
{
|
||||
if (OpenInv.hasPermission(player, Permissions.PERM_SILENT) && OpenInv.GetPlayerSilentChestStatus(player.getName()))
|
||||
{
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getType() == org.bukkit.Material.ENDER_CHEST) {
|
||||
if (OpenInv.hasPermission(player, Permissions.PERM_SILENT) && OpenInv.GetPlayerSilentChestStatus(player.getName())) {
|
||||
event.setCancelled(true);
|
||||
player.openInventory(player.getEnderChest());
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Chest)
|
||||
{
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Chest) {
|
||||
boolean silentchest = false;
|
||||
boolean anychest = false;
|
||||
int x = event.getClickedBlock().getX();
|
||||
int y = event.getClickedBlock().getY();
|
||||
int z = event.getClickedBlock().getZ();
|
||||
|
||||
if (OpenInv.hasPermission(player, Permissions.PERM_SILENT) && OpenInv.GetPlayerSilentChestStatus(player.getName()))
|
||||
{
|
||||
|
||||
if (OpenInv.hasPermission(player, Permissions.PERM_SILENT) && OpenInv.GetPlayerSilentChestStatus(player.getName())) {
|
||||
silentchest = true;
|
||||
}
|
||||
|
||||
if (OpenInv.hasPermission(player, Permissions.PERM_ANYCHEST) && OpenInv.GetPlayerAnyChestStatus(player.getName()))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
if (OpenInv.hasPermission(player, Permissions.PERM_ANYCHEST) && OpenInv.GetPlayerAnyChestStatus(player.getName())) {
|
||||
try {
|
||||
anychest = OpenInv.anySilentChest.IsAnyChestNeeded(player, x, y, z);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
catch (Exception e) {
|
||||
player.sendMessage(ChatColor.RED + "Error while executing openinv. Unsupported CraftBukkit.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the anychest or silentchest is active
|
||||
if (anychest || silentchest)
|
||||
{
|
||||
if (!OpenInv.anySilentChest.ActivateChest(player, anychest, silentchest, x, y, z))
|
||||
{
|
||||
if (anychest || silentchest) {
|
||||
if (!OpenInv.anySilentChest.ActivateChest(player, anychest, silentchest, x, y, z)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Sign)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Sign) {
|
||||
try {
|
||||
Sign sign = ((Sign) event.getClickedBlock().getState());
|
||||
if (OpenInv.hasPermission(player, Permissions.PERM_OPENINV) && sign.getLine(0).equalsIgnoreCase("[openinv]"))
|
||||
{
|
||||
if (OpenInv.hasPermission(player, Permissions.PERM_OPENINV) && sign.getLine(0).equalsIgnoreCase("[openinv]")) {
|
||||
String text = sign.getLine(1).trim() + sign.getLine(2).trim() + sign.getLine(3).trim();
|
||||
player.performCommand("openinv " + text);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
catch (Exception ex) {
|
||||
player.sendMessage("Internal Error.");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)
|
||||
{
|
||||
if (!(player.getItemInHand().getType().getId() == OpenInv.GetItemOpenInvItem()) || (!OpenInv.GetPlayerItemOpenInvStatus(player.getName()))
|
||||
|| !OpenInv.hasPermission(player, Permissions.PERM_OPENINV))
|
||||
{
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
||||
if (!(player.getItemInHand().getType().getId() == OpenInv.GetItemOpenInvItem()) || (!OpenInv.GetPlayerItemOpenInvStatus(player.getName())) || !OpenInv.hasPermission(player, Permissions.PERM_OPENINV)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
player.performCommand("openinv");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.lishid.openinv;
|
||||
|
||||
public class Permissions
|
||||
{
|
||||
public class Permissions {
|
||||
public static final String PERM_OPENINV = "OpenInv.openinv";
|
||||
public static final String PERM_OVERRIDE = "OpenInv.override";
|
||||
public static final String PERM_EXEMPT = "OpenInv.exempt";
|
||||
|
|
|
@ -4,28 +4,29 @@ import java.io.File;
|
|||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import com.lishid.openinv.utils.Updater.UpdateResult;
|
||||
import com.lishid.openinv.utils.Updater.UpdateType;
|
||||
|
||||
public class UpdateManager
|
||||
{
|
||||
public class UpdateManager {
|
||||
public Updater updater;
|
||||
|
||||
public void Initialize(OpenInv plugin, File file)
|
||||
{
|
||||
updater = new Updater(plugin, OpenInv.logger, "openinv", file);
|
||||
|
||||
|
||||
public void Initialize(OpenInv plugin, File file) {
|
||||
updater = new Updater(plugin, 31432, file);
|
||||
|
||||
// Create task to update
|
||||
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable()
|
||||
{
|
||||
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
public void run() {
|
||||
// Check for updates
|
||||
if (OpenInv.GetCheckForUpdates())
|
||||
{
|
||||
UpdateResult result = updater.update(UpdateType.DEFAULT);
|
||||
if (result != UpdateResult.NO_UPDATE)
|
||||
OpenInv.log(result.toString());
|
||||
if (OpenInv.GetCheckForUpdates()) {
|
||||
UpdateResult result = updater.update();
|
||||
if (result != UpdateResult.NO_UPDATE) {
|
||||
if (result == UpdateResult.SUCCESS) {
|
||||
OpenInv.log("Update found! Downloaded new version.");
|
||||
OpenInv.log("This behaviour can be disabled in the config.yml");
|
||||
}
|
||||
else {
|
||||
OpenInv.log("Update failed, reason: " + result.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0, 20 * 60 * 1000); // Update every once a while
|
||||
|
|
|
@ -1,570 +1,412 @@
|
|||
/*
|
||||
* Updater for Bukkit.
|
||||
*
|
||||
* This class provides the means to safely and easily update a plugin, or check to see if it is updated using dev.bukkit.org
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
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.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import java.util.Enumeration;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
/**
|
||||
* Check dev.bukkit.org to find updates for a given plugin, and download the updates if needed.
|
||||
* <p>
|
||||
* <p/>
|
||||
* <b>VERY, VERY IMPORTANT</b>: Because there are no standards for adding auto-update toggles in your plugin's config, this system provides NO CHECK WITH YOUR CONFIG to make sure the user has allowed
|
||||
* auto-updating. <br>
|
||||
* It is a <b>BUKKIT POLICY</b> that you include a boolean value in your config that prevents the auto-updater from running <b>AT ALL</b>. <br>
|
||||
* If you fail to include this option in your config, your plugin will be <b>REJECTED</b> when you attempt to submit it to dev.bukkit.org.
|
||||
* <p>
|
||||
* <p/>
|
||||
* An example of a good configuration option would be something similar to 'auto-update: true' - if this value is set to false you may NOT run the auto-updater. <br>
|
||||
* If you are unsure about these rules, please read the plugin submission guidelines: http://goo.gl/8iU5l
|
||||
*
|
||||
* @author H31IX
|
||||
* @author Gravity
|
||||
* @version 2.0
|
||||
*/
|
||||
|
||||
public class Updater
|
||||
{
|
||||
// If the version number contains one of these, don't update.
|
||||
private static final String[] noUpdateTag = { "test", "unstable" };
|
||||
|
||||
// Slugs will be appended to this to get to the project's RSS feed
|
||||
private static final String DBOUrl = "http://dev.bukkit.org/server-mods/";
|
||||
public class Updater {
|
||||
|
||||
private Plugin plugin;
|
||||
private String versionName;
|
||||
private String versionLink;
|
||||
@SuppressWarnings("unused")
|
||||
private String versionType;
|
||||
@SuppressWarnings("unused")
|
||||
private String versionGameVersion;
|
||||
|
||||
private boolean announce; // Whether to announce file downloads
|
||||
|
||||
private URL url; // Connecting to RSS
|
||||
private File file; // The plugin's file
|
||||
|
||||
private int id = 31432; // Project's Curse ID
|
||||
// SEE https://dev.bukkit.org/home/servermods-apikey/
|
||||
private String apiKey = "853a6cc95ff44c08e19cdb3ef96f4001f049ae7c"; // BukkitDev ServerMods API key
|
||||
private static final String TITLE_VALUE = "name"; // Gets remote file's title
|
||||
private static final String LINK_VALUE = "downloadUrl"; // Gets remote file's download link
|
||||
private static final String TYPE_VALUE = "releaseType"; // Gets remote file's release type
|
||||
private static final String VERSION_VALUE = "gameVersion"; // Gets remote file's build version
|
||||
private static final String QUERY = "/servermods/files?projectIds="; // Path to GET
|
||||
private static final String HOST = "https://api.curseforge.com"; // Slugs will be appended to this to get to the project's RSS feed
|
||||
|
||||
private static final String[] NO_UPDATE_TAG = { "-DEV", "-PRE", "-SNAPSHOT" }; // If the version number contains one of these, don't update.
|
||||
private static final int BYTE_SIZE = 1024; // Used for downloading files
|
||||
|
||||
private final Plugin plugin;
|
||||
private final String slug;
|
||||
|
||||
private volatile long totalSize; // Holds the total size of the file
|
||||
private volatile int sizeLine; // Used for detecting file size
|
||||
private volatile int multiplier; // Used for determining when to broadcast download updates
|
||||
|
||||
private volatile URL url; // Connecting to RSS
|
||||
|
||||
private volatile String updateFolder = YamlConfiguration.loadConfiguration(new File("bukkit.yml")).getString("settings.update-folder"); // The folder that downloads will be placed in
|
||||
|
||||
// Used for determining the outcome of the update process
|
||||
private volatile Updater.UpdateResult result = Updater.UpdateResult.SUCCESS;
|
||||
|
||||
// Whether to announce file downloads
|
||||
private volatile boolean announce = false;
|
||||
|
||||
private volatile UpdateType type;
|
||||
private volatile String versionTitle;
|
||||
private volatile String versionLink;
|
||||
|
||||
private volatile String versionDownloaded = "";
|
||||
private volatile File file;
|
||||
|
||||
// Used to announce progress
|
||||
private volatile Logger logger;
|
||||
|
||||
// Strings for reading RSS
|
||||
private static final String TITLE = "title";
|
||||
private static final String LINK = "link";
|
||||
private static final String ITEM = "item";
|
||||
|
||||
private String updateFolder;// The folder that downloads will be placed in
|
||||
private Updater.UpdateResult result = Updater.UpdateResult.SUCCESS; // Used for determining the outcome of the update process
|
||||
|
||||
/**
|
||||
* Gives the dev the result of the update process. Can be obtained by called getResult().
|
||||
*/
|
||||
public enum UpdateResult
|
||||
{
|
||||
public enum UpdateResult {
|
||||
/**
|
||||
* The updater found an update, and has readied it to be loaded the next time the server restarts/reloads.
|
||||
*/
|
||||
SUCCESS(1, "The updater found an update, and has readied it to be loaded the next time the server restarts/reloads."),
|
||||
|
||||
SUCCESS,
|
||||
/**
|
||||
* The updater did not find an update, and nothing was downloaded.
|
||||
*/
|
||||
NO_UPDATE(2, "The updater did not find an update, and nothing was downloaded."),
|
||||
|
||||
NO_UPDATE,
|
||||
/**
|
||||
* The server administrator has disabled the updating system
|
||||
*/
|
||||
DISABLED,
|
||||
/**
|
||||
* The updater found an update, but was unable to download it.
|
||||
*/
|
||||
FAIL_DOWNLOAD(3, "The updater found an update, but was unable to download it."),
|
||||
|
||||
FAIL_DOWNLOAD,
|
||||
/**
|
||||
* For some reason, the updater was unable to contact dev.bukkit.org to download the file.
|
||||
*/
|
||||
FAIL_DBO(4, "For some reason, the updater was unable to contact dev.bukkit.org to download the file."),
|
||||
|
||||
FAIL_DBO,
|
||||
/**
|
||||
* When running the version check, the file on DBO did not contain the a version in the format 'vVersion' such as 'v1.0'.
|
||||
*/
|
||||
FAIL_NOVERSION(5, "When running the version check, the file on DBO did not contain the a version in the format 'vVersion' such as 'v1.0'."),
|
||||
|
||||
FAIL_NOVERSION,
|
||||
/**
|
||||
* The slug provided by the plugin running the updater was invalid and doesn't exist on DBO.
|
||||
* The id provided by the plugin running the updater was invalid and doesn't exist on DBO.
|
||||
*/
|
||||
FAIL_BADSLUG(6, "The slug provided by the plugin running the updater was invalid and doesn't exist on DBO."),
|
||||
|
||||
FAIL_BADID,
|
||||
/**
|
||||
* The server administrator has improperly configured their API key in the configuration
|
||||
*/
|
||||
FAIL_APIKEY,
|
||||
/**
|
||||
* The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded.
|
||||
*/
|
||||
UPDATE_AVAILABLE(7, "The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded.");
|
||||
|
||||
private static final Map<Integer, Updater.UpdateResult> valueList = new HashMap<Integer, Updater.UpdateResult>();
|
||||
private final int value;
|
||||
private final String description;
|
||||
|
||||
private UpdateResult(int value, String description)
|
||||
{
|
||||
this.value = value;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public static Updater.UpdateResult getResult(int value)
|
||||
{
|
||||
return valueList.get(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
for (Updater.UpdateResult result : Updater.UpdateResult.values())
|
||||
{
|
||||
valueList.put(result.value, result);
|
||||
}
|
||||
}
|
||||
UPDATE_AVAILABLE
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the dev to specify the type of update that will be run.
|
||||
*/
|
||||
public enum UpdateType
|
||||
{
|
||||
/**
|
||||
* Run a version check, and then if the file is out of date, download the newest version.
|
||||
*/
|
||||
DEFAULT(1),
|
||||
/**
|
||||
* Don't run a version check, just find the latest update and download it.
|
||||
*/
|
||||
NO_VERSION_CHECK(2),
|
||||
/**
|
||||
* Get information about the version and the download size, but don't actually download anything.
|
||||
*/
|
||||
NO_DOWNLOAD(3);
|
||||
|
||||
private static final Map<Integer, Updater.UpdateType> valueList = new HashMap<Integer, Updater.UpdateType>();
|
||||
private final int value;
|
||||
|
||||
private UpdateType(int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public static Updater.UpdateType getResult(int value)
|
||||
{
|
||||
return valueList.get(value);
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
for (Updater.UpdateType result : Updater.UpdateType.values())
|
||||
{
|
||||
valueList.put(result.value, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the updater
|
||||
*
|
||||
* @param plugin
|
||||
* The plugin that is checking for an update.
|
||||
* @param slug
|
||||
* The dev.bukkit.org slug of the project (http://dev.bukkit.org/server-mods/SLUG_IS_HERE)
|
||||
* @param file
|
||||
* The file that the plugin is running from, get this by doing this.getFile() from within your main class.
|
||||
* @param permission
|
||||
* Permission needed to read the output of the update process.
|
||||
* @param plugin The plugin that is checking for an update.
|
||||
* @param id The dev.bukkit.org id of the project
|
||||
* @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class.
|
||||
*/
|
||||
public Updater(Plugin plugin, Logger logger, String slug, File file)
|
||||
{
|
||||
// I hate NULL
|
||||
Preconditions.checkNotNull(plugin, "plugin");
|
||||
Preconditions.checkNotNull(logger, "logger");
|
||||
Preconditions.checkNotNull(slug, "slug");
|
||||
Preconditions.checkNotNull(file, "file");
|
||||
|
||||
public Updater(Plugin plugin, int id, File file) {
|
||||
this.plugin = plugin;
|
||||
this.file = file;
|
||||
this.slug = slug;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the plugin.
|
||||
*
|
||||
* @param type
|
||||
* Specify the type of update this will be. See {@link UpdateType}
|
||||
* @return The result of the update process.
|
||||
*/
|
||||
public synchronized UpdateResult update(UpdateType type)
|
||||
{
|
||||
this.type = type;
|
||||
|
||||
try
|
||||
{
|
||||
// Obtain the results of the project's file feed
|
||||
url = null;
|
||||
url = new URL(DBOUrl + slug + "/files.rss");
|
||||
this.id = id;
|
||||
this.updateFolder = plugin.getServer().getUpdateFolder();
|
||||
|
||||
try {
|
||||
this.url = new URL(Updater.HOST + Updater.QUERY + id);
|
||||
}
|
||||
catch (MalformedURLException ex)
|
||||
{
|
||||
// The slug doesn't exist
|
||||
logger.warning("The author of this plugin has misconfigured their Auto Update system");
|
||||
logger.warning("The project slug added ('" + slug + "') is invalid, and does not exist on dev.bukkit.org");
|
||||
result = Updater.UpdateResult.FAIL_BADSLUG; // Bad slug! Bad!
|
||||
catch (final MalformedURLException e) {
|
||||
plugin.getLogger().severe("The project ID provided for updating, " + id + " is invalid.");
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (url != null)
|
||||
{
|
||||
// Obtain the results of the project's file feed
|
||||
readFeed();
|
||||
if (versionTitle != null && !versionTitle.equals(versionDownloaded) && versionCheck(versionTitle))
|
||||
{
|
||||
String fileLink = getFile(versionLink);
|
||||
if (fileLink != null && type != UpdateType.NO_DOWNLOAD)
|
||||
{
|
||||
String name = file.getName();
|
||||
saveFile(new File("plugins/" + updateFolder), name, fileLink);
|
||||
versionDownloaded = versionTitle;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = UpdateResult.UPDATE_AVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of the update process.
|
||||
*/
|
||||
public Updater.UpdateResult getResult()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total bytes of the file (can only be used after running a version check or a normal run).
|
||||
*/
|
||||
public long getFileSize()
|
||||
{
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version string latest file avaliable online.
|
||||
*/
|
||||
public String getLatestVersionString()
|
||||
{
|
||||
return versionTitle;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save an update from dev.bukkit.org into the server's update folder.
|
||||
*/
|
||||
private void saveFile(File folder, String file, String u)
|
||||
{
|
||||
if (!folder.exists())
|
||||
{
|
||||
private void saveFile(File folder, String file, String u) {
|
||||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
BufferedInputStream in = null;
|
||||
FileOutputStream fout = null;
|
||||
try
|
||||
{
|
||||
try {
|
||||
// Download the file
|
||||
URL url = new URL(u);
|
||||
int fileLength = url.openConnection().getContentLength();
|
||||
final URL url = new URL(u);
|
||||
final int fileLength = url.openConnection().getContentLength();
|
||||
in = new BufferedInputStream(url.openStream());
|
||||
fout = new FileOutputStream(folder.getAbsolutePath() + "/" + file);
|
||||
|
||||
byte[] data = new byte[BYTE_SIZE];
|
||||
|
||||
final byte[] data = new byte[Updater.BYTE_SIZE];
|
||||
int count;
|
||||
if (announce)
|
||||
logger.info("About to download a new update: " + versionTitle);
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("About to download a new update: " + this.versionName);
|
||||
}
|
||||
long downloaded = 0;
|
||||
while ((count = in.read(data, 0, BYTE_SIZE)) != -1)
|
||||
{
|
||||
while ((count = in.read(data, 0, Updater.BYTE_SIZE)) != -1) {
|
||||
downloaded += count;
|
||||
fout.write(data, 0, count);
|
||||
int percent = (int) (downloaded * 100 / fileLength);
|
||||
if (announce && (percent % 10 == 0))
|
||||
{
|
||||
logger.info("Downloading update: " + percent + "% of " + fileLength + " bytes.");
|
||||
final int percent = (int) ((downloaded * 100) / fileLength);
|
||||
if (this.announce && ((percent % 10) == 0)) {
|
||||
this.plugin.getLogger().info("Downloading update: " + percent + "% of " + fileLength + " bytes.");
|
||||
}
|
||||
}
|
||||
|
||||
if (announce)
|
||||
logger.info("Finished updating.");
|
||||
// Just a quick check to make sure we didn't leave any files from last time...
|
||||
for (final File xFile : new File(this.plugin.getDataFolder().getParent(), this.updateFolder).listFiles()) {
|
||||
if (xFile.getName().endsWith(".zip")) {
|
||||
xFile.delete();
|
||||
}
|
||||
}
|
||||
// Check to see if it's a zip file, if it is, unzip it.
|
||||
final File dFile = new File(folder.getAbsolutePath() + "/" + file);
|
||||
if (dFile.getName().endsWith(".zip")) {
|
||||
// Unzip
|
||||
this.unzip(dFile.getCanonicalPath());
|
||||
}
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("Finished updating.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.warning("The auto-updater tried to download a new update, but was unsuccessful.");
|
||||
logger.log(Level.INFO, "Error message to submit as a ticket.", ex);
|
||||
result = Updater.UpdateResult.FAIL_DOWNLOAD;
|
||||
catch (final Exception ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to download a new update, but was unsuccessful.");
|
||||
this.result = Updater.UpdateResult.FAIL_DOWNLOAD;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (in != null)
|
||||
{
|
||||
finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (fout != null)
|
||||
{
|
||||
if (fout != null) {
|
||||
fout.close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
catch (final Exception ex) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Part of Zip-File-Extractor, modified by Gravity for use with Bukkit
|
||||
*/
|
||||
private void unzip(String file) {
|
||||
try {
|
||||
final File fSourceZip = new File(file);
|
||||
final String zipPath = file.substring(0, file.length() - 4);
|
||||
ZipFile zipFile = new ZipFile(fSourceZip);
|
||||
Enumeration<? extends ZipEntry> e = zipFile.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
ZipEntry entry = e.nextElement();
|
||||
File destinationFilePath = new File(zipPath, entry.getName());
|
||||
destinationFilePath.getParentFile().mkdirs();
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
final BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
|
||||
int b;
|
||||
final byte buffer[] = new byte[Updater.BYTE_SIZE];
|
||||
final FileOutputStream fos = new FileOutputStream(destinationFilePath);
|
||||
final BufferedOutputStream bos = new BufferedOutputStream(fos, Updater.BYTE_SIZE);
|
||||
while ((b = bis.read(buffer, 0, Updater.BYTE_SIZE)) != -1) {
|
||||
bos.write(buffer, 0, b);
|
||||
}
|
||||
bos.flush();
|
||||
bos.close();
|
||||
bis.close();
|
||||
final String name = destinationFilePath.getName();
|
||||
if (name.endsWith(".jar") && this.pluginFile(name)) {
|
||||
destinationFilePath.renameTo(new File(this.plugin.getDataFolder().getParent(), this.updateFolder + "/" + name));
|
||||
}
|
||||
}
|
||||
entry = null;
|
||||
destinationFilePath = null;
|
||||
}
|
||||
e = null;
|
||||
zipFile.close();
|
||||
zipFile = null;
|
||||
|
||||
// Move any plugin data folders that were included to the right place, Bukkit won't do this for us.
|
||||
for (final File dFile : new File(zipPath).listFiles()) {
|
||||
if (dFile.isDirectory()) {
|
||||
if (this.pluginFile(dFile.getName())) {
|
||||
final File oFile = new File(this.plugin.getDataFolder().getParent(), dFile.getName()); // Get current dir
|
||||
final File[] contents = oFile.listFiles(); // List of existing files in the current dir
|
||||
for (final File cFile : dFile.listFiles()) // Loop through all the files in the new dir
|
||||
{
|
||||
boolean found = false;
|
||||
for (final File xFile : contents) // Loop through contents to see if it exists
|
||||
{
|
||||
if (xFile.getName().equals(cFile.getName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Move the new file into the current dir
|
||||
cFile.renameTo(new File(oFile.getCanonicalFile() + "/" + cFile.getName()));
|
||||
}
|
||||
else {
|
||||
// This file already exists, so we don't need it anymore.
|
||||
cFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dFile.delete();
|
||||
}
|
||||
new File(zipPath).delete();
|
||||
fSourceZip.delete();
|
||||
}
|
||||
catch (final IOException ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to unzip a new update file, but was unsuccessful.");
|
||||
this.result = Updater.UpdateResult.FAIL_DOWNLOAD;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
new File(file).delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the name of a jar is one of the plugins currently installed, used for extracting the correct files out of a zip.
|
||||
*/
|
||||
public boolean pluginFile(String name)
|
||||
{
|
||||
for (File file : new File("plugins").listFiles())
|
||||
{
|
||||
if (file.getName().equals(name))
|
||||
{
|
||||
private boolean pluginFile(String name) {
|
||||
for (final File file : new File("plugins").listFiles()) {
|
||||
if (file.getName().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the direct download file url from the file's page.
|
||||
*/
|
||||
private String getFile(String link)
|
||||
{
|
||||
String download = null;
|
||||
try
|
||||
{
|
||||
// Open a connection to the page
|
||||
URL url = new URL(link);
|
||||
URLConnection urlConn = url.openConnection();
|
||||
InputStreamReader inStream = new InputStreamReader(urlConn.getInputStream());
|
||||
BufferedReader buff = new BufferedReader(inStream);
|
||||
|
||||
int counter = 0;
|
||||
String line;
|
||||
while ((line = buff.readLine()) != null)
|
||||
{
|
||||
counter++;
|
||||
// Search for the download link
|
||||
if (line.contains("<li class=\"user-action user-action-download\">"))
|
||||
{
|
||||
// Get the raw link
|
||||
download = line.split("<a href=\"")[1].split("\">Download</a>")[0];
|
||||
}
|
||||
// Search for size
|
||||
else if (line.contains("<dt>Size</dt>"))
|
||||
{
|
||||
sizeLine = counter + 1;
|
||||
}
|
||||
else if (counter == sizeLine)
|
||||
{
|
||||
String size = line.replaceAll("<dd>", "").replaceAll("</dd>", "");
|
||||
multiplier = size.contains("MiB") ? 1048576 : 1024;
|
||||
size = size.replace(" KiB", "").replace(" MiB", "");
|
||||
totalSize = (long) (Double.parseDouble(size) * multiplier);
|
||||
}
|
||||
}
|
||||
urlConn = null;
|
||||
inStream = null;
|
||||
buff.close();
|
||||
buff = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
logger.warning("The auto-updater tried to contact dev.bukkit.org, but was unsuccessful.");
|
||||
result = Updater.UpdateResult.FAIL_DBO;
|
||||
return null;
|
||||
}
|
||||
return download;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check to see if the program should continue by evaluation whether the plugin is already updated, or shouldn't be updated
|
||||
*/
|
||||
private boolean versionCheck(String title)
|
||||
{
|
||||
if (type != UpdateType.NO_VERSION_CHECK)
|
||||
{
|
||||
String[] parts = title.split(" ");
|
||||
String version = plugin.getDescription().getVersion();
|
||||
|
||||
if (parts.length >= 2)
|
||||
{
|
||||
String remoteVersion = parts[1].split(" ")[0]; // Get the newest file's version number
|
||||
int remVer = -1, curVer = 0;
|
||||
try
|
||||
{
|
||||
remVer = calVer(remoteVersion);
|
||||
curVer = calVer(version);
|
||||
}
|
||||
catch (NumberFormatException nfe)
|
||||
{
|
||||
remVer = -1;
|
||||
}
|
||||
|
||||
if (hasTag(version) || version.equalsIgnoreCase(remoteVersion) || curVer >= remVer)
|
||||
{
|
||||
// We already have the latest version, or this build is tagged for no-update
|
||||
result = Updater.UpdateResult.NO_UPDATE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The file's name did not contain the string 'vVersion'
|
||||
logger.warning("The author of this plugin has misconfigured their Auto Update system");
|
||||
logger.warning("Files uploaded to BukkitDev should contain the version number, seperated from the name by a 'v', such as PluginName v1.0");
|
||||
logger.warning("Please notify the author (" + plugin.getDescription().getAuthors().get(0) + ") of this error.");
|
||||
result = Updater.UpdateResult.FAIL_NOVERSION;
|
||||
private boolean versionCheck(String title) {
|
||||
final String version = this.plugin.getDescription().getVersion();
|
||||
if (title.split(" ").length == 2) {
|
||||
final String remoteVersion = title.split(" ")[1].split(" ")[0]; // Get the newest file's version number
|
||||
|
||||
if (this.hasTag(version) || version.equalsIgnoreCase(remoteVersion) || !isNewer(version, remoteVersion)) {
|
||||
// We already have the latest version, or this build is tagged for no-update
|
||||
this.result = Updater.UpdateResult.NO_UPDATE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.plugin.getLogger().warning("File versions should follow the format 'PluginName VERSION'");
|
||||
this.result = Updater.UpdateResult.FAIL_NOVERSION;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to calculate the version string as an Integer
|
||||
*/
|
||||
private Integer calVer(String s) throws NumberFormatException
|
||||
{
|
||||
if (s.contains("."))
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++)
|
||||
{
|
||||
Character c = s.charAt(i);
|
||||
if (Character.isLetterOrDigit(c))
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return Integer.parseInt(sb.toString());
|
||||
}
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate whether the version number is marked showing that it should not be updated by this program
|
||||
*/
|
||||
private boolean hasTag(String version)
|
||||
{
|
||||
for (String string : noUpdateTag)
|
||||
{
|
||||
if (version.contains(string))
|
||||
{
|
||||
private boolean hasTag(String version) {
|
||||
for (final String string : Updater.NO_UPDATE_TAG) {
|
||||
if (version.contains(string)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of RSS Reader by Vogella, modified by H31IX for use with Bukkit
|
||||
*/
|
||||
private void readFeed()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Set header values intial to the empty string
|
||||
String title = "";
|
||||
String link = "";
|
||||
// First create a new XMLInputFactory
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
// Setup a new eventReader
|
||||
InputStream in = read();
|
||||
XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
|
||||
// Read the XML document
|
||||
while (eventReader.hasNext())
|
||||
{
|
||||
XMLEvent event = eventReader.nextEvent();
|
||||
if (event.isStartElement())
|
||||
{
|
||||
if (event.asStartElement().getName().getLocalPart().equals(TITLE))
|
||||
{
|
||||
event = eventReader.nextEvent();
|
||||
title = event.asCharacters().getData();
|
||||
continue;
|
||||
}
|
||||
if (event.asStartElement().getName().getLocalPart().equals(LINK))
|
||||
{
|
||||
event = eventReader.nextEvent();
|
||||
link = event.asCharacters().getData();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (event.isEndElement())
|
||||
{
|
||||
if (event.asEndElement().getName().getLocalPart().equals(ITEM))
|
||||
{
|
||||
// Store the title and link of the first entry we get - the first file on the list is all we need
|
||||
versionTitle = title;
|
||||
versionLink = link;
|
||||
// All done, we don't need to know about older files.
|
||||
break;
|
||||
|
||||
private boolean read() {
|
||||
try {
|
||||
final URLConnection conn = this.url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
|
||||
if (this.apiKey != null) {
|
||||
conn.addRequestProperty("X-API-Key", this.apiKey);
|
||||
}
|
||||
conn.addRequestProperty("User-Agent", "Updater");
|
||||
|
||||
conn.setDoOutput(true);
|
||||
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
final String response = reader.readLine();
|
||||
|
||||
final JSONArray array = (JSONArray) JSONValue.parse(response);
|
||||
|
||||
if (array.size() == 0) {
|
||||
this.plugin.getLogger().warning("The updater could not find any files for the project id " + this.id);
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.versionName = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.TITLE_VALUE);
|
||||
this.versionLink = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.LINK_VALUE);
|
||||
this.versionType = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.TYPE_VALUE);
|
||||
this.versionGameVersion = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.VERSION_VALUE);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (final IOException e) {
|
||||
if (e.getMessage().contains("HTTP response code: 403")) {
|
||||
this.plugin.getLogger().warning("dev.bukkit.org rejected the API key provided in plugins/Updater/config.yml");
|
||||
this.plugin.getLogger().warning("Please double-check your configuration to ensure it is correct.");
|
||||
this.result = UpdateResult.FAIL_APIKEY;
|
||||
}
|
||||
else {
|
||||
this.plugin.getLogger().warning("The updater could not contact curse for updating.");
|
||||
this.result = UpdateResult.FAIL_DBO;
|
||||
}
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isNewer(String oldVers, String newVers) {
|
||||
String s1 = normalisedVersion(oldVers);
|
||||
String s2 = normalisedVersion(newVers);
|
||||
int cmp = s1.compareTo(s2);
|
||||
return cmp < 0;
|
||||
}
|
||||
|
||||
public static String normalisedVersion(String version) {
|
||||
return normalisedVersion(version, ".", 3);
|
||||
}
|
||||
|
||||
public static String normalisedVersion(String version, String sep, int maxWidth) {
|
||||
String[] split = Pattern.compile(sep, Pattern.LITERAL).split(version);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String s : split) {
|
||||
sb.append(String.format("%" + maxWidth + 's', s));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public UpdateResult update() {
|
||||
if (Updater.this.url != null) {
|
||||
// Obtain the results of the project's file feed
|
||||
if (Updater.this.read()) {
|
||||
if (Updater.this.versionCheck(Updater.this.versionName)) {
|
||||
if (Updater.this.versionLink != null) {
|
||||
String name = Updater.this.file.getName();
|
||||
// If it's a zip file, it shouldn't be downloaded as the plugin's name
|
||||
if (Updater.this.versionLink.endsWith(".zip")) {
|
||||
final String[] split = Updater.this.versionLink.split("/");
|
||||
name = split[split.length - 1];
|
||||
}
|
||||
Updater.this.saveFile(new File(Updater.this.plugin.getDataFolder().getParent(), Updater.this.updateFolder), name, Updater.this.versionLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the RSS feed
|
||||
*/
|
||||
private InputStream read()
|
||||
{
|
||||
try
|
||||
{
|
||||
return url.openStream();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this.result;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue