From 8ca2dbd8e11d471525c660b85fd202dac39bb6aa Mon Sep 17 00:00:00 2001 From: angelsl Date: Sun, 6 Feb 2011 12:01:14 +0800 Subject: [PATCH] Add own versions of Authorize & BackupPlugin --- .gitignore | 8 + Authorize/Authorize.iml | 13 + Authorize/META-INF/MANIFEST.MF | 2 + .../com/rena4ka/bukkit/auth/Authorize.java | 836 ++++++++++++++++++ .../bukkit/auth/AuthorizeBlockListener.java | 51 ++ .../bukkit/auth/AuthorizeEntityListener.java | 43 + .../bukkit/auth/AuthorizePlayerListener.java | 442 +++++++++ Authorize/plugin.yml | 3 + BackupPlugin/.gitignore | 2 + BackupPlugin/META-INF/MANIFEST.MF | 2 + .../backupplugin/AsyncStreamReader.java | 70 ++ .../bukkit/backupplugin/BackupPlugin.java | 358 ++++++++ .../BackupPluginPlayerListener.java | 101 +++ .../bukkit/backupplugin/BackupUnit.java | 78 ++ .../bukkit/backupplugin/CacheControl.java | 308 +++++++ .../bukkit/backupplugin/Configuration.java | 178 ++++ .../mysticx/bukkit/backupplugin/IOHelper.java | 262 ++++++ .../bukkit/backupplugin/MapperUnit.java | 177 ++++ .../bukkit/backupplugin/MessageHandler.java | 168 ++++ .../bukkit/backupplugin/PluginUnit.java | 233 +++++ .../backupplugin/SysCommandExecutor.java | 140 +++ BackupPlugin/plugin.yml | 5 + 22 files changed, 3480 insertions(+) create mode 100644 .gitignore create mode 100644 Authorize/Authorize.iml create mode 100644 Authorize/META-INF/MANIFEST.MF create mode 100644 Authorize/com/rena4ka/bukkit/auth/Authorize.java create mode 100644 Authorize/com/rena4ka/bukkit/auth/AuthorizeBlockListener.java create mode 100644 Authorize/com/rena4ka/bukkit/auth/AuthorizeEntityListener.java create mode 100644 Authorize/com/rena4ka/bukkit/auth/AuthorizePlayerListener.java create mode 100644 Authorize/plugin.yml create mode 100644 BackupPlugin/.gitignore create mode 100644 BackupPlugin/META-INF/MANIFEST.MF create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/AsyncStreamReader.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/BackupPlugin.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/BackupPluginPlayerListener.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/BackupUnit.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/CacheControl.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/Configuration.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/IOHelper.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/MapperUnit.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/MessageHandler.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/PluginUnit.java create mode 100644 BackupPlugin/com/mysticx/bukkit/backupplugin/SysCommandExecutor.java create mode 100644 BackupPlugin/plugin.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e539459 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ + +*.ipr +*.iws +*.jar +/out +/Bukkit/ +/CraftBukkit/ +/mc-dev/ \ No newline at end of file diff --git a/Authorize/Authorize.iml b/Authorize/Authorize.iml new file mode 100644 index 0000000..2b15371 --- /dev/null +++ b/Authorize/Authorize.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Authorize/META-INF/MANIFEST.MF b/Authorize/META-INF/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/Authorize/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/Authorize/com/rena4ka/bukkit/auth/Authorize.java b/Authorize/com/rena4ka/bukkit/auth/Authorize.java new file mode 100644 index 0000000..6e0cb60 --- /dev/null +++ b/Authorize/com/rena4ka/bukkit/auth/Authorize.java @@ -0,0 +1,836 @@ +/* */ +package com.rena4ka.bukkit.auth; +/* */ +/* */ + +import org.bukkit.ChatColor; +import org.bukkit.Server; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.PluginLoader; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.sql.*; +import java.util.*; +import java.util.logging.Logger; + +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ + +/* */ +/* */ public class Authorize extends JavaPlugin +/* */ { + /* 42 */ private final AuthorizePlayerListener playerListener = new AuthorizePlayerListener(this); + /* */ +/* 44 */ private final AuthorizeBlockListener blockListener = new AuthorizeBlockListener(this); + /* 45 */ private final AuthorizeEntityListener entityListener = new AuthorizeEntityListener(this); + /* 46 */ private List authorizedIds = new ArrayList(); + /* 47 */ public boolean allowRegister = true; + /* 48 */ public boolean allowPassChange = true; + /* 49 */ public boolean forceRegister = true; + /* 50 */ public boolean kickOnBadPassword = true; + /* 51 */ public boolean allowUnregister = false; + /* 52 */ public boolean requireEmail = false; + /* 53 */ public boolean allowEmailChange = false; + /* 54 */ private int sourcetype = 0; + /* */ +/* 60 */ public String loginMessage = ChatColor.RED + "Please login with command /login "; + /* 61 */ public String registerMessage = ChatColor.RED + "Please register with command /register "; + /* 62 */ public String authorizedMessage = ChatColor.DARK_RED + "You are already authorized!"; + /* 63 */ public String loginUsageMessage = ChatColor.DARK_RED + "Correct usage is: /login "; + /* 64 */ public String passwordAcceptedMessage = ChatColor.GREEN + "Password accepted. Welcome!"; + /* 65 */ public String badPasswordMessage = "Bad password!"; + /* 66 */ public String registerUsageMessage = ChatColor.DARK_RED + "Correct usage is: /register "; + /* 67 */ public String alreadyRegisteredMessage = ChatColor.DARK_RED + "You are already registered!"; + /* 68 */ public String registrationNotAllowedMessage = ChatColor.DARK_RED + "Registration not allowed!"; + /* 69 */ public String registeredMessage = ChatColor.GREEN + "You have been registered!"; + /* 70 */ public String registerErrorMessage = ChatColor.RED + "Error while registering you!"; + /* 71 */ public String passwordUsageMessage = ChatColor.DARK_RED + "Correct usage is: /password "; + /* 72 */ public String passwordNotRegisteredMessage = ChatColor.DARK_RED + "Register first!"; + /* 73 */ public String passNotAllowedMessage = ChatColor.DARK_RED + "Password changing not allowed!"; + /* 74 */ public String badOldPasswordMessage = ChatColor.DARK_RED + "Bad old password!"; + /* 75 */ public String passwordChangedMessage = ChatColor.GREEN + "You'r password has been changed!"; + /* 76 */ public String passwordChangeErrorMessage = ChatColor.RED + "Error while changing your password!"; + /* 77 */ public String emailRequiredMessage = ChatColor.RED + "Email required for registration!"; + /* 78 */ public String emailUsageMessage = ChatColor.RED + "Correct usage is: /email "; + /* 79 */ public String emailChangeNotAllowedMessage = ChatColor.RED + "Email changing not allowed!"; + /* 80 */ public String emailUnexpectedMessage = ChatColor.RED + "Email contains unexpected letters!"; + /* 81 */ public String emailChangedMessage = ChatColor.RED + "Email successfully changed!"; + /* 82 */ public String emailChangeErrorMessage = ChatColor.RED + "Error while changing email!"; + /* 83 */ public String notAdminMessage = ChatColor.RED + "You're not admin!"; + /* 84 */ public String resetUsageMessage = ChatColor.RED + "Correct usage is: /loginreset "; + /* 85 */ public String userResettedMessage = "resetted"; + /* 86 */ public String reloadedMessage = ChatColor.GREEN + "Authorize is reloaded!"; + /* */ public String unregisterUsageMessage; + /* */ public String unregisterNotRegisteredMessage; + /* */ public String unregNotAllowedMessage; + /* */ public String unregisteredMessage; + /* */ public String unregisterErrorMessage; + /* 92 */ private HashMap db = new HashMap(); + /* 93 */ private String dbFileName = "auths.db"; + /* 94 */ public Logger log = Logger.getLogger("Minecraft"); + /* 95 */ private HashMap inventories = new HashMap(); + /* 96 */ private Connection mysql = null; + /* 97 */ private List admins = new ArrayList(); + + /* */ +/* */ + public Authorize(PluginLoader pluginLoader, Server instance, PluginDescriptionFile desc, File folder, File plugin, ClassLoader cLoader) { +/* 100 */ + super(pluginLoader, instance, desc, folder, plugin, cLoader); +/* */ + } + + /* */ +/* */ + public void onDisable() { +/* 104 */ + this.authorizedIds.clear(); +/* 105 */ + this.db.clear(); +/* 106 */ + Set pl = this.inventories.keySet(); +/* 107 */ + Iterator i = pl.iterator(); +/* 108 */ + while (i.hasNext()) { +/* 109 */ + String player = (String) i.next(); +/* 110 */ + Player pla = getServer().getPlayer(player); +/* 111 */ + if (pl != null) +/* 112 */ pla.getInventory().setContents((ItemStack[]) this.inventories.get(player)); +/* */ + } +/* 114 */ + this.inventories.clear(); +/* 115 */ + this.admins.clear(); +/* 116 */ + if (this.mysql != null) +/* */ try { +/* 118 */ + this.mysql.close(); + } catch (SQLException localSQLException) { +/* */ + } +/* */ + } + + /* */ +/* */ + public void onEnable() { +/* 123 */ + this.allowRegister = getConfiguration().getBoolean("allow-register", this.allowRegister); +/* 124 */ + this.allowPassChange = getConfiguration().getBoolean("allow-pass-change", this.allowPassChange); +/* 125 */ + this.forceRegister = getConfiguration().getBoolean("force-register", this.forceRegister); +/* 126 */ + this.kickOnBadPassword = getConfiguration().getBoolean("kick-on-bad-password", this.kickOnBadPassword); +/* 127 */ + this.allowUnregister = getConfiguration().getBoolean("allow-unregister", this.allowUnregister); +/* 128 */ + this.requireEmail = getConfiguration().getBoolean("require-email", this.requireEmail); +/* 129 */ + this.allowEmailChange = getConfiguration().getBoolean("allow-email-change", this.allowEmailChange); +/* 130 */ + String stype = getConfiguration().getString("source-type", "flatfile"); +/* 131 */ + if (stype.equalsIgnoreCase("flatfile")) +/* 132 */ this.sourcetype = 0; +/* */ + else +/* 134 */ this.sourcetype = 1; +/* 135 */ + String dbDriver = getConfiguration().getString("db-driver", "com.mysql.jdbc.Driver"); +/* 136 */ + String dbUsername = getConfiguration().getString("db-username", "root"); +/* 137 */ + String dbPassword = getConfiguration().getString("db-password", ""); +/* 138 */ + String dbDb = getConfiguration().getString("db-db", "jdbc:mysql://localhost:3306/minecraft"); +/* 139 */ + Boolean convertOnStart = Boolean.valueOf(getConfiguration().getBoolean("db-convert", false)); +/* 140 */ + String[] adm = getConfiguration().getString("admins", "").split(","); +/* 141 */ + for (short i = 0; i < adm.length; i = (short) (i + 1)) +/* 142 */ + this.admins.add(adm[i].toLowerCase()); +/* 143 */ + this.loginMessage = getConfiguration().getString("login-message", this.loginMessage); +/* 144 */ + this.registerMessage = getConfiguration().getString("register-message", this.registerMessage); +/* 145 */ + this.authorizedMessage = getConfiguration().getString("authorized-message", this.authorizedMessage); +/* 146 */ + this.loginUsageMessage = getConfiguration().getString("login-usage-message", this.loginUsageMessage); +/* 147 */ + this.passwordAcceptedMessage = getConfiguration().getString("password-accepted-message", this.passwordAcceptedMessage); +/* 148 */ + this.badPasswordMessage = getConfiguration().getString("bad-password-message", this.badPasswordMessage); +/* 149 */ + this.registerUsageMessage = getConfiguration().getString("register-usage-message", this.registerUsageMessage); +/* 150 */ + this.alreadyRegisteredMessage = getConfiguration().getString("already-registered-message", this.alreadyRegisteredMessage); +/* 151 */ + this.registrationNotAllowedMessage = getConfiguration().getString("registration-not-allowed-message", this.registrationNotAllowedMessage); +/* 152 */ + this.registeredMessage = getConfiguration().getString("registered-message", this.registeredMessage); +/* 153 */ + this.registerErrorMessage = getConfiguration().getString("register-error-message", this.registerErrorMessage); +/* 154 */ + this.passwordUsageMessage = getConfiguration().getString("password-usage-message", this.passwordUsageMessage); +/* 155 */ + this.passwordNotRegisteredMessage = getConfiguration().getString("password-not-registered-message", this.passwordNotRegisteredMessage); +/* 156 */ + this.passNotAllowedMessage = getConfiguration().getString("pass-not-allowed-message", this.passNotAllowedMessage); +/* 157 */ + this.badOldPasswordMessage = getConfiguration().getString("bad-old-password-message", this.badOldPasswordMessage); +/* 158 */ + this.passwordChangedMessage = getConfiguration().getString("password-сhanged-message", this.passwordChangedMessage); +/* 159 */ + this.passwordChangeErrorMessage = getConfiguration().getString("password-сhange-error-message", this.passwordChangeErrorMessage); +/* 160 */ + this.unregisterUsageMessage = getConfiguration().getString("unregister-usage-message", this.unregisterUsageMessage); +/* 161 */ + this.unregisterNotRegisteredMessage = getConfiguration().getString("unregister-not-registered-message", this.unregisterNotRegisteredMessage); +/* 162 */ + this.unregNotAllowedMessage = getConfiguration().getString("unreg-not-allowed-message", this.unregNotAllowedMessage); +/* 163 */ + this.unregisteredMessage = getConfiguration().getString("unregistered-message", this.unregisteredMessage); +/* 164 */ + this.unregisterErrorMessage = getConfiguration().getString("unregister-error-message", this.unregisterErrorMessage); +/* 165 */ + this.emailRequiredMessage = getConfiguration().getString("email-required-message", this.emailRequiredMessage); +/* 166 */ + this.emailUsageMessage = getConfiguration().getString("email-usage-message", this.emailUsageMessage); +/* 167 */ + this.emailChangeNotAllowedMessage = getConfiguration().getString("email-change-not-allowed-message", this.emailChangeNotAllowedMessage); +/* 168 */ + this.emailUnexpectedMessage = getConfiguration().getString("email-unexpected-message", this.emailUnexpectedMessage); +/* 169 */ + this.emailChangedMessage = getConfiguration().getString("email-changed-message", this.emailChangedMessage); +/* 170 */ + this.emailChangeErrorMessage = getConfiguration().getString("email-change-error-message", this.emailChangeErrorMessage); +/* 171 */ + PluginDescriptionFile pdfFile = getDescription(); +/* 172 */ + PreparedStatement ps = null; +/* 173 */ + ResultSet rs = null; +/* */ + try { +/* 175 */ + if (this.sourcetype == 0) { +/* 176 */ + if (!getDataFolder().exists()) +/* 177 */ getDataFolder().mkdir(); +/* 178 */ + File dbFile = new File(getDataFolder(), this.dbFileName); +/* 179 */ + if (!dbFile.exists()) { +/* 180 */ + dbFile.createNewFile(); +/* */ + } +/* 182 */ + Scanner scanner = new Scanner(dbFile); +/* 183 */ + while (scanner.hasNext()) { +/* 184 */ + String str = scanner.next(); +/* 185 */ + String[] split = str.split(":"); +/* 186 */ + if (split.length >= 2) +/* 187 */ this.db.put(split[0], split[1]); +/* */ + } +/* 189 */ + scanner.close(); +/* 190 */ + this.log.info("[" + pdfFile.getName() + "] " + this.db.size() + " user registrations loaded"); +/* */ + } else { +/* 192 */ + Class.forName(dbDriver); +/* 193 */ + this.mysql = DriverManager.getConnection(dbDb + "?autoReconnect=true&user=" + dbUsername + "&password=" + dbPassword); +/* 194 */ + if (convertOnStart.booleanValue()) { +/* 195 */ + File dbFile = new File(getDataFolder(), this.dbFileName); +/* 196 */ + if (dbFile.exists()) { +/* 197 */ + int i = 0; +/* 198 */ + Scanner scanner = new Scanner(dbFile); +/* 199 */ + while (scanner.hasNext()) { +/* 200 */ + String str = scanner.next(); +/* 201 */ + String[] split = str.split(":"); +/* 202 */ + if (split.length >= 2) { +/* 203 */ + ps = this.mysql.prepareStatement("INSERT INTO `authorize_users` (`name`,`password`) VALUES (?,?)", 1); +/* 204 */ + ps.setString(1, split[0]); +/* 205 */ + ps.setString(2, split[1]); +/* 206 */ + ps.executeUpdate(); +/* 207 */ + ps.close(); +/* 208 */ + i++; +/* */ + } +/* */ + } +/* 211 */ + scanner.close(); +/* 212 */ + this.log.info("[" + pdfFile.getName() + "] " + i + " users converted from flatfile to mysql"); +/* */ + } +/* */ + } +/* 215 */ + ps = this.mysql.prepareStatement("SELECT COUNT(*) as `cnt` FROM `authorize_users`"); +/* 216 */ + rs = ps.executeQuery(); +/* 217 */ + if (rs.next()) { +/* 218 */ + this.log.info("[" + pdfFile.getName() + "] " + rs.getInt("cnt") + " user registrations in database"); +/* */ + } +/* */ + } +/* 221 */ + PluginManager pm = getServer().getPluginManager(); +/* 222 */ + pm.registerEvent(Event.Type.PLAYER_JOIN, this.playerListener, Event.Priority.Lowest, this); +/* 223 */ + pm.registerEvent(Event.Type.PLAYER_QUIT, this.playerListener, Event.Priority.Lowest, this); +/* 224 */ + pm.registerEvent(Event.Type.PLAYER_COMMAND, this.playerListener, Event.Priority.Lowest, this); +/* 225 */ + pm.registerEvent(Event.Type.PLAYER_MOVE, this.playerListener, Event.Priority.Lowest, this); +/* 226 */ + pm.registerEvent(Event.Type.PLAYER_ITEM, this.playerListener, Event.Priority.Lowest, this); +/* 227 */ + pm.registerEvent(Event.Type.PLAYER_CHAT, this.playerListener, Event.Priority.Lowest, this); +/* 228 */ + pm.registerEvent(Event.Type.BLOCK_PLACED, this.blockListener, Event.Priority.Lowest, this); +/* 229 */ + pm.registerEvent(Event.Type.BLOCK_DAMAGED, this.blockListener, Event.Priority.Lowest, this); +/* 230 */ + pm.registerEvent(Event.Type.ENTITY_DAMAGED, this.entityListener, Event.Priority.Lowest, this); +/* 231 */ + this.log.info("[" + pdfFile.getName() + "] " + pdfFile.getName() + " plugin build " + pdfFile.getVersion() + " is enabled"); +/* */ + } catch (IOException e) { +/* 233 */ + this.log.warning("[" + pdfFile.getName() + "] Exception while parsing user db file:"); +/* 234 */ + e.printStackTrace(); +/* 235 */ + this.log.warning("[" + pdfFile.getName() + "] " + pdfFile.getName() + " plugin won't work!"); +/* */ + try +/* */ { +/* 246 */ + if (ps != null) +/* 247 */ ps.close(); +/* 248 */ + if (rs != null) +/* 249 */ rs.close(); +/* */ + } +/* */ catch (SQLException localSQLException1) +/* */ { +/* */ + } +/* */ + } +/* */ catch (SQLException e) +/* */ { +/* 237 */ + this.log.warning("[" + pdfFile.getName() + "] SQL Exception happend:"); +/* 238 */ + e.printStackTrace(); +/* 239 */ + this.log.warning("[" + pdfFile.getName() + "] " + pdfFile.getName() + " plugin won't work!"); +/* */ + try +/* */ { +/* 246 */ + if (ps != null) +/* 247 */ ps.close(); +/* 248 */ + if (rs != null) +/* 249 */ rs.close(); +/* */ + } +/* */ catch (SQLException localSQLException2) +/* */ { +/* */ + } +/* */ + } +/* */ catch (ClassNotFoundException e) +/* */ { +/* 241 */ + this.log.warning("[" + pdfFile.getName() + "] unable to found MySQL driver:"); +/* 242 */ + e.printStackTrace(); +/* 243 */ + this.log.warning("[" + pdfFile.getName() + "] " + pdfFile.getName() + " plugin won't work!"); +/* */ + try +/* */ { +/* 246 */ + if (ps != null) +/* 247 */ ps.close(); +/* 248 */ + if (rs != null) +/* 249 */ rs.close(); +/* */ + } +/* */ catch (SQLException localSQLException3) +/* */ { +/* */ + } +/* */ + } +/* */ finally +/* */ { +/* */ + try +/* */ { +/* 246 */ + if (ps != null) +/* 247 */ ps.close(); +/* 248 */ + if (rs != null) +/* 249 */ rs.close(); +/* */ + } catch (SQLException localSQLException4) { +/* */ + } +/* */ + } +/* */ + } + + /* */ +/* */ + public boolean isAuthorized(int id) { +/* 255 */ + return this.authorizedIds.contains(Integer.valueOf(id)); +/* */ + } + + /* */ +/* */ + public void unauthorize(int id) { +/* 259 */ + this.authorizedIds.remove(Integer.valueOf(id)); +/* */ + } + + /* */ +/* */ + public void authorize(int id) { +/* 263 */ + this.authorizedIds.add(Integer.valueOf(id)); +/* */ + } + + /* */ +/* */ + private String md5(String string) { +/* */ + try { +/* 268 */ + MessageDigest digest = MessageDigest.getInstance("MD5"); +/* 269 */ + digest.update(string.getBytes()); +/* 270 */ + byte[] hash = digest.digest(); +/* 271 */ + String result = ""; +/* 272 */ + for (int i = 0; i < hash.length; i++) { +/* 273 */ + result = result + Integer.toString((hash[i] & 0xFF) + 256, 16).substring(1); +/* */ + } +/* 275 */ + return result; +/* */ + } catch (NoSuchAlgorithmException e) { +/* 277 */ + e.printStackTrace(); +/* */ + } +/* 279 */ + return null; +/* */ + } + + /* */ +/* */ + public boolean checkPassword(String player, String password) { +/* 283 */ + if (this.sourcetype == 0) { +/* 284 */ + String rmd5 = (String) this.db.get(player.toLowerCase()); +/* 285 */ + if ((rmd5 != null) && +/* 286 */ (rmd5.equals(md5(password)))) +/* 287 */ return true; +/* */ + } else { +/* */ + try { +/* 290 */ + PreparedStatement ps = this.mysql.prepareStatement("SELECT `name` FROM `authorize_users` WHERE lower(`name`) = '" + player.toLowerCase() + "' and `password` = '" + md5(password) + "'"); +/* 291 */ + ResultSet rs = ps.executeQuery(); +/* 292 */ + if (rs.next()) +/* 293 */ return true; +/* */ + } catch (SQLException e) { +/* 295 */ + this.log.warning("[Authorize] SQL Exception:"); +/* 296 */ + e.printStackTrace(); +/* */ + } +/* */ + } +/* 299 */ + return false; +/* */ + } + + /* */ +/* */ + public void register(String player, String password) throws IOException, SQLException { +/* 303 */ + register(player, password, ""); +/* */ + } + + /* */ +/* */ + public void register(String player, String password, String email) throws IOException, SQLException { +/* 307 */ + String md5 = md5(password); +/* 308 */ + if (this.sourcetype == 0) { +/* 309 */ + this.db.put(player.toLowerCase(), md5); +/* 310 */ + BufferedWriter bw = new BufferedWriter(new FileWriter(new File(getDataFolder(), this.dbFileName), true)); +/* 311 */ + bw.append(player.toLowerCase() + ":" + md5); +/* 312 */ + bw.newLine(); +/* 313 */ + bw.close(); +/* */ + } else { +/* 315 */ + PreparedStatement ps = this.mysql.prepareStatement("INSERT INTO `authorize_users` (`name`,`password`,`email`) VALUES (?,?,?)", 1); +/* 316 */ + ps.setString(1, player); +/* 317 */ + ps.setString(2, md5); +/* 318 */ + ps.setString(3, email); +/* 319 */ + ps.executeUpdate(); +/* */ + } +/* */ + } + + /* */ +/* */ + public void unregister(String player) throws IOException, SQLException { +/* 324 */ + if (this.sourcetype == 0) { +/* 325 */ + this.db.remove(player); +/* 326 */ + updateDb(); +/* */ + } else { +/* 328 */ + PreparedStatement ps = this.mysql.prepareStatement("DELETE FROM `authorize_users` WHERE `name` = '" + player + "' or `name` = '" + player.toLowerCase() + "'"); +/* 329 */ + ps.executeUpdate(); +/* */ + } +/* */ + } + + /* */ +/* */ + public void changePassword(String player, String password) throws IOException, SQLException { +/* 334 */ + String md5 = md5(password); +/* 335 */ + if (this.sourcetype == 0) { +/* 336 */ + this.db.put(player.toLowerCase(), md5); +/* 337 */ + updateDb(); +/* */ + } else { +/* 339 */ + PreparedStatement ps = this.mysql.prepareStatement("UPDATE `authorize_users` SET `password` = '" + md5 + "' WHERE `name` = '" + player + "' or `name` = '" + player.toLowerCase() + "'"); +/* 340 */ + ps.executeUpdate(); +/* */ + } +/* */ + } + + /* */ +/* */ + public void updateDb() throws IOException { +/* 345 */ + BufferedWriter bw = new BufferedWriter(new FileWriter(new File(getDataFolder(), this.dbFileName))); +/* 346 */ + Set keys = this.db.keySet(); +/* 347 */ + Iterator i = keys.iterator(); +/* 348 */ + while (i.hasNext()) { +/* 349 */ + String key = (String) i.next(); +/* 350 */ + bw.append(key + ":" + (String) this.db.get(key)); +/* 351 */ + bw.newLine(); +/* */ + } +/* 353 */ + bw.close(); +/* */ + } + + /* */ +/* */ + public boolean isRegistered(String player) { +/* 357 */ + if ((this.sourcetype == 0) && (this.db.containsKey(player.toLowerCase()))) +/* 358 */ return true; +/* 359 */ + if (this.sourcetype == 1) { +/* */ + try { +/* 361 */ + PreparedStatement ps = this.mysql.prepareStatement("SELECT * FROM `authorize_users` WHERE lower(`name`) = '" + player.toLowerCase() + "'"); +/* 362 */ + ResultSet rs = ps.executeQuery(); +/* 363 */ + if (rs.next()) { +/* 364 */ + this.db.put(rs.getString("name").toLowerCase(), rs.getString("password")); +/* 365 */ + return true; +/* */ + } +/* */ + } catch (SQLException e) { +/* 368 */ + this.log.warning("[Authorize] SQL Exception:"); +/* 369 */ + e.printStackTrace(); +/* */ + } +/* */ + } +/* 372 */ + return false; +/* */ + } + + /* */ +/* */ + public void storeInventory(String player, ItemStack[] inventory) throws IOException { +/* 376 */ + File inv = new File(getDataFolder(), player + "_inv"); +/* 377 */ + if (inv.exists()) +/* 378 */ return; +/* 379 */ + inv.createNewFile(); +/* 380 */ + BufferedWriter bw = new BufferedWriter(new FileWriter(inv)); +/* 381 */ + for (short i = 0; i < inventory.length; i = (short) (i + 1)) { +/* 382 */ + bw.write(inventory[i].getTypeId() + ":" + inventory[i].getAmount() + ":" + (inventory[i].getData() == null ? "" : Byte.valueOf(inventory[i].getData().getData())) + ":" + inventory[i].getDurability()); +/* 383 */ + bw.newLine(); +/* */ + } +/* 385 */ + bw.close(); +/* 386 */ + this.inventories.put(player.toLowerCase(), inventory); +/* */ + } + + /* */ +/* */ + public ItemStack[] getInventory(String player) { +/* 390 */ + File f = new File(getDataFolder(), player + "_inv"); +/* 391 */ + if (this.inventories.containsKey(player.toLowerCase())) { +/* 392 */ + if ((f.exists()) && (!f.delete())) +/* 393 */ this.log.warning("[Authorize] Unable to delete user inventory file: " + player + "_inv"); +/* 394 */ + return (ItemStack[]) this.inventories.remove(player.toLowerCase()); +/* */ + } +/* 396 */ + if (f.exists()) { +/* 397 */ + ItemStack[] inv = new ItemStack[36]; +/* */ + try { +/* 399 */ + Scanner s = new Scanner(f); +/* 400 */ + short i = 0; +/* 401 */ + while (s.hasNextLine()) { +/* 402 */ + String line = s.nextLine(); +/* 403 */ + String[] split = line.split(":"); +/* 404 */ + if (split.length == 4) { +/* 405 */ + inv[i] = +/* 406 */ new ItemStack(Integer.valueOf(split[0]).intValue(), Integer.valueOf(split[1]).intValue(), +/* 406 */ Short.valueOf(split[3]).shortValue(), split[2].length() == 0 ? null : Byte.valueOf(split[2])); +/* 407 */ + i = (short) (i + 1); +/* */ + } +/* */ + } +/* 410 */ + s.close(); +/* 411 */ + if (!f.delete()) +/* 412 */ this.log.warning("[Authorize] Unable to delete user inventory file: " + player + "_inv"); +/* */ + } catch (IOException e) { +/* 414 */ + this.log.severe("[Authorize] Inventory file read error:"); +/* 415 */ + e.printStackTrace(); +/* */ + } +/* 417 */ + return inv; +/* */ + } +/* */ +/* 420 */ + return null; +/* */ + } + + /* */ +/* */ + public void changeEmail(String player, String email) throws SQLException { +/* 424 */ + if (this.sourcetype != 1) +/* 425 */ return; +/* 426 */ + PreparedStatement ps = this.mysql.prepareStatement("UPDATE `authorize_users` SET `email` = '" + email + "' WHERE `name` = '" + player + "' or `name` = '" + player.toLowerCase() + "'"); +/* 427 */ + ps.executeUpdate(); +/* */ + } + + /* */ +/* */ + public boolean checkEmail(String email) +/* */ { +/* 432 */ + return !email.contains("'"); +/* */ + } + + /* */ +/* */ + public boolean isAdmin(String player) +/* */ { +/* 437 */ + return this.admins.contains(player.toLowerCase()); +/* */ + } +/* */ +} + +/* Location: D:\Misc\Games\Minecraft\Beta\Development\Server Bukkit\Authorize.jar + * Qualified Name: com.rena4ka.bukkit.auth.Authorize + * JD-Core Version: 0.6.0 + */ \ No newline at end of file diff --git a/Authorize/com/rena4ka/bukkit/auth/AuthorizeBlockListener.java b/Authorize/com/rena4ka/bukkit/auth/AuthorizeBlockListener.java new file mode 100644 index 0000000..1c6cf22 --- /dev/null +++ b/Authorize/com/rena4ka/bukkit/auth/AuthorizeBlockListener.java @@ -0,0 +1,51 @@ +/* */ +package com.rena4ka.bukkit.auth; +/* */ +/* */ + +import org.bukkit.event.block.BlockDamageEvent; +import org.bukkit.event.block.BlockListener; +import org.bukkit.event.block.BlockPlaceEvent; + +/* */ +/* */ +/* */ + +/* */ +/* */ public class AuthorizeBlockListener extends BlockListener +/* */ { + /* */ private final Authorize plugin; + + /* */ +/* */ + public AuthorizeBlockListener(Authorize instance) +/* */ { +/* 17 */ + this.plugin = instance; +/* */ + } + + /* */ +/* */ + public void onBlockPlace(BlockPlaceEvent event) { +/* 21 */ + if (!this.plugin.isAuthorized(event.getPlayer().getEntityId())) +/* 22 */ event.setCancelled(true); +/* */ + } + + /* */ +/* */ + public void onBlockDamage(BlockDamageEvent event) { +/* 26 */ + if (!this.plugin.isAuthorized(event.getPlayer().getEntityId())) +/* 27 */ event.setCancelled(true); +/* */ + } +/* */ +} + +/* Location: D:\Misc\Games\Minecraft\Beta\Development\Server Bukkit\Authorize.jar + * Qualified Name: com.rena4ka.bukkit.auth.AuthorizeBlockListener + * JD-Core Version: 0.6.0 + */ \ No newline at end of file diff --git a/Authorize/com/rena4ka/bukkit/auth/AuthorizeEntityListener.java b/Authorize/com/rena4ka/bukkit/auth/AuthorizeEntityListener.java new file mode 100644 index 0000000..87b0b19 --- /dev/null +++ b/Authorize/com/rena4ka/bukkit/auth/AuthorizeEntityListener.java @@ -0,0 +1,43 @@ +/* */ +package com.rena4ka.bukkit.auth; +/* */ +/* */ + +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityListener; + +/* */ +/* */ +/* */ + +/* */ +/* */ public class AuthorizeEntityListener extends EntityListener +/* */ { + /* */ private final Authorize plugin; + + /* */ +/* */ + public AuthorizeEntityListener(Authorize instance) +/* */ { +/* 18 */ + this.plugin = instance; +/* */ + } + + /* */ +/* */ + public void onEntityDamage(EntityDamageEvent event) { +/* 22 */ + if (((event.getEntity() instanceof Player)) && +/* 23 */ (!this.plugin.isAuthorized(event.getEntity().getEntityId()))) +/* 24 */ event.setCancelled(true); +/* */ + } +/* */ +} + +/* Location: D:\Misc\Games\Minecraft\Beta\Development\Server Bukkit\Authorize.jar + * Qualified Name: com.rena4ka.bukkit.auth.AuthorizeEntityListener + * JD-Core Version: 0.6.0 + */ \ No newline at end of file diff --git a/Authorize/com/rena4ka/bukkit/auth/AuthorizePlayerListener.java b/Authorize/com/rena4ka/bukkit/auth/AuthorizePlayerListener.java new file mode 100644 index 0000000..c787c00 --- /dev/null +++ b/Authorize/com/rena4ka/bukkit/auth/AuthorizePlayerListener.java @@ -0,0 +1,442 @@ +/* */ +package com.rena4ka.bukkit.auth; +/* */ +/* */ + +import org.bukkit.entity.Player; +import org.bukkit.event.player.*; +import org.bukkit.inventory.ItemStack; + +import java.awt.*; +import java.io.IOException; +import java.sql.SQLException; + +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* */ + +/* */ +/* */ public class AuthorizePlayerListener extends PlayerListener +/* */ { + /* */ private final Authorize plugin; + + /* */ +/* */ + public AuthorizePlayerListener(Authorize instance) +/* */ { +/* 26 */ + this.plugin = instance; +/* */ + } + + /* */ +/* */ + public void onPlayerJoin(PlayerEvent event) +/* */ { +/* 31 */ + Player player = event.getPlayer(); +/* */ + try { +/* 33 */ + if (this.plugin.isRegistered(player.getName())) { +/* 34 */ + this.plugin.storeInventory(player.getName(), player.getInventory().getContents()); +/* 35 */ + player.getInventory().clear(); +/* 36 */ + player.sendMessage(this.plugin.loginMessage); +/* 37 */ + } else if (this.plugin.forceRegister) { +/* 38 */ + this.plugin.storeInventory(player.getName(), player.getInventory().getContents()); +/* 39 */ + player.getInventory().clear(); +/* 40 */ + player.sendMessage(this.plugin.registerMessage); +/* */ + } else { +/* 42 */ + this.plugin.authorize(event.getPlayer().getEntityId()); +/* */ + } +/* */ + } catch (IOException e) { +/* 44 */ + this.plugin.log.severe("[Authorize] Inventory file error:"); +/* 45 */ + e.printStackTrace(); +/* 46 */ + player.sendMessage(Color.red + "Error happend, report to admins!"); +/* */ + } +/* */ + } + + /* */ +/* */ + public void onPlayerQuit(PlayerEvent event) +/* */ { +/* 52 */ + Player player = event.getPlayer(); +/* 53 */ + ItemStack[] inv = this.plugin.getInventory(player.getName()); +/* 54 */ + if ((inv != null) && (!this.plugin.isAuthorized(player.getEntityId()))) { +/* 55 */ + player.getInventory().setContents(inv); +/* 56 */ + player.kickPlayer("inventory protection kicked"); +/* */ + } +/* 58 */ + this.plugin.unauthorize(player.getEntityId()); +/* */ + } + + /* */ +/* */ + public void onPlayerCommand(PlayerChatEvent event) +/* */ { +/* 63 */ + String[] split = event.getMessage().split(" "); +/* 64 */ + Player player = event.getPlayer(); +/* 65 */ + if (split[0].equals("/login")) { +/* 66 */ + if (this.plugin.isAuthorized(player.getEntityId())) { +/* 67 */ + player.sendMessage(this.plugin.authorizedMessage); +/* */ + } +/* 69 */ + else if (split.length < 2) { +/* 70 */ + player.sendMessage(this.plugin.loginUsageMessage); +/* */ + } +/* 72 */ + else if (this.plugin.checkPassword(player.getName(), split[1])) { +/* 73 */ + ItemStack[] inv = this.plugin.getInventory(player.getName()); +/* 74 */ + if (inv != null) +/* 75 */ player.getInventory().setContents(inv); +/* 76 */ + this.plugin.authorize(player.getEntityId()); +/* 77 */ + player.sendMessage(this.plugin.passwordAcceptedMessage); +/* 78 */ + } else if (this.plugin.kickOnBadPassword) { +/* 79 */ + ItemStack[] inv = this.plugin.getInventory(player.getName()); +/* 80 */ + if (inv != null) +/* 81 */ player.getInventory().setContents(inv); +/* 82 */ + player.kickPlayer(this.plugin.badPasswordMessage); +/* */ + } else { +/* 84 */ + player.sendMessage(this.plugin.badPasswordMessage); +/* */ + } +/* 86 */ + event.setMessage("/login ******"); +/* 87 */ + event.setCancelled(true); +/* 88 */ + } else if (split[0].equals("/register")) { +/* 89 */ + if (split.length < 2) { +/* 90 */ + player.sendMessage(this.plugin.registerUsageMessage); +/* */ + } +/* 92 */ + else if (this.plugin.isRegistered(player.getName())) +/* 93 */ player.sendMessage(this.plugin.alreadyRegisteredMessage); +/* 94 */ + else if (!this.plugin.allowRegister) +/* 95 */ player.sendMessage(this.plugin.registrationNotAllowedMessage); +/* 96 */ + else if ((this.plugin.requireEmail) && (split.length < 3)) +/* 97 */ player.sendMessage(this.plugin.emailRequiredMessage); +/* 98 */ + else if ((split.length >= 3) && (!this.plugin.checkEmail(split[2]))) +/* 99 */ player.sendMessage(this.plugin.emailUnexpectedMessage); +/* */ + else { +/* */ + try { +/* 102 */ + if (split.length >= 3) +/* 103 */ this.plugin.register(player.getName(), split[1], split[2]); +/* */ + else +/* 105 */ this.plugin.register(player.getName(), split[1]); +/* 106 */ + ItemStack[] inv = this.plugin.getInventory(player.getName()); +/* 107 */ + if (inv != null) +/* 108 */ player.getInventory().setContents(inv); +/* 109 */ + player.sendMessage(this.plugin.registeredMessage); +/* 110 */ + this.plugin.authorize(player.getEntityId()); +/* */ + } catch (IOException e) { +/* 112 */ + player.sendMessage(this.plugin.registerErrorMessage); +/* 113 */ + e.printStackTrace(); +/* */ + } catch (SQLException e) { +/* 115 */ + player.sendMessage(this.plugin.registerErrorMessage); +/* 116 */ + e.printStackTrace(); +/* */ + } +/* */ + } +/* 119 */ + event.setMessage("/register *****"); +/* 120 */ + event.setCancelled(true); +/* 121 */ + } else if (split[0].equals("/password")) { +/* 122 */ + if (split.length < 3) { +/* 123 */ + player.sendMessage(this.plugin.passwordUsageMessage); +/* */ + } +/* 125 */ + else if (!this.plugin.isRegistered(player.getName())) +/* 126 */ player.sendMessage(this.plugin.passwordNotRegisteredMessage); +/* 127 */ + else if (!this.plugin.allowPassChange) +/* 128 */ player.sendMessage(this.plugin.passNotAllowedMessage); +/* 129 */ + else if (!this.plugin.checkPassword(player.getName(), split[1])) +/* 130 */ player.sendMessage(this.plugin.badOldPasswordMessage); +/* */ + else { +/* */ + try { +/* 133 */ + this.plugin.changePassword(player.getName(), split[2]); +/* 134 */ + player.sendMessage(this.plugin.passwordChangedMessage); +/* */ + } catch (IOException e) { +/* 136 */ + player.sendMessage(this.plugin.passwordChangeErrorMessage); +/* 137 */ + e.printStackTrace(); +/* */ + } catch (SQLException e) { +/* 139 */ + player.sendMessage(this.plugin.passwordChangeErrorMessage); +/* 140 */ + e.printStackTrace(); +/* */ + } +/* */ + } +/* 143 */ + event.setMessage("/password ***** *****"); +/* 144 */ + event.setCancelled(true); +/* 145 */ + } else if (split[0].equals("/email")) { +/* 146 */ + if (split.length < 3) +/* 147 */ player.sendMessage(this.plugin.emailUsageMessage); +/* 148 */ + else if (!this.plugin.allowEmailChange) +/* 149 */ player.sendMessage(this.plugin.emailChangeNotAllowedMessage); +/* 150 */ + else if (!this.plugin.checkEmail(split[2])) { +/* 151 */ + player.sendMessage(this.plugin.emailUnexpectedMessage); +/* */ + } +/* 153 */ + else if (this.plugin.checkPassword(player.getName(), split[1])) +/* 154 */ player.sendMessage(this.plugin.badPasswordMessage); +/* */ + else { +/* */ + try { +/* 157 */ + this.plugin.changeEmail(player.getName(), split[2]); +/* 158 */ + player.sendMessage(this.plugin.emailChangedMessage); +/* */ + } catch (SQLException e) { +/* 160 */ + player.sendMessage(this.plugin.emailChangeErrorMessage); +/* 161 */ + e.printStackTrace(); +/* */ + } +/* */ + } +/* 164 */ + event.setMessage("/email ***** *****"); +/* 165 */ + event.setCancelled(true); +/* 166 */ + } else if (split[0].equals("/unregister")) { +/* 167 */ + if (split.length < 2) { +/* 168 */ + player.sendMessage(this.plugin.unregisterUsageMessage); +/* */ + } +/* 170 */ + else if (!this.plugin.isRegistered(player.getName())) +/* 171 */ player.sendMessage(this.plugin.unregisterNotRegisteredMessage); +/* 172 */ + else if (!this.plugin.allowUnregister) +/* 173 */ player.sendMessage(this.plugin.unregNotAllowedMessage); +/* 174 */ + else if (!this.plugin.checkPassword(player.getName(), split[1])) +/* 175 */ player.sendMessage(this.plugin.badPasswordMessage); +/* */ + else { +/* */ + try { +/* 178 */ + this.plugin.unregister(player.getName()); +/* 179 */ + player.sendMessage(this.plugin.unregisteredMessage); +/* */ + } catch (IOException e) { +/* 181 */ + player.sendMessage(this.plugin.unregisterErrorMessage); +/* 182 */ + e.printStackTrace(); +/* */ + } catch (SQLException e) { +/* 184 */ + player.sendMessage(this.plugin.unregisterErrorMessage); +/* 185 */ + e.printStackTrace(); +/* */ + } +/* */ + } +/* 188 */ + event.setMessage("/unregiter *****"); +/* 189 */ + event.setCancelled(true); +/* 190 */ + } else if (split[0].equals("/loginreset")) { +/* 191 */ + if (!this.plugin.isAdmin(player.getName())) +/* 192 */ player.sendMessage(this.plugin.notAdminMessage); +/* 193 */ + else if (split.length < 2) +/* 194 */ player.sendMessage(this.plugin.resetUsageMessage); +/* */ + else +/* */ try { +/* 197 */ + this.plugin.unregister(split[1]); +/* 198 */ + player.sendMessage(split[1] + " " + this.plugin.userResettedMessage); +/* */ + } catch (SQLException e) { +/* 200 */ + player.sendMessage("Error happend!"); +/* 201 */ + e.printStackTrace(); +/* */ + } catch (IOException e) { +/* 203 */ + player.sendMessage("Error happend!"); +/* 204 */ + e.printStackTrace(); +/* */ + } +/* */ + } +/* 207 */ + else if (split[0].equals("/loginreload")) { +/* 208 */ + if (!this.plugin.isAdmin(player.getName())) { +/* 209 */ + player.sendMessage(this.plugin.notAdminMessage); +/* */ + } else { +/* 211 */ + this.plugin.onDisable(); +/* 212 */ + this.plugin.onEnable(); +/* 213 */ + player.sendMessage(this.plugin.reloadedMessage); +/* */ + } +/* 215 */ + } else if (!this.plugin.isAuthorized(player.getEntityId())) { +/* 216 */ + event.setCancelled(true); +/* 217 */ + event.setMessage("/authorize_notloggedin_donothandlethis"); +/* */ + } +/* */ + } + + /* */ +/* */ + public void onPlayerMove(PlayerMoveEvent event) +/* */ { +/* 223 */ + if (!this.plugin.isAuthorized(event.getPlayer().getEntityId())) { +/* 224 */ + event.setCancelled(true); +/* 225 */ + event.getPlayer().teleportTo(event.getFrom()); +/* */ + } +/* */ + } + + /* */ +/* */ + public void onPlayerChat(PlayerChatEvent event) +/* */ { +/* 231 */ + if (!this.plugin.isAuthorized(event.getPlayer().getEntityId())) +/* 232 */ event.setCancelled(true); +/* */ + } + + /* */ +/* */ + public void onPlayerItem(PlayerItemEvent event) +/* */ { +/* 237 */ + if (!this.plugin.isAuthorized(event.getPlayer().getEntityId())) +/* 238 */ event.setCancelled(true); +/* */ + } +/* */ +} + +/* Location: D:\Misc\Games\Minecraft\Beta\Development\Server Bukkit\Authorize.jar + * Qualified Name: com.rena4ka.bukkit.auth.AuthorizePlayerListener + * JD-Core Version: 0.6.0 + */ \ No newline at end of file diff --git a/Authorize/plugin.yml b/Authorize/plugin.yml new file mode 100644 index 0000000..547af90 --- /dev/null +++ b/Authorize/plugin.yml @@ -0,0 +1,3 @@ +name: Authorization +main: com.rena4ka.bukkit.auth.Authorize +version: 14 diff --git a/BackupPlugin/.gitignore b/BackupPlugin/.gitignore new file mode 100644 index 0000000..b03abdc --- /dev/null +++ b/BackupPlugin/.gitignore @@ -0,0 +1,2 @@ + +*.iml \ No newline at end of file diff --git a/BackupPlugin/META-INF/MANIFEST.MF b/BackupPlugin/META-INF/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/BackupPlugin/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/AsyncStreamReader.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/AsyncStreamReader.java new file mode 100644 index 0000000..35ad155 --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/AsyncStreamReader.java @@ -0,0 +1,70 @@ +package com.mysticx.bukkit.backupplugin; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.logging.Level; + +/** + * http://www.javalobby.org/java/forums/t53333.html + * + * @author Venkat + */ +class AsyncStreamReader extends Thread { + private StringBuffer fBuffer = null; + private InputStream fInputStream = null; + private String fThreadId = null; + private boolean fStop = false; + + private String fNewLine = null; + + public AsyncStreamReader(InputStream inputStream, StringBuffer buffer, String threadId) { + fInputStream = inputStream; + fBuffer = buffer; + fThreadId = threadId; + + fNewLine = System.getProperty("line.separator"); + } + + public String getBuffer() { + return fBuffer.toString(); + } + + public void run() { + try { + readCommandOutput(); + } catch (Exception ex) { + //ex.printStackTrace(); //DEBUG + } + } + + private void readCommandOutput() throws IOException { + BufferedReader bufOut = new BufferedReader(new InputStreamReader(fInputStream)); + String line = null; + while ((fStop == false) && ((line = bufOut.readLine()) != null)) { + fBuffer.append(line + fNewLine); + printToDisplayDevice(line); + } + bufOut.close(); + //printToConsole("END OF: " + fThreadId); //DEBUG + } + + public void stopReading() { + fStop = true; + } + + private void printToDisplayDevice(String line) { + MessageHandler.log(Level.FINEST, "(" + fThreadId + ") " + line); +// if( fLogDevice != null ) +// fLogDevice.log(line); +// else +// { +// //printToConsole(line);//DEBUG +// } + } + + private synchronized void printToConsole(String line) { + System.out.println(line); + } +} \ No newline at end of file diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupPlugin.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupPlugin.java new file mode 100644 index 0000000..acc5741 --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupPlugin.java @@ -0,0 +1,358 @@ +package com.mysticx.bukkit.backupplugin; + +import com.nijiko.permissions.PermissionHandler; +import com.nijikokun.bukkit.Permissions.Permissions; +import net.minecraft.server.MinecraftServer; +import org.bukkit.Server; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.PluginLoader; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +/** + * BackupPlugin for Bukkit + * 2011-01-18 + *

+ * BackupPlugin by MysticX is licensed under a Creative Commons + * Attribution-NonCommercial-ShareAlike 3.0 Unported License. + * http://creativecommons.org/licenses/by-nc-sa/3.0/ + *

+ * Permissions beyond the scope of this license may be available + * at http://forum.hey0.net/showthread.php?tid=179 + * + * @author MysticX + */ +public class BackupPlugin extends JavaPlugin implements Observer { + + // listeners + private final BackupPluginPlayerListener playerListener = new BackupPluginPlayerListener(this); + // private final BackupPluginBlockListener blockListener = new BackupPluginBlockListener(this); + private final HashMap debugees = new HashMap(); + + // config +// private Configuration config; + private TimeUnit timeunit = TimeUnit.MINUTES; + + // cache control + private CacheControl cc; + + // Units + private BackupUnit bu; + private MapperUnit mu; + + private static PermissionHandler permissions = null; + + public static PermissionHandler getPermissions() + { + return permissions; + } + + public BackupPlugin(PluginLoader pluginLoader, Server instance, PluginDescriptionFile desc, File folder, File plugin, ClassLoader cLoader) { + super(pluginLoader, instance, desc, folder, plugin, cLoader); + +// File directory = new File(desc.getName()); +// if (!directory.exists()) +// directory.mkdir(); + + MessageHandler.setServer(instance); + } + + /* + * (non-Javadoc) + * @see org.bukkit.plugin.Plugin#onEnable() + */ + public void onEnable() { + + try { + // + ((MinecraftServer) (CraftServer.class.getDeclaredField("console").get(this.getServer()))).console.isPlayer(); + } catch (Throwable e) { + MessageHandler.log(Level.SEVERE, "Not running on CraftBukkit/Notchian Server! Unloading self."); + getServer().getPluginManager().disablePlugin(this); + return; + } + if (!setupPermissions()) { + MessageHandler.log(Level.SEVERE, "Permissions plugin not loaded! No one can use commands."); + } + // Register our events + PluginManager pm = getServer().getPluginManager(); + pm.registerEvent(Event.Type.PLAYER_COMMAND, this.playerListener, Event.Priority.Normal, this); + + PluginDescriptionFile pdfFile = this.getDescription(); + MessageHandler.info(pdfFile.getName() + " version " + pdfFile.getVersion() + " is enabled!"); + load(); + } + + private boolean setupPermissions() { + Plugin p = this.getServer().getPluginManager().getPlugin("Permissions"); + if (permissions == null && p != null) { + permissions = ((Permissions) p).getHandler(); + return true; + } + return false; + } + + /** + * Loads property files and initializes some other stuff + * + * @return true if successful + */ + protected boolean load() { +// Configuration config = this.getConfiguration(); + + //TODO: use Bukkit config when its finally working! + com.mysticx.bukkit.backupplugin.Configuration config = new com.mysticx.bukkit.backupplugin.Configuration("BackupPlugin.properties"); + config.load(); + + String separator = System.getProperty("file.separator"); + + // some important values + String world = config.getString("level-name", "world"); + String backup_folder = config.getString("backup-path", "world-backups"); + String mapper_path = config.getString("mapper-executable", "mcmap" + separator + "mcmap.exe"); + String map_folder = config.getString("map-path", "world-maps"); + String map_options = config.getString("map-options", "-png -file $o $w;-night -png -file $o $w"); + Integer autobackup_period = config.getInt("autobackup-period", 0); + Integer automap_period = config.getInt("automap-period", 0); + Integer cache_lifetime = config.getInt("cache-lifetime", 30); + String tempdir = backup_folder + "/temp"; + String loglevel = config.getString("log-level", "INFO"); + String time_unit = config.getString("time-unit", "MINUTES"); + Integer num_backups = config.getInt("backup-history", 5); + Boolean useLatest = config.getBoolean("use-latest", false); + String firstRun = config.getString("first-run", "1200"); + String admins = config.getString("authorized-users", ""); + + MessageHandler.setLogLevel(loglevel); + + // authorized users + authorizedUsers = new ArrayList(); + + String[] access = admins.split(";"); + + String logInfo = ""; + + for (String name : access) { + if (!name.isEmpty()) { + authorizedUsers.add(name); + logInfo += name + ", "; + } + } + + + MessageHandler.log(Level.FINE, String.format("There are %d user(s) in the authorized-users list: %s", authorizedUsers.size(), logInfo)); + + // timeUnit + try { + TimeUnit tu = TimeUnit.valueOf(time_unit); + this.timeunit = tu; + } catch (Exception e) { + MessageHandler.warning("Failed to parse time-unit, using default."); + } + + // init cache + this.cc = CacheControl.getInstance(); + this.cc.setWorld(world); + this.cc.setTimeUnit(timeunit); + this.cc.setCacheLifetime(cache_lifetime); + this.cc.setTempDir(new File(tempdir)); + this.cc.setCacheHistory(num_backups); + + // init BackupUnit + this.bu = new BackupUnit(this.getServer(), new File(backup_folder), true); + this.bu.addObserver(this); + + // init MapperUnit + this.mu = new MapperUnit(this.getServer(), new File(map_folder), false); + this.mu.setMapperPath(new File(mapper_path)); + this.mu.setUseLatest(useLatest); + this.mu.addObserver(this); + + String[] parameters = map_options.split(";"); + this.mu.setMapOptions(parameters); + + // init scheduler + scheduler.shutdownNow(); + scheduler = Executors.newScheduledThreadPool(2); + + // schedule timer + long backup_delay = -1; + long map_delay = -1; + + try { + long timeToExecuteB = calcNextPointOfTime(firstRun, "HHmm", TimeUnit.MILLISECONDS.convert(autobackup_period, timeunit)); + backup_delay = timeToExecuteB - System.currentTimeMillis(); + + long timeToExecuteM = calcNextPointOfTime(firstRun, "HHmm", TimeUnit.MILLISECONDS.convert(automap_period, timeunit)); + map_delay = timeToExecuteM - System.currentTimeMillis(); + } catch (ParseException pe) { + MessageHandler.log(Level.WARNING, "Failed to parse firstRun, disabled automatic execution", pe); + } + + if (autobackup_period != null && backup_delay >= 0 && autobackup_period > 0) { + setupTimer(bu, backup_delay, autobackup_period, this.timeunit); + } + + if (automap_period != null && map_delay >= 0 && automap_period > 0) { + setupTimer(mu, map_delay, automap_period, this.timeunit); + } + + return true; + } + + /* + * (non-Javadoc) + * @see org.bukkit.plugin.Plugin#onDisable() + */ + public void onDisable() { + System.out.println("BackupPlugin disabled!"); + } + + /** + * Checks whether player is in debug mode or not + * + * @param player + * @return + */ + public boolean isDebugging(final Player player) { + if (debugees.containsKey(player)) { + return debugees.get(player); + } else { + return false; + } + } + + /** + * Sets debug status of player + * + * @param player + * @param value + */ + public void setDebugging(final Player player, final boolean value) { + debugees.put(player, value); + } + + /** + * @param time + * @param pattern + * @param period + * @return next scheduled point in time, 0 if there is none + * @throws ParseException + */ + private long calcNextPointOfTime(String time, String pattern, long period) throws ParseException { + if (period <= 0) + return 0; + + Date d = new Date(); + + DateFormat df = new SimpleDateFormat(pattern); + df.setLenient(true); + Date date = df.parse(time); + + //TODO rewrite + d.setHours(date.getHours()); + d.setMinutes(date.getMinutes()); + d.setSeconds(0); + + MessageHandler.log(Level.FINEST, "firstRun: " + d.toString()); + + long nextRun = d.getTime(); + + while (nextRun < System.currentTimeMillis()) { + MessageHandler.log(Level.FINEST, "Date is in the past, adding some minutes: " + period / 1000 / 60); + nextRun += period; + } + + return nextRun; + } + + /** + * Scheduled Executor for plugin units + */ + private ScheduledExecutorService scheduler = Executors + .newScheduledThreadPool(2); + + /** + * Starts a new timer with given Runnable and times + * + * @param r the Runnable object + * @param delay in milliseconds + * @param period period + * @param TimeUnit TimeUnit + * @return + */ + private boolean setupTimer(Runnable r, long delay, Integer period, TimeUnit tu) { + ScheduledFuture sf = scheduler.scheduleAtFixedRate(r, tu.convert(delay, TimeUnit.MILLISECONDS), period, tu); + + MessageHandler.info("Finished setting up a thread: " + r.getClass() + " Next run in: " + TimeUnit.MINUTES.convert(delay, TimeUnit.MILLISECONDS) + " minutes."); + return true; + } + + /** + * update only happens after a manual unit run, reset force for scheduler afterwards + */ + @Override + public void update(Observable arg0, Object arg1) { + if (arg0 instanceof PluginUnit) { + PluginUnit pu = (PluginUnit) arg0; + pu.resetForce(); + } + } + + /** + * Backups current world + * + * @param force true disables cache usage + * @return true if successful + */ + protected void performBackup(boolean force) { + bu.setForce(force); + scheduler.execute(bu); + } + + + /** + * Creates map of current world + * + * @param force true disables cache usage + * @return true if successful + */ + protected void performMapping(boolean force) { + mu.setForce(force); + scheduler.execute(mu); + } + + // authorized users go in here + List authorizedUsers = new ArrayList(); + + /** + * checks if an user is authorized to use ingame commands + * + * @param userName + * @return + */ + protected boolean isAuthorized(String userName) { + for (String user : authorizedUsers) { + if (userName.compareToIgnoreCase(user) == 0) { + return true; + } + } + return false; + } +} + diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupPluginPlayerListener.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupPluginPlayerListener.java new file mode 100644 index 0000000..ac8461c --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupPluginPlayerListener.java @@ -0,0 +1,101 @@ +package com.mysticx.bukkit.backupplugin; + +import com.nijiko.permissions.PermissionHandler; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerChatEvent; +import org.bukkit.event.player.PlayerListener; + +/** + * Handle events for all Player related events + * + * @author MysticX + */ +public class BackupPluginPlayerListener extends PlayerListener { + private final BackupPlugin plugin; + + public BackupPluginPlayerListener(BackupPlugin instance) { + plugin = instance; + } + + @Override + public void onPlayerCommand(PlayerChatEvent event) { + Player player = event.getPlayer(); + String[] split = event.getMessage().split(" "); + + // check for backup command + if (split[0].equals("/backup") && canUseCommand(player, "backup")) { + if (split.length > 2) { + player.sendMessage(ChatColor.RED + "Correct usage is: /backup (optional)"); + } else { + boolean force = false; + if (split.length == 2) force = Boolean.valueOf(split[1]); + + String broadcast = player.getName() + " triggered world backup."; + MessageHandler.info(broadcast + " force = " + force); + MessageHandler.broadcast(broadcast); + + plugin.performBackup(force); + } + + event.setCancelled(true); + return; + } else if (split[0].equals("/map") && canUseCommand(player, "map")) { + if (split.length > 2) { + player.sendMessage(ChatColor.RED + "Correct usage is: /map (optional)"); + } else { + boolean force = false; + if (split.length == 2) force = Boolean.valueOf(split[1]); + + String broadcast = player.getName() + " triggered world mapping."; + MessageHandler.info(broadcast + " force = " + force); + MessageHandler.broadcast(broadcast); + + plugin.performMapping(force); + } + + event.setCancelled(true); + return; + } else if (split[0].equals("/breload") && canUseCommand(player, "reload")) { + String broadcast = player.getName() + " triggered config reload."; + MessageHandler.info(broadcast); + MessageHandler.broadcast(broadcast); + + plugin.load(); + + event.setCancelled(true); + return; + } else if (split[0].equals("/loglevel") && split.length == 2 && canUseCommand(player, "loglevel")) { + MessageHandler.info(player.getName() + " is changing log level to " + split[1]); + boolean b = MessageHandler.setLogLevel(split[1]); + if (b) player.sendMessage("Done!"); + else player.sendMessage("Failed!"); + + event.setCancelled(true); + return; + } + + // no match + event.setCancelled(false); + } + + /** + * Checks if a given player can use a given command + * (Tries to user Group Users Plugin first, own config only if there is no plugin) + * + * @param player + * @param command + * @return + */ + private boolean canUseCommand(Player player, String command) { + // check for groupUserPlugin + if (BackupPlugin.getPermissions() != null) { + PermissionHandler ph = BackupPlugin.getPermissions(); + return ph.has(player, "backupplugin." + command); + } + // no permissions ... + return false; + } + +} + diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupUnit.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupUnit.java new file mode 100644 index 0000000..4c53900 --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/BackupUnit.java @@ -0,0 +1,78 @@ +package com.mysticx.bukkit.backupplugin; + +import org.bukkit.Server; + +import java.io.File; +import java.util.logging.Level; + +/** + * BackupPlugin + *

+ * Backup Unit + * + * @author MysticX + */ +public class BackupUnit extends PluginUnit { + + /** + * Default constructor + */ + public BackupUnit(Server instance, File workdir) { + super(instance, workdir); + this.name = "BackupUnit"; + } + + /** + * Default constructor + */ + public BackupUnit(Server instance, File workdir, boolean force) { + super(instance, workdir, force); + this.name = "BackupUnit"; + } + + /** + * creates backup of world data + */ + @Override + public void run() { + + while (!isEnabled) { + MessageHandler.log(Level.WARNING, + " is disabled. Thread goes to sleep."); + try { + this.wait(); + } catch (InterruptedException e) { + MessageHandler.log(Level.WARNING, + "woke up from sleep unexpectedly!", e); + } + } + + MessageHandler.log(Level.INFO, "Starting backup process.."); + + consoleCommandLog("Backup process started."); + // save world and disable saving for backup process + saveWorld(); + consoleCommandLog("Creating backup."); + try { + // generate filename + String filename = generateFilename(".zip"); + + File outputFile = new File(this.getWorkDir(), filename); + + if (cc.persistCache(outputFile, this.isForce())) { + MessageHandler.log(Level.INFO, "Backup sucessfull"); + } else { + MessageHandler.log(Level.WARNING, "Backup failed"); + } + } catch (Exception e) { + MessageHandler.log(Level.SEVERE, "Error during backup: ", e); + } finally { + // TODO: enable saving + consoleCommandLog("Backup process complete. Enabling level saving ..."); + console.e.C = false; + setChanged(); + notifyObservers(); + } + } + +} diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/CacheControl.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/CacheControl.java new file mode 100644 index 0000000..2b94e73 --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/CacheControl.java @@ -0,0 +1,308 @@ +package com.mysticx.bukkit.backupplugin; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; + +/** + * CacheControl is to be used as singleton. + *

+ * Cache is located on hdd and contains all map data. cache-lifetime determines + * when cache becomes obsolete CacheControl needs to ensure that no concurrent + * access to the cache is granted + * + * @author MysticX + */ +public class CacheControl { + + // singleton + public static CacheControl cc; + + /** + * Cache cleanup task for timer + * + * @author MysticX + */ + private class CacheCleanerTask extends TimerTask { + + @Override + public void run() { + deleteCache(); + timer.cancel(); + MessageHandler.log(Level.INFO, "Cache lifetime ended."); + } + + } + + // helper stuff + private IOHelper iohelper; + private File cache; + private File world; + + // cache lifetime + private int cache_lifetime; + private int cache_history; + private TimeUnit tu; + private Timer timer; + private Lock lock; + + /** + * Private constructor, use getInstance() + */ + private CacheControl() { + this.iohelper = IOHelper.getInstance(); + this.cache = null; + this.world = null; + this.tu = TimeUnit.MINUTES; + this.cache_lifetime = 30; + this.cache_history = 5; + this.timer = new Timer(); + this.lock = new ReentrantLock(); + } + + /** + * @return instance of CacheControl + */ + public static CacheControl getInstance() { + if (cc == null) { + cc = new CacheControl(); + } + return cc; + } + + /** + * Sets TimeUnit + * + * @param tu + */ + public void setTimeUnit(TimeUnit tu) { + this.tu = tu; + } + + /** + * Sets TimeUnit + * + * @param tu + */ + public void setTimeUnit(String tu) { + try { + TimeUnit timeunit = TimeUnit.valueOf(tu); + setTimeUnit(timeunit); + } catch (Exception e) { + MessageHandler.warning("Failed to parse time-unit, using default."); + } + } + + /** + * Sets temp/cache dir + * + * @param tempdir + */ + public void setTempDir(File tempdir) { + this.cache = tempdir; + + // TODO: maybe somewhere else + // if (isCacheObsolete()) { + // deleteCache(); + // } + } + + /** + * Sets world name and path + * + * @param worldname + */ + public void setWorld(String worldname) { + this.world = new File(worldname); + } + + /** + * @return file object representing the current world + */ + public File getWorld() { + return world; + } + + /** + * Returns cache lock + * + * @return lock + */ + public Lock getLock() { + return lock; + } + + /** + * Sets cache lifetime + * + * @param lifetime according to TimeUnit + */ + public void setCacheLifetime(int lifetime) { + this.cache_lifetime = lifetime; + } + + /** + * Sets cache history + * + * @param history number of backups to keep + */ + public void setCacheHistory(int history) { + this.cache_history = history; + } + + /** + * Checks if cache exists and is up to date + * + * @return true, if cache is too old + */ + private boolean isCacheObsolete() { + return (!this.cache.exists() || (System.currentTimeMillis() - this.cache + .lastModified()) > tu.toMillis(this.cache_lifetime)); + } + + /** + * Resets timer + */ + private void scheduleTimer() { + timer = new Timer(); + timer.schedule(new CacheCleanerTask(), tu.toMillis(this.cache_lifetime)); + MessageHandler.log(Level.FINEST, "CacheCleaner was scheduled."); + } + + /** + * Deletes the temp dir / cache dir + * + * @return true if successful + */ + private boolean deleteCache() { + + if (!cache.exists()) + return true; + + MessageHandler.log(Level.FINEST, "deleteCache() obtaining lock.."); + lock.lock(); + MessageHandler.log(Level.INFO, "Deleting cache, might be obsolete."); + + try { + if (!iohelper.deleteDirectory(cache)) { + MessageHandler.log(Level.WARNING, + "Failed to delete temp folder."); + return false; + } + } finally { + lock.unlock(); + MessageHandler.log(Level.FINEST, "deleteCache() unlocked.."); + } + + return true; + } + + /** + * Returns cache + * + * @param force initializes cache rebuild + * @return cache + */ + public synchronized File getCache(boolean force) { + // return existing cache + if (!force && !isCacheObsolete()) { + MessageHandler.log(Level.FINEST, "Cache still up to date!"); + return cache; + } else { + // cancel timer + if (timer != null) { + timer.cancel(); + } + // rebuild cache + if (rebuildCache()) { + // setup timer + scheduleTimer(); + return cache; + } else { + MessageHandler.log(Level.WARNING, "Cache couldn't be rebuilt!"); + return null; + } + } + } + + /** + * Initializes map cache on hdd + * + * @return Cache + */ + private boolean rebuildCache() { + // check if world exists + if (!world.exists()) { + MessageHandler.log(Level.WARNING, "World path doesn't exist!"); + return false; + } + + // lock.lock(); + MessageHandler + .log(Level.INFO, + "Rebuilding Cache. This can take several minutes, depending on the world size."); + + if (cache.exists() && !deleteCache()) { + // lock.unlock(); + return false; + } + + try { + MessageHandler.log(Level.FINEST, "rebuildCache() obtaining lock.."); + lock.lock(); + MessageHandler.log(Level.FINEST, + "rebuildCache() got lock, copy dir.."); + // copy world to temp/cache + iohelper.copyDir(world, cache); + } catch (FileNotFoundException e) { + MessageHandler.log(Level.SEVERE, "Error rebuilding cache: ", e); + return false; + } catch (IOException e) { + MessageHandler.log(Level.SEVERE, "Error rebuilding cache: ", e); + return false; + } finally { + lock.unlock(); + MessageHandler.log(Level.FINEST, "rebuildCache() unlocked.."); + } + + return true; + + } + + /** + * Persists cache to zip + */ + public boolean persistCache(File outputFile, boolean force) { + MessageHandler + .log(Level.FINE, "Persisting cache / creating zip file.."); + try { + File cache = this.getCache(force); + MessageHandler.log(Level.FINEST, + "persistCache() got cache, obtaining lock.."); + lock.lock(); + MessageHandler.log(Level.FINEST, + "persistCache() got lock, starting zip operation.."); + iohelper.zipDirectory(cache, outputFile); + MessageHandler.log(Level.FINEST, + "persistCache() finished zip operation.."); + + if (cache_history > 0) + iohelper.deleteOldFiles(cache.getParentFile(), this.world.getName(), cache_history); + return true; + } catch (IOException e) { + MessageHandler.log(Level.SEVERE, + "Error while zipping temp folder!", e); + } finally { + lock.unlock(); + MessageHandler.log(Level.FINEST, "persistCache() unlocked.."); + } + return false; + } + +} diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/Configuration.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/Configuration.java new file mode 100644 index 0000000..9455b69 --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/Configuration.java @@ -0,0 +1,178 @@ +package com.mysticx.bukkit.backupplugin; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Level; + +public class Configuration { + + private Properties properties; + private String name; + + public Configuration(String name) { + this.properties = new Properties(); + this.name = name; + + File file = new File(name); + + if (file.exists()) + load(); + else + save(); + } + + public void load() { + try { + this.properties.load(new FileInputStream(this.name)); + } catch (IOException ioex) { + MessageHandler.log(Level.SEVERE, "Can't load config!", ioex); + } + } + + public void save() { + try { + this.properties.store(new FileOutputStream(this.name), + "BackupPlugin Config File"); + } catch (IOException ioex) { + MessageHandler.log(Level.SEVERE, "Can't save config!", ioex); + } + } + + public Map returnMap() throws FileNotFoundException, IOException { + Map map = new HashMap(); + BufferedReader reader = new BufferedReader( + new FileReader(this.name)); + String line; + while ((line = reader.readLine()) != null) { + if ((line.trim().length() == 0) || (line.charAt(0) == '#')) { + continue; + } + int delimPosition = line.indexOf('='); + String key = line.substring(0, delimPosition).trim(); + String value = line.substring(delimPosition + 1).trim(); + map.put(key, value); + } + reader.close(); + return map; + } + + public void removeKey(String key) { + this.properties.remove(key); + save(); + } + + public boolean keyExists(String key) { + return this.properties.containsKey(key); + } + + public String getString(String key) { + if (this.properties.containsKey(key)) { + return this.properties.getProperty(key); + } + + return ""; + } + + public String getString(String key, String value) { + if (this.properties.containsKey(key)) { + return this.properties.getProperty(key); + } + setString(key, value); + return value; + } + + public void setString(String key, String value) { + this.properties.setProperty(key, value); + save(); + } + + public int getInt(String key) { + if (this.properties.containsKey(key)) { + return Integer.parseInt(this.properties.getProperty(key)); + } + + return 0; + } + + public int getInt(String key, int value) { + if (this.properties.containsKey(key)) { + return Integer.parseInt(this.properties.getProperty(key)); + } + + setInt(key, value); + return value; + } + + public void setInt(String key, int value) { + this.properties.setProperty(key, String.valueOf(value)); + save(); + } + + public double getDouble(String key) { + if (this.properties.containsKey(key)) { + return Double.parseDouble(this.properties.getProperty(key)); + } + + return 0.0D; + } + + public double getDouble(String key, double value) { + if (this.properties.containsKey(key)) { + return Double.parseDouble(this.properties.getProperty(key)); + } + + setDouble(key, value); + return value; + } + + public void setDouble(String key, double value) { + this.properties.setProperty(key, String.valueOf(value)); + save(); + } + + public long getLong(String key) { + if (this.properties.containsKey(key)) { + return Long.parseLong(this.properties.getProperty(key)); + } + + return 0L; + } + + public long getLong(String key, long value) { + if (this.properties.containsKey(key)) { + return Long.parseLong(this.properties.getProperty(key)); + } + + setLong(key, value); + return value; + } + + public void setLong(String key, long value) { + this.properties.setProperty(key, String.valueOf(value)); + save(); + } + + public boolean getBoolean(String key) { + if (this.properties.containsKey(key)) { + return Boolean.parseBoolean(this.properties.getProperty(key)); + } + + return false; + } + + public boolean getBoolean(String key, boolean value) { + if (this.properties.containsKey(key)) { + return Boolean.parseBoolean(this.properties.getProperty(key)); + } + + setBoolean(key, value); + return value; + } + + public void setBoolean(String key, boolean value) { + this.properties.setProperty(key, String.valueOf(value)); + save(); + } +} diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/IOHelper.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/IOHelper.java new file mode 100644 index 0000000..df146d5 --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/IOHelper.java @@ -0,0 +1,262 @@ +package com.mysticx.bukkit.backupplugin; + +import java.io.*; +import java.util.Arrays; +import java.util.Comparator; +import java.util.logging.Level; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * Some helper methods for I/O handling + * + * @author MysticX + */ +class IOHelper { + + // singleton + private static IOHelper instance = new IOHelper(); + + /** + * @return an instance of IOHelper + */ + public static IOHelper getInstance() { + return instance; + } + + /** + * Default constructor + */ + private IOHelper() { + } + + + // Buffer size for zipping + public static int BUFFER = 8192; + + + /** + * Zips given directory + * + * @param directory + * @param zip + * @throws IOException + */ + public void zipDirectory(File directory, File zip) throws IOException { + zip.getParentFile().mkdirs(); +// zip.mkdirs(); + if (!zip.exists()) { + zip.createNewFile(); + } + ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip)); + zip(directory, directory, zos); + zos.close(); + } + + private void zip(File directory, File base, ZipOutputStream zos) + throws IOException { + File[] files = directory.listFiles(); + byte[] buffer = new byte[BUFFER]; + int read = 0; + for (int i = 0, n = files.length; i < n; i++) { + if (files[i].isDirectory()) { + zip(files[i], base, zos); + } else { + FileInputStream in = new FileInputStream(files[i]); + ZipEntry entry = new ZipEntry(files[i].getPath().substring( + base.getPath().length() + 1)); + zos.putNextEntry(entry); + while (-1 != (read = in.read(buffer))) { + zos.write(buffer, 0, read); + } + in.close(); + } + } + } + + + // streams + private BufferedInputStream in = null; + private BufferedOutputStream out = null; + + + /** + * Copies a directory + * + * @param source + * @param target + * @throws FileNotFoundException + * @throws IOException + */ + public void copyDir(File source, File target) throws FileNotFoundException, + IOException { + + File[] files = source.listFiles(); + target.mkdirs(); + for (File file : files) { + if (file.isDirectory()) { + copyDir(file, + new File(target.getAbsolutePath() + + System.getProperty("file.separator") + + file.getName())); + } else { + copyFile(file, + new File(target.getAbsolutePath() + + System.getProperty("file.separator") + + file.getName())); + } + } + } + + + /** + * Copies a file + * + * @param file + * @param target + * @throws FileNotFoundException + * @throws IOException + */ + public void copyFile(File file, File target) throws FileNotFoundException, + IOException { + in = new BufferedInputStream(new FileInputStream(file)); + out = new BufferedOutputStream(new FileOutputStream(target, true)); + int bytes = 0; + while ((bytes = in.read()) != -1) { + out.write(bytes); + } + in.close(); + out.close(); + } + + /** + * Copies a file + * + * @param file + * @param target + * @param append + * @throws FileNotFoundException + * @throws IOException + */ + public void copyFile(File file, File target, boolean append) throws FileNotFoundException, + IOException { + MessageHandler.log(Level.FINEST, "copy operation: " + file + " to " + target + " (" + append + ")"); + in = new BufferedInputStream(new FileInputStream(file)); + out = new BufferedOutputStream(new FileOutputStream(target, append)); + int bytes = 0; + while ((bytes = in.read()) != -1) { + out.write(bytes); + } + in.close(); + out.close(); + } + + + /** + * Delete given directory + * + * @param path + * @return true, if successful + */ + public boolean deleteDirectory(File path) { + if (path.exists()) { + File[] files = path.listFiles(); + for (int i = 0; i < files.length; i++) { + if (files[i].isDirectory()) { + deleteDirectory(files[i]); + } else { + files[i].delete(); + } + } + } + return (path.delete()); + } + + /** + * Delete given file + * + * @param path + * @return true, if successful + */ + public boolean deleteFile(File path) { + MessageHandler.log(Level.FINE, "deleting file: " + path); + return (path.delete()); + } + + /** + * Delete old files in given directory + * + * @param path + * @param world - the worldname + * @param number of backups to keep + * @return true, if successful + */ + public boolean deleteOldFiles(File path, String world, int number) { + boolean success = true; + + if (path.exists()) { + File[] files = path.listFiles(new BackupFilter(world)); + + if (files.length > number) { + // too many files + + // sort array + Arrays.sort(files, new Comparator() { + + @Override + public int compare(File o1, File o2) { + if (o1.lastModified() == o2.lastModified()) + return 0; + if (o1.lastModified() < o2.lastModified()) + return -1; + else + return 1; + + } + }); + + for (int i = 0; i < files.length - number; i++) { + MessageHandler.log(Level.INFO, "deleting old backup file: " + files[i]); + if (!files[i].delete()) + success = false; + } + + } + } + return success; + } + + + /** + * Simple existence check for files or directories + * + * @param file + */ + private boolean checkFile(File file) { + if (!file.exists()) { +// l.warning("[BackupPlugin] Can't find specified file: " +// + file.getAbsolutePath()); + return false; + } + return true; + } + +} + +class BackupFilter implements FilenameFilter { + + String world; + + public BackupFilter(String world) { + super(); + this.world = world; + } + + @Override + public boolean accept(File dir, String name) { + if (name.startsWith(world)) + return true; + else + return false; + } +} \ No newline at end of file diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/MapperUnit.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/MapperUnit.java new file mode 100644 index 0000000..df9c669 --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/MapperUnit.java @@ -0,0 +1,177 @@ +package com.mysticx.bukkit.backupplugin; + +import org.bukkit.Server; + +import java.io.File; +import java.io.IOException; +import java.util.logging.Level; + +/** + * Backup Plugin + *

+ * Mapper Unit + * + * @author MysticX + */ +public class MapperUnit extends PluginUnit { + + // values + private File mapper_path; + private String[] map_options; + private boolean useLatest; + + /** + * Default constructor + */ + public MapperUnit(Server instance, File workdir) { + super(instance, workdir); + this.name = "MapperUnit"; + } + + /** + * Default constructor + */ + public MapperUnit(Server instance, File workdir, boolean force) { + super(instance, workdir, force); + this.name = "MapperUnit"; + } + + + /** + * Sets path to mapper executable + * + * @param mapper_path + */ + public void setMapperPath(File mapper_tool) { + this.mapper_path = mapper_tool; + if (mapper_path == null || !mapper_path.exists()) { + setEnabled(false); + MessageHandler.warning("Disabled MapperUnit, mapper_path invalid: " + mapper_path); + } + } + + /** + * Sets mapping options + * + * @param map_options + */ + public void setMapOptions(String[] map_options) { + this.map_options = map_options; + } + + /** + * Enables or disables usage of latest.png + * + * @param true, if enabled + */ + public void setUseLatest(boolean useLatest) { + this.useLatest = useLatest; + } + + /** + * Generates maps via commandline + */ + @Override + public void run() { + + while (!isEnabled) { + MessageHandler.log(Level.WARNING, " is disabled. Thread goes to sleep."); + try { + this.wait(); + } catch (InterruptedException e) { + MessageHandler.log(Level.WARNING, "woke up from sleep unexpectedly!", e); + } + } + + MessageHandler.log(Level.INFO, "Starting map generation process.. this could take a while!"); + + // save world and disable saving for mapping process + consoleCommandLog("Caching process started."); + saveWorld(); + + File inputFolder = null; + + try { + // retrieve cache + inputFolder = cc.getCache(this.isForce()); + } catch (Exception e) { + MessageHandler.log(Level.SEVERE, "An error ocurred during mapping", e); + return; + } finally { + // TODO: enable saving again + consoleCommandLog("Caching process completed. Enabling level saving."); + console.e.C = false; + } + + + // create folders + if (!this.getWorkDir().exists()) { + this.getWorkDir().mkdirs(); + } + + // lock cache while generating maps + cc.getLock().lock(); + MessageHandler.log(Level.FINEST, "got lock, starting map generation"); + + // do mappings + for (int i = 0; i < map_options.length; i++) { + MessageHandler.info("Mapping pass " + (i + 1) + " of " + map_options.length + "..."); + + // modify parameters + String filename = generateFilename(".png"); + String map_parameters = new String(map_options[i]); + map_parameters = map_parameters.replace("$o", new File(this.getWorkDir(), filename).getAbsolutePath()); + map_parameters = map_parameters.replace("$w", inputFolder.getAbsolutePath()); + + if (map_parameters.contains("$m")) + map_parameters = map_parameters.replace("$m", mapper_path.getParent()); + + MessageHandler.log(Level.FINE, "Mapper usage: " + mapper_path + " " + map_parameters); + + // generate maps + executeExternal(mapper_path, map_parameters); + + // save latest.png at first run + if (i == 0 && useLatest) { + try { + iohelper.deleteFile(new File(this.getWorkDir(), "latest.png")); + iohelper.copyFile(new File(this.getWorkDir(), filename), new File(this.getWorkDir(), "latest.png"), false); + } catch (IOException e) { + MessageHandler.log(Level.WARNING, "Creating latest.png failed: ", e); + } + + } + } + + MessageHandler.info("Mapping process finished."); + cc.getLock().unlock(); + + setChanged(); + notifyObservers(); + } + + /** + * Executes external binaries + * + * @param program path to executable + * @param arguments arguments to invoke + * @return true if successful + */ + private void executeExternal(File program, String arguments) { + try { + long start = System.currentTimeMillis(); + SysCommandExecutor cmdExecutor = new SysCommandExecutor(); + int exitStatus = cmdExecutor.runCommand(program + " " + arguments); + + if (exitStatus != 0) { + MessageHandler.warning("Mapping failed, something went wrong while executing external code! Exit Status: " + exitStatus); + } else { + MessageHandler.info("Mapping successful! Executing mapper took " + calculateTimeDifference(start, System.currentTimeMillis()) + " seconds."); + } + } catch (Exception e) { + MessageHandler.log(Level.SEVERE, + "Error while executing external code!", e); + } + } + +} diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/MessageHandler.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/MessageHandler.java new file mode 100644 index 0000000..2b52fce --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/MessageHandler.java @@ -0,0 +1,168 @@ +package com.mysticx.bukkit.backupplugin; + +import org.bukkit.ChatColor; +import org.bukkit.Server; +import org.bukkit.entity.Player; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Class to handle log messages and broadcasts + * + * @author MysticX + */ +public class MessageHandler { + + // server + private static Server server; + + // Minecraft logger + private static Logger l = Logger.getLogger("Minecraft"); + + // message prefixes and stuff + private static final ChatColor BROADCAST_COLOR = ChatColor.GREEN; + private static final String PLUGIN_PREFIX = "[BackupPlugin] "; + private static Level logLevel = Level.INFO; + + /** + * Logs a message with PLUGIN_PREFIX + * + * @param level + * @param message + * @param thrown + */ + protected static void log(Level level, String message, Throwable thrown) { + if (compareLevel(level)) + l.log(level, addPrefix(message), thrown); + } + + /** + * Logs a message with PLUGIN_PREFIX + * + * @param level + * @param message + */ + protected static void log(Level level, String message) { + //TODO quick hack for output < INFO + if ((level == Level.FINE || level == Level.FINEST) && compareLevel(level)) + l.log(Level.INFO, addPrefix("[DEBUG] " + message)); + + if (compareLevel(level)) + l.log(level, addPrefix(message)); + } + + + /** + * Logs a info with PLUGIN_PREFIX + * + * @param message + */ + protected static void info(String message) { + if (compareLevel(Level.INFO)) + l.info(addPrefix(message)); + } + + /** + * Logs a warning with PLUGIN_PREFIX + * + * @param message + */ + protected static void warning(String message) { + if (compareLevel(Level.WARNING)) + l.warning(addPrefix(message)); + } + + /** + * broadcasts an ingame message to all players + * + * @param message + */ + protected static void broadcast(String message) { + server.broadcastMessage(addPrefix(BROADCAST_COLOR + message)); +// for (Player p : etc.getServer().getPlayerList()) { +// p.sendMessage(addPrefix(BROADCAST_COLOR + message)); +// } + } + + /** + * broadcasts an ingame message to a given player + * + * @param player + * @param message + */ + protected static void broadcast(Player p, String message) { + p.sendMessage(addPrefix(BROADCAST_COLOR + message)); + } + + /** + * adds given prefix to given String + * + * @param prefix + * @param message + * @return modified String + */ + public static String addPrefix(String prefix, String message) { + return prefix + message; + } + + /** + * Sets LogLevel for this MessageHandler + * + * @param level + */ + public static void setLogLevel(Level loglevel) { + logLevel = loglevel; +// l.setLevel(logLevel); + } + + /** + * Sets LogLevel for this MessageHandler + * + * @param level + */ + public static boolean setLogLevel(String loglevel) { + try { + Level level = Level.parse(loglevel); + MessageHandler.setLogLevel(level); + return true; + } catch (Exception e) { + MessageHandler.warning("Failed to parse log-level, using default."); + return false; + } + } + + /** + * adds PLUGIN_PREFIX and calling class to given String + * + * @param message + * @return modified String + */ + private static String addPrefix(String message) { + return PLUGIN_PREFIX + "(" + getCallingClassName(4) + ") " + message; + } + + /** + * Compares two log levels + * + * @param arg0 + * @return true, if logging is enabled for this level + */ + private static boolean compareLevel(Level arg0) { + return (arg0.intValue() >= logLevel.intValue()); + } + + /** + * @param grade grade of call + * @return calling class name + */ + private static String getCallingClassName(int grade) { + String s = Thread.currentThread().getStackTrace()[grade].getClassName(); + return s; + } + + protected static void setServer(Server instance) { + server = instance; + } + +} diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/PluginUnit.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/PluginUnit.java new file mode 100644 index 0000000..8772ede --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/PluginUnit.java @@ -0,0 +1,233 @@ +package com.mysticx.bukkit.backupplugin; + +import net.minecraft.server.MinecraftServer; +import org.bukkit.Server; +import org.bukkit.craftbukkit.CraftServer; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Observable; +import java.util.logging.Level; + +/** + * Abstract class for PluginUnits + * similar to a "plugin-in-plugin" system + * + * @author MysticX + */ +public abstract class PluginUnit extends Observable implements Runnable { + + protected String name; + + private long sleepTime = 10000; + + // Objects + protected CacheControl cc; + protected Server etc; + protected IOHelper iohelper; + protected File work_path; + protected MinecraftServer console; + + // values + protected boolean isEnabled; + protected boolean isForce; + protected boolean initialForce; + + /** + * Default constructor + * initializes some stuff, force = false + * + * @param workdir working directory + */ + public PluginUnit(Server instance, File workdir) { + this.cc = CacheControl.getInstance(); + this.etc = instance; + this.iohelper = IOHelper.getInstance(); + this.isEnabled = true; + this.isForce = false; + this.initialForce = false; + this.work_path = workdir; + + try { + this.console = (MinecraftServer) CraftServer.class.getDeclaredField("console").get(etc); + } catch (Throwable e) { + MessageHandler.log(Level.SEVERE, "Not running on CraftBukkit/Notchian Server!!"); + } + } + + /** + * Default constructor + * initializes some stuff + * + * @param workdir working directory + * @param force true if cache rebuild should be forced at execution + */ + public PluginUnit(Server instance, File workdir, boolean force) { + this.cc = CacheControl.getInstance(); + this.etc = instance; + this.iohelper = IOHelper.getInstance(); + this.isEnabled = true; + this.isForce = force; + this.initialForce = force; + this.work_path = workdir; + + try { + this.console = (MinecraftServer) CraftServer.class.getDeclaredField("console").get(etc); + } catch (Throwable e) { + MessageHandler.log(Level.SEVERE, "Not running on CraftBukkit/Notchian Server!!"); + } + } + + /** + * @return name of PluginUnit + */ + public String getName() { + return this.name; + } + + + /** + * sets plugin work path + * + * @param folder + */ + public void setWorkDir(File work_path) { + this.work_path = work_path; + } + + /** + * @return working directory + */ + protected File getWorkDir() { + return work_path; + } + + + /** + * calculates elapsed time between two values in ms + * + * @param start + * @param end + * @return elapsed time in seconds + */ + protected int calculateTimeDifference(long start, long end) { + Long time = (end - start) / 1000; + return time.intValue(); + } + + /** + * Generates a generic filename + * + * @param suffix + * @return the filename + */ + public String generateFilename(String suffix) { + // generate filename + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmssSSSS"); + String time = sdf.format(new Date(System.currentTimeMillis())); + + // escape spaces in world name + String worldname = cc.getWorld().getName().replaceAll(" ", ""); + + String filename = (worldname + "_" + time + suffix); + MessageHandler.log(Level.FINEST, "Generated filename: " + filename); + return filename; + } + + + /** + * @return true if the unit is enabled + */ + public boolean isEnabled() { + return this.isEnabled; + } + + /** + * @return true if the unit is forced + */ + public boolean isForce() { + return this.isForce; + } + + /** + * Enables or disables a unit + * + * @param bool + */ + public void setEnabled(boolean bool) { + this.isEnabled = bool; + if (bool) + notifyAll(); + } + + /** + * Enables or disables cache force + * + * @param bool + */ + public void setForce(boolean bool) { + this.isForce = bool; + } + + + /** + * do nothing + */ + protected void sleep(long millis) { + try { + MessageHandler.log(Level.FINE, getName() + " going to sleep for " + (millis / 1000) + " seconds.."); + Thread.sleep(millis); + MessageHandler.log(Level.FINE, getName() + " woke up from sleep as expected."); + } catch (InterruptedException e) { + MessageHandler.log(Level.WARNING, getName() + "woke up too early!", e); + // continue + } + } + + /** + * Saves the world and disables saving! + * Remember to enable saving again afterwards + */ + protected void saveWorld() { + // TODO: save world and disable saving for mapping process + consoleCommandLog("Enabling level saving. Forcing save."); + console.e.C = false; + console.e.a(true, null); + consoleCommandLog("Save complete. Disabling level saving."); + console.e.C = true; + + sleep(3000); + } + + protected void consoleCommandLog(String c) { + console.f.i("§7(BackupPlugin: " + c + ")"); + console.a.info("BackupPlugin: " + c); + } + + /** + * resets force to initial value + */ + public void resetForce() { + MessageHandler.log(Level.FINE, "Resetting force to " + this.initialForce); + this.isForce = this.initialForce; + } + + /** + * main functionality of Unit + */ + abstract public void run(); + + /** + * main functionality of Unit + * + * @param force + */ + public void run(boolean force) { + boolean oldforce = isForce(); + setForce(force); + run(); + setForce(oldforce); + } + +} diff --git a/BackupPlugin/com/mysticx/bukkit/backupplugin/SysCommandExecutor.java b/BackupPlugin/com/mysticx/bukkit/backupplugin/SysCommandExecutor.java new file mode 100644 index 0000000..8b73600 --- /dev/null +++ b/BackupPlugin/com/mysticx/bukkit/backupplugin/SysCommandExecutor.java @@ -0,0 +1,140 @@ +package com.mysticx.bukkit.backupplugin; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Usage of following class can go as ... + *


+ * SysCommandExecutor cmdExecutor = new SysCommandExecutor();
+ * cmdExecutor.setOutputLogDevice(new LogDevice());
+ * cmdExecutor.setErrorLogDevice(new LogDevice());
+ * int exitStatus = cmdExecutor.runCommand(commandLine);
+ * 

+ *

+ * OR + *

+ *


+ * SysCommandExecutor cmdExecutor = new SysCommandExecutor();
+ * int exitStatus = cmdExecutor.runCommand(commandLine);
+ * 

+ * String cmdError = cmdExecutor.getCommandError(); + * String cmdOutput = cmdExecutor.getCommandOutput(); + *

+ *

+ * http://www.javalobby.org/java/forums/t53333.html + * + * @author Venkat + */ +public class SysCommandExecutor { + private String fWorkingDirectory = null; + private List fEnvironmentVarList = null; + + private StringBuffer fCmdOutput = null; + private StringBuffer fCmdError = null; + private AsyncStreamReader fCmdOutputThread = null; + private AsyncStreamReader fCmdErrorThread = null; + + + public void setWorkingDirectory(String workingDirectory) { + fWorkingDirectory = workingDirectory; + } + + public void setEnvironmentVar(String name, String value) { + if (fEnvironmentVarList == null) + fEnvironmentVarList = new ArrayList(); + + fEnvironmentVarList.add(new EnvironmentVar(name, value)); + } + + public String getCommandOutput() { + return fCmdOutput.toString(); + } + + public String getCommandError() { + return fCmdError.toString(); + } + + public int runCommand(String commandLine) throws Exception { + /* run command */ + Process process = runCommandHelper(commandLine); + + /* start output and error read threads */ + startOutputAndErrorReadThreads(process.getInputStream(), process.getErrorStream()); + + /* wait for command execution to terminate */ + int exitStatus = -1; + try { + exitStatus = process.waitFor(); + + } catch (Throwable ex) { + throw new Exception(ex.getMessage()); + + } finally { + /* notify output and error read threads to stop reading */ + notifyOutputAndErrorReadThreadsToStopReading(); + } + + return exitStatus; + } + + private Process runCommandHelper(String commandLine) throws IOException { + Process process = null; + if (fWorkingDirectory == null) + process = Runtime.getRuntime().exec(commandLine, getEnvTokens()); + else + process = Runtime.getRuntime().exec(commandLine, getEnvTokens(), new File(fWorkingDirectory)); + + return process; + } + + private void startOutputAndErrorReadThreads(InputStream processOut, InputStream processErr) { + fCmdOutput = new StringBuffer(); + fCmdOutputThread = new AsyncStreamReader(processOut, fCmdOutput, "OUTPUT"); + fCmdOutputThread.start(); + + fCmdError = new StringBuffer(); + fCmdErrorThread = new AsyncStreamReader(processErr, fCmdError, "ERROR"); + fCmdErrorThread.start(); + } + + private void notifyOutputAndErrorReadThreadsToStopReading() { + fCmdOutputThread.stopReading(); + fCmdErrorThread.stopReading(); + } + + private String[] getEnvTokens() { + if (fEnvironmentVarList == null) + return null; + + String[] envTokenArray = new String[fEnvironmentVarList.size()]; + Iterator envVarIter = fEnvironmentVarList.iterator(); + int nEnvVarIndex = 0; + while (envVarIter.hasNext() == true) { + EnvironmentVar envVar = (EnvironmentVar) (envVarIter.next()); + String envVarToken = envVar.fName + "=" + envVar.fValue; + envTokenArray[nEnvVarIndex++] = envVarToken; + } + + return envTokenArray; + } +} + +/** + * http://www.javalobby.org/java/forums/t53333.html + * + * @author Venkat + */ +class EnvironmentVar { + public String fName = null; + public String fValue = null; + + public EnvironmentVar(String name, String value) { + fName = name; + fValue = value; + } +} \ No newline at end of file diff --git a/BackupPlugin/plugin.yml b/BackupPlugin/plugin.yml new file mode 100644 index 0000000..c19f1e3 --- /dev/null +++ b/BackupPlugin/plugin.yml @@ -0,0 +1,5 @@ +name: BackupPlugin + +main: com.mysticx.bukkit.backupplugin.BackupPlugin + +version: 0.8.5 \ No newline at end of file