From 19865969d2d6cdd8129fe044c8a1a4c6d2c662c5 Mon Sep 17 00:00:00 2001 From: tastybento Date: Thu, 25 May 2017 22:54:04 -0700 Subject: [PATCH] Added a lot of MySQL stuff. WIP, not tested at all. Beware test conde on onEnable(). --- .../us/tastybento/bskyblock/BSkyBlock.java | 9 ++ .../tastybento/bskyblock/config/Settings.java | 9 +- .../database/AbstractDatabaseHandler.java | 15 +-- .../bskyblock/database/BSBDatabase.java | 6 +- .../bskyblock/database/DatabaseConnecter.java | 12 ++ .../DatabaseConnectionSettingsImpl.java | 92 ++++++++++++++- .../bskyblock/database/IslandsManager.java | 12 +- .../database/mysql/MySQLDatabase.java | 6 +- .../database/mysql/MySQLDatabaseHandler.java | 106 ++++++++++++++++-- .../mysql/MySqlDatabaseConnecter.java | 34 ++++-- .../bskyblock/database/objects/Island.java | 1 + 11 files changed, 261 insertions(+), 41 deletions(-) diff --git a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java index b9a0165db..cc6cef48d 100755 --- a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java +++ b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java @@ -11,6 +11,7 @@ import us.tastybento.bskyblock.config.BSBLocale; import us.tastybento.bskyblock.config.PluginConfig; import us.tastybento.bskyblock.config.Settings; import us.tastybento.bskyblock.database.BSBDatabase; +import us.tastybento.bskyblock.database.BSBDatabase.DatabaseType; import us.tastybento.bskyblock.database.IslandsManager; import us.tastybento.bskyblock.database.OfflineHistoryMessages; import us.tastybento.bskyblock.database.PlayersManager; @@ -40,6 +41,14 @@ public class BSkyBlock extends JavaPlugin{ // Load configuration and locales. If there are no errors, load the plugin. if(PluginConfig.loadPluginConfig(this)){ + // TEMP DEBUG DATABASE + Settings.databaseType = DatabaseType.MYSQL; + Settings.dbHost = "localhost"; + Settings.dbPort = 3306; + Settings.dbName = "ASkyBlock"; + Settings.dbUsername = "user"; + Settings.dbPassword = "password"; + playersManager = new PlayersManager(this); islandsManager = new IslandsManager(this); diff --git a/src/main/java/us/tastybento/bskyblock/config/Settings.java b/src/main/java/us/tastybento/bskyblock/config/Settings.java index ada617635..88e0f344a 100755 --- a/src/main/java/us/tastybento/bskyblock/config/Settings.java +++ b/src/main/java/us/tastybento/bskyblock/config/Settings.java @@ -33,7 +33,6 @@ public class Settings { public static boolean purgeRemoveUserData; // TODO Database - public static DatabaseType databaseType; public static int databaseBackupPeriod; public static boolean recoverSuperFlat; @@ -156,4 +155,12 @@ public class Settings { // TODO added this just to avoid compilation errors, but will be changed in the future public static List historyMessagesTypes; + + // Database settings + public static DatabaseType databaseType; + public static String dbHost; + public static int dbPort; + public static String dbName; + public static String dbUsername; + public static String dbPassword; } diff --git a/src/main/java/us/tastybento/bskyblock/database/AbstractDatabaseHandler.java b/src/main/java/us/tastybento/bskyblock/database/AbstractDatabaseHandler.java index d19afbb1a..5b8fff7bf 100644 --- a/src/main/java/us/tastybento/bskyblock/database/AbstractDatabaseHandler.java +++ b/src/main/java/us/tastybento/bskyblock/database/AbstractDatabaseHandler.java @@ -7,7 +7,6 @@ import java.sql.SQLException; import java.util.List; import us.tastybento.bskyblock.BSkyBlock; -import us.tastybento.bskyblock.database.objects.Island; /** * An abstract class that handles insert/select-operations into/from a database @@ -19,11 +18,6 @@ import us.tastybento.bskyblock.database.objects.Island; * * @param */ -/** - * @author tastybento - * - * @param - */ public abstract class AbstractDatabaseHandler { /** @@ -45,7 +39,7 @@ public abstract class AbstractDatabaseHandler { protected BSkyBlock plugin; - + /** * Constructor * @@ -56,8 +50,7 @@ public abstract class AbstractDatabaseHandler { * Contains the settings to create a connection to the database * like host/port/database/user/password */ - protected AbstractDatabaseHandler(BSkyBlock plugin, Class type, - DatabaseConnecter databaseConnecter) { + protected AbstractDatabaseHandler(BSkyBlock plugin, Class type, DatabaseConnecter databaseConnecter) { this.plugin = plugin; this.databaseConnecter = databaseConnecter; @@ -103,7 +96,7 @@ public abstract class AbstractDatabaseHandler { return sb.toString(); } - + /** * Loads all the records in this table and returns a list of them * @return list of @@ -129,7 +122,7 @@ public abstract class AbstractDatabaseHandler { * @throws InstantiationException */ protected abstract T selectObject(String uniqueId) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException; - + /** * Inserts T into the corresponding database-table * diff --git a/src/main/java/us/tastybento/bskyblock/database/BSBDatabase.java b/src/main/java/us/tastybento/bskyblock/database/BSBDatabase.java index 88f83c500..257857d83 100755 --- a/src/main/java/us/tastybento/bskyblock/database/BSBDatabase.java +++ b/src/main/java/us/tastybento/bskyblock/database/BSBDatabase.java @@ -8,6 +8,11 @@ import us.tastybento.bskyblock.database.sqlite.SQLiteDatabase; public abstract class BSBDatabase { + /** + * Gets the type of database being used. Currently supported options are + * FLATFILE, MYSQL and SQLITE. Default is FLATFILE + * @return Database type + */ public static BSBDatabase getDatabase(){ for(DatabaseType type : DatabaseType.values()){ if(type == Settings.databaseType) return type.database; @@ -31,7 +36,6 @@ public abstract class BSBDatabase { * Gets a handler for this class type with this database connection * @param plugin * @param type - * @param databaseConnecter * @return selector object */ public abstract AbstractDatabaseHandler getHandler(BSkyBlock plugin, Class type); diff --git a/src/main/java/us/tastybento/bskyblock/database/DatabaseConnecter.java b/src/main/java/us/tastybento/bskyblock/database/DatabaseConnecter.java index 0561f7dd9..3de6994e1 100644 --- a/src/main/java/us/tastybento/bskyblock/database/DatabaseConnecter.java +++ b/src/main/java/us/tastybento/bskyblock/database/DatabaseConnecter.java @@ -34,8 +34,20 @@ public interface DatabaseConnecter { */ public String getUniqueId(String tableName); + /** + * Loads a YAML file. Used by the flat file database + * @param string + * @param key + * @return Yaml Configuration + */ public YamlConfiguration loadYamlFile(String string, String key); + /** + * Save the Yaml Config + * @param yamlFile + * @param tableName - analogous to a table in a database + * @param fileName - the name of the record. Must be unique. + */ public void saveYamlFile(YamlConfiguration yamlFile, String tableName, String fileName); } diff --git a/src/main/java/us/tastybento/bskyblock/database/DatabaseConnectionSettingsImpl.java b/src/main/java/us/tastybento/bskyblock/database/DatabaseConnectionSettingsImpl.java index aee0838e1..a08fe3f89 100644 --- a/src/main/java/us/tastybento/bskyblock/database/DatabaseConnectionSettingsImpl.java +++ b/src/main/java/us/tastybento/bskyblock/database/DatabaseConnectionSettingsImpl.java @@ -1,10 +1,96 @@ package us.tastybento.bskyblock.database; +import us.tastybento.bskyblock.config.Settings; + public class DatabaseConnectionSettingsImpl { - public DatabaseConnectionSettingsImpl(String string, int i, String string2, - String string3, String string4) { - // TODO Auto-generated constructor stub + private String host; + private int port; + private String databaseName; + private String username; + private String password; + /** + * Hosts database settings + * @param host + * @param port + * @param databaseName + * @param username + * @param password + */ + public DatabaseConnectionSettingsImpl(String host, int port, + String databaseName, String username, String password) { + this.host = host; + this.port = port; + this.databaseName = databaseName; + this.username = username; + this.password = password; + } + public DatabaseConnectionSettingsImpl() { + this.host = Settings.dbHost; + this.port = Settings.dbPort; + this.databaseName = Settings.dbName; + this.username = Settings.dbUsername; + this.password = Settings.dbPassword; + } + /** + * @return the host + */ + public String getHost() { + return host; + } + /** + * @param host the host to set + */ + public void setHost(String host) { + this.host = host; + } + /** + * @return the port + */ + public int getPort() { + return port; + } + /** + * @param port the port to set + */ + public void setPort(int port) { + this.port = port; + } + /** + * @return the databaseName + */ + public String getDatabaseName() { + return databaseName; + } + /** + * @param databaseName the databaseName to set + */ + public void setDatabaseName(String databaseName) { + this.databaseName = databaseName; + } + /** + * @return the username + */ + public String getUsername() { + return username; + } + /** + * @param username the username to set + */ + public void setUsername(String username) { + this.username = username; + } + /** + * @return the password + */ + public String getPassword() { + return password; + } + /** + * @param password the password to set + */ + public void setPassword(String password) { + this.password = password; } } diff --git a/src/main/java/us/tastybento/bskyblock/database/IslandsManager.java b/src/main/java/us/tastybento/bskyblock/database/IslandsManager.java index 8893627e8..c7099183e 100755 --- a/src/main/java/us/tastybento/bskyblock/database/IslandsManager.java +++ b/src/main/java/us/tastybento/bskyblock/database/IslandsManager.java @@ -13,6 +13,11 @@ import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.config.Settings; import us.tastybento.bskyblock.database.objects.Island; +/** + * The job of this class is manage all island related data. + * @author tastybento + * + */ public class IslandsManager { private BSkyBlock plugin; @@ -23,12 +28,16 @@ public class IslandsManager { // 2D islandGrid of islands, x,z private TreeMap> islandGrid = new TreeMap>(); + /** + * One island can be spawn, this is the one - otherwise, this value is null + */ private Island spawn; // Metrics data private int metrics_createdcount = 0; private AbstractDatabaseHandler handler; - + + @SuppressWarnings("unchecked") public IslandsManager(BSkyBlock plugin){ this.plugin = plugin; database = BSBDatabase.getDatabase(); @@ -36,7 +45,6 @@ public class IslandsManager { islands = new HashMap(); islandsByUUID = new HashMap(); spawn = null; - //load(); } public void load(){ diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabase.java b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabase.java index 0c593cf31..17c3d5fde 100755 --- a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabase.java +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabase.java @@ -3,14 +3,16 @@ package us.tastybento.bskyblock.database.mysql; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.BSBDatabase; -import us.tastybento.bskyblock.database.flatfile.FlatFileDatabaseConnecter; +import us.tastybento.bskyblock.database.DatabaseConnectionSettingsImpl; import us.tastybento.bskyblock.database.objects.Island; public class MySQLDatabase extends BSBDatabase{ @Override public AbstractDatabaseHandler getHandler(BSkyBlock plugin, Class type) { - return new MySQLDatabaseHandler(plugin, Island.class, new FlatFileDatabaseConnecter(plugin, null)); + + return new MySQLDatabaseHandler(plugin, Island.class, + new MySqlDatabaseConnecter(new DatabaseConnectionSettingsImpl())); } diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java index 7790debaf..77b390c10 100644 --- a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java @@ -5,13 +5,23 @@ import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.World; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.database.AbstractDatabaseHandler; @@ -27,11 +37,85 @@ import us.tastybento.bskyblock.database.DatabaseConnecter; */ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { - public MySQLDatabaseHandler(BSkyBlock plugin, Class type, - DatabaseConnecter databaseConnecter) { + private Connection connection = null; + private static HashMap mySQLmapping; + { + mySQLmapping = new HashMap(); + mySQLmapping.put(boolean.class.getTypeName(), "BOOL"); + mySQLmapping.put(byte.class.getTypeName(), "TINYINT"); + mySQLmapping.put(short.class.getTypeName(), "SMALLINT"); + mySQLmapping.put(int.class.getTypeName(), "INTEGER"); + mySQLmapping.put(long.class.getTypeName(), "BIGINT"); + mySQLmapping.put(double.class.getTypeName(), "DOUBLE PRECISION"); + mySQLmapping.put(Boolean.class.getTypeName(), "BOOL"); + mySQLmapping.put(Byte.class.getTypeName(), "TINYINT"); + mySQLmapping.put(Short.class.getTypeName(), "SMALLINT"); + mySQLmapping.put(Integer.class.getTypeName(), "INTEGER"); + mySQLmapping.put(Long.class.getTypeName(), "BIGINT"); + mySQLmapping.put(Double.class.getTypeName(), "DOUBLE PRECISION"); + mySQLmapping.put(BigDecimal.class.getTypeName(), "DECIMAL(13,0)"); + mySQLmapping.put(String.class.getTypeName(), "VARCHAR(254)"); + mySQLmapping.put(Date.class.getTypeName(), "DATE"); + mySQLmapping.put(Time.class.getTypeName(), "TIME"); + mySQLmapping.put(Timestamp.class.getTypeName(), "TIMESTAMP"); + mySQLmapping.put(UUID.class.getTypeName(), "VARCHAR(32)"); // TODO: How long is a UUID to string? + + // Bukkit Mappings + mySQLmapping.put(Location.class.getTypeName(), "VARCHAR(254)"); + mySQLmapping.put(World.class.getTypeName(), "VARCHAR(254)"); + + // Sets - this stores just the name of the set which is another table + mySQLmapping.put(Set.class.getTypeName(), "VARCHAR(254)"); + + } + + public MySQLDatabaseHandler(BSkyBlock plugin, Class type, DatabaseConnecter databaseConnecter) { super(plugin, type, databaseConnecter); + // Check if the table exists in the database and if not, create it + try { + createSchema(); + } catch (IntrospectionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } - + + /** + * Creates the table in the database if it doesn't exist already + * @throws IntrospectionException + * @throws SQLException + */ + private void createSchema() throws IntrospectionException, SQLException { + PreparedStatement pstmt = null; + connection = databaseConnecter.createConnection(); + try { + String sql = "CREATE TABLE IF NOT EXISTS " + type.getSimpleName() + "("; + for (Field field : type.getDeclaredFields()) { + PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), type); + plugin.getLogger().info("DEBUG: Field = " + field.getName()); + String mapping = mySQLmapping.get(propertyDescriptor.getPropertyType().getTypeName()); + if (mapping != null) { + sql += field.getName() + " " + mapping + ","; + } else { + sql += field.getName() + " VARCHAR(254),"; + plugin.getLogger().severe("Unknown type! Hoping it'll fit in a string!"); + } + } + sql = sql.substring((sql.length()-1), sql.length()) + ")"; + plugin.getLogger().info("DEBUG: SQL string = " + sql); + pstmt = connection.prepareStatement(sql.toString()); + pstmt.executeUpdate(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + MySQLDatabaseResourceCloser.close(pstmt); + MySQLDatabaseResourceCloser.close(pstmt); + } + } + @Override protected String createSelectQuery() { @@ -46,7 +130,7 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { return sb.toString(); } - + @Override protected String createInsertQuery() { @@ -130,9 +214,9 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { */ @Override public List selectObjects() throws SQLException, - SecurityException, IllegalArgumentException, - InstantiationException, IllegalAccessException, - IntrospectionException, InvocationTargetException { + SecurityException, IllegalArgumentException, + InstantiationException, IllegalAccessException, + IntrospectionException, InvocationTargetException { Connection connection = null; Statement statement = null; @@ -154,13 +238,13 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { @Override protected T selectObject(String uniqueId) throws InstantiationException, - IllegalAccessException, IllegalArgumentException, - InvocationTargetException, IntrospectionException { + IllegalAccessException, IllegalArgumentException, + InvocationTargetException, IntrospectionException { // TODO Auto-generated method stub return null; } - - + + /** * * Creates a list of s filled with values from the provided ResultSet diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/MySqlDatabaseConnecter.java b/src/main/java/us/tastybento/bskyblock/database/mysql/MySqlDatabaseConnecter.java index 9a59459de..0378c8ea0 100644 --- a/src/main/java/us/tastybento/bskyblock/database/mysql/MySqlDatabaseConnecter.java +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/MySqlDatabaseConnecter.java @@ -1,6 +1,7 @@ package us.tastybento.bskyblock.database.mysql; import java.sql.Connection; +import java.sql.DriverManager; import java.sql.SQLException; import org.bukkit.configuration.file.YamlConfiguration; @@ -10,39 +11,52 @@ import us.tastybento.bskyblock.database.DatabaseConnectionSettingsImpl; public class MySqlDatabaseConnecter implements DatabaseConnecter { + private String connectionUrl; + private DatabaseConnectionSettingsImpl dbSettings; + private Connection connection = null; + /** + * Class for MySQL database connections using the settings provided + * @param dbSettings + */ public MySqlDatabaseConnecter( - DatabaseConnectionSettingsImpl databaseConnectionSettingsImpl) { - // TODO Auto-generated constructor stub + DatabaseConnectionSettingsImpl dbSettings) { + this.dbSettings = dbSettings; + try { + Class.forName("com.mysql.jdbc.Driver").newInstance(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + connectionUrl = "jdbc:mysql://" + dbSettings.getHost() + "/" + dbSettings.getDatabaseName(); } @Override public Connection createConnection() throws SQLException { - // TODO Auto-generated method stub - return null; + connection = DriverManager.getConnection(connectionUrl, dbSettings.getUsername(), dbSettings.getPassword()); + return connection; } @Override public String getConnectionUrl() { - // TODO Auto-generated method stub - return null; + return connectionUrl; } @Override public String getUniqueId(String tableName) { - // TODO Auto-generated method stub - return null; + // Not used + return ""; } @Override public YamlConfiguration loadYamlFile(String string, String key) { - // TODO Auto-generated method stub + // Not used return null; } @Override public void saveYamlFile(YamlConfiguration yamlFile, String tableName, String fileName) { - // TODO Auto-generated method stub + // Not used } diff --git a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java index af4a2ef26..84d09df4c 100755 --- a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java +++ b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java @@ -801,4 +801,5 @@ public class Island extends DataObject { this.uniqueId = uniqueId; } + } \ No newline at end of file