Browse Source

Release 1.8.5
- Implemented Issue #56 - Always save all.
- Closes Issue #29 - Update handler.
- Minor edits to the way strings are loaded, Improvements on strings class.
- Strings now have different version numbers, so we can change plugin version without replacing string.
- Strings version checking.
- Config file update - Extra Settings!
- Minor changes to make the commandlistener more effective, added upgradeconf to command line.
- Edited all classes to be easier to read and understand.
- Added onload configuration overview, can be disabled in settings.
- Minor changes to notification of backup start and finish.
- Extra setting srelatin gto LogUtils as to where the entries are visible.
- Removed fileConfiguration save methods, as it is not required.

gamerx 8 years ago
parent
commit
2a2ad949b0

+ 20 - 20
README

@@ -1,21 +1,21 @@
-/*
- *  Backup - CraftBukkit server Backup plugin (continued)
- *  Copyright (C) 2011 Domenic Horner <https://github.com/gamerx/Backup>
- *  Copyright (C) 2011 Lycano <https://github.com/gamerx/Backup>
- *
- *  Backup - CraftBukkit server Backup plugin (original author)
- *  Copyright (C) 2011 Kilian Gaertner <https://github.com/Meldanor/Backup>
- * 
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- * 
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- * 
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/*
+ *  Backup - CraftBukkit server Backup plugin (continued)
+ *  Copyright (C) 2011-2012 Domenic Horner (gamerx) <https://github.com/gamerx/Backup>
+ *  Copyright (C) 2011 Lycano <https://github.com/gamerx/Backup>
+ *
+ *  Backup - CraftBukkit server Backup plugin (original author)
+ *  Copyright (C) 2011 Kilian Gaertner <https://github.com/Meldanor/Backup>
+ * 
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */

+ 93 - 93
pom.xml

@@ -1,94 +1,94 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>net.tgxn.bukkit</groupId>
-    <artifactId>Backup</artifactId>
-    <version>1.8.5-dev</version>
-    <name>Backup</name>
-    <description>A Backup plugin for Bukkit's Server mod API.</description>
-    <url>https://github.com/gamerx/Backup</url>
-    <repositories>
-        <repository>
-            <id>tgxn.net-repo</id>
-            <url>http://maven.tgxn.net/bukkit-plugins/</url>
-        </repository>
-        <repository>
-            <id>bukkit.org-repo</id>
-            <url>http://repo.bukkit.org/content/groups/repo/</url>
-        </repository>
-    </repositories>
-    <issueManagement>
-        <system>GitHub</system>
-        <url>https://github.com/gamerx/Backup/issues</url>
-    </issueManagement>
-    <build>
-        <finalName>Backup</finalName>
-        <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
-        <resources>
-            <resource>
-                <targetPath>.</targetPath>
-                    <filtering>true</filtering>
-                    <directory>${basedir}/src/main/resources/</directory>
-                    <includes>
-                        <include>plugin.yml</include>
-                    </includes>
-            </resource>
-            <resource>
-                <targetPath>settings/</targetPath>
-                <filtering>true</filtering>
-                <directory>${basedir}/src/main/resources/</directory>
-                <includes>
-                    <include>config.yml</include>
-                    <include>strings.yml</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <version>2.2.1</version>
-                <configuration>
-                    <descriptors>
-                        <descriptor>src/main/assembly/package.xml</descriptor>
-                    </descriptors>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>build</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>2.3.2</version>
-                <configuration>
-                    <source>1.7</source>
-                    <target>1.7</target>
-                    <encoding>UTF-8</encoding>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <dependencies>
-        <dependency>
-            <groupId>com.nijikokun.bukkit</groupId>
-            <artifactId>Permissions</artifactId>
-            <version>2.7.3</version>
-            <type>jar</type>
-            <scope>compile</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.bukkit</groupId>
-            <artifactId>bukkit</artifactId>
-            <version>1.0.1-R1</version>
-        </dependency>
-    </dependencies>
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    </properties>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>net.tgxn.bukkit</groupId>
+    <artifactId>Backup</artifactId>
+    <version>1.8.5</version>
+    <name>Backup</name>
+    <description>A Backup plugin for Bukkit's Server mod API.</description>
+    <url>https://github.com/gamerx/Backup</url>
+    <repositories>
+        <repository>
+            <id>tgxn.net-repo</id>
+            <url>http://maven.tgxn.net/bukkit-plugins/</url>
+        </repository>
+        <repository>
+            <id>bukkit.org-repo</id>
+            <url>http://repo.bukkit.org/content/groups/repo/</url>
+        </repository>
+    </repositories>
+    <issueManagement>
+        <system>GitHub</system>
+        <url>https://github.com/gamerx/Backup/issues</url>
+    </issueManagement>
+    <build>
+        <finalName>Backup</finalName>
+        <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
+        <resources>
+            <resource>
+                <targetPath>.</targetPath>
+                    <filtering>true</filtering>
+                    <directory>${basedir}/src/main/resources/</directory>
+                    <includes>
+                        <include>plugin.yml</include>
+                    </includes>
+            </resource>
+            <resource>
+                <targetPath>settings/</targetPath>
+                <filtering>true</filtering>
+                <directory>${basedir}/src/main/resources/</directory>
+                <includes>
+                    <include>config.yml</include>
+                    <include>strings.yml</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>2.2.1</version>
+                <configuration>
+                    <descriptors>
+                        <descriptor>src/main/assembly/package.xml</descriptor>
+                    </descriptors>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>build</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.2</version>
+                <configuration>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>com.nijikokun.bukkit</groupId>
+            <artifactId>Permissions</artifactId>
+            <version>2.7.3</version>
+            <type>jar</type>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.bukkit</groupId>
+            <artifactId>bukkit</artifactId>
+            <version>1.0.1-R1</version>
+        </dependency>
+    </dependencies>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
 </project>

+ 137 - 122
src/main/java/net/tgxn/bukkit/backup/BackupMain.java

@@ -1,122 +1,137 @@
-package net.tgxn.bukkit.backup;
-
-import com.nijiko.permissions.PermissionHandler;
-import com.nijikokun.bukkit.Permissions.Permissions;
-
-import net.tgxn.bukkit.backup.utils.*;
-import net.tgxn.bukkit.backup.config.*;
-import net.tgxn.bukkit.backup.listeners.*;
-import net.tgxn.bukkit.backup.threading.PrepareBackup;
-
-import org.bukkit.Server;
-import org.bukkit.event.Event.Priority;
-import org.bukkit.event.Event.Type;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.plugin.PluginManager;
-import org.bukkit.plugin.java.JavaPlugin;
-
-import java.io.File;
-
-/**
- * Main class file for Backup.
- *
- * @author Domenic Horner (gamerx)
- */
-public class BackupMain extends JavaPlugin {
-    
-    public static PermissionHandler permissionsHandler;
-    public int mainBackupTaskID = -2;
-    public File mainDataFolder;
-    
-    private static Strings strings;
-    private static Settings settings;
-    private PrepareBackup prepareBackup;
-    
-    @Override
-    public void onLoad() {
-        
-        // Initalize main data folder.
-        mainDataFolder = this.getDataFolder();
-        
-        // Initalize log utilities.
-        LogUtils.initLogUtils(this);
-        
-        // Perform datafile check.
-        SharedUtils.checkFolderAndCreate(mainDataFolder);
-        
-        // Load plugin configuration.
-        strings = new Strings(this, new File(mainDataFolder, "strings.yml"));
-        settings = new Settings(this, new File(mainDataFolder, "config.yml"), strings);
-        
-        // Finish init of LogUtils.
-        LogUtils.finishInitLogUtils(settings.getBooleanProperty("displaylog"));
-        
-        // Do folder checking for backups folder.
-        if(SharedUtils.checkFolderAndCreate(new File(settings.getStringProperty("backuppath"))))
-            LogUtils.sendLog(strings.getString("createbudir"));
-    }
-    
-    @Override
-    public void onEnable() {
-        
-        // Initalize permissions handler.
-        initPermissions();
-
-        // Get server and plugin manager instances.
-        Server pluginServer = getServer();
-        PluginManager pluginManager = pluginServer.getPluginManager();
-
-        // Create new "PrepareBackup" instance.
-        prepareBackup = new PrepareBackup(pluginServer, settings, strings);
-
-        // Initalize plugin listeners.
-        getCommand("backup").setExecutor(new CommandListener(prepareBackup, this, settings, strings));
-        LoginListener loginListener = new LoginListener(prepareBackup, this, settings, strings);
-        pluginManager.registerEvent(Type.PLAYER_QUIT, loginListener, Priority.Normal, this);
-        pluginManager.registerEvent(Type.PLAYER_KICK, loginListener, Priority.Normal, this);
-        pluginManager.registerEvent(Type.PLAYER_JOIN, loginListener, Priority.Normal, this);
-
-        // Schedule timer, checks if there is a timer and enables task.
-        int backupInterval = settings.getIntervalInMinutes();
-        if (backupInterval != 0) {
-            backupInterval *= 1200;
-            mainBackupTaskID = pluginServer.getScheduler().scheduleSyncRepeatingTask(this, prepareBackup, backupInterval, backupInterval);
-        } else {
-            LogUtils.sendLog(strings.getString("disbaledauto"));
-        }
-        
-        // Loading complete.
-        LogUtils.sendLog(this.getDescription().getFullName() + " has completed loading!", false);
-    }
-    
-    @Override
-    public void onDisable () {
-        
-        // Stop and scheduled tasks.
-        this.getServer().getScheduler().cancelTasks(this);
-        
-        // Shutdown complete.
-        LogUtils.sendLog(this.getDescription().getFullName() + " has completed un-loading!", false);
-    }
-    
-    /**
-     * Check if the Permissions System is available, and setup the handler.
-     */
-    private void initPermissions() {
-
-        // Check if not already initalized.
-        if (permissionsHandler != null)
-            return;
-                
-        // Get permissions plugin.
-        Plugin testPermissions = this.getServer().getPluginManager().getPlugin("Permissions");
-        
-        // If we were able to get the permissions plugin.
-        if (testPermissions != null) {
-            permissionsHandler = ((Permissions) testPermissions).getHandler();
-            LogUtils.sendLog(strings.getString("hookedperms"));
-        } else {
-            LogUtils.sendLog(strings.getString("defaultperms"));
-        }
-    }
-}
+package net.tgxn.bukkit.backup;
+
+import com.nijiko.permissions.PermissionHandler;
+import com.nijikokun.bukkit.Permissions.Permissions;
+import java.io.File;
+import net.tgxn.bukkit.backup.config.Settings;
+import net.tgxn.bukkit.backup.config.Strings;
+import net.tgxn.bukkit.backup.listeners.CommandListener;
+import net.tgxn.bukkit.backup.listeners.LoginListener;
+import net.tgxn.bukkit.backup.threading.PrepareBackup;
+import net.tgxn.bukkit.backup.utils.LogUtils;
+import net.tgxn.bukkit.backup.utils.SharedUtils;
+import org.bukkit.Server;
+import org.bukkit.event.Event.Priority;
+import org.bukkit.event.Event.Type;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+
+/**
+ * Main class file for Backup.
+ *
+ * @author Domenic Horner (gamerx)
+ */
+public class BackupMain extends JavaPlugin {
+    
+    public static PermissionHandler permissionsHandler;
+    public int mainBackupTaskID = -2;
+    public File mainDataFolder;
+    
+    private static Strings strings;
+    private static Settings settings;
+    private PrepareBackup prepareBackup;
+    
+    @Override
+    public void onLoad() {
+        
+        // Initalize main data folder.
+        mainDataFolder = this.getDataFolder();
+        
+        // Initalize log utilities.
+        LogUtils.initLogUtils(this);
+        
+        // Perform datafile check.
+        SharedUtils.checkFolderAndCreate(mainDataFolder);
+        
+        // Load plugin configuration.
+        strings = new Strings(new File(mainDataFolder, "strings.yml"));
+        settings = new Settings(this, new File(mainDataFolder, "config.yml"), strings);
+        
+        strings.checkStringsVersion(settings.getStringProperty("requiredstrings"));
+        
+        // Finish init of LogUtils.
+        LogUtils.finishInitLogUtils(settings.getBooleanProperty("displaylog"), settings.getBooleanProperty("logtofile"), settings.getStringProperty("backuplogname"));
+        
+        // Do folder checking for backups folder.
+        if(SharedUtils.checkFolderAndCreate(new File(settings.getStringProperty("backuppath"))))
+            LogUtils.sendLog(strings.getString("createbudir"));
+    }
+    
+    @Override
+    public void onEnable() {
+        
+        // Initalize permissions handler.
+        initPermissions();
+
+        // Get server and plugin manager instances.
+        Server pluginServer = getServer();
+        PluginManager pluginManager = pluginServer.getPluginManager();
+
+        // Create new "PrepareBackup" instance.
+        prepareBackup = new PrepareBackup(pluginServer, settings, strings);
+
+        // Initalize plugin listeners.
+        getCommand("backup").setExecutor(new CommandListener(prepareBackup, this, settings, strings));
+        LoginListener loginListener = new LoginListener(prepareBackup, this, settings, strings);
+        pluginManager.registerEvent(Type.PLAYER_QUIT, loginListener, Priority.Normal, this);
+        pluginManager.registerEvent(Type.PLAYER_KICK, loginListener, Priority.Normal, this);
+        pluginManager.registerEvent(Type.PLAYER_JOIN, loginListener, Priority.Normal, this);
+
+        // Schedule timer, checks if there is a timer and enables task.
+        int backupInterval = settings.getIntervalInMinutes();
+        if (backupInterval != 0) {
+            backupInterval *= 1200;
+            mainBackupTaskID = pluginServer.getScheduler().scheduleSyncRepeatingTask(this, prepareBackup, backupInterval, backupInterval);
+        } else {
+            LogUtils.sendLog(strings.getString("disbaledauto"));
+        }
+        
+        String interval = settings.getStringProperty("backupinterval");
+        String max = Integer.toString(settings.getIntProperty("maxbackups"));
+        String empty = (settings.getBooleanProperty("backupemptyserver")) ? "Yes" : "No";
+        String everything = (settings.getBooleanProperty("backupeverything")) ? "Yes" : "No";
+        String split = (settings.getBooleanProperty("splitbackup")) ? "Yes" : "No";
+        String zip = (settings.getBooleanProperty("zipbackup")) ? "Yes" : "No";
+        String path = settings.getStringProperty("backuppath");
+        
+        if(settings.getBooleanProperty("showconfigonstartup")) {
+            LogUtils.sendLog("Configuration:");
+            LogUtils.sendLog("Interval: "+interval+", Max: "+max+", On Empty: "+empty+", Everything: "+everything+".", false);
+            LogUtils.sendLog("Split: "+split+", ZIP: "+zip+", Path: "+path+".", false);
+        }
+        // Loading complete.
+        LogUtils.sendLog(this.getDescription().getFullName() + " has completed loading!", false);
+    }
+    
+    @Override
+    public void onDisable () {
+        
+        // Stop and scheduled tasks.
+        this.getServer().getScheduler().cancelTasks(this);
+        
+        // Shutdown complete.
+        LogUtils.sendLog(this.getDescription().getFullName() + " has completed un-loading!", false);
+    }
+    
+    /**
+     * Check if the Permissions System is available, and setup the handler.
+     */
+    private void initPermissions() {
+
+        // Check if not already initalized.
+        if (permissionsHandler != null)
+            return;
+                
+        // Get permissions plugin.
+        Plugin testPermissions = this.getServer().getPluginManager().getPlugin("Permissions");
+        
+        // If we were able to get the permissions plugin.
+        if (testPermissions != null) {
+            permissionsHandler = ((Permissions) testPermissions).getHandler();
+            LogUtils.sendLog(strings.getString("hookedperms"));
+        } else {
+            LogUtils.sendLog(strings.getString("defaultperms"));
+        }
+    }
+}

+ 204 - 224
src/main/java/net/tgxn/bukkit/backup/config/Settings.java

@@ -1,224 +1,204 @@
-package net.tgxn.bukkit.backup.config;
-
-import net.tgxn.bukkit.backup.utils.*;
-
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.logging.Level;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-
-/**
- * Loads all settings for the plugin.
- * 
- * @author gamerx
- */
-public final class Settings {
-
-    private Plugin plugin;
-    private Strings strings;
-    
-    private File configFile;
-    private FileConfiguration fileSettingConfiguration;
-    
-    
-    public Settings(Plugin plugin, File configFile, Strings strings) {
-        this.plugin = plugin;
-        this.configFile = configFile;
-        this.strings = strings;
-        
-        checkAndCreate();
-        
-        loadProperties();
-        
-        checkConfigVersion();
-    }
-    
-    public void checkAndCreate() {
-        try {
-            if (!configFile.exists()) {
-                LogUtils.sendLog(Level.WARNING, strings.getString("newconfigfile"));
-                createDefaultSettings();
-            }
-        } catch (SecurityException | NullPointerException se) {
-            LogUtils.exceptionLog(se.getStackTrace());
-        }
-    }
-    
-    /**
-     * Load the properties from the configFile, create if needed.
-     */
-    private void loadProperties() {
-        
-        fileSettingConfiguration = new YamlConfiguration();
-        try {
-            // Attempt to load configuration.
-            fileSettingConfiguration.load(configFile);
-        } catch (IOException | InvalidConfigurationException ex) {
-            LogUtils.exceptionLog(ex.getStackTrace(), "Failed to load settings.");
-            
-        }
-    }
-    
-    private void saveProperties() {
-        
-        // Check they are loaded.
-        if (fileSettingConfiguration == null) {
-            return;
-        }
-        
-        // Attempt to save configuration to file forcibly.
-        try {
-            fileSettingConfiguration.save(configFile);
-        } catch (IOException ex) {
-            LogUtils.exceptionLog(ex.getStackTrace(), "Error saving config file.");
-        }
-    }
-    
-    /**
-     * Checks configuration version and then based on the outcome, either runs the update, or returns false.
-     * 
-     * @return False for no update done, True for update done.
-     */
-    public boolean checkConfigVersion() {
-        
-        boolean doUpgrade = false;
-        
-        // Check configuration is loaded.
-        if (fileSettingConfiguration != null) {
-
-            // Get the version information from the file.
-            String configVersion = fileSettingConfiguration.getString("version", plugin.getDescription().getVersion());
-            String pluginVersion = plugin.getDescription().getVersion();
-
-            // Check we got a version from the config file.
-            if (configVersion == null) {
-                LogUtils.sendLog(strings.getString("failedtogetpropsver"), Level.SEVERE, true);
-                doUpgrade = true;
-            }
-
-            // Check if the config is outdated.
-            if (!configVersion.equals(pluginVersion))
-                doUpgrade = true;
-
-            // After we have checked the versions, we have determined that we need to update.
-            if (doUpgrade) {
-                LogUtils.sendLog(Level.SEVERE, strings.getString("configupdate"));
-                doConfigurationUpdate();
-            }
-        }
-        return doUpgrade;
-    }
-    
-    public void doConfigurationUpdate() {
-        loadProperties();
-        createDefaultSettings();
-        fileSettingConfiguration.set("version", this.plugin.getDescription().getVersion());
-        saveProperties();
-    }
-    
-    /**
-     * Load the properties file from the JAR and place it in the backup DIR.
-     */
-    private void createDefaultSettings() {
-        
-        if (configFile.exists()) {
-            configFile.delete();
-        }
-        
-        BufferedReader bReader = null;
-        BufferedWriter bWriter = null;
-        String line;
-        try {
-            // Open a stream to the properties file in the jar, because we can only access over the class loader.
-            bReader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/settings/config.yml")));
-            bWriter = new BufferedWriter(new FileWriter(configFile));
-
-            // Copy the content to the configfile location.
-            while ((line = bReader.readLine()) != null) {
-                bWriter.write(line);
-                bWriter.newLine();
-            }
-        } catch (IOException ioe) {
-            LogUtils.exceptionLog(ioe.getStackTrace(), "Error opening stream.");
-        }
-        
-        finally {
-            try {
-                if (bReader != null) {
-                    bReader.close();
-                }
-                if (bWriter != null) {
-                    bWriter.close();
-                }
-            } catch (IOException ioe) {
-                LogUtils.exceptionLog(ioe.getStackTrace(), "Error closing stream.");
-            }
-        }
-    }
-
-
-    /**
-     * Gets the value of a integer property.
-     * 
-     * @param property The name of the property.
-     * @return The value of the property, defaults to -1.
-     */
-    public int getIntProperty(String property) {
-        return fileSettingConfiguration.getInt(property, -1);
-    }
-
-    /**
-     * Gets the value of a boolean property.
-     * 
-     * @param property The name of the property.
-     * @return The value of the property, defaults to true.
-     */
-    public boolean getBooleanProperty(String property) {
-        return fileSettingConfiguration.getBoolean(property, true);
-    }
-
-    /**
-     * Gets a value of the string property and make sure it is not null.
-     * 
-     * @param property The name of the property.
-     * @return The value of the property.
-     */
-    public String getStringProperty(String property) {
-        return fileSettingConfiguration.getString(property, "");
-    }
-    
-    /**
-     * 
-     * @return minutes between backups.
-     */
-    public int getIntervalInMinutes() {
-        String settingBackupInterval = getStringProperty("backupinterval");
-        
-        if(settingBackupInterval.equals("-1")) {
-            return 0;
-        }
-        
-        String lastLetter = settingBackupInterval.substring(settingBackupInterval.length()-1, settingBackupInterval.length());
-        int amountTime =  Integer.parseInt(settingBackupInterval.substring(0, settingBackupInterval.length()-1));
-        switch(lastLetter) {
-            case "H": // Hours
-                amountTime = (amountTime * 60);
-            break;
-            case "D": // Days.
-                amountTime = (amountTime * 1440);
-            break;
-            case "W": // Weeks
-                amountTime = (amountTime * 10080);
-            break;
-        }
-        return amountTime;
-    }
-}
+package net.tgxn.bukkit.backup.config;
+
+import java.io.*;
+import java.util.logging.Level;
+import net.tgxn.bukkit.backup.utils.LogUtils;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.plugin.Plugin;
+
+/**
+ * Loads all settings for the plugin.
+ * 
+ * @author Domenic Horner (gamerx)
+ */
+public final class Settings {
+
+    private Plugin plugin;
+    private Strings strings;
+    
+    private File configFile;
+    private FileConfiguration fileSettingConfiguration;
+    
+    
+    public Settings(Plugin plugin, File configFile, Strings strings) {
+        this.plugin = plugin;
+        this.configFile = configFile;
+        this.strings = strings;
+        
+        checkAndCreate();
+        
+        loadProperties();
+        
+        checkConfigVersion(true);
+    }
+    
+    /**
+     * Check if the config file exists, if it does not, create it from the JAR.
+     * 
+     */
+    private void checkAndCreate() {
+        try {
+            if (!configFile.exists()) {
+                LogUtils.sendLog(Level.WARNING, strings.getString("newconfigfile"));
+                createDefaultSettings();
+            }
+        } catch (SecurityException | NullPointerException se) {
+            LogUtils.exceptionLog(se.getStackTrace(), "Failed to create default configuration file.");
+        }
+    }
+    
+    /**
+     * Load the properties to memory from the configFile.
+     */
+    private void loadProperties() {
+        fileSettingConfiguration = new YamlConfiguration();
+        try {
+            fileSettingConfiguration.load(configFile);
+        } catch (IOException | InvalidConfigurationException ex) {
+            LogUtils.exceptionLog(ex.getStackTrace(), "Failed to load configuration.");
+            
+        }
+    }
+    
+    /**
+     * Checks configuration version, and return true if it requires an update.
+     * 
+     * @return False for no update done, True for update done.
+     */
+    public boolean checkConfigVersion(boolean notify) {
+        
+        boolean needsUpgrade = false;
+        
+        // Check configuration is loaded.
+        if (fileSettingConfiguration != null) {
+
+            // Get the version information from the file.
+            String configVersion = fileSettingConfiguration.getString("version", plugin.getDescription().getVersion());
+            String pluginVersion = plugin.getDescription().getVersion();
+
+            // Check we got a version from the config file.
+            if (configVersion == null) {
+                LogUtils.sendLog(strings.getString("failedtogetpropsver"), Level.SEVERE, true);
+                needsUpgrade = true;
+            }
+
+            // Check if the config is outdated.
+            if (!configVersion.equals(pluginVersion))
+                needsUpgrade = true;
+
+            // After we have checked the versions, we have determined that we need to update.
+            if (needsUpgrade && notify) {
+                LogUtils.sendLog(Level.SEVERE, strings.getString("configupdate"));
+            }
+        }
+        return needsUpgrade;
+    }
+    
+    /**
+     * Used to upgrade the configuration file.
+     */
+    public void doConfigurationUpgrade() {
+        LogUtils.sendLog(strings.getString("updatingconf"), true);
+        if (configFile.exists()) {
+            configFile.delete();
+        }
+        createDefaultSettings();
+        LogUtils.sendLog(strings.getString("updatingconf"), true);
+    }
+    
+    /**
+     * Load the properties file from the JAR and place it in the backup DIR.
+     */
+    private void createDefaultSettings() {
+        
+        BufferedReader bReader = null;
+        BufferedWriter bWriter = null;
+        String line;
+        try {
+            // Open a stream to the properties file in the jar, because we can only access over the class loader.
+            bReader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/settings/config.yml")));
+            bWriter = new BufferedWriter(new FileWriter(configFile));
+
+            // Copy the content to the configfile location.
+            while ((line = bReader.readLine()) != null) {
+                bWriter.write(line);
+                bWriter.newLine();
+            }
+        } catch (IOException ioe) {
+            LogUtils.exceptionLog(ioe.getStackTrace(), "Error opening stream.");
+        }
+        
+        finally {
+            try {
+                if (bReader != null) {
+                    bReader.close();
+                }
+                if (bWriter != null) {
+                    bWriter.close();
+                }
+            } catch (IOException ioe) {
+                LogUtils.exceptionLog(ioe.getStackTrace(), "Error closing stream.");
+            }
+        }
+    }
+
+    /**
+     * Gets the value of a integer property.
+     * 
+     * @param property The name of the property.
+     * @return The value of the property, defaults to -1.
+     */
+    public int getIntProperty(String property) {
+        return fileSettingConfiguration.getInt(property, -1);
+    }
+
+    /**
+     * Gets the value of a boolean property.
+     * 
+     * @param property The name of the property.
+     * @return The value of the property, defaults to true.
+     */
+    public boolean getBooleanProperty(String property) {
+        return fileSettingConfiguration.getBoolean(property, true);
+    }
+
+    /**
+     * Gets a value of the string property and make sure it is not null.
+     * 
+     * @param property The name of the property.
+     * @return The value of the property.
+     */
+    public String getStringProperty(String property) {
+        return fileSettingConfiguration.getString(property, "");
+    }
+    
+    /**
+     * Method to get and interpret the interval.
+     * 
+     * @return minutes between backups.
+     */
+    public int getIntervalInMinutes() {
+        String settingBackupInterval = getStringProperty("backupinterval");
+        
+        if(settingBackupInterval.equals("-1")) {
+            return 0;
+        }
+        
+        String lastLetter = settingBackupInterval.substring(settingBackupInterval.length()-1, settingBackupInterval.length());
+        int amountTime =  Integer.parseInt(settingBackupInterval.substring(0, settingBackupInterval.length()-1));
+        switch(lastLetter) {
+            case "H": // Hours
+                amountTime = (amountTime * 60);
+            break;
+            case "D": // Days.
+                amountTime = (amountTime * 1440);
+            break;
+            case "W": // Weeks
+                amountTime = (amountTime * 10080);
+            break;
+        }
+        return amountTime;
+    }
+}

+ 183 - 179
src/main/java/net/tgxn/bukkit/backup/config/Strings.java

@@ -1,179 +1,183 @@
-package net.tgxn.bukkit.backup.config;
-
-import net.tgxn.bukkit.backup.utils.LogUtils;
-
-import org.bukkit.plugin.Plugin;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-
-/**
- * String loader for the plugin, provides strings for each event.
- *
- * @author gamerx
- */
-public class Strings {
-    
-    private Plugin plugin;
-    private File stringsFile;
-    private FileConfiguration fileStringConfiguration;
-    
-    /**
-     * Loads the strings configuration file.
-     * If it does not exist, it creates it from defaults.
-     * 
-     * @param plugin The plugin this is for.
-     */
-    public Strings(Plugin plugin, File stringsFile) {
-        this.plugin = plugin;
-        this.stringsFile = stringsFile;
-        
-        checkAndCreate();
-        loadStrings();
-    }
-
-    private void checkAndCreate() {
-        // Check for the config file, have it created if needed.
-        try {
-            if (!stringsFile.exists()) {
-                createDefaultStrings();
-            }
-        } catch (SecurityException | NullPointerException se) {
-            LogUtils.exceptionLog(se.getStackTrace(), "Error checking strings file.");
-        }
-    }
-    
-    
-    
-    private void loadStrings() {
-        fileStringConfiguration = new YamlConfiguration();
-        try {
-            fileStringConfiguration.load(stringsFile);
-        } catch (FileNotFoundException ex) {
-            LogUtils.exceptionLog(ex.getStackTrace(), "Error loading strings file.");
-        } catch (IOException | InvalidConfigurationException ex) {
-            LogUtils.exceptionLog(ex.getStackTrace(), "Error loading strings file.");
-        }
-    }
-    
-    private void saveStrings() {
-        if(fileStringConfiguration == null)
-            return;
-        try {
-            fileStringConfiguration.save(stringsFile);
-        } catch (IOException ex) {
-            LogUtils.exceptionLog(ex.getStackTrace(), "Error saving strings file.");
-        }
-    }
-    
-    private void createDefaultStrings() {
-    
-        if(stringsFile.exists())
-            stringsFile.delete();
-        
-    /**
-     * Load the properties file from the JAR and place it in the backup DIR.
-     */
-    
-        BufferedReader bReader = null;
-        BufferedWriter bWriter = null;
-        String line;
-
-        try {
-
-            // Open a stream to the properties file in the jar, because we can only access over the class loader.
-            bReader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/settings/strings.yml")));
-            bWriter = new BufferedWriter(new FileWriter(stringsFile));
-
-            // Copy the content to the configfile location.
-            while ((line = bReader.readLine()) != null) {
-                bWriter.write(line);
-                bWriter.newLine();
-            }
-        } catch (IOException ioe) {
-            LogUtils.exceptionLog(ioe.getStackTrace(), "Error opening streams.");
-        }
-        
-        finally {
-            try {
-                if (bReader != null) {
-                    bReader.close();
-                }
-                if (bWriter != null) {
-                    bWriter.close();
-                }
-            } catch (IOException ioe) {
-                LogUtils.exceptionLog(ioe.getStackTrace(), "Error closing streams.");
-            }
-        }
-    
-
-    }
-    
-    public void doConfigUpdate() {
-        loadStrings();
-        
-    }
-    
-    /**
-     * Gets a value of the string property.
-     * 
-     * @param sname The identifier for the string.
-     * @return The string from properties, with colors encoded.
-     */
-    public String getString(String property) {
-        
-        // Get string for this name.
-        String string = fileStringConfiguration.getString(property);
-        
-        // If we cannot find a string for this, return default.
-        if (string != null)
-            return colorizeString(string);
-        else
-            return fileStringConfiguration.getString("stringnotfound") + property;
-    }
-    
-    /**
-     * Gets a value of the string property, and replaces options.
-     * 
-     * @param property The identifier for the string.
-     * @param option The variable to replace %%ARG%% with.
-     * @return The string from properties, with colors encoded, and text replaced.
-     */
-    public String getString(String property, String option) {
-        
-        // Get string for this name.
-        String string = fileStringConfiguration.getString(property);
-        
-        // If we cannot find a string for this, return default.
-        if (string != null)
-            return colorizeString(string.replaceAll("%%ARG%%", option));
-        else
-            return fileStringConfiguration.getString("stringnotfound") + property;
-    }
-    
-    /**
-     * Encodes the color codes, and returns the encoded string.
-     * If the parameter is blank or null, return blank.
-     * 
-     * @param toColour The string to encode.
-     * @return The encoded string.
-     */
-    private String colorizeString(String toColor) {
-        
-        // Check we got passed a string.
-        if (toColor != null)
-            return toColor.replaceAll("&([0-9a-f])", "\u00A7$1");
-        else
-            return "";
-    }
-}
+package net.tgxn.bukkit.backup.config;
+
+import java.io.*;
+import java.util.logging.Level;
+import net.tgxn.bukkit.backup.utils.LogUtils;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+/**
+ * String loader for the plugin, provides strings for each event.
+ *
+ * @author Domenic Horner (gamerx)
+ */
+public class Strings {
+    
+    private File stringsFile;
+    private FileConfiguration fileStringConfiguration;
+    
+    /**
+     * Loads the strings configuration file.
+     * If it does not exist, it creates it from defaults.
+     * 
+     * @param plugin The plugin this is for.
+     */
+    public Strings(File stringsFile) {
+        this.stringsFile = stringsFile;
+        
+        checkAndCreate();
+        loadStrings();
+    }
+    
+    private void checkAndCreate() {
+        // Check for the config file, have it created if needed.
+        try {
+            if (!stringsFile.exists()) {
+                createDefaultStrings();
+            }
+        } catch (SecurityException | NullPointerException se) {
+            LogUtils.exceptionLog(se.getStackTrace(), "Error checking strings file.");
+        }
+    }
+    
+    public void checkStringsVersion(String requiredVersion) {
+    
+        boolean needsUpdate = false;
+        
+        // Check configuration is loaded.
+        if (fileStringConfiguration != null) {
+
+            // Get the version information from the file.
+            String stringVersion = fileStringConfiguration.getString("version", null);
+
+            // Check we got a version from the config file.
+            if (stringVersion == null) {
+                LogUtils.sendLog("Failed to get strings file verison.", Level.SEVERE, true);
+                needsUpdate = true;
+            }
+
+            // Check if the config is outdated.
+            if (!stringVersion.equals(requiredVersion))
+                needsUpdate = true;
+
+            // After we have checked the versions, we have determined that we need to update.
+            if (needsUpdate) {
+                LogUtils.sendLog(Level.SEVERE, this.getString("stringsupdate"));
+            }
+        }
+    }
+    
+    private void loadStrings() {
+        fileStringConfiguration = new YamlConfiguration();
+        try {
+            fileStringConfiguration.load(stringsFile);
+        } catch (FileNotFoundException ex) {
+            LogUtils.exceptionLog(ex.getStackTrace(), "Error loading strings file.");
+        } catch (IOException | InvalidConfigurationException ex) {
+            LogUtils.exceptionLog(ex.getStackTrace(), "Error loading strings file.");
+        }
+    }
+    
+    private void createDefaultStrings() {
+    
+        if(stringsFile.exists())
+            stringsFile.delete();
+        
+    /**
+     * Load the properties file from the JAR and place it in the backup DIR.
+     */
+    
+        BufferedReader bReader = null;
+        BufferedWriter bWriter = null;
+        String line;
+
+        try {
+
+            // Open a stream to the properties file in the jar, because we can only access over the class loader.
+            bReader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/settings/strings.yml")));
+            bWriter = new BufferedWriter(new FileWriter(stringsFile));
+
+            // Copy the content to the configfile location.
+            while ((line = bReader.readLine()) != null) {
+                bWriter.write(line);
+                bWriter.newLine();
+            }
+        } catch (IOException ioe) {
+            LogUtils.exceptionLog(ioe.getStackTrace(), "Error opening streams.");
+        }
+        
+        finally {
+            try {
+                if (bReader != null) {
+                    bReader.close();
+                }
+                if (bWriter != null) {
+                    bWriter.close();
+                }
+            } catch (IOException ioe) {
+                LogUtils.exceptionLog(ioe.getStackTrace(), "Error closing streams.");
+            }
+        }
+    
+
+    }
+    
+    public void doStringsUpdate() {
+        loadStrings();
+        
+    }
+    
+    /**
+     * Gets a value of the string property.
+     * 
+     * @param sname The identifier for the string.
+     * @return The string from properties, with colors encoded.
+     */
+    public String getString(String property) {
+        
+        // Get string for this name.
+        String string = fileStringConfiguration.getString(property);
+        
+        // If we cannot find a string for this, return default.
+        if (string != null)
+            return colorizeString(string);
+        else
+            return fileStringConfiguration.getString("stringnotfound") + property;
+    }
+    
+    /**
+     * Gets a value of the string property, and replaces options.
+     * 
+     * @param property The identifier for the string.
+     * @param option The variable to replace %%ARG%% with.
+     * @return The string from properties, with colors encoded, and text replaced.
+     */
+    public String getString(String property, String option) {
+        
+        // Get string for this name.
+        String string = fileStringConfiguration.getString(property);
+        
+        // If we cannot find a string for this, return default.
+        if (string != null)
+            return colorizeString(string.replaceAll("%%ARG%%", option));
+        else
+            return fileStringConfiguration.getString("stringnotfound") + property;
+    }
+    
+    /**
+     * Encodes the color codes, and returns the encoded string.
+     * If the parameter is blank or null, return blank.
+     * 
+     * @param toColour The string to encode.
+     * @return The encoded string.
+     */
+    private String colorizeString(String toColor) {
+        
+        // Check we got passed a string.
+        if (toColor != null)
+            return toColor.replaceAll("&([0-9a-f])", "\u00A7$1");
+        else
+            return "";
+    }
+}

+ 292 - 280
src/main/java/net/tgxn/bukkit/backup/listeners/CommandListener.java

@@ -1,280 +1,292 @@
-package net.tgxn.bukkit.backup.listeners;
-
-import net.tgxn.bukkit.backup.BackupMain;
-import net.tgxn.bukkit.backup.config.*;
-import net.tgxn.bukkit.backup.threading.PrepareBackup;
-
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerListener;
-import org.bukkit.plugin.Plugin;
-
-import java.io.File;
-
-/**
- * Command listener and handler.
- *
- * @author gamerx
- */
-public class CommandListener extends PlayerListener implements CommandExecutor {
-
-    private PrepareBackup backupTask = null;
-    private final Plugin plugin;
-    private Settings settings;
-    private Strings strings;
-
-    /**
-     * The main constructor to initalize listening for commands.
-     * 
-     * @param prepareBackup The instance of prepareBackup.
-     * @param plugin The plugin object itself
-     * @param settings Load settings for the plugin.
-     * @param strings The strings configuration for th plugin.
-     */
-    public CommandListener(PrepareBackup prepareBackup, Plugin plugin, Settings settings, Strings strings) {
-        this.backupTask = prepareBackup;
-        this.plugin = plugin;
-        this.settings = settings;
-        this.strings = strings;
-    }
-
-    @Override
-    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-
-        // Initalize variables.
-        Player player = null;
-
-        // Process in-game commands.
-        if ((sender instanceof Player)) {
-
-            // Get player object
-            player = (Player) sender;
-        }
-
-        // Do the actual processing.
-        return processCommand(label, args, player);
-    }
-
-    /**
-     * Method to process every command.
-     * 
-     * @param command The command (Usually "backup")
-     * @param args Arguments passed along with the command.
-     * @param player The player that requested the command.
-     * @return True is success, False if fail.
-     */
-    public boolean processCommand(String command, String[] args, Player player) {
-
-        if (player == null) {
-            // Only console command will be "backup"
-            if (command.equalsIgnoreCase("backup")) {
-                doManualBackup();
-            }
-        } else {
-            // For all playercommands.
-
-
-
-            // For everything under the backup command.
-            if (command.equalsIgnoreCase("backup")) {
-
-
-                // Contains auguments.
-                if (args.length > 0) {
-                    if (args[0].equals("help")) {
-                        if (checkPerms(player, "backup.help")) {
-                            sendHelp(player);
-                        }
-                    }
-
-                    if (args[0].equals("reload")) {
-                        if (checkPerms(player, "backup.reload")) {
-                            reloadPlugin(plugin, player);
-                        }
-                    }
-
-                    if (args[0].equals("list")) {
-                        if (checkPerms(player, "backup.list")) {
-                            listBackups(player);
-                        }
-                    }
-
-                    if (args[0].equals("config")) {
-                        if (checkPerms(player, "backup.config")) {
-                            showConfig(player);
-                        }
-                    }
-
-                    if (args[0].equals("log")) {
-                        if (checkPerms(player, "backup.log")) {
-                            showLog(player);
-                        }
-                    }
-
-                    if (args[0].equals("updateconf")) {
-                        if (checkPerms(player, "backup.updateconf")) {
-                            updateConfig(player);
-                        }
-                    }
-                } else {
-                    if (checkPerms(player, "backup.backup")) {
-                        doManualBackup();
-                    }
-                }
-            }
-
-        }
-        return true;
-    }
-
-    public void reloadPlugin(Plugin plugin, Player player) {
-        plugin.onDisable();
-        plugin.onLoad();
-        plugin.onEnable();
-        player.sendMessage(strings.getString("reloadedok", plugin.getDescription().getVersion()));
-    }
-
-    /**
-     * Start a manual backup.
-     */
-    private void doManualBackup() {
-        backupTask.setAsManualBackup();
-        plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, backupTask);
-    }
-
-    /**
-     * Send the plugin help to the player.
-     * 
-     * @param player The player who requested the help.
-     */
-    private void sendHelp(Player player) {
-        player.sendMessage("Backup v" + plugin.getDescription().getVersion() + " Help Menu");
-        player.sendMessage("Commands:");
-        player.sendMessage("/backup");
-        player.sendMessage("- Performs a backup.");
-        player.sendMessage("/backup updateconf");
-        player.sendMessage("- Re-Installs config file.");
-        player.sendMessage(".");
-        player.sendMessage(".");
-        player.sendMessage("Coming Soon :)");
-        player.sendMessage(".");
-    }
-
-    /**
-     * Checks if the player has permissions.
-     * Also sends a message if the player does not have permissions.
-     * 
-     * @param player The player's object.
-     * @param permission The name of the permission
-     * @return True if they have permission, false if no permission
-     */
-    private boolean checkPerms(Player player, String permission) {
-
-        // We hooked a perms system.
-        if (BackupMain.permissionsHandler != null) {
-            if (!BackupMain.permissionsHandler.has(player, permission)) {
-                player.sendMessage(strings.getString("norights"));
-                return false;
-            } else {
-                return true;
-            }
-
-        } else {
-
-            // Check what to do in case of no permissions.
-            if (settings.getBooleanProperty("onlyops") && !player.isOp()) {
-                player.sendMessage(strings.getString("norights"));
-                return false;
-            } else {
-                return true;
-            }
-        }
-    }
-
-    /**
-     * For listing all the backups for a user.
-     * Lists to a maximum of 8 so that it doesn't flow off screen.
-     * 
-     * @param player The player that requested the list.
-     */
-    private void listBackups(Player player) {
-
-        // Get the backups path.
-        String backupDir = settings.getStringProperty("backuppath");
-
-        // Make a list.
-        String[] filesList = new File(backupDir).list();
-
-        // Inform what is happenning.
-        player.sendMessage("Listing backup directory: \"" + backupDir + "\".");
-
-        // Check if the directory exists.
-        if (filesList == null) {
-
-            // Error message.
-            player.sendMessage("Error listing directory!");
-        } else {
-
-            // How many files in array.
-            int amountoffiles = filesList.length;
-
-            // Limit listings, so it doesnt flow off screen.
-            if (amountoffiles > 8) {
-                amountoffiles = 8;
-            }
-
-            // Send informal message.
-            player.sendMessage("" + amountoffiles + " backups found, listing...");
-
-            // Loop through files, and list them.
-            for (int i = 0; i < amountoffiles; i++) {
-
-                // Get filename of file.
-                String filename = filesList[i];
-
-                // Send messages for each file.
-                int number = i + 1;
-                player.sendMessage(number + "). " + filename);
-            }
-        }
-    }
-
-    /**
-     * To show the plugins configuration.
-     * 
-     * @param player The player that requested the configuration.
-     */
-    private void showConfig(Player player) {
-
-        player.sendMessage("Backup Configuration");
-
-        int interval = settings.getIntervalInMinutes();
-        if (interval != 0) {
-            player.sendMessage("Scheduled Backups: Enabled, " + interval + " mins between backups.");
-        } else {
-            player.sendMessage("Scheduled backups: Disabled, Manual backups only.");
-        }
-
-        boolean hasToZIP = settings.getBooleanProperty("zipbackup");
-        if (hasToZIP) {
-            player.sendMessage("Backup compression is Enabled.");
-        } else {
-            player.sendMessage("Backup compression is Disabled.");
-        }
-    }
-
-    private void showLog(Player player) {
-        player.sendMessage("Coming Soon :)");
-    }
-
-    private void updateConfig(Player player) {
-        if(settings.checkConfigVersion()) {
-            player.sendMessage(strings.getString("updatingconf"));
-            settings.doConfigurationUpdate();
-        } else {
-            player.sendMessage(strings.getString("confuptodate"));
-        }
-    }
-}
+package net.tgxn.bukkit.backup.listeners;
+
+import java.io.File;
+import net.tgxn.bukkit.backup.BackupMain;
+import net.tgxn.bukkit.backup.config.Settings;
+import net.tgxn.bukkit.backup.config.Strings;
+import net.tgxn.bukkit.backup.threading.PrepareBackup;
+import net.tgxn.bukkit.backup.utils.LogUtils;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerListener;
+import org.bukkit.plugin.Plugin;
+
+/**
+ * Command listener and handler.
+ *
+ * @author Domenic Horner (gamerx)
+ */
+public class CommandListener extends PlayerListener implements CommandExecutor {
+
+    private PrepareBackup backupTask = null;
+    private final Plugin plugin;
+    private Settings settings;
+    private Strings strings;
+
+    /**
+     * The main constructor to initalize listening for commands.
+     * 
+     * @param prepareBackup The instance of prepareBackup.
+     * @param plugin The plugin object itself
+     * @param settings Load settings for the plugin.
+     * @param strings The strings configuration for th plugin.
+     */
+    public CommandListener(PrepareBackup prepareBackup, Plugin plugin, Settings settings, Strings strings) {
+        this.backupTask = prepareBackup;
+        this.plugin = plugin;
+        this.settings = settings;
+        this.strings = strings;
+    }
+
+    @Override
+    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+
+        // Initalize variables.
+        Player player = null;
+
+        // Process in-game commands.
+        if ((sender instanceof Player)) {
+
+            // Get player object
+            player = (Player) sender;
+        }
+
+        // Do the actual processing.
+        return processCommand(label, args, player);
+    }
+
+    /**
+     * Method to process every command.
+     * 
+     * @param command The command (Usually "backup")
+     * @param args Arguments passed along with the command.
+     * @param player The player that requested the command.
+     * @return True is success, False if fail.
+     */
+    public boolean processCommand(String command, String[] args, Player player) {
+
+        if (player == null) {
+            if (command.equalsIgnoreCase("backup")) {
+                
+                if (args.length > 0) {
+                    switch (args[0]) {
+                        case "updateconf":
+                            updateConfig(null);
+                            break;
+                        case "reload":
+                            reloadPlugin(plugin, player);
+                            break;
+                    }
+                } else {
+                    doManualBackup();
+                }
+            }
+        } else {
+            // For all playercommands.
+
+
+
+            // For everything under the backup command.
+            if (command.equalsIgnoreCase("backup")) {
+
+
+                // Contains auguments.
+                if (args.length > 0) {
+                    switch (args[0]) {
+                        case "help":
+                            if (checkPerms(player, "backup.help")) {
+                                sendHelp(player);
+                            }
+                            break;
+                        case "reload":
+                            if (checkPerms(player, "backup.reload")) {
+                                reloadPlugin(plugin, player);
+                            }
+                            break;
+                        case "list":
+                            if (checkPerms(player, "backup.list")) {
+                                listBackups(player);
+                            }
+                            break;
+                        case "config":
+                            if (checkPerms(player, "backup.config")) {
+                                showConfig(player);
+                            }
+                            break;
+                        case "log":
+                            if (checkPerms(player, "backup.log")) {
+                                showLog(player);
+                            }
+                            break;
+                        case "updateconf":
+                            if (checkPerms(player, "backup.upgradeconf")) {
+                                updateConfig(player);
+                            }
+                            break;
+                    }
+                } else {
+                    if (checkPerms(player, "backup.backup")) {
+                        doManualBackup();
+                    }
+                }
+            }
+
+        }
+        return true;
+    }
+
+    public void reloadPlugin(Plugin plugin, Player player) {
+        plugin.onDisable();
+        plugin.onLoad();
+        plugin.onEnable();
+        player.sendMessage(strings.getString("reloadedok", plugin.getDescription().getVersion()));
+    }
+
+    /**
+     * Start a manual backup.
+     */
+    private void doManualBackup() {
+        backupTask.setAsManualBackup();
+        plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, backupTask);
+    }
+
+    /**
+     * Send the plugin help to the player.
+     * 
+     * @param player The player who requested the help.
+     */
+    private void sendHelp(Player player) {
+        player.sendMessage("Backup v" + plugin.getDescription().getVersion() + " Help Menu");
+        player.sendMessage("Commands:");
+        player.sendMessage("/backup");
+        player.sendMessage("- Performs a backup.");
+        player.sendMessage("/backup upgradeconf");
+        player.sendMessage("- Re-Installs config file.");
+        player.sendMessage(".");
+        player.sendMessage(".");
+        player.sendMessage("Coming Soon :)");
+        player.sendMessage(".");
+    }
+
+    /**
+     * Checks if the player has permissions.
+     * Also sends a message if the player does not have permissions.
+     * 
+     * @param player The player's object.
+     * @param permission The name of the permission
+     * @return True if they have permission, false if no permission
+     */
+    private boolean checkPerms(Player player, String permission) {
+
+        // We hooked a perms system.
+        if (BackupMain.permissionsHandler != null) {
+            if (!BackupMain.permissionsHandler.has(player, permission)) {
+                player.sendMessage(strings.getString("norights"));
+                return false;
+            } else {
+                return true;
+            }
+
+        } else {
+
+            // Check what to do in case of no permissions.
+            if (settings.getBooleanProperty("onlyops") && !player.isOp()) {
+                player.sendMessage(strings.getString("norights"));
+                return false;
+            } else {
+                return true;
+            }
+        }
+    }
+
+    /**
+     * For listing all the backups for a user.
+     * Lists to a maximum of 8 so that it doesn't flow off screen.
+     * 
+     * @param player The player that requested the list.
+     */
+    private void listBackups(Player player) {
+
+        // Get the backups path.
+        String backupDir = settings.getStringProperty("backuppath");
+
+        // Make a list.
+        String[] filesList = new File(backupDir).list();
+
+        // Inform what is happenning.
+        player.sendMessage("Listing backup directory: \"" + backupDir + "\".");
+
+        // Check if the directory exists.
+        if (filesList == null) {
+
+            // Error message.
+            player.sendMessage("Error listing directory!");
+        } else {
+
+            // How many files in array.
+            int amountoffiles = filesList.length;
+
+            // Limit listings, so it doesnt flow off screen.
+            if (amountoffiles > 8) {
+                amountoffiles = 8;
+            }
+
+            // Send informal message.
+            player.sendMessage("" + amountoffiles + " backups found, listing...");
+
+            // Loop through files, and list them.
+            for (int i = 0; i < amountoffiles; i++) {
+
+                // Get filename of file.
+                String filename = filesList[i];
+
+                // Send messages for each file.
+                int number = i + 1;
+                player.sendMessage(number + "). " + filename);
+            }
+        }
+    }
+
+    /**
+     * To show the plugins configuration.
+     * 
+     * @param player The player that requested the configuration.
+     */
+    private void showConfig(Player player) {
+
+        player.sendMessage("Backup Configuration");
+
+        int interval = settings.getIntervalInMinutes();
+        if (interval != 0) {
+            player.sendMessage("Scheduled Backups: Enabled, " + interval + " mins between backups.");
+        } else {
+            player.sendMessage("Scheduled backups: Disabled, Manual backups only.");
+        }
+
+        boolean hasToZIP = settings.getBooleanProperty("zipbackup");
+        if (hasToZIP) {
+            player.sendMessage("Backup compression is Enabled.");
+        } else {
+            player.sendMessage("Backup compression is Disabled.");
+        }
+    }
+
+    private void showLog(Player player) {
+        player.sendMessage("Coming Soon :)");
+    }
+
+    private void updateConfig(Player player) {
+        if(settings.checkConfigVersion(false)) {
+            if(player != null)
+                player.sendMessage(strings.getString("updatingconf"));
+            settings.doConfigurationUpgrade();
+        } else {
+            if(player != null)
+                player.sendMessage(strings.getString("confuptodate"));
+            else
+                LogUtils.sendLog(strings.getString("confuptodate"), false);
+        }
+    }
+}

+ 89 - 93
src/main/java/net/tgxn/bukkit/backup/listeners/LoginListener.java

@@ -1,93 +1,89 @@
-package net.tgxn.bukkit.backup.listeners;
-
-import net.tgxn.bukkit.backup.BackupMain;
-import net.tgxn.bukkit.backup.config.*;
-import net.tgxn.bukkit.backup.utils.*;
-import net.tgxn.bukkit.backup.threading.PrepareBackup;
-
-import org.bukkit.event.player.PlayerJoinEvent;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.event.player.PlayerKickEvent;
-import org.bukkit.event.player.PlayerListener;
-import org.bukkit.event.player.PlayerQuitEvent;
-
-/**
- * Listens for login events, and perform actions based on what happened.
- *
- * Updated 16.11.11
- * = Added Login Listener to cancel scheduled backup.
- *
- * @author gamerx
- */
-public class LoginListener extends PlayerListener {
-    
-    private PrepareBackup prepareBackup = null;
-    private Plugin plugin;
-    private Settings settings;
-    private Strings strings;
-    private int lastBackupID;
-    
-    /**
-     * Constructor for listening for login events.
-     * 
-     * @param backupTask The BackupTast to call.
-     * @param plugin Plugin to link this class too.
-     */
-    public LoginListener(PrepareBackup backupTask, Plugin plugin, Settings settings, Strings strings) {
-        this.prepareBackup = backupTask;
-        this.plugin = plugin;
-        this.settings = settings;
-        this.strings = strings;
-        lastBackupID = -2;
-    }
-    
-    @Override
-    public void onPlayerQuit(PlayerQuitEvent event) {
-        playerPart();
-    }
-    
-    @Override
-    public void onPlayerKick(PlayerKickEvent event) {
-        playerPart();
-    }
-
-    @Override
-    public void onPlayerJoin(PlayerJoinEvent event) {
-        playerJoin();
-    }
-
-    /**
-     * Called when a player leaves the server.
-     *
-     */
-    private void playerPart() {
-         int onlinePlayers = plugin.getServer().getOnlinePlayers().length;
-         // Check if it was the last player.
-         if (onlinePlayers == 1) {
-            prepareBackup.setAsLastBackup(true);
-            //plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, backupTask);
-            int intervalInMinutes = settings.getIntervalInMinutes();
-            if (intervalInMinutes != -1) {
-                int interval =  intervalInMinutes * 1200;
-                lastBackupID = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, prepareBackup, interval, interval);
-                LogUtils.sendLog("Scheduled last backup for " + intervalInMinutes +" minutes;");
-            } else {
-                LogUtils.sendLog(strings.getString("disbaledauto"));
-            }
-         }
-    }
-
-    /**
-     * Called when a player joins the server.
-     *
-     */
-    private void playerJoin() {
-        if(prepareBackup.isLastBackup || lastBackupID != -2) {
-            plugin.getServer().getScheduler().cancelTask(lastBackupID);
-            lastBackupID = -2;
-            prepareBackup.setAsLastBackup(false);
-            LogUtils.sendLog("Stopped last backup, because someone joined.");
-        }
-    }
-}
-
+package net.tgxn.bukkit.backup.listeners;
+
+import net.tgxn.bukkit.backup.config.Settings;
+import net.tgxn.bukkit.backup.config.Strings;
+import net.tgxn.bukkit.backup.threading.PrepareBackup;
+import net.tgxn.bukkit.backup.utils.LogUtils;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerKickEvent;
+import org.bukkit.event.player.PlayerListener;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.plugin.Plugin;
+
+/**
+ * Listens for login events, and perform actions based on what happened.
+ *
+ * @author Domenic Horner (gamerx)
+ */
+public class LoginListener extends PlayerListener {
+    
+    private PrepareBackup prepareBackup = null;
+    private Plugin plugin;
+    private Settings settings;
+    private Strings strings;
+    private int lastBackupID;
+    
+    /**
+     * Constructor for listening for login events.
+     * 
+     * @param backupTask The BackupTast to call.
+     * @param plugin Plugin to link this class too.
+     */
+    public LoginListener(PrepareBackup backupTask, Plugin plugin, Settings settings, Strings strings) {
+        this.prepareBackup = backupTask;
+        this.plugin = plugin;
+        this.settings = settings;
+        this.strings = strings;
+        lastBackupID = -2;
+    }
+    
+    @Override
+    public void onPlayerQuit(PlayerQuitEvent event) {
+        playerPart();
+    }
+    
+    @Override
+    public void onPlayerKick(PlayerKickEvent event) {
+        playerPart();
+    }
+
+    @Override
+    public void onPlayerJoin(PlayerJoinEvent event) {
+        playerJoin();
+    }
+
+    /**
+     * Called when a player leaves the server.
+     *
+     */
+    private void playerPart() {
+         int onlinePlayers = plugin.getServer().getOnlinePlayers().length;
+         // Check if it was the last player.
+         if (onlinePlayers == 1) {
+            prepareBackup.setAsLastBackup(true);
+            //plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, backupTask);
+            int intervalInMinutes = settings.getIntervalInMinutes();
+            if (intervalInMinutes != -1) {
+                int interval =  intervalInMinutes * 1200;
+                lastBackupID = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, prepareBackup, interval, interval);
+                LogUtils.sendLog("Scheduled last backup for " + intervalInMinutes +" minutes;");
+            } else {
+                LogUtils.sendLog(strings.getString("disbaledauto"));
+            }
+         }
+    }
+
+    /**
+     * Called when a player joins the server.
+     *
+     */
+    private void playerJoin() {
+        if(prepareBackup.isLastBackup || lastBackupID != -2) {
+            plugin.getServer().getScheduler().cancelTask(lastBackupID);
+            lastBackupID = -2;
+            prepareBackup.setAsLastBackup(false);
+            LogUtils.sendLog("Stopped last backup, because someone joined.");
+        }
+    }
+}
+

+ 471 - 490
src/main/java/net/tgxn/bukkit/backup/threading/BackupTask.java

@@ -1,490 +1,471 @@
-package net.tgxn.bukkit.backup.threading;
-
-import net.tgxn.bukkit.backup.BackupMain;
-import net.tgxn.bukkit.backup.config.*;
-import net.tgxn.bukkit.backup.utils.*;
-
-import org.bukkit.entity.Player;
-import org.bukkit.Server;
-import org.bukkit.plugin.Plugin;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.FileFilter;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.LinkedList;
-import java.util.logging.Level;
-import java.util.List;
-
-import static net.tgxn.bukkit.backup.utils.FileUtils.FILE_SEPARATOR;
-
-/**
- * The Task copies and backups the worlds and delete older backups. This task
- * is only runes once in doBackup and doing all the thread safe options.
- * The PrepareBackupTask and BackupTask are two threads to find a compromise between
- * security and performance.
- *
- * @author Kilian Gaertner
- */
-public class BackupTask implements Runnable {
-
-    private Server server;
-    private Plugin plugin;
-    private Settings settings;
-    private Strings strings;
-    private LinkedList<String> worldsToBackup;
-
-    private List<String> pluginList;
-    private boolean splitbackup;
-    private boolean shouldZIP;
-    private String backupsPath;
-    private String thisBackupFolder;
-    private boolean backupEverything;
-
-    /**
-     * The main doBackup constructor.
-     * 
-     * @param settings The settings object, to get the plugins settings.
-     * @param strings Strings object, for all string values
-     * @param worldsToBackup The list of worlds that need to be backed up.
-     * @param server The server we are backing up.
-     */
-    public BackupTask(Server server, Settings settings, Strings strings, LinkedList<String> worldsToBackup) {
-        this.server = server;
-        this.plugin = server.getPluginManager().getPlugin("Backup");
-        this.settings = settings;
-        this.strings = strings;
-        this.worldsToBackup = worldsToBackup;
-    }
-
-    @Override
-    public void run() {
-        // Load settings.
-        backupsPath = settings.getStringProperty("backuppath").concat(FILE_SEPARATOR);
-        thisBackupFolder = backupsPath.concat(getFolderName());
-        backupEverything = settings.getBooleanProperty("backupeverything");
-        splitbackup = settings.getBooleanProperty("splitbackup");
-        shouldZIP = settings.getBooleanProperty("zipbackup");
-        pluginList = Arrays.asList(settings.getStringProperty("skipplugins").split(";"));
-
-        // Starts the process.
-        doBackup();
-    }
-
-    /**
-     * This method does high-level backup processes.
-     *
-     */
-    public void doBackup() {
-
-        // We are performing a full server doBackup.
-        if (backupEverything) {
-
-            // Setup FileFilter to exclude the backups path.
-            FileFilter ff = new FileFilter() {
-
-                /**
-                 * Files to accept/deny.
-                 */
-                @Override
-                public boolean accept(File f) {
-
-                    // Disallow server.log and the backuppath.
-                    if (f.getName().equals(settings.getStringProperty("backuppath"))) {
-                        return false;
-                    }
-
-                    if (f.getName().equals("server.log")) {
-                        return false;
-                    }
-
-                    return true;
-                }
-            };
-
-            // Setup Source and destination DIR's.
-            File srcDIR = new File("./");
-            File destDIR = new File(thisBackupFolder);
-
-            // Copy this world into the doBackup directory, in a folder called the worlds name.
-            try {
-
-                // Copy the directory.
-                FileUtils.copyDirectory(srcDIR, destDIR, ff, true);
-                
-                // Perform the zipping action. 
-                doZIP(thisBackupFolder);
-
-            } catch (FileNotFoundException fnfe) {
-                LogUtils.exceptionLog(fnfe.getStackTrace(), "Failed to copy world: File not found.");
-            } catch (IOException ioe) {
-                LogUtils.exceptionLog(ioe.getStackTrace(), "Failed to copy world: IO Exception.");
-            }
-        } else {
-
-            // World backup checking.
-            if ((worldsToBackup != null) && (settings.getBooleanProperty("backupworlds"))) {
-                backupWorlds();
-            } else {
-                LogUtils.sendLog(strings.getString("skipworlds"), Level.INFO, true);
-            }
-
-            // Plugin backup checking.
-            if (settings.getBooleanProperty("backupplugins")) {
-                backupPlugins();
-            } else {
-                LogUtils.sendLog(strings.getString("skipplugins"), Level.INFO, true);
-            }
-
-            // Check if split backup.
-            if (!splitbackup) {
-                doZIP(thisBackupFolder);
-            }
-        }
-
-        // Should we delete any old backups.
-        if (!deleteOldBackups()) {
-            LogUtils.sendLog("Failed to delete old backups.");
-        }
-
-        // Finish backup.
-        finishBackup();
-    }
-
-    /**
-     * This backs up worlds.
-     *
-     * No checking if they are needed is required, it is already done.
-     *
-     */
-    private void backupWorlds() {
-
-        // Loops each world that needs to backed up.
-        while (!worldsToBackup.isEmpty()) {
-
-            // Remove first world from the array and put it into a var.
-            String currentWorldName = worldsToBackup.removeFirst();
-
-            // Check for split backup.
-            if (splitbackup) {
-
-                // Check this worlds folder exists.
-                File worldBackupFolder = new File(backupsPath.concat(FILE_SEPARATOR).concat(currentWorldName));
-                
-                // Create if needed.
-                SharedUtils.checkFolderAndCreate(worldBackupFolder);
-
-                // This worlds backup folder.
-                String thisWorldBackupFolder = backupsPath.concat(currentWorldName).concat(FILE_SEPARATOR).concat(getFolderName());
-
-                // Copy the current world into it's backup folder.
-                try {
-                    FileUtils.copyDirectory(currentWorldName, thisWorldBackupFolder);
-                } catch (IOException ioe) {
-                    ioe.printStackTrace(System.out);
-                    LogUtils.sendLog("Failed to copy world: IO Exception.");
-                }
-
-                // Check and ZIP folder.
-                doZIP(thisWorldBackupFolder);
-
-            } else {
-                
-                // This worlds backup folder.
-                String thisWorldBackupFolder = thisBackupFolder.concat(FILE_SEPARATOR).concat(currentWorldName);
-
-                // Copy the current world into it's backup folder.
-                try {
-                    FileUtils.copyDirectory(currentWorldName, thisWorldBackupFolder);
-
-                } catch (FileNotFoundException ex) {
-                    LogUtils.exceptionLog(ex.getStackTrace());
-                } catch (IOException ioe) {
-                    LogUtils.exceptionLog(ioe.getStackTrace());
-                }
-            }
-        }
-    }
-
-    /**
-     * This backs up plugins.
-     *
-     * No checking if they are needed is required, it is already done.
-     *
-     */
-    private void backupPlugins() {
-
-        // The FileFilter instance for skipped/enabled plugins.
-        FileFilter pluginsFileFilter = new FileFilter() {
-            @Override
-            public boolean accept(File name) {
-
-                // Check if there are plugins listed.
-                if (pluginList.size() > 0 && !pluginList.get(0).isEmpty()) {
-
-                    // Loop each plugin.
-                    for (int i = 0; i < pluginList.size(); i++) {
-
-                        // Check if the current plugin matches the string.
-                        if (pluginList.get(i).equals(name.getName())) {
-                            return false;
-                        }
-                    }
-                }
-                return true;
-            }
-        };
-
-        // Setup Source and destination DIR's.
-        File pluginsFolder = new File("plugins");
-
-        // Touch the folder to update the modified date.
-        pluginsFolder.setLastModified(System.currentTimeMillis());
-
-        // Check if this is a split backup or not, and set backup path depending on this.
-        String pluginsBackupPath;
-        if (splitbackup) {
-            pluginsBackupPath = backupsPath.concat("plugins").concat(FILE_SEPARATOR).concat(getFolderName());
-        } else {
-            pluginsBackupPath = thisBackupFolder.concat(FILE_SEPARATOR).concat("plugins");
-        }
-
-        // Create if needed.
-        SharedUtils.checkFolderAndCreate(new File(pluginsBackupPath));
-
-        // Perform plugin backup.
-        try {
-            if (pluginList.size() > 0 && !pluginList.get(0).isEmpty()) {
-                LogUtils.sendLog(strings.getString("disabledplugins"));
-                LogUtils.sendLog(pluginList.toString());
-            }
-            FileUtils.copyDirectory(pluginsFolder, new File(pluginsBackupPath), pluginsFileFilter, true);
-        } catch (FileNotFoundException ex) {
-            LogUtils.exceptionLog(ex.getStackTrace());
-        } catch (IOException ioe) {
-            LogUtils.exceptionLog(ioe.getStackTrace());
-        }
-
-        // Check if ZIP is required.
-        if (splitbackup) {
-            doZIP(pluginsBackupPath);
-        }
-    }
-
-    /**
-     * Get the name of this backups folder.
-     * 
-     * @return The name, as a string.
-     */
-    private String getFolderName() {
-
-        // Get the calendar, and initalize the date format string.
-        Calendar calendar = Calendar.getInstance();
-        String formattedDate;
-
-        // Java string (and date) formatting:
-        // http://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html#syntax
-        try {
-            formattedDate = String.format(settings.getStringProperty("dateformat"), calendar);
-        } catch (Exception e) {
-            e.printStackTrace(System.out);
-            formattedDate = String.format("%1$td%1$tm%1$tY-%1$tH%1$tM%1$tS", calendar);
-        }
-        return formattedDate;
-    }
-
-    /**
-     * Add the folder specified to a ZIP file.
-     * 
-     * @param folderToZIP The folder that needs to be ZIP'ed
-     */
-    private void doZIP(String folderToZIP) {
-        if (shouldZIP) {
-            // ZIP the Folder.
-            try {
-                FileUtils.zipDir(folderToZIP, folderToZIP);
-            } catch (IOException ioe) {
-                LogUtils.exceptionLog(ioe.getStackTrace(), "Failed to ZIP backup: IO Exception.");
-            }
-            // Delete the folder.
-            try {
-                // Delete the original doBackup directory.
-                FileUtils.deleteDirectory(new File(folderToZIP));
-                new File(folderToZIP).delete();
-            } catch (IOException ioe) {
-                LogUtils.exceptionLog(ioe.getStackTrace(), "Failed to delete temp folder: IO Exception.");
-            }
-        }
-    }
-
-    /**
-     * Check whether there are more backups as allowed to store. 
-     * When this case is true, it deletes oldest ones.
-     */
-    private boolean deleteOldBackups() {
-
-        // Get the doBackup's directory.
-        File backupDir = new File(settings.getStringProperty("backuppath"));
-
-        // Check if split doBackup or not.
-        if (splitbackup) {
-            try {
-                // Loop the folders, and clean for each.
-                File[] foldersToClean = backupDir.listFiles();
-                for (int l = 0; l < foldersToClean.length; l++) {
-
-                    // Make sure we are cleaning a directory.
-                    if(foldersToClean[l].isDirectory())
-                        cleanFolder(foldersToClean[l]);
-                }
-            } catch (IOException | NullPointerException ex) {
-                LogUtils.exceptionLog(ex.getStackTrace());
-                return false;
-            }
-
-        } else {
-
-            // Clean entire directory.
-            try {
-                cleanFolder(backupDir);
-            } catch (IOException | NullPointerException ex) {
-                LogUtils.exceptionLog(ex.getStackTrace());
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private void cleanFolder(File backupDir) throws IOException {
-
-        // Get properties.
-        try {
-            final int maxBackups = settings.getIntProperty("maxbackups");
-
-            // Store all doBackup files in an array.
-            File[] filesList = backupDir.listFiles();
-
-            if (filesList == null) {
-                LogUtils.sendLog(Level.SEVERE, "Failed to list backup directory.");
-                return;
-            }
-
-            // If the amount of files exceeds the max backups to keep.
-            if (filesList.length > maxBackups) {
-                ArrayList<File> backupList = new ArrayList<>(filesList.length);
-                backupList.addAll(Arrays.asList(filesList));
-
-                int maxModifiedIndex;
-                long maxModified;
-
-                //Remove the newst backups from the list.
-                for (int i = 0; i < maxBackups; ++i) {
-                    maxModifiedIndex = 0;
-                    maxModified = backupList.get(0).lastModified();
-                    for (int j = 1; j < backupList.size(); ++j) {
-                        File currentFile = backupList.get(j);
-                        if (currentFile.lastModified() > maxModified) {
-                            maxModified = currentFile.lastModified();
-                            maxModifiedIndex = j;
-                        }
-                    }
-                    backupList.remove(maxModifiedIndex);
-                }
-
-                // Inform the user what backups are being deleted.
-                LogUtils.sendLog(strings.getString("removeold"));
-                LogUtils.sendLog(Arrays.toString(backupList.toArray()));
-
-                // Finally delete the backups.
-                for (File backupToDelete : backupList) {
-                    deleteDir(backupToDelete);
-                }
-            }
-        } catch (SecurityException se) {
-            LogUtils.exceptionLog(se.getStackTrace(), "Failed to clean old backups: Security Exception.");
-        }
-    }
-
-    public boolean deleteDir(File dir) {
-        if (dir.isDirectory()) {
-            String[] children = dir.list();
-            for (int i = 0; i < children.length; i++) {
-                boolean success = deleteDir(new File(dir, children[i]));
-                if (!success) {
-                    return false;
-                }
-            }
-        }
-        return dir.delete();
-    }
-
-    /**
-     * Creates a temporary Runnable that is running on the main thread by the scheduler to prevent thread problems.
-     */
-    private void finishBackup() {
-
-        // Create new Runnable instance.
-        Runnable run = new Runnable() {
-
-            @Override
-            public void run() {
-
-                // Should we enable auto-save again?
-                if (settings.getBooleanProperty("enableautosave"))
-                    server.dispatchCommand(server.getConsoleSender(), "save-on");
-
-                // Notify that it has completed.
-                notifyCompleted();
-            }
-
-
-            private void notifyCompleted() {
-
-                // Set the message.
-                String completedBackupMessage = strings.getString("backupfinished");
-
-                // Check there is a message.
-                if (completedBackupMessage != null && !completedBackupMessage.trim().isEmpty()) {
-
-                    // Verify Permissions
-                    if (BackupMain.permissionsHandler != null) {
-
-                        // Get all players.
-                        Player[] players = server.getOnlinePlayers();
-                        boolean sent = false;
-                        // Loop through all online players.
-                        for (int i = 0; i < players.length; i++) {
-                            Player currentplayer = players[i];
-
-                            // If the current player has the right permissions, notify them.
-                            if (BackupMain.permissionsHandler.has(currentplayer, "backup.notify")) {
-                                currentplayer.sendMessage(completedBackupMessage);
-                                sent = true;
-                            }
-                        }
-                        if (!sent) {
-                            if (settings.getBooleanProperty("broardcastmessages")) {
-                                server.broadcastMessage(completedBackupMessage);
-                            }
-                        }
-
-
-
-                    } else {
-
-                        // Check we should be notifying all players.
-                        if (settings.getBooleanProperty("broardcastmessages"))
-                            server.broadcastMessage(completedBackupMessage);
-                    }
-                }
-                // Send message to log, to be sure.
-                LogUtils.sendLog("Backup completed!");
-            }
-        };
-        server.getScheduler().scheduleSyncDelayedTask(plugin, run);
-    }
-}
+package net.tgxn.bukkit.backup.threading;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.*;
+import java.util.logging.Level;
+import net.tgxn.bukkit.backup.BackupMain;
+import net.tgxn.bukkit.backup.config.Settings;
+import net.tgxn.bukkit.backup.config.Strings;
+import net.tgxn.bukkit.backup.utils.FileUtils;
+import static net.tgxn.bukkit.backup.utils.FileUtils.FILE_SEPARATOR;
+import net.tgxn.bukkit.backup.utils.LogUtils;
+import net.tgxn.bukkit.backup.utils.SharedUtils;
+import org.bukkit.Server;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+
+/**
+ * The Task copies and backups the worlds and delete older backups. This task
+ * is only runes once in doBackup and doing all the thread safe options.
+ * The PrepareBackupTask and BackupTask are two threads to find a compromise between
+ * security and performance.
+ *
+ * @author Kilian Gaertner, Domenic Horner (gamerx)
+ */
+public class BackupTask implements Runnable {
+
+    private Server server;
+    private Plugin plugin;
+    private Settings settings;
+    private Strings strings;
+    private LinkedList<String> worldsToBackup;
+    private List<String> pluginList;
+    private boolean splitbackup;
+    private boolean shouldZIP;
+    private String backupsPath;
+    private String thisBackupFolder;
+    private boolean backupEverything;
+
+    /**
+     * The main doBackup constructor.
+     * 
+     * @param settings The settings object, to get the plugins settings.
+     * @param strings Strings object, for all string values
+     * @param worldsToBackup The list of worlds that need to be backed up.
+     * @param server The server we are backing up.
+     */
+    public BackupTask(Server server, Settings settings, Strings strings, LinkedList<String> worldsToBackup) {
+        this.server = server;
+        this.plugin = server.getPluginManager().getPlugin("Backup");
+        this.settings = settings;
+        this.strings = strings;
+        this.worldsToBackup = worldsToBackup;
+    }
+
+    @Override
+    public void run() {
+        // Load settings.
+        backupsPath = settings.getStringProperty("backuppath").concat(FILE_SEPARATOR);
+        thisBackupFolder = backupsPath.concat(getFolderName());
+        backupEverything = settings.getBooleanProperty("backupeverything");
+        splitbackup = settings.getBooleanProperty("splitbackup");
+        shouldZIP = settings.getBooleanProperty("zipbackup");
+        pluginList = Arrays.asList(settings.getStringProperty("skipplugins").split(";"));
+
+        // Starts the process.
+        doBackup();
+    }
+
+    /**
+     * This method does high-level backup processes.
+     *
+     */
+    public void doBackup() {
+
+        // We are performing a full server doBackup.
+        if (backupEverything) {
+
+            // Setup FileFilter to exclude the backups path.
+            FileFilter ff = new FileFilter() {
+
+                /**
+                 * Files to accept/deny.
+                 */
+                @Override
+                public boolean accept(File f) {
+
+                    // Disallow server.log and the backuppath.
+                    if (f.getName().equals(settings.getStringProperty("backuppath"))) {
+                        return false;
+                    }
+
+                    if (f.getName().equals("server.log")) {
+                        return false;
+                    }
+
+                    return true;
+                }
+            };
+
+            // Setup Source and destination DIR's.
+            File srcDIR = new File("./");
+            File destDIR = new File(thisBackupFolder);
+
+            // Copy this world into the doBackup directory, in a folder called the worlds name.
+            try {
+
+                // Copy the directory.
+                FileUtils.copyDirectory(srcDIR, destDIR, ff, true);
+
+                // Perform the zipping action. 
+                doZIP(thisBackupFolder);
+
+            } catch (FileNotFoundException fnfe) {
+                LogUtils.exceptionLog(fnfe.getStackTrace(), "Failed to copy world: File not found.");
+            } catch (IOException ioe) {
+                LogUtils.exceptionLog(ioe.getStackTrace(), "Failed to copy world: IO Exception.");
+            }
+        } else {
+
+            // World backup checking.
+            if ((worldsToBackup != null) && (settings.getBooleanProperty("backupworlds"))) {
+                backupWorlds();
+            } else {
+                LogUtils.sendLog(strings.getString("skipworlds"), Level.INFO, true);
+            }
+
+            // Plugin backup checking.
+            if (settings.getBooleanProperty("backupplugins")) {
+                backupPlugins();
+            } else {
+                LogUtils.sendLog(strings.getString("skipplugins"), Level.INFO, true);
+            }
+
+            // Check if split backup.
+            if (!splitbackup) {
+                doZIP(thisBackupFolder);
+            }
+        }
+
+        // Should we delete any old backups.
+        if (!deleteOldBackups()) {
+            LogUtils.sendLog("Failed to delete old backups.");
+        }
+
+        // Finish backup.
+        finishBackup();
+    }
+
+    /**
+     * This backs up worlds.
+     *
+     * No checking if they are needed is required, it is already done.
+     *
+     */
+    private void backupWorlds() {
+
+        // Loops each world that needs to backed up.
+        while (!worldsToBackup.isEmpty()) {
+
+            // Remove first world from the array and put it into a var.
+            String currentWorldName = worldsToBackup.removeFirst();
+
+            // Check for split backup.
+            if (splitbackup) {
+
+                // Check this worlds folder exists.
+                File worldBackupFolder = new File(backupsPath.concat(FILE_SEPARATOR).concat(currentWorldName));
+
+                // Create if needed.
+                SharedUtils.checkFolderAndCreate(worldBackupFolder);
+
+                // This worlds backup folder.
+                String thisWorldBackupFolder = backupsPath.concat(currentWorldName).concat(FILE_SEPARATOR).concat(getFolderName());
+
+                // Copy the current world into it's backup folder.
+                try {
+                    FileUtils.copyDirectory(currentWorldName, thisWorldBackupFolder);
+                } catch (IOException ioe) {
+                    ioe.printStackTrace(System.out);
+                    LogUtils.sendLog("Failed to copy world: IO Exception.");
+                }
+
+                // Check and ZIP folder.
+                doZIP(thisWorldBackupFolder);
+
+            } else {
+
+                // This worlds backup folder.
+                String thisWorldBackupFolder = thisBackupFolder.concat(FILE_SEPARATOR).concat(currentWorldName);
+
+                // Copy the current world into it's backup folder.
+                try {
+                    FileUtils.copyDirectory(currentWorldName, thisWorldBackupFolder);
+
+                } catch (FileNotFoundException ex) {
+                    LogUtils.exceptionLog(ex.getStackTrace());
+                } catch (IOException ioe) {
+                    LogUtils.exceptionLog(ioe.getStackTrace());
+                }
+            }
+        }
+    }
+
+    /**
+     * This backs up plugins.
+     *
+     * No checking if they are needed is required, it is already done.
+     *
+     */
+    private void backupPlugins() {
+
+        // The FileFilter instance for skipped/enabled plugins.
+        FileFilter pluginsFileFilter = new FileFilter() {
+
+            @Override
+            public boolean accept(File name) {
+
+                // Check if there are plugins listed.
+                if (pluginList.size() > 0 && !pluginList.get(0).isEmpty()) {
+
+                    // Loop each plugin.
+                    for (int i = 0; i < pluginList.size(); i++) {
+
+                        // Check if the current plugin matches the string.
+                        if (pluginList.get(i).equals(name.getName())) {
+                            return false;
+                        }
+                    }
+                }
+                return true;
+            }
+        };
+
+        // Setup Source and destination DIR's.
+        File pluginsFolder = new File("plugins");
+
+        // Touch the folder to update the modified date.
+        pluginsFolder.setLastModified(System.currentTimeMillis());
+
+        // Check if this is a split backup or not, and set backup path depending on this.
+        String pluginsBackupPath;
+        if (splitbackup) {
+            pluginsBackupPath = backupsPath.concat("plugins").concat(FILE_SEPARATOR).concat(getFolderName());
+        } else {
+            pluginsBackupPath = thisBackupFolder.concat(FILE_SEPARATOR).concat("plugins");
+        }
+
+        // Create if needed.
+        SharedUtils.checkFolderAndCreate(new File(pluginsBackupPath));
+
+        // Perform plugin backup.
+        try {
+            if (pluginList.size() > 0 && !pluginList.get(0).isEmpty()) {
+                LogUtils.sendLog(strings.getString("disabledplugins"));
+                LogUtils.sendLog(pluginList.toString());
+            }
+            FileUtils.copyDirectory(pluginsFolder, new File(pluginsBackupPath), pluginsFileFilter, true);
+        } catch (FileNotFoundException ex) {
+            LogUtils.exceptionLog(ex.getStackTrace());
+        } catch (IOException ioe) {
+            LogUtils.exceptionLog(ioe.getStackTrace());
+        }
+
+        // Check if ZIP is required.
+        if (splitbackup) {
+            doZIP(pluginsBackupPath);
+        }
+    }
+
+    /**
+     * Get the name of this backups folder.
+     * 
+     * @return The name, as a string.
+     */
+    private String getFolderName() {
+
+        // Get the calendar, and initalize the date format string.
+        Calendar calendar = Calendar.getInstance();
+        String formattedDate;
+
+        // Java string (and date) formatting:
+        // http://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html#syntax
+        try {
+            formattedDate = String.format(settings.getStringProperty("dateformat"), calendar);
+        } catch (Exception e) {
+            e.printStackTrace(System.out);
+            formattedDate = String.format("%1$td%1$tm%1$tY-%1$tH%1$tM%1$tS", calendar);
+        }
+        return formattedDate;
+    }
+
+    /**
+     * Add the folder specified to a ZIP file.
+     * 
+     * @param folderToZIP The folder that needs to be ZIP'ed
+     */
+    private void doZIP(String folderToZIP) {
+        if (shouldZIP) {
+            // ZIP the Folder.
+            try {
+                FileUtils.zipDir(folderToZIP, folderToZIP);
+            } catch (IOException ioe) {
+                LogUtils.exceptionLog(ioe.getStackTrace(), "Failed to ZIP backup: IO Exception.");
+            }
+            // Delete the folder.
+            try {
+                // Delete the original doBackup directory.
+                FileUtils.deleteDirectory(new File(folderToZIP));
+                new File(folderToZIP).delete();
+            } catch (IOException ioe) {
+                LogUtils.exceptionLog(ioe.getStackTrace(), "Failed to delete temp folder: IO Exception.");
+            }
+        }
+    }
+
+    /**
+     * Check whether there are more backups as allowed to store. 
+     * When this case is true, it deletes oldest ones.
+     */
+    private boolean deleteOldBackups() {
+
+        // Get the doBackup's directory.
+        File backupDir = new File(settings.getStringProperty("backuppath"));
+
+        // Check if split doBackup or not.
+        if (splitbackup) {
+            try {
+                // Loop the folders, and clean for each.
+                File[] foldersToClean = backupDir.listFiles();
+                for (int l = 0; l < foldersToClean.length; l++) {
+
+                    // Make sure we are cleaning a directory.
+                    if (foldersToClean[l].isDirectory()) {
+                        cleanFolder(foldersToClean[l]);
+                    }
+                }
+            } catch (IOException | NullPointerException ex) {
+                LogUtils.exceptionLog(ex.getStackTrace());
+                return false;
+            }
+
+        } else {
+
+            // Clean entire directory.
+            try {
+                cleanFolder(backupDir);
+            } catch (IOException | NullPointerException ex) {
+                LogUtils.exceptionLog(ex.getStackTrace());
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void cleanFolder(File backupDir) throws IOException {
+
+        // Get properties.
+        try {
+            final int maxBackups = settings.getIntProperty("maxbackups");
+
+            // Store all doBackup files in an array.
+            File[] filesList = backupDir.listFiles();
+
+            if (filesList == null) {
+                LogUtils.sendLog(Level.SEVERE, "Failed to list backup directory.");
+                return;
+            }
+
+            // If the amount of files exceeds the max backups to keep.
+            if (filesList.length > maxBackups) {
+                ArrayList<File> backupList = new ArrayList<>(filesList.length);
+                backupList.addAll(Arrays.asList(filesList));
+
+                int maxModifiedIndex;
+                long maxModified;
+
+                //Remove the newst backups from the list.
+                for (int i = 0; i < maxBackups; ++i) {
+                    maxModifiedIndex = 0;
+                    maxModified = backupList.get(0).lastModified();
+                    for (int j = 1; j < backupList.size(); ++j) {
+                        File currentFile = backupList.get(j);
+                        if (currentFile.lastModified() > maxModified) {
+                            maxModified = currentFile.lastModified();
+                            maxModifiedIndex = j;
+                        }
+                    }
+                    ba