diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/WorkListener.java b/EssentialsUpdate/src/com/earth2me/essentials/update/AbstractWorkListener.java similarity index 80% rename from EssentialsUpdate/src/com/earth2me/essentials/update/WorkListener.java rename to EssentialsUpdate/src/com/earth2me/essentials/update/AbstractWorkListener.java index da6bdb978..487e372c8 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/WorkListener.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/AbstractWorkListener.java @@ -1,12 +1,11 @@ package com.earth2me.essentials.update; -import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; -public abstract class WorkListener +public abstract class AbstractWorkListener { - public WorkListener(final Plugin plugin, final VersionInfo newVersionInfo) + public AbstractWorkListener(final Plugin plugin, final VersionInfo newVersionInfo) { this.plugin = plugin; this.newVersionInfo = newVersionInfo; diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/EssentialsHelp.java b/EssentialsUpdate/src/com/earth2me/essentials/update/EssentialsHelp.java index 3caa22cc3..ec62566ca 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/EssentialsHelp.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/EssentialsHelp.java @@ -1,16 +1,16 @@ package com.earth2me.essentials.update; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.Charset; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.bukkit.Bukkit; +import com.earth2me.essentials.update.chat.Command; +import com.earth2me.essentials.update.chat.ConfigCommand; +import com.earth2me.essentials.update.chat.ErrorsCommand; +import com.earth2me.essentials.update.chat.HelpCommand; +import com.earth2me.essentials.update.chat.IrcBot; +import com.earth2me.essentials.update.chat.ListCommand; +import com.earth2me.essentials.update.chat.StartupCommand; +import com.earth2me.essentials.update.chat.UsernameUtil; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -21,7 +21,6 @@ import org.bukkit.event.player.PlayerListener; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginManager; -import org.jibble.pircbot.User; public class EssentialsHelp extends PlayerListener @@ -29,14 +28,19 @@ public class EssentialsHelp extends PlayerListener private transient Player chatUser; private final transient Server server; private final transient Plugin plugin; - private final static Charset UTF8 = Charset.forName("utf-8"); private transient IrcBot ircBot; + private final transient Map commands = new HashMap(); public EssentialsHelp(final Plugin plugin) { super(); this.plugin = plugin; this.server = plugin.getServer(); + commands.put("!help", new HelpCommand()); + commands.put("!list", new ListCommand()); + commands.put("!startup", new StartupCommand(plugin)); + commands.put("!errors", new ErrorsCommand(plugin)); + commands.put("!config", new ConfigCommand(plugin)); } public void registerEvents() @@ -46,7 +50,7 @@ public class EssentialsHelp extends PlayerListener pluginManager.registerEvent(Type.PLAYER_CHAT, this, Priority.Low, plugin); } - public void onCommand(CommandSender sender) + public void onCommand(final CommandSender sender) { if (sender instanceof Player && sender.hasPermission("essentials.helpchat")) { @@ -74,11 +78,7 @@ public class EssentialsHelp extends PlayerListener public void onDisable() { - if ( ircBot != null) - { - ircBot.quit(); - ircBot = null; - } + closeConnection(); } private boolean sendChatMessage(final Player player, final String message) @@ -90,35 +90,19 @@ public class EssentialsHelp extends PlayerListener } if (ircBot == null) { - if (messageCleaned.equalsIgnoreCase("yes")) - { - player.sendMessage("Connecting..."); - connectToIRC(player); - return true; - } - if (messageCleaned.equalsIgnoreCase("no") || message.equalsIgnoreCase("!quit")) - { - chatUser = null; - return true; - } - return false; + return handleAnswer(messageCleaned, player); } else { - if (ircBot.isKicked()) { - chatUser = null; - ircBot.quit(); - ircBot = null; + if (ircBot.isKicked()) + { + closeConnection(); return false; } - final String lowMessage = messageCleaned.toLowerCase(); + final String lowMessage = messageCleaned.toLowerCase(Locale.ENGLISH); if (lowMessage.startsWith("!quit")) { - chatUser = null; - if (ircBot != null) { - ircBot.quit(); - ircBot = null; - } + closeConnection(); player.sendMessage("Connection closed."); return true; } @@ -126,52 +110,8 @@ public class EssentialsHelp extends PlayerListener { return false; } - if (lowMessage.startsWith("!list")) + if (handleCommands(lowMessage, player)) { - final User[] members = ircBot.getUsers(); - final StringBuilder sb = new StringBuilder(); - for (User user : members) - { - if (sb.length() > 0) - { - sb.append("§f, "); - } - if (user.isOp() || user.hasVoice()) - { - sb.append("§6"); - } - else - { - sb.append("§7"); - } - sb.append(user.getPrefix()).append(user.getNick()); - } - player.sendMessage(sb.toString()); - return true; - } - if (lowMessage.startsWith("!help")) - { - player.sendMessage("Commands: (Note: Files send to the chat will be public viewable.)"); - player.sendMessage("!errors - Send the last server errors to the chat."); - player.sendMessage("!startup - Send the last startup messages to the chat."); - player.sendMessage("!config - Sends your Essentials config to the chat."); - player.sendMessage("!list - List all players in chat."); - player.sendMessage("!quit - Leave chat."); - return true; - } - if (lowMessage.startsWith("!errors")) - { - sendErrors(); - return true; - } - if (lowMessage.startsWith("!startup")) - { - sendStartup(); - return true; - } - if (lowMessage.startsWith("!config")) - { - sendConfig(); return true; } ircBot.sendMessage(messageCleaned); @@ -180,300 +120,62 @@ public class EssentialsHelp extends PlayerListener } } - private String buildIrcName() + private void closeConnection() { - final StringBuilder nameBuilder = new StringBuilder(); - nameBuilder.append(chatUser.getName()); - - final Matcher versionMatch = Pattern.compile("git-Bukkit-([0-9]+).([0-9]+).([0-9]+)-[0-9]+-[0-9a-z]+-b([0-9]+)jnks.*").matcher(server.getVersion()); - if (versionMatch.matches()) + chatUser = null; + if (ircBot != null) { - nameBuilder.append(" CB"); - nameBuilder.append(versionMatch.group(4)); + ircBot.quit(); + ircBot = null; } + } - final Plugin essentials = server.getPluginManager().getPlugin("Essentials"); - if (essentials != null) + private boolean handleAnswer(final String message, final Player player) + { + if (message.equalsIgnoreCase("yes")) { - nameBuilder.append(" ESS"); - nameBuilder.append(essentials.getDescription().getVersion()); + player.sendMessage("Connecting..."); + connectToIRC(player); + return true; } - - final Plugin groupManager = server.getPluginManager().getPlugin("GroupManager"); - if (groupManager != null) + if (message.equalsIgnoreCase("no") || message.equalsIgnoreCase("!quit")) { - nameBuilder.append(" GM"); - if (!groupManager.isEnabled()) - { - nameBuilder.append('!'); - } + chatUser = null; + return true; } + return false; + } - final Plugin pex = server.getPluginManager().getPlugin("PermissionsEx"); - if (pex != null) + private boolean handleCommands(final String lowMessage, final Player player) + { + final String[] parts = lowMessage.split(" "); + if (commands.containsKey(parts[0])) { - nameBuilder.append(" PEX"); - if (!pex.isEnabled()) - { - nameBuilder.append('!'); - } - nameBuilder.append(pex.getDescription().getVersion()); + commands.get(parts[0]).run(ircBot, player); + return true; } - - final Plugin pb = server.getPluginManager().getPlugin("PermissionsBukkit"); - if (pb != null) - { - nameBuilder.append(" PB"); - if (!pb.isEnabled()) - { - nameBuilder.append('!'); - } - nameBuilder.append(pb.getDescription().getVersion()); - } - - final Plugin bp = server.getPluginManager().getPlugin("bPermissions"); - if (bp != null) - { - nameBuilder.append(" BP"); - if (!bp.isEnabled()) - { - nameBuilder.append('!'); - } - nameBuilder.append(bp.getDescription().getVersion()); - } - - final Plugin perm = server.getPluginManager().getPlugin("Permissions"); - if (perm != null) - { - nameBuilder.append(" P"); - if (!perm.isEnabled()) - { - nameBuilder.append('!'); - } - nameBuilder.append(perm.getDescription().getVersion()); - } - - return nameBuilder.toString(); + return false; } private void connectToIRC(final Player player) { - ircBot = new IrcBot(player, "Ess_" + player.getName(), buildIrcName()); - } - - private void sendErrors() - { - BufferedReader page = null; - try - { - File bukkitFolder = plugin.getDataFolder().getAbsoluteFile().getParentFile().getParentFile(); - if (bukkitFolder == null || !bukkitFolder.exists()) - { - chatUser.sendMessage("Bukkit folder not found."); - return; - } - File logFile = new File(bukkitFolder, "server.log"); - if (!logFile.exists()) - { - chatUser.sendMessage("Server log not found."); - return; - } - FileInputStream fis = new FileInputStream(logFile); - if (logFile.length() > 1000000) - { - fis.skip(logFile.length() - 1000000); - } - page = new BufferedReader(new InputStreamReader(fis)); - final StringBuilder input = new StringBuilder(); - String line; - Pattern pattern = Pattern.compile("^[0-9 :-]+\\[INFO\\].*"); - while ((line = page.readLine()) != null) - { - if (!pattern.matcher(line).matches()) - { - input.append(line).append("\n"); - } - } - if (input.length() > 10000) - { - input.delete(0, input.length() - 10000); - } - final PastieUpload pastie = new PastieUpload(); - final String url = pastie.send(input.toString()); - String message = "Errors: " + url; - chatUser.sendMessage("§6" + ircBot.getNick() + ": §7" + message); - ircBot.sendMessage(message); - } - catch (IOException ex) - { - Bukkit.getLogger().log(Level.SEVERE, null, ex); - chatUser.sendMessage(ex.getMessage()); - } - finally - { - try - { - if (page != null) - { - page.close(); - } - } - catch (IOException ex) - { - Logger.getLogger(EssentialsHelp.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - private void sendStartup() - { - BufferedReader page = null; - try - { - File bukkitFolder = plugin.getDataFolder().getAbsoluteFile().getParentFile().getParentFile(); - if (bukkitFolder == null || !bukkitFolder.exists()) - { - chatUser.sendMessage("Bukkit folder not found."); - return; - } - File logFile = new File(bukkitFolder, "server.log"); - if (!logFile.exists()) - { - chatUser.sendMessage("Server log not found."); - return; - } - FileInputStream fis = new FileInputStream(logFile); - if (logFile.length() > 1000000) - { - fis.skip(logFile.length() - 1000000); - } - page = new BufferedReader(new InputStreamReader(fis)); - final StringBuilder input = new StringBuilder(); - String line; - Pattern patternStart = Pattern.compile("^[0-9 :-]+\\[INFO\\] Starting minecraft server version.*"); - Pattern patternEnd = Pattern.compile("^[0-9 :-]+\\[INFO\\] Done \\([0-9.,]+s\\)! For help, type \"help\".*"); - boolean log = false; - while ((line = page.readLine()) != null) - { - if (patternStart.matcher(line).matches()) - { - if (input.length() > 0) - { - input.delete(0, input.length()); - } - log = true; - } - if (log) - { - input.append(line).append("\n"); - } - if (patternEnd.matcher(line).matches()) - { - log = false; - } - } - if (input.length() > 10000) - { - input.delete(0, input.length() - 10000); - } - final PastieUpload pastie = new PastieUpload(); - final String url = pastie.send(input.toString()); - String message = "Startup: " + url; - chatUser.sendMessage("§6" + ircBot.getNick() + ": §7" + message); - ircBot.sendMessage(message); - } - catch (IOException ex) - { - Bukkit.getLogger().log(Level.SEVERE, null, ex); - chatUser.sendMessage(ex.getMessage()); - } - finally - { - try - { - if (page != null) - { - page.close(); - } - } - catch (IOException ex) - { - Logger.getLogger(EssentialsHelp.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - private void sendConfig() - { - BufferedReader page = null; - try - { - File configFolder = new File(plugin.getDataFolder().getParentFile(), "Essentials"); - if (!configFolder.exists()) - { - chatUser.sendMessage("Essentials plugin folder not found."); - return; - } - File configFile = new File(configFolder, "config.yml"); - if (!configFile.exists()) - { - chatUser.sendMessage("Essentials config file not found."); - return; - } - page = new BufferedReader(new InputStreamReader(new FileInputStream(configFile), UTF8)); - final StringBuilder input = new StringBuilder(); - String line; - while ((line = page.readLine()) != null) - { - input.append(line).append("\n"); - } - final PastieUpload pastie = new PastieUpload(); - final String url = pastie.send(input.toString()); - String message = "Essentials config.yml: " + url; - chatUser.sendMessage("§6" + ircBot.getNick() + ": §7" + message); - ircBot.sendMessage(message); - - } - catch (IOException ex) - { - Bukkit.getLogger().log(Level.SEVERE, null, ex); - chatUser.sendMessage(ex.getMessage()); - } - finally - { - try - { - if (page != null) - { - page.close(); - } - } - catch (IOException ex) - { - Logger.getLogger(EssentialsHelp.class.getName()).log(Level.SEVERE, null, ex); - } - } + ircBot = new IrcBot(player, "Ess_" + player.getName(), UsernameUtil.createUsername(player)); } @Override - public void onPlayerChat(PlayerChatEvent event) + public void onPlayerChat(final PlayerChatEvent event) { if (event.getPlayer() == chatUser) { - boolean success = sendChatMessage(event.getPlayer(), event.getMessage()); + final boolean success = sendChatMessage(event.getPlayer(), event.getMessage()); event.setCancelled(success); return; } } @Override - public void onPlayerQuit(PlayerQuitEvent event) + public void onPlayerQuit(final PlayerQuitEvent event) { - chatUser = null; - if (ircBot != null) { - ircBot.quit(); - ircBot = null; - } - return; + closeConnection(); } } diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/EssentialsUpdate.java b/EssentialsUpdate/src/com/earth2me/essentials/update/EssentialsUpdate.java index d4ee6c0fc..98dbeb2ef 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/EssentialsUpdate.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/EssentialsUpdate.java @@ -1,6 +1,7 @@ package com.earth2me.essentials.update; import com.earth2me.essentials.update.UpdateCheck.CheckResult; +import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -16,26 +17,20 @@ public class EssentialsUpdate extends JavaPlugin public void onEnable() { if (!getDataFolder().exists() && !getDataFolder().mkdirs() ) { - Bukkit.getLogger().severe("Could not create data folder:"+getDataFolder().getPath()); + Bukkit.getLogger().log(Level.SEVERE, "Could not create data folder: {0}", getDataFolder().getPath()); } essentialsHelp = new EssentialsHelp(this); essentialsHelp.registerEvents(); final UpdateCheck updateCheck = new UpdateCheck(this); + updateCheck.checkForUpdates(); updateProcess = new UpdateProcess(this, updateCheck); updateProcess.registerEvents(); - Bukkit.getLogger().info("EssentialsUpdate " + getDescription().getVersion() + " loaded."); + Bukkit.getLogger().log(Level.INFO, "EssentialsUpdate {0} loaded.", getDescription().getVersion()); if (updateCheck.isEssentialsInstalled()) { - updateCheck.checkForUpdates(); - final Version myVersion = new Version(getDescription().getVersion()); - if (updateCheck.getResult() == CheckResult.NEW_ESS && myVersion.equals(updateCheck.getNewVersion())) - { - Bukkit.getLogger().info("Versions of EssentialsUpdate and Essentials do not match. Starting automatic update."); - updateProcess.doAutomaticUpdate(); - } updateCheck.scheduleUpdateTask(); } else diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/GetFile.java b/EssentialsUpdate/src/com/earth2me/essentials/update/GetFile.java index 8727d2f3b..b48d95dd2 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/GetFile.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/GetFile.java @@ -12,7 +12,8 @@ import java.net.URL; import java.net.URLConnection; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.logging.Logger; +import java.util.logging.Level; +import org.bukkit.Bukkit; public class GetFile @@ -53,7 +54,7 @@ public class GetFile } catch (NoSuchAlgorithmException ex) { - // Ignore because the code is never called + throw new RuntimeException(ex); } } @@ -101,7 +102,7 @@ public class GetFile } if (brokenFile && !file.delete()) { - Logger.getLogger("Minecraft").severe("Could not delete file " + file.getPath()); + Bukkit.getLogger().log(Level.SEVERE, "Could not delete file {0}", file.getPath()); } } finally diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateCheck.java b/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateCheck.java index dcda252a0..29afc4d3f 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateCheck.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateCheck.java @@ -3,7 +3,6 @@ package com.earth2me.essentials.update; import java.io.File; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bukkit.Bukkit; @@ -22,7 +21,7 @@ public class UpdateCheck private final transient Plugin plugin; private transient boolean essentialsInstalled; - public UpdateCheck(Plugin plugin) + public UpdateCheck(final Plugin plugin) { this.plugin = plugin; updateFile = new UpdateFile(plugin); @@ -31,21 +30,20 @@ public class UpdateCheck private void checkForEssentials() { - PluginManager pm = plugin.getServer().getPluginManager(); - Plugin essentials = pm.getPlugin("Essentials"); - if (essentials == null) + final PluginManager pluginManager = plugin.getServer().getPluginManager(); + final Plugin essentials = pluginManager.getPlugin("Essentials"); + essentialsInstalled = essentials != null; + if (essentialsInstalled) + { + currentVersion = new Version(essentials.getDescription().getVersion()); + } + else { - essentialsInstalled = false; if (new File(plugin.getDataFolder().getParentFile(), "Essentials.jar").exists()) { Bukkit.getLogger().severe("Essentials.jar found, but not recognized by Bukkit. Broken download?"); } } - else - { - essentialsInstalled = true; - currentVersion = new Version(essentials.getDescription().getVersion()); - } } public void scheduleUpdateTask() @@ -71,16 +69,17 @@ public class UpdateCheck return result; } - int getNewBukkitVersion() + public int getNewBukkitVersion() { return bukkitResult; } - VersionInfo getNewVersionInfo() + public VersionInfo getNewVersionInfo() { return updateFile.getVersions().get(newVersion); } + public enum CheckResult { NEW_ESS, NEW_ESS_BUKKIT, NEW_BUKKIT, OK, UNKNOWN diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateFile.java b/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateFile.java index 8f34bffc4..95ef5e64e 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateFile.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateFile.java @@ -14,13 +14,14 @@ import java.util.Map; import java.util.TreeMap; import java.util.logging.Level; import java.util.logging.Logger; +import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.bukkit.configuration.file.YamlConfiguration; public class UpdateFile { - private final static Logger LOGGER = Logger.getLogger("Minecraft"); + private final static Logger LOGGER = Bukkit.getLogger(); private final static String UPDATE_URL = "http://goo.gl/67jev"; private final static BigInteger PUBLIC_KEY = new BigInteger("5ha6a2d4qdy17ttkg8evh74sl5a87djojwenu12k1lvy8ui6003e6l06rntczpoh99mhc3txj8mqlxw111oyy9yl7s7qpyluyzix3j1odxrxx4u52gxvyu6qiteapczkzvi7rxgeqsozz7b19rdx73a7quo9ybwpz1cr82r7x5k0pg2a73pjjsv2j1awr13azo7klrcxp9y5xxwf5qv1s3tw4zqftli18u0ek5qkbzfbgk1v5n2f11pkwwk6p0mibrn26wnjbv11vyiqgu95o7busmt6vf5q7grpcenl637w83mbin56s3asj1131b2mscj9xep3cbj7la9tgsxl5bj87vzy8sk2d34kzwqdqgh9nry43nqqus12l1stmiv184r8r3jcy8w43e8h1u1mzklldb5eytkuhayqik8l3ns04hwt8sgacvw534be8sx26qrn5s1", 36); private final transient File file; diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateProcess.java b/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateProcess.java index 80434480f..1b26f1d32 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateProcess.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/UpdateProcess.java @@ -1,10 +1,14 @@ package com.earth2me.essentials.update; +import com.earth2me.essentials.update.states.InstallationFinishedEvent; import com.earth2me.essentials.update.states.StateMachine; -import java.util.List; +import com.earth2me.essentials.update.tasks.SelfUpdate; +import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.bukkit.event.CustomEventListener; +import org.bukkit.event.Event; import org.bukkit.event.Event.Priority; import org.bukkit.event.Event.Type; import org.bukkit.event.player.PlayerChatEvent; @@ -23,6 +27,7 @@ public class UpdateProcess extends PlayerListener public UpdateProcess(final Plugin plugin, final UpdateCheck updateCheck) { + super(); this.plugin = plugin; this.updateCheck = updateCheck; } @@ -32,6 +37,77 @@ public class UpdateProcess extends PlayerListener final PluginManager pluginManager = plugin.getServer().getPluginManager(); pluginManager.registerEvent(Type.PLAYER_QUIT, this, Priority.Low, plugin); pluginManager.registerEvent(Type.PLAYER_CHAT, this, Priority.Lowest, plugin); + pluginManager.registerEvent(Type.PLAYER_JOIN, this, Priority.Normal, plugin); + pluginManager.registerEvent(Type.CUSTOM_EVENT, new CustomEventListener() + { + @Override + public void onCustomEvent(final Event event) + { + if (event instanceof InstallationFinishedEvent) + { + UpdateProcess.this.currentPlayer = null; + } + } + }, Priority.Normal, plugin); + } + + public boolean selfUpdate() + { + if (new Version(plugin.getDescription().getVersion()).compareTo(updateCheck.getNewVersion()) < 0) + { + if (currentPlayer != null) + { + currentPlayer.sendMessage("A newer version of EssentialsUpdate is found. Downloading new file and reloading server."); + } + Bukkit.getLogger().log(Level.INFO, "A newer version of EssentialsUpdate is found. Downloading new file and reloading server."); + new SelfUpdate(new AbstractWorkListener(plugin, updateCheck.getNewVersionInfo()) + { + @Override + public void onWorkAbort(final String message) + { + if (message != null && !message.isEmpty() + && UpdateProcess.this.currentPlayer != null + && UpdateProcess.this.currentPlayer.isOnline()) + { + UpdateProcess.this.currentPlayer.sendMessage(message); + } + if (message != null && !message.isEmpty()) + { + Bukkit.getLogger().log(Level.SEVERE, message); + } + UpdateProcess.this.currentPlayer = null; + } + + @Override + public void onWorkDone(final String message) + { + if (message != null && !message.isEmpty() + && UpdateProcess.this.currentPlayer != null + && UpdateProcess.this.currentPlayer.isOnline()) + { + UpdateProcess.this.currentPlayer.sendMessage(message); + } + if (message != null && !message.isEmpty()) + { + Bukkit.getLogger().log(Level.INFO, message); + } + UpdateProcess.this.currentPlayer = null; + } + }).start(); + return true; + } + if (updateCheck.getResult() == UpdateCheck.CheckResult.NEW_ESS_BUKKIT) + { + final String message = "Please update bukkit to version " + updateCheck.getNewBukkitVersion() + " before updating Essentials."; + if (currentPlayer != null) + { + currentPlayer.sendMessage(message); + } + Bukkit.getLogger().log(Level.INFO, message); + currentPlayer = null; + return true; + } + return false; } @Override @@ -58,6 +134,14 @@ public class UpdateProcess extends PlayerListener public void onPlayerJoin(final PlayerJoinEvent event) { final Player player = event.getPlayer(); + if (currentPlayer.getName().equals(player.getName())) + { + currentPlayer = player; + player.sendMessage("You quit the game, while the installation wizard was running."); + player.sendMessage("The installation wizard will now resume."); + player.sendMessage("You can exit the wizard by typing quit into the chat."); + stateMachine.resumeInstallation(player); + } if (player.hasPermission("essentials.update") && !updateCheck.isEssentialsInstalled()) { player.sendMessage("Hello " + player.getDisplayName()); @@ -82,48 +166,22 @@ public class UpdateProcess extends PlayerListener } } - public void doAutomaticUpdate() - { - - final VersionInfo info = updateCheck.getNewVersionInfo(); - final List changelog = info.getChangelog(); - Bukkit.getLogger().info("Essentials changelog " + updateCheck.getNewVersion().toString()); - for (String line : changelog) - { - Bukkit.getLogger().info(" - " + line); - } - final UpdatesDownloader downloader = new UpdatesDownloader(plugin, info); - downloader.start(); - } - - public void doManualUpdate() - { - } - public void onCommand(final CommandSender sender) { - if (sender instanceof Player && sender.hasPermission("essentials.install")) + if (sender instanceof Player && sender.hasPermission("essentials.update")) { if (currentPlayer == null) { currentPlayer = (Player)sender; - if (updateCheck.isEssentialsInstalled()) + if (selfUpdate()) { - doManualUpdate(); + return; } - else + stateMachine = new StateMachine(plugin, currentPlayer, updateCheck); + final StateMachine.MachineResult result = stateMachine.askQuestion(); + if (result == StateMachine.MachineResult.DONE) { - sender.sendMessage("Thank you for choosing Essentials."); - sender.sendMessage("The following installation wizard will guide you through the installation of Essentials."); - sender.sendMessage("Your answers will be saved for a later update."); - sender.sendMessage("Please answer the messages with yes or no, if not otherwise stated."); - sender.sendMessage("Write bye/exit/quit if you want to exit the wizard at anytime."); - stateMachine = new StateMachine(plugin, currentPlayer, updateCheck.getNewVersionInfo()); - final StateMachine.MachineResult result = stateMachine.askQuestion(); - if (result == StateMachine.MachineResult.DONE) - { - startWork(); - } + startWork(); } } if (!currentPlayer.equals(sender)) diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/UpdatesDownloader.java b/EssentialsUpdate/src/com/earth2me/essentials/update/UpdatesDownloader.java deleted file mode 100644 index 717163726..000000000 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/UpdatesDownloader.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.earth2me.essentials.update; - -import org.bukkit.plugin.Plugin; - - -public class UpdatesDownloader extends WorkListener -{ - public UpdatesDownloader(final Plugin plugin, final VersionInfo newVersionInfo) - { - super(plugin, newVersionInfo); - } - - public void start() - { - } - - @Override - public void onWorkAbort(String message) - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void onWorkDone(String message) - { - throw new UnsupportedOperationException("Not supported yet."); - } -} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/Version.java b/EssentialsUpdate/src/com/earth2me/essentials/update/Version.java index 8e6cbc97f..a82f49abf 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/Version.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/Version.java @@ -147,7 +147,7 @@ public class Version implements Comparable hash = 71 * hash + this.major; hash = 71 * hash + this.minor; hash = 71 * hash + this.build; - hash = 71 * hash + (this.type != null ? this.type.hashCode() : 0); + hash = 71 * hash + (this.type == null ? 0 : this.type.hashCode()); return hash; } diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/chat/AbstractFileCommand.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/AbstractFileCommand.java new file mode 100644 index 000000000..824383285 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/AbstractFileCommand.java @@ -0,0 +1,77 @@ +package com.earth2me.essentials.update.chat; + +import com.earth2me.essentials.update.PastieUpload; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import org.bukkit.plugin.Plugin; + + +public abstract class AbstractFileCommand implements Command +{ + private final transient Plugin plugin; + private final static Charset UTF8 = Charset.forName("utf-8"); + + public AbstractFileCommand(final Plugin plugin) + { + this.plugin = plugin; + } + + protected BufferedReader getServerLogReader() throws IOException + { + final File bukkitFolder = plugin.getDataFolder().getAbsoluteFile().getParentFile().getParentFile(); + if (bukkitFolder == null || !bukkitFolder.exists()) + { + throw new IOException("Bukkit folder not found."); + } + final File logFile = new File(bukkitFolder, "server.log"); + if (!logFile.exists()) + { + throw new IOException("Server log not found."); + } + final FileInputStream fis = new FileInputStream(logFile); + try + { + if (logFile.length() > 1000000) + { + fis.skip(logFile.length() - 1000000); + } + return new BufferedReader(new InputStreamReader(fis)); + } + catch (IOException ex) + { + fis.close(); + throw ex; + } + } + + protected BufferedReader getPluginConfig(final String pluginName, final String fileName) throws IOException + { + final File configFolder = new File(plugin.getDataFolder().getAbsoluteFile().getParentFile(), pluginName); + if (!configFolder.exists()) + { + throw new IOException(pluginName + " plugin folder not found."); + } + final File configFile = new File(configFolder, fileName); + if (!configFile.exists()) + { + throw new IOException(pluginName + " plugin file " + fileName + " not found."); + } + return new BufferedReader(new InputStreamReader(new FileInputStream(configFile), UTF8)); + + } + + protected String uploadToPastie(final StringBuilder input) throws IOException + { + if (input.length() > 15000) + { + input.delete(0, input.length() - 15000); + input.append("## Cropped after 15000 bytes"); + } + final PastieUpload pastie = new PastieUpload(); + return pastie.send(input.toString()); + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/chat/Command.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/Command.java new file mode 100644 index 000000000..ad4c75e43 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/Command.java @@ -0,0 +1,9 @@ +package com.earth2me.essentials.update.chat; + +import org.bukkit.entity.Player; + + +public interface Command +{ + void run(final IrcBot ircBot, final Player player); +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ConfigCommand.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ConfigCommand.java new file mode 100644 index 000000000..5fda07106 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ConfigCommand.java @@ -0,0 +1,62 @@ +package com.earth2me.essentials.update.chat; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.logging.Level; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + + +public class ConfigCommand extends AbstractFileCommand implements Command +{ + public ConfigCommand(final Plugin plugin) + { + super(plugin); + } + + @Override + public void run(final IrcBot ircBot, final Player player) + { + BufferedReader page = null; + try + { + page = getPluginConfig("Essentials", "config.yml"); + final StringBuilder input = new StringBuilder(); + do + { + final String line = page.readLine(); + if (line == null) { + break; + } else { + input.append(line).append("\n"); + } + } while (true); + page.close(); + final String message = "Essentials config.yml: " + uploadToPastie(input); + player.sendMessage("§6" + ircBot.getNick() + ": §7" + message); + ircBot.sendMessage(message); + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.SEVERE, null, ex); + player.sendMessage(ex.getMessage()); + } + finally + { + try + { + if (page != null) + { + page.close(); + } + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.SEVERE, null, ex); + player.sendMessage(ex.getMessage()); + } + } + + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ErrorsCommand.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ErrorsCommand.java new file mode 100644 index 000000000..41aa551c4 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ErrorsCommand.java @@ -0,0 +1,71 @@ +package com.earth2me.essentials.update.chat; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.regex.Pattern; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + + +public class ErrorsCommand extends AbstractFileCommand implements Command +{ + private final transient Pattern pattern = Pattern.compile("^[0-9 :-]+\\[INFO\\].*"); + + public ErrorsCommand(final Plugin plugin) + { + super(plugin); + } + + @Override + public void run(final IrcBot ircBot, final Player player) + { + BufferedReader page = null; + try + { + page = getServerLogReader(); + final StringBuilder input = new StringBuilder(); + do + { + final String line = page.readLine(); + if (line == null) + { + break; + } + else + { + if (!pattern.matcher(line).matches()) + { + input.append(line).append("\n"); + } + } + } + while (true); + page.close(); + final String message = "Errors: " + uploadToPastie(input); + player.sendMessage("§6" + ircBot.getNick() + ": §7" + message); + ircBot.sendMessage(message); + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.SEVERE, null, ex); + player.sendMessage(ex.getMessage()); + } + finally + { + try + { + if (page != null) + { + page.close(); + } + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.SEVERE, null, ex); + player.sendMessage(ex.getMessage()); + } + } + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/chat/HelpCommand.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/HelpCommand.java new file mode 100644 index 000000000..a6f76cece --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/HelpCommand.java @@ -0,0 +1,18 @@ +package com.earth2me.essentials.update.chat; + +import org.bukkit.entity.Player; + + +public class HelpCommand implements Command +{ + @Override + public void run(final IrcBot ircBot, final Player player) + { + player.sendMessage("Commands: (Note: Files send to the chat will be public viewable.)"); + player.sendMessage("!errors - Send the last server errors to the chat."); + player.sendMessage("!startup - Send the last startup messages to the chat."); + player.sendMessage("!config - Sends your Essentials config to the chat."); + player.sendMessage("!list - List all players in chat."); + player.sendMessage("!quit - Leave chat."); + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/IrcBot.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/IrcBot.java similarity index 82% rename from EssentialsUpdate/src/com/earth2me/essentials/update/IrcBot.java rename to EssentialsUpdate/src/com/earth2me/essentials/update/chat/IrcBot.java index a314df15d..31e9384ee 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/IrcBot.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/IrcBot.java @@ -1,4 +1,4 @@ -package com.earth2me.essentials.update; +package com.earth2me.essentials.update.chat; import java.io.IOException; import java.util.logging.Level; @@ -95,7 +95,9 @@ public class IrcBot extends PircBot } @Override - protected void onKick(String channel, String kickerNick, String kickerLogin, String kickerHostname, String recipientNick, String reason) + protected void onKick(final String channel, final String kickerNick, + final String kickerLogin, final String kickerHostname, + final String recipientNick, final String reason) { if (recipientNick.equals(getNick())) { @@ -111,25 +113,33 @@ public class IrcBot extends PircBot } @Override - protected void onMessage(String channel, String sender, String login, String hostname, String message) + protected void onMessage(final String channel, final String sender, + final String login, final String hostname, + final String message) { player.sendMessage(formatChatMessage(sender, message, false)); } @Override - protected void onAction(String sender, String login, String hostname, String target, String action) + protected void onAction(final String sender, final String login, + final String hostname, final String target, + final String action) { player.sendMessage(formatChatMessage(sender, action, true)); } @Override - protected void onNotice(String sourceNick, String sourceLogin, String sourceHostname, String target, String notice) + protected void onNotice(final String sourceNick, final String sourceLogin, + final String sourceHostname, final String target, + final String notice) { player.sendMessage(formatChatMessage(sourceNick, notice, false)); } @Override - protected void onTopic(String channel, String topic, String setBy, long date, boolean changed) + protected void onTopic(final String channel, final String topic, + final String setBy, final long date, + final boolean changed) { player.sendMessage(formatChatMessage(channel, topic, false)); } diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ListCommand.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ListCommand.java new file mode 100644 index 000000000..9aa932efa --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/ListCommand.java @@ -0,0 +1,32 @@ +package com.earth2me.essentials.update.chat; + +import org.bukkit.entity.Player; +import org.jibble.pircbot.User; + + +public class ListCommand implements Command +{ + @Override + public void run(final IrcBot ircBot, final Player player) + { + final User[] members = ircBot.getUsers(); + final StringBuilder message = new StringBuilder(); + for (User user : members) + { + if (message.length() > 0) + { + message.append("§f, "); + } + if (user.isOp() || user.hasVoice()) + { + message.append("§6"); + } + else + { + message.append("§7"); + } + message.append(user.getPrefix()).append(user.getNick()); + } + player.sendMessage(message.toString()); + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/chat/StartupCommand.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/StartupCommand.java new file mode 100644 index 000000000..f244d6e3a --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/StartupCommand.java @@ -0,0 +1,77 @@ +package com.earth2me.essentials.update.chat; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.regex.Pattern; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + + +public class StartupCommand extends AbstractFileCommand implements Command +{ + private final transient Pattern patternStart = Pattern.compile("^[0-9 :-]+\\[INFO\\] Starting minecraft server version.*"); + private final transient Pattern patternEnd = Pattern.compile("^[0-9 :-]+\\[INFO\\] Done \\([0-9.,]+s\\)! For help, type \"help\".*"); + + public StartupCommand(final Plugin plugin) + { + super(plugin); + } + + @Override + public void run(final IrcBot ircBot, final Player player) + { + BufferedReader page = null; + try + { + page = getServerLogReader(); + final StringBuilder input = new StringBuilder(); + String line; + boolean log = false; + while ((line = page.readLine()) != null) + { + if (patternStart.matcher(line).matches()) + { + if (input.length() > 0) + { + input.delete(0, input.length()); + } + log = true; + } + if (log) + { + input.append(line).append("\n"); + } + if (patternEnd.matcher(line).matches()) + { + log = false; + } + } + page.close(); + final String message = "Startup: " + uploadToPastie(input); + player.sendMessage("§6" + ircBot.getNick() + ": §7" + message); + ircBot.sendMessage(message); + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.SEVERE, null, ex); + player.sendMessage(ex.getMessage()); + } + finally + { + try + { + if (page != null) + { + page.close(); + } + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.SEVERE, null, ex); + player.sendMessage(ex.getMessage()); + } + } + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/chat/UsernameUtil.java b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/UsernameUtil.java new file mode 100644 index 000000000..3df615652 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/chat/UsernameUtil.java @@ -0,0 +1,124 @@ +package com.earth2me.essentials.update.chat; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + + +public final class UsernameUtil +{ + private static final Pattern CB_PATTERN = Pattern.compile("git-Bukkit-([0-9]+).([0-9]+).([0-9]+)-[0-9]+-[0-9a-z]+-b([0-9]+)jnks.*"); + + private UsernameUtil() + { + } + + public static String createUsername(final Player player) + { + final StringBuilder nameBuilder = new StringBuilder(); + final Server server = Bukkit.getServer(); + nameBuilder.append(player.getName()); + + addCraftBukkitVersion(server, nameBuilder); + addEssentialsVersion(server, nameBuilder); + addGroupManagerVersion(server, nameBuilder); + addPermissionsExVersion(server, nameBuilder); + addPermissionsBukkitVersion(server, nameBuilder); + addBPermissionsVersion(server, nameBuilder); + addPermissionsVersion(server, nameBuilder); + + return nameBuilder.toString(); + } + + private static void addPermissionsVersion(final Server server, final StringBuilder nameBuilder) + { + final Plugin perm = server.getPluginManager().getPlugin("Permissions"); + if (perm != null) + { + nameBuilder.append(" P"); + if (!perm.isEnabled()) + { + nameBuilder.append('!'); + } + nameBuilder.append(perm.getDescription().getVersion()); + } + } + + private static void addBPermissionsVersion(final Server server, final StringBuilder nameBuilder) + { + final Plugin bperm = server.getPluginManager().getPlugin("bPermissions"); + if (bperm != null) + { + nameBuilder.append(" BP"); + if (!bperm.isEnabled()) + { + nameBuilder.append('!'); + } + nameBuilder.append(bperm.getDescription().getVersion()); + } + } + + private static void addPermissionsBukkitVersion(final Server server, final StringBuilder nameBuilder) + { + final Plugin permb = server.getPluginManager().getPlugin("PermissionsBukkit"); + if (permb != null) + { + nameBuilder.append(" PB"); + if (!permb.isEnabled()) + { + nameBuilder.append('!'); + } + nameBuilder.append(permb.getDescription().getVersion()); + } + } + + private static void addPermissionsExVersion(final Server server, final StringBuilder nameBuilder) + { + final Plugin pex = server.getPluginManager().getPlugin("PermissionsEx"); + if (pex != null) + { + nameBuilder.append(" PEX"); + if (!pex.isEnabled()) + { + nameBuilder.append('!'); + } + nameBuilder.append(pex.getDescription().getVersion()); + } + } + + private static void addGroupManagerVersion(final Server server, final StringBuilder nameBuilder) + { + final Plugin groupManager = server.getPluginManager().getPlugin("GroupManager"); + if (groupManager != null) + { + nameBuilder.append(" GM"); + if (!groupManager.isEnabled()) + { + nameBuilder.append('!'); + } + } + } + + private static void addEssentialsVersion(final Server server, final StringBuilder nameBuilder) + { + final Plugin essentials = server.getPluginManager().getPlugin("Essentials"); + if (essentials != null) + { + nameBuilder.append(" ESS"); + nameBuilder.append(essentials.getDescription().getVersion()); + } + } + + private static void addCraftBukkitVersion(final Server server, final StringBuilder nameBuilder) + { + final Matcher versionMatch = CB_PATTERN.matcher(server.getVersion()); + if (versionMatch.matches()) + { + nameBuilder.append(" CB"); + nameBuilder.append(versionMatch.group(4)); + } + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/AbstractState.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/AbstractState.java index 22fadc0de..7478d81b7 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/states/AbstractState.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/AbstractState.java @@ -1,6 +1,6 @@ package com.earth2me.essentials.update.states; -import com.earth2me.essentials.update.WorkListener; +import com.earth2me.essentials.update.AbstractWorkListener; import org.bukkit.entity.Player; @@ -14,9 +14,26 @@ public abstract class AbstractState this.stateMap = stateMap; } - public AbstractState getState(final Class stateClass) + public T getState(final Class stateClass) { - return stateMap.get(stateClass); + if (!stateMap.containsKey(stateClass)) + { + try + { + final AbstractState state = stateClass.getConstructor(StateMap.class).newInstance(stateMap); + stateMap.put(stateClass, state); + } + catch (Exception ex) + { + /* + * This should never happen. + * All states that are added to the map automatically, + * have to have a Constructor that accepts the StateMap. + */ + throw new RuntimeException(ex); + } + } + return (T)stateMap.get(stateClass); } public abstract AbstractState getNextState(); @@ -49,19 +66,29 @@ public abstract class AbstractState final String trimmedAnswer = answer.trim(); if (trimmedAnswer.equalsIgnoreCase("quit") || trimmedAnswer.equalsIgnoreCase("bye") - || trimmedAnswer.equalsIgnoreCase("abort")) + || trimmedAnswer.equalsIgnoreCase("abort") + || trimmedAnswer.equalsIgnoreCase("cancel") + || trimmedAnswer.equalsIgnoreCase("exit")) { abort(); return null; } - final boolean found = reactOnAnswer(trimmedAnswer); - if (found) + try { - return getNextState(); + final boolean found = reactOnAnswer(trimmedAnswer); + if (found) + { + return getNextState(); + } + else + { + sender.sendMessage("Answer not recognized."); + return this; + } } - else + catch (RuntimeException ex) { - sender.sendMessage("Answer not recognized."); + sender.sendMessage(ex.toString()); return this; } } @@ -69,7 +96,10 @@ public abstract class AbstractState /** * Do something based on the answer, that the user gave. */ - public abstract void doWork(WorkListener workListener); + public void doWork(final AbstractWorkListener listener) + { + listener.onWorkDone(); + } public boolean isAbortion() { diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/AdvancedMode.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/AdvancedMode.java new file mode 100644 index 000000000..88d9efc4a --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/AdvancedMode.java @@ -0,0 +1,20 @@ +package com.earth2me.essentials.update.states; + +import org.bukkit.entity.Player; + + +public class AdvancedMode extends AbstractYesNoState +{ + public AdvancedMode(final StateMap states) + { + super(states, EssentialsChat.class); + } + + @Override + public void askQuestion(final Player sender) + { + sender.sendMessage("This installation mode has a lot of options."); + sender.sendMessage("Do you want use the advanced mode to see all questions?"); + sender.sendMessage("Otherwise the default values will be used."); + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/Changelog.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/Changelog.java new file mode 100644 index 000000000..10a4f33c5 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/Changelog.java @@ -0,0 +1,91 @@ +package com.earth2me.essentials.update.states; + +import com.earth2me.essentials.update.UpdateCheck; +import com.earth2me.essentials.update.VersionInfo; +import java.util.List; +import org.bukkit.entity.Player; + + +public class Changelog extends AbstractState +{ + private static final int CHANGES_PER_PAGE = 5; + private transient int page = 0; + private transient boolean confirmed = false; + private transient final List changes; + private transient final int pages; + + public Changelog(final StateMap stateMap) + { + super(stateMap); + changes = getChanges(); + pages = changes.size() / CHANGES_PER_PAGE + (changes.size() % CHANGES_PER_PAGE > 0 ? 1 : 0); + } + + @Override + public AbstractState getNextState() + { + return confirmed ? getState(EssentialsChat.class) : this; + } + + @Override + public boolean guessAnswer() + { + if (pages == 0) + { + confirmed = true; + } + return confirmed; + } + + private List getChanges() + { + final UpdateCheck updateCheck = getState(UpdateOrInstallation.class).getUpdateCheck(); + final VersionInfo versionInfo = updateCheck.getNewVersionInfo(); + return versionInfo.getChangelog(); + } + + @Override + public void askQuestion(final Player sender) + { + if (pages > 1) + { + sender.sendMessage("Changelog, page " + page + " of " + pages + ":"); + } + else + { + sender.sendMessage("Changelog:"); + } + for (int i = page * CHANGES_PER_PAGE; i < Math.min(page * CHANGES_PER_PAGE + CHANGES_PER_PAGE, changes.size()); i++) + { + sender.sendMessage(changes.get(i)); + } + if (pages > 1) + { + sender.sendMessage("Select a page by typing the numbers 1 to " + pages + " to view all changes and then type confirm or abort."); + } + else + { + sender.sendMessage("Type confirm to update Essentials or abort to cancel the update."); + } + } + + @Override + public boolean reactOnAnswer(final String answer) + { + if (answer.equalsIgnoreCase("confirm")) + { + confirmed = true; + return true; + } + if (answer.matches("[0-9]+")) + { + final int page = Integer.parseInt(answer); + if (page <= pages && page > 0) + { + this.page = page - 1; + return true; + } + } + return false; + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsChat.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsChat.java index ef560bdc3..6aaed634a 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsChat.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsChat.java @@ -1,6 +1,6 @@ package com.earth2me.essentials.update.states; -import com.earth2me.essentials.update.WorkListener; +import com.earth2me.essentials.update.AbstractWorkListener; import com.earth2me.essentials.update.tasks.InstallModule; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -35,7 +35,7 @@ public class EssentialsChat extends AbstractYesNoState } @Override - public void doWork(final WorkListener listener) + public void doWork(final AbstractWorkListener listener) { if (getAnswer()) { diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsChatSettings.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsChatSettings.java index 1401f7191..6666ff371 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsChatSettings.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsChatSettings.java @@ -1,10 +1,6 @@ package com.earth2me.essentials.update.states; -import com.earth2me.essentials.update.WorkListener; -import com.earth2me.essentials.update.tasks.InstallModule; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; public class EssentialsChatSettings extends AbstractYesNoState @@ -14,21 +10,20 @@ public class EssentialsChatSettings extends AbstractYesNoState super(states, EssentialsSpawn.class); } + @Override + public boolean guessAnswer() + { + if (getState(AdvancedMode.class).getAnswer()) + { + setAnswer(false); + return true; + } + return false; + } + @Override public void askQuestion(final Player sender) { sender.sendMessage("Would you like to configure EssentialsChat to prefix ingame messages with their group?"); } - - @Override - public void doWork(final WorkListener listener) - { - if (getAnswer()) - { - //TODO: Configure plugin - - return; - } - listener.onWorkDone(); - } } diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsGeoIP.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsGeoIP.java index b96f17c02..a91a44787 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsGeoIP.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsGeoIP.java @@ -1,6 +1,6 @@ package com.earth2me.essentials.update.states; -import com.earth2me.essentials.update.WorkListener; +import com.earth2me.essentials.update.AbstractWorkListener; import com.earth2me.essentials.update.tasks.InstallModule; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -35,7 +35,7 @@ public class EssentialsGeoIP extends AbstractYesNoState } @Override - public void doWork(final WorkListener listener) + public void doWork(final AbstractWorkListener listener) { if (getAnswer()) { diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsProtect.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsProtect.java index 7ffb61268..ca0337d30 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsProtect.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsProtect.java @@ -1,6 +1,6 @@ package com.earth2me.essentials.update.states; -import com.earth2me.essentials.update.WorkListener; +import com.earth2me.essentials.update.AbstractWorkListener; import com.earth2me.essentials.update.tasks.InstallModule; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -35,7 +35,7 @@ public class EssentialsProtect extends AbstractYesNoState } @Override - public void doWork(final WorkListener listener) + public void doWork(final AbstractWorkListener listener) { if (getAnswer()) { diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsSpawn.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsSpawn.java index 95cc6599b..2a87638ba 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsSpawn.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/EssentialsSpawn.java @@ -1,6 +1,6 @@ package com.earth2me.essentials.update.states; -import com.earth2me.essentials.update.WorkListener; +import com.earth2me.essentials.update.AbstractWorkListener; import com.earth2me.essentials.update.tasks.InstallModule; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -35,7 +35,7 @@ public class EssentialsSpawn extends AbstractYesNoState } @Override - public void doWork(final WorkListener listener) + public void doWork(final AbstractWorkListener listener) { if (getAnswer()) { diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/InstallationFinishedEvent.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/InstallationFinishedEvent.java new file mode 100644 index 000000000..cb88cc642 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/InstallationFinishedEvent.java @@ -0,0 +1,12 @@ +package com.earth2me.essentials.update.states; + +import org.bukkit.event.Event; + + +public class InstallationFinishedEvent extends Event +{ + public InstallationFinishedEvent() + { + super(Type.CUSTOM_EVENT); + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/StateMachine.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/StateMachine.java index 77fb9ce20..6db8734e7 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/states/StateMachine.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/StateMachine.java @@ -1,82 +1,113 @@ package com.earth2me.essentials.update.states; -import com.earth2me.essentials.update.WorkListener; -import com.earth2me.essentials.update.VersionInfo; +import com.earth2me.essentials.update.UpdateCheck; +import com.earth2me.essentials.update.AbstractWorkListener; import java.util.Iterator; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; -public class StateMachine extends WorkListener +public class StateMachine extends AbstractWorkListener implements Runnable { public enum MachineResult { - ABORT, WAIT, DONE + ABORT, WAIT, DONE, NONE } private final transient StateMap states = new StateMap(); private transient AbstractState current; - private final transient Player player; + private transient Player player; + private transient MachineResult result = MachineResult.NONE; - public StateMachine(final Plugin plugin, final Player player, final VersionInfo newVersionInfo) + public StateMachine(final Plugin plugin, final Player player, final UpdateCheck updateCheck) { - super(plugin, newVersionInfo); + super(plugin, updateCheck.getNewVersionInfo()); this.player = player; states.clear(); - states.add(new EssentialsChat(states)); - states.add(new EssentialsSpawn(states)); - states.add(new EssentialsProtect(states)); - states.add(new EssentialsGeoIP(states)); - current = states.values().iterator().next(); + final UpdateOrInstallation state = new UpdateOrInstallation(states, updateCheck); + current = states.put(UpdateOrInstallation.class, state); } public MachineResult askQuestion() { - while (current.guessAnswer()) + try { - current = current.getNextState(); - if (current == null) + while (current.guessAnswer()) { - return MachineResult.DONE; + current = current.getNextState(); + if (current == null) + { + result = MachineResult.DONE; + break; + } + } + if (current != null) + { + if (player.isOnline()) + { + current.askQuestion(player); + } + result = MachineResult.WAIT; } } - current.askQuestion(player); - return MachineResult.WAIT; + catch (RuntimeException ex) + { + player.sendMessage(ex.getMessage()); + finish(); + result = MachineResult.ABORT; + } + return result; } public MachineResult reactOnMessage(final String message) { + result = MachineResult.NONE; final AbstractState next = current.reactOnAnswer(player, message); if (next == null) { if (current.isAbortion()) { - return MachineResult.ABORT; + finish(); + result = MachineResult.ABORT; } else { - return MachineResult.DONE; + result = MachineResult.DONE; } } - current = next; - return askQuestion(); + else + { + current = next; + askQuestion(); + } + return result; } private transient Iterator iterator; public void startWork() { iterator = states.values().iterator(); - callStateWork(); + Bukkit.getScheduler().scheduleAsyncDelayedTask(getPlugin(), this); } - private void callStateWork() + @Override + public void run() { if (!iterator.hasNext()) { - if (player.isOnline()) + Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable() { - player.sendMessage("Installation done."); - } + @Override + public void run() + { + if (StateMachine.this.player.isOnline()) + { + StateMachine.this.player.sendMessage("Installation done. Reloading server."); + } + finish(); + Bukkit.getServer().reload(); + } + }); return; } final AbstractState state = iterator.next(); @@ -86,6 +117,7 @@ public class StateMachine extends WorkListener @Override public void onWorkAbort(final String message) { + finish(); Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable() { @Override @@ -111,8 +143,41 @@ public class StateMachine extends WorkListener { StateMachine.this.player.sendMessage(message); } - StateMachine.this.callStateWork(); + Bukkit.getScheduler().scheduleAsyncDelayedTask(getPlugin(), StateMachine.this); } }); } + + private void finish() + { + current = null; + iterator = null; + states.clear(); + getPlugin().getServer().getPluginManager().callEvent(new InstallationFinishedEvent()); + } + + public void resumeInstallation(final Player player) + { + this.player = player; + if (result == MachineResult.WAIT) + { + if (current == null) + { + throw new RuntimeException("State is WAIT, but current state is null!"); + } + current.askQuestion(player); + } + if (result == MachineResult.DONE && iterator != null) + { + player.sendMessage("Installation is still running."); + } + if (result == MachineResult.ABORT) + { + throw new RuntimeException("Player should not be able to resume an aborted installation."); + } + if (result == MachineResult.NONE) + { + throw new RuntimeException("State machine in an undefined state."); + } + } } diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/StateMap.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/StateMap.java index a2cf7b719..cca4223d6 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/states/StateMap.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/StateMap.java @@ -7,11 +7,6 @@ public class StateMap extends LinkedHashMap, Abst { public StateMap() { - super(); - } - - public AbstractState add(AbstractState state) - { - return put(state.getClass(), state); + super(50); } } diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/states/UpdateOrInstallation.java b/EssentialsUpdate/src/com/earth2me/essentials/update/states/UpdateOrInstallation.java new file mode 100644 index 000000000..5671275f0 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/states/UpdateOrInstallation.java @@ -0,0 +1,59 @@ +package com.earth2me.essentials.update.states; + +import com.earth2me.essentials.update.UpdateCheck; +import org.bukkit.entity.Player; + + +public class UpdateOrInstallation extends AbstractState +{ + private final transient UpdateCheck updateCheck; + private transient boolean update = false; + + public UpdateOrInstallation(final StateMap stateMap, final UpdateCheck updateCheck) + { + super(stateMap); + this.updateCheck = updateCheck; + } + + @Override + public boolean guessAnswer() + { + if (getUpdateCheck().isEssentialsInstalled()) { + update = true; + } + return update; + } + + @Override + public AbstractState getNextState() + { + return update ? getState(Changelog.class) : getState(EssentialsChat.class); + } + + @Override + public void askQuestion(final Player sender) + { + sender.sendMessage("Thank you for choosing Essentials."); + sender.sendMessage("The following installation wizard will guide you through the installation of Essentials."); + sender.sendMessage("Your answers will be saved for a later update."); + sender.sendMessage("Please answer the messages with yes or no, if not otherwise stated."); + sender.sendMessage("Write bye/exit/quit if you want to exit the wizard at anytime."); + sender.sendMessage("Type ok to continue..."); + } + + @Override + public boolean reactOnAnswer(final String answer) + { + return answer.equalsIgnoreCase("ok") || answer.equalsIgnoreCase("k") || answer.equalsIgnoreCase("continue"); + } + + public UpdateCheck getUpdateCheck() + { + return updateCheck; + } + + public boolean isUpdate() + { + return update; + } +} diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/tasks/InstallModule.java b/EssentialsUpdate/src/com/earth2me/essentials/update/tasks/InstallModule.java index b97991a04..66eeb380d 100644 --- a/EssentialsUpdate/src/com/earth2me/essentials/update/tasks/InstallModule.java +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/tasks/InstallModule.java @@ -3,7 +3,7 @@ package com.earth2me.essentials.update.tasks; import com.earth2me.essentials.update.GetFile; import com.earth2me.essentials.update.ModuleInfo; import com.earth2me.essentials.update.VersionInfo; -import com.earth2me.essentials.update.WorkListener; +import com.earth2me.essentials.update.AbstractWorkListener; import java.io.File; import java.net.URL; import java.util.logging.Level; @@ -12,16 +12,16 @@ import org.bukkit.Bukkit; public class InstallModule implements Runnable, Task { - protected final transient WorkListener listener; + protected final transient AbstractWorkListener listener; private final transient String moduleName; private final transient String fileName; - public InstallModule(final WorkListener listener, final String moduleName) + public InstallModule(final AbstractWorkListener listener, final String moduleName) { this(listener, moduleName, moduleName + ".jar"); } - public InstallModule(final WorkListener listener, final String moduleName, final String fileName) + public InstallModule(final AbstractWorkListener listener, final String moduleName, final String fileName) { this.listener = listener; this.moduleName = moduleName; diff --git a/EssentialsUpdate/src/com/earth2me/essentials/update/tasks/SelfUpdate.java b/EssentialsUpdate/src/com/earth2me/essentials/update/tasks/SelfUpdate.java new file mode 100644 index 000000000..777e42517 --- /dev/null +++ b/EssentialsUpdate/src/com/earth2me/essentials/update/tasks/SelfUpdate.java @@ -0,0 +1,57 @@ +package com.earth2me.essentials.update.tasks; + +import com.earth2me.essentials.update.AbstractWorkListener; +import org.bukkit.Bukkit; + + +public class SelfUpdate extends AbstractWorkListener implements Task, Runnable +{ + private final transient AbstractWorkListener listener; + + public SelfUpdate(final AbstractWorkListener listener) + { + super(listener.getPlugin(), listener.getNewVersionInfo()); + this.listener = listener; + } + + @Override + public void onWorkAbort(final String message) + { + listener.onWorkAbort(message); + } + + @Override + public void onWorkDone(final String message) + { + listener.onWorkDone(message); + Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable() + { + @Override + public void run() + { + Bukkit.getServer().reload(); + } + }); + } + + @Override + public void start() + { + Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), this); + } + + @Override + public void run() + { + Bukkit.getScheduler().scheduleAsyncDelayedTask(getPlugin(), new Runnable() { + + @Override + public void run() + { + new InstallModule(SelfUpdate.this, "EssentialsUpdate").start(); + } + }); + } + + +} diff --git a/EssentialsUpdate/test/com/earth2me/essentials/update/VersionTest.java b/EssentialsUpdate/test/com/earth2me/essentials/update/VersionTest.java index 901a8f9dc..92faade26 100644 --- a/EssentialsUpdate/test/com/earth2me/essentials/update/VersionTest.java +++ b/EssentialsUpdate/test/com/earth2me/essentials/update/VersionTest.java @@ -49,39 +49,39 @@ public class VersionTest extends TestCase @Test public void testCompareTo() { - Version a = new Version("1.1.1"); - Version b = new Version("Dev1.1.2"); - Version c = new Version("1.1.2"); - Version d = new Version("1.2.0"); - Version e = new Version("2.0.0"); - Version f = new Version("Pre1.1.1.1"); - Version g = new Version("Dev1.2.2"); - assertTrue("Testing dev", a.compareTo(b) < 0); - assertTrue("Testing dev", b.compareTo(a) > 0); - assertTrue("Testing build", a.compareTo(c) < 0); - assertTrue("Testing build", c.compareTo(a) > 0); - assertTrue("Testing minor", a.compareTo(d) < 0); - assertTrue("Testing minor", d.compareTo(a) > 0); - assertTrue("Testing major", a.compareTo(e) < 0); - assertTrue("Testing major", e.compareTo(a) > 0); - assertTrue("Testing pre", f.compareTo(a) < 0); - assertTrue("Testing pre", a.compareTo(f) > 0); - assertTrue("Testing dev vs dev", b.compareTo(g) < 0); - assertTrue("Testing dev vs dev", g.compareTo(b) > 0); + final Version verA = new Version("1.1.1"); + final Version verB = new Version("Dev1.1.2"); + final Version verC = new Version("1.1.2"); + final Version verD = new Version("1.2.0"); + final Version verE = new Version("2.0.0"); + final Version verF = new Version("Pre1.1.1.1"); + final Version verG = new Version("Dev1.2.2"); + assertTrue("Testing dev", verA.compareTo(verB) < 0); + assertTrue("Testing dev", verB.compareTo(verA) > 0); + assertTrue("Testing build", verA.compareTo(verC) < 0); + assertTrue("Testing build", verC.compareTo(verA) > 0); + assertTrue("Testing minor", verA.compareTo(verD) < 0); + assertTrue("Testing minor", verD.compareTo(verA) > 0); + assertTrue("Testing major", verA.compareTo(verE) < 0); + assertTrue("Testing major", verE.compareTo(verA) > 0); + assertTrue("Testing pre", verF.compareTo(verA) < 0); + assertTrue("Testing pre", verA.compareTo(verF) > 0); + assertTrue("Testing dev vs dev", verB.compareTo(verG) < 0); + assertTrue("Testing dev vs dev", verG.compareTo(verB) > 0); final TreeSet set = new TreeSet(); - set.add(a); - set.add(b); - set.add(c); - set.add(d); - set.add(e); - set.add(f); - set.add(g); - assertEquals("Testing sorting", f, set.pollFirst()); - assertEquals("Testing sorting", a, set.pollFirst()); - assertEquals("Testing sorting", c, set.pollFirst()); - assertEquals("Testing sorting", d, set.pollFirst()); - assertEquals("Testing sorting", e, set.pollFirst()); - assertEquals("Testing sorting", b, set.pollFirst()); - assertEquals("Testing sorting", g, set.pollFirst()); + set.add(verA); + set.add(verB); + set.add(verC); + set.add(verD); + set.add(verE); + set.add(verF); + set.add(verG); + assertEquals("Testing sorting", verF, set.pollFirst()); + assertEquals("Testing sorting", verA, set.pollFirst()); + assertEquals("Testing sorting", verC, set.pollFirst()); + assertEquals("Testing sorting", verD, set.pollFirst()); + assertEquals("Testing sorting", verE, set.pollFirst()); + assertEquals("Testing sorting", verB, set.pollFirst()); + assertEquals("Testing sorting", verG, set.pollFirst()); } }