Database additions

This commit is contained in:
tastybento 2017-05-21 16:53:17 -07:00
parent 521e4b8b83
commit edc5c9c642
14 changed files with 822 additions and 1 deletions

View File

@ -1,5 +1,5 @@
name: BSkyBlock
main: us.tastybento.askyblock.BSkyBlock
main: us.tastybento.bskyblock.BSkyBlock
version: ${version}
authors: [Tastybento, Poslovitch]

View File

@ -13,6 +13,7 @@ import us.tastybento.bskyblock.database.BSBDatabase;
import us.tastybento.bskyblock.database.IslandsManager;
import us.tastybento.bskyblock.database.OfflineHistoryMessages;
import us.tastybento.bskyblock.database.PlayersManager;
import us.tastybento.bskyblock.database.RunTest;
import us.tastybento.bskyblock.util.VaultHelper;
/**
@ -36,6 +37,7 @@ public class BSkyBlock extends JavaPlugin{
@Override
public void onEnable(){
plugin = this;
new RunTest(this);
playersManager = new PlayersManager(this);
islandsManager = new IslandsManager(this);

View File

@ -0,0 +1,89 @@
package us.tastybento.bskyblock.database;
import java.lang.reflect.Field;
import us.tastybento.bskyblock.BSkyBlock;
/**
* An abstract class that handles insert/select-operations into/from a database
*
* @author Tino for http://www.java-blog.com
*
* @param <T>
*/
public abstract class AbstractDatabaseHandler<T> {
/**
* The type of the objects that should be created and filled with values
* from the database or inserted into the database
*/
protected Class<T> type;
/**
* Contains the settings to create a connection to the database like
* host/port/database/user/password
*/
protected DatabaseConnecter databaseConnecter;
/** The SQL-select-query */
protected final String query;
protected BSkyBlock plugin;
/**
* Constructor
*
* @param type
* The type of the objects that should be created and filled with
* values from the database or inserted into the database
* @param databaseConnecter
* Contains the settings to create a connection to the database
* like host/port/database/user/password
*/
protected AbstractDatabaseHandler(BSkyBlock plugin, Class<T> type,
DatabaseConnecter databaseConnecter) {
this.plugin = plugin;
this.databaseConnecter = databaseConnecter;
this.type = type;
this.query = createQuery();
}
/**
* Create the SQL-String to insert into / select from the database
*
* @return the SQL-String
*/
protected abstract String createQuery();
/**
*
* Creates a comma-separated-String with the names of the variables in this
* class
*
* @param usePlaceHolders
* true, if PreparedStatement-placeholders ('?') should be used
* instead of the names of the variables
* @return
*/
protected String getColumns(boolean usePlaceHolders) {
StringBuilder sb = new StringBuilder();
boolean first = true;
/* Iterate the column-names */
for (Field f : type.getDeclaredFields()) {
if (first)
first = false;
else
sb.append(", ");
if (usePlaceHolders)
sb.append("?");
else
sb.append(f.getName());
}
return sb.toString();
}
}

View File

@ -0,0 +1,42 @@
package us.tastybento.bskyblock.database;
import java.sql.Connection;
import java.sql.SQLException;
import org.bukkit.configuration.file.YamlConfiguration;
/**
*
* Creates a connection to a database.
*
*/
public interface DatabaseConnecter {
/**
* Establishes a new connection to the database
*
* @return A new connection to the database
* @throws SQLException
*/
public Connection createConnection() throws SQLException;
/**
* Returns the connection url
*
* @return
*/
public String getConnectionUrl();
/**
* @param simpleName
* @return
*/
public YamlConfiguration loadYamlFile(String simpleName);
/**
* @param config
* @param simpleName
*/
public void saveYamlFile(YamlConfiguration config, String simpleName);
}

View File

@ -0,0 +1,10 @@
package us.tastybento.bskyblock.database;
public class DatabaseConnectionSettingsImpl {
public DatabaseConnectionSettingsImpl(String string, int i, String string2,
String string3, String string4) {
// TODO Auto-generated constructor stub
}
}

View File

@ -0,0 +1,42 @@
package us.tastybento.bskyblock.database;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.flatfile.FlatFileDatabaseInserter;
import us.tastybento.bskyblock.database.flatfile.FlatFileDatabaseSelecter;
import us.tastybento.bskyblock.database.flatfile.FlatFileDatabaseConnecter;
public class RunTest {
public RunTest(BSkyBlock plugin) {
try {
DatabaseConnecter connecter = new FlatFileDatabaseConnecter(plugin, null);
/*
new DatabaseConnectionSettingsImpl(
"127.0.0.1", 3306, "exampleDatabase","user", "pass"));
*/
Test test = new Test();
test.setId(34);
test.setName("testname");
FlatFileDatabaseInserter<Test> inserter = new FlatFileDatabaseInserter<Test>(plugin, Test.class, connecter);
inserter.insertObject(test);
FlatFileDatabaseSelecter<Test> selecter = new FlatFileDatabaseSelecter<Test>(plugin, Test.class, connecter);
test = selecter.selectObject();
plugin.getLogger().info("DEBUG: name = " + test.getName());
plugin.getLogger().info("DEBUG: id = " + test.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,44 @@
package us.tastybento.bskyblock.database;
public class Test {
private int id;
private String name;
public Test() {}
public Test(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
final String TAB = " \n";
StringBuilder retValue = new StringBuilder();
retValue.append("Test (\n ")
.append(super.toString()).append(TAB)
.append(" id = ").append(this.id).append(TAB)
.append(" name = ").append(this.name).append(TAB)
.append(" )");
return retValue.toString();
}
}

View File

@ -0,0 +1,90 @@
package us.tastybento.bskyblock.database.flatfile;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import org.bukkit.configuration.file.YamlConfiguration;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.DatabaseConnecter;
import us.tastybento.bskyblock.database.DatabaseConnectionSettingsImpl;
public class FlatFileDatabaseConnecter implements DatabaseConnecter {
private BSkyBlock plugin;
public FlatFileDatabaseConnecter(BSkyBlock plugin, DatabaseConnectionSettingsImpl databaseConnectionSettingsImpl) {
this.plugin = plugin;
}
@Override
public Connection createConnection() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getConnectionUrl() {
// TODO Auto-generated method stub
return null;
}
/**
* Loads a YAML file and if it does not exist it is looked for in the JAR
*
* @param fileName
* @return
*/
@Override
public YamlConfiguration loadYamlFile(String fileName) {
File dataFolder = new File(plugin.getDataFolder(), "database");
File yamlFile = new File(dataFolder, fileName + ".yml");
YamlConfiguration config = null;
if (yamlFile.exists()) {
try {
config = new YamlConfiguration();
config.load(yamlFile);
} catch (Exception e) {
e.printStackTrace();
}
} else {
// Create the missing file
config = new YamlConfiguration();
plugin.getLogger().info("No " + fileName + " found. Creating it...");
try {
if (plugin.getResource(fileName) != null) {
plugin.getLogger().info("Using default found in jar file.");
plugin.saveResource(fileName, false);
config = new YamlConfiguration();
config.load(yamlFile);
} else {
config.save(yamlFile);
}
} catch (Exception e) {
plugin.getLogger().severe("Could not create the " + fileName + " file!");
}
}
return config;
}
/**
* Saves a YAML file
*
* @param yamlFile
* @param fileName
*/
@Override
public void saveYamlFile(YamlConfiguration yamlFile, String fileName) {
File dataFolder = new File(plugin.getDataFolder(), "database");
File file = new File(dataFolder, fileName + ".yml");
try {
yamlFile.save(file);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,63 @@
package us.tastybento.bskyblock.database.flatfile;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.bukkit.configuration.file.YamlConfiguration;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.AbstractDatabaseHandler;
import us.tastybento.bskyblock.database.DatabaseConnecter;
/**
*
* Class that inserts a list of <T>s into the corresponding YAML file.
*
* @author tastybento
*
* @param <T>
*/
public class FlatFileDatabaseInserter<T> extends AbstractDatabaseHandler<T> {
public FlatFileDatabaseInserter(BSkyBlock plugin, Class<T> type, DatabaseConnecter databaseConnecter) {
super(plugin, type, databaseConnecter);
}
@Override
protected String createQuery() {
// Not used for flat file
return "";
}
/**
* Inserts T into the corresponding database-table
*
* @param instance that should be inserted into the database
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws IntrospectionException
*/
public void insertObject(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
YamlConfiguration config = databaseConnecter.loadYamlFile(type.getSimpleName());
for (Field field : type.getDeclaredFields()) {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), type);
Method method = propertyDescriptor.getReadMethod();
Object value = method.invoke(instance);
// TODO: depending on the type, it'll need serializing
config.set(field.getName(), value);
}
databaseConnecter.saveYamlFile(config, type.getSimpleName());
}
}

View File

@ -0,0 +1,89 @@
package us.tastybento.bskyblock.database.flatfile;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.bukkit.configuration.file.YamlConfiguration;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.AbstractDatabaseHandler;
import us.tastybento.bskyblock.database.DatabaseConnecter;
/**
*
* Class that creates a list of <T>s filled with values from the corresponding
* database-table.
*
* @author tastybento
*
* @param <T>
*/
public class FlatFileDatabaseSelecter<T> extends AbstractDatabaseHandler<T> {
public FlatFileDatabaseSelecter(BSkyBlock plugin, Class<T> type,
DatabaseConnecter databaseConnecter) {
super(plugin, type, databaseConnecter);
}
@Override
protected String createQuery() {
return "";
}
/**
* Creates a <T> filled with values from the corresponding
* database file
*
* @return <T> filled with values from the corresponding database file
* @throws IntrospectionException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public T selectObject() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
YamlConfiguration config = databaseConnecter.loadYamlFile(type.getSimpleName());
return createObject(config);
}
/**
*
* Creates a list of <T>s filled with values from the provided ResultSet
*
* @param config - YAML config file
*
* @return <T> filled with values
*
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IntrospectionException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
private T createObject(YamlConfiguration config) throws InstantiationException, IllegalAccessException,
IntrospectionException, IllegalArgumentException, InvocationTargetException
{
T instance = type.newInstance();
for (Field field : type.getDeclaredFields()) {
/* We assume the table-column-names exactly match the variable-names of T */
// TODO: depending on the data type, it'll need deserializing
Object value = config.get(field.getName());
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
field.getName(), type);
Method method = propertyDescriptor.getWriteMethod();
method.invoke(instance, value);
}
return instance;
}
}

View File

@ -0,0 +1,95 @@
package us.tastybento.bskyblock.database.mysql;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.AbstractDatabaseHandler;
import us.tastybento.bskyblock.database.DatabaseConnecter;
/**
*
* Class that inserts a <T> into the corresponding database-table.
*
* @author tastybento
*
* @param <T>
*/
public class MySQLDatabaseInserter<T> extends AbstractDatabaseHandler<T> {
public MySQLDatabaseInserter(BSkyBlock plugin, Class<T> type,
DatabaseConnecter databaseConnecter) {
super(plugin, type, databaseConnecter);
}
@Override
protected String createQuery() {
StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO ");
sb.append(type.getSimpleName());
sb.append("(");
sb.append(super.getColumns(false));
sb.append(")");
sb.append(" VALUES (");
sb.append(super.getColumns(true));
sb.append(")");
return sb.toString();
}
/**
* Inserts a <T> into the corresponding database-table
*
* @param instance <T> that should be inserted into the corresponding database-table
* @throws SQLException
* @throws SecurityException
* @throws IllegalArgumentException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IntrospectionException
* @throws InvocationTargetException
*/
public void insertObject(T instance) throws SQLException,
SecurityException, IllegalArgumentException,
InstantiationException, IllegalAccessException,
IntrospectionException, InvocationTargetException {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = databaseConnecter.createConnection();
preparedStatement = connection.prepareStatement(query);
int i = 0;
for (Field field : type.getDeclaredFields()) {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
field.getName(), type);
Method method = propertyDescriptor
.getReadMethod();
Object value = method.invoke(instance);
preparedStatement.setObject(++i, value);
}
preparedStatement.addBatch();
preparedStatement.executeBatch();
} finally {
MySQLDatabaseResourceCloser.close(preparedStatement);
MySQLDatabaseResourceCloser.close(preparedStatement);
}
}
}

View File

@ -0,0 +1,77 @@
package us.tastybento.bskyblock.database.mysql;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class MySQLDatabaseResourceCloser {
/**
* Closes the provided ResultSets
*
* @param resultSets
* ResultSets that should be closed
*/
public static void close(ResultSet... resultSets) {
if (resultSets == null)
return;
for (ResultSet resultSet : resultSets)
if (resultSet != null)
try {
resultSet.close();
} catch (SQLException e) {
/* Do some exception-logging here. */
e.printStackTrace();
}
}
/**
* Closes the provided Statements
*
* @param statements
* Statements that should be closed
*/
public static void close(Statement... statements) {
/*
* No need to create methods for PreparedStatement and
* CallableStatement, because they extend Statement.
*/
if (statements == null)
return;
for (Statement statement : statements)
if (statement != null)
try {
statement.close();
} catch (SQLException e) {
/* Do some exception-logging here. */
e.printStackTrace();
}
}
/**
* Closes the provided Connections
*
* @param connections
* Connections that should be closed
*/
public static void close(Connection... connections) {
if (connections == null)
return;
for (Connection connection : connections)
if (connection != null)
try {
connection.close();
} catch (SQLException e) {
/* Do some exception-logging here. */
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,136 @@
package us.tastybento.bskyblock.database.mysql;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.AbstractDatabaseHandler;
import us.tastybento.bskyblock.database.DatabaseConnecter;
/**
*
* Class that creates a list of <T>s filled with values from the corresponding
* database-table.
*
* @author Tino for http://www.java-blog.com
*
* @param <T>
*/
public class MySQLDatabaseSelecter<T> extends AbstractDatabaseHandler<T> {
public MySQLDatabaseSelecter(BSkyBlock plugin, Class<T> type,
DatabaseConnecter databaseConnecter) {
super(plugin, type, databaseConnecter);
}
@Override
protected String createQuery() {
StringBuilder sb = new StringBuilder();
sb.append("SELECT ");
sb.append(super.getColumns(false));
sb.append(" FROM ");
/* We assume the table-name exactly matches the simpleName of T */
sb.append(type.getSimpleName());
return sb.toString();
}
/**
* Creates a list of <T>s filled with values from the corresponding
* database-table
*
* @return List of <T>s filled with values from the corresponding
* database-table
*
* @throws SQLException
* @throws SecurityException
* @throws IllegalArgumentException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IntrospectionException
* @throws InvocationTargetException
*/
public List<T> selectObjects() throws SQLException,
SecurityException, IllegalArgumentException,
InstantiationException, IllegalAccessException,
IntrospectionException, InvocationTargetException {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = databaseConnecter.createConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery(query);
return createObjects(resultSet);
} finally {
MySQLDatabaseResourceCloser.close(resultSet);
MySQLDatabaseResourceCloser.close(statement);
MySQLDatabaseResourceCloser.close(connection);
}
}
/**
*
* Creates a list of <T>s filled with values from the provided ResultSet
*
* @param resultSet
* ResultSet that contains the result of the
* database-select-query
*
* @return List of <T>s filled with values from the provided ResultSet
*
* @throws SecurityException
* @throws IllegalArgumentException
* @throws SQLException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IntrospectionException
* @throws InvocationTargetException
*/
private List<T> createObjects(ResultSet resultSet)
throws SecurityException, IllegalArgumentException,
SQLException, InstantiationException,
IllegalAccessException, IntrospectionException,
InvocationTargetException {
List<T> list = new ArrayList<T>();
while (resultSet.next()) {
T instance = type.newInstance();
for (Field field : type.getDeclaredFields()) {
/* We assume the table-column-names exactly match the variable-names of T */
Object value = resultSet.getObject(field.getName());
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
field.getName(), type);
Method method = propertyDescriptor.getWriteMethod();
method.invoke(instance, value);
}
list.add(instance);
}
return list;
}
}

View File

@ -0,0 +1,42 @@
package us.tastybento.bskyblock.database.mysql;
import java.sql.Connection;
import java.sql.SQLException;
import org.bukkit.configuration.file.YamlConfiguration;
import us.tastybento.bskyblock.database.DatabaseConnecter;
import us.tastybento.bskyblock.database.DatabaseConnectionSettingsImpl;
public class MySqlDatabaseConnecter implements DatabaseConnecter {
public MySqlDatabaseConnecter(
DatabaseConnectionSettingsImpl databaseConnectionSettingsImpl) {
// TODO Auto-generated constructor stub
}
@Override
public Connection createConnection() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getConnectionUrl() {
// TODO Auto-generated method stub
return null;
}
@Override
public YamlConfiguration loadYamlFile(String simpleName) {
// TODO Auto-generated method stub
return null;
}
@Override
public void saveYamlFile(YamlConfiguration config, String simpleName) {
// TODO Auto-generated method stub
}
}