diff --git a/pom.xml b/pom.xml
index 38f3e79..f21b5b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,12 @@
mongo-java-driver
2.10.1
+
+ org.apache.tomcat
+ tomcat-jdbc
+ 7.0.52
+ compile
+
clean package install
@@ -79,6 +85,8 @@
org.mongodb:mongo-java-driver
+ org.apache.tomcat:tomcat-jdbc
+ org.apache.tomcat:tomcat-juli
diff --git a/src/org/melonbrew/fe/database/Database.java b/src/org/melonbrew/fe/database/Database.java
index 43aa1d3..e5b68a2 100644
--- a/src/org/melonbrew/fe/database/Database.java
+++ b/src/org/melonbrew/fe/database/Database.java
@@ -10,13 +10,15 @@
public abstract class Database {
private final Fe plugin;
- private final Set cachedAccounts;
+ private final HashMap cachedAccountsUUID;
+ private final HashMap cachedAccountsUsername;
protected boolean cacheAccounts;
public Database(Fe plugin) {
this.plugin = plugin;
- this.cachedAccounts = new HashSet();
+ this.cachedAccountsUUID = new HashMap();
+ this.cachedAccountsUsername = new HashMap();
}
public boolean init() {
@@ -26,38 +28,27 @@ public boolean init() {
}
public List getTopAccounts(int size) {
- List topAccounts = loadTopAccounts(size * 2);
-
- if (!cachedAccounts.isEmpty()) {
- for (Account account : cachedAccounts) {
+ List topAccounts = this.loadTopAccounts(size * 2);
+ if (!this.cachedAccountsUUID.isEmpty()) {
+ final Account lowest = topAccounts.get(topAccounts.size() - 1);
+ final List cachedTopAccounts = new ArrayList();
+ for (final Account account : this.cachedAccountsUUID.values()) {
topAccounts.remove(account);
- }
-
- List cachedTopAccounts = new ArrayList(cachedAccounts);
-
- Collections.sort(cachedTopAccounts, new Comparator() {
- public int compare(Account account1, Account account2) {
- return (int) (account2.getMoney() - account1.getMoney());
+ if (lowest.getMoney() <= account.getMoney()) {
+ cachedTopAccounts.add(account);
}
- });
-
- if (cachedAccounts.size() > size) {
- cachedTopAccounts = cachedTopAccounts.subList(0, size);
}
-
topAccounts.addAll(cachedTopAccounts);
}
-
Collections.sort(topAccounts, new Comparator() {
- public int compare(Account account1, Account account2) {
- return (int) (account2.getMoney() - account1.getMoney());
+ @Override
+ public int compare(final Account account1, final Account account2) {
+ return (int)(account2.getMoney() - account1.getMoney());
}
});
-
if (topAccounts.size() > size) {
topAccounts = topAccounts.subList(0, size);
}
-
return topAccounts;
}
@@ -82,9 +73,8 @@ public void removeAccount(String name, String uuid) {
public abstract void clean();
public void removeAllAccounts() {
- for (Account account : new HashSet(cachedAccounts)) {
- cachedAccounts.remove(account);
- }
+ cachedAccountsUUID.clear();
+ cachedAccountsUsername.clear();
}
protected boolean convertToUUID() {
@@ -146,15 +136,11 @@ protected boolean convertToUUID() {
}
public void close() {
- Iterator iterator = cachedAccounts.iterator();
-
- while (iterator.hasNext()) {
- Account account = iterator.next();
-
+ for (final Account account : this.cachedAccountsUUID.values()) {
account.save(account.getMoney());
-
- iterator.remove();
}
+ this.cachedAccountsUUID.clear();
+ this.cachedAccountsUsername.clear();
}
public abstract String getName();
@@ -202,7 +188,8 @@ private Account createAndAddAccount(String name, String uuid, double money) {
Player player = plugin.getServer().getPlayerExact(name);
if (player != null) {
- cachedAccounts.add(account);
+ this.cachedAccountsUsername.put(name, account);
+ this.cachedAccountsUUID.put(UUID.fromString(uuid), account);
}
}
@@ -218,17 +205,16 @@ public boolean cacheAccounts() {
}
public Account getCachedAccount(String name, String uuid) {
- for (Account account : cachedAccounts) {
- if (account.getName().equals(name)) {
- return account;
- }
+ if (uuid != null) {
+ return this.cachedAccountsUUID.get(UUID.fromString(uuid));
}
-
- return null;
+ return this.cachedAccountsUsername.get(name);
}
public boolean removeCachedAccount(Account account) {
- return cachedAccounts.remove(account);
+ this.cachedAccountsUUID.remove(UUID.fromString(account.getUUID()));
+ this.cachedAccountsUsername.remove(account.getName());
+ return true;
}
public abstract int getVersion();
diff --git a/src/org/melonbrew/fe/database/databases/MySQLDB.java b/src/org/melonbrew/fe/database/databases/MySQLDB.java
index 1fe36af..be07321 100644
--- a/src/org/melonbrew/fe/database/databases/MySQLDB.java
+++ b/src/org/melonbrew/fe/database/databases/MySQLDB.java
@@ -1,36 +1,56 @@
package org.melonbrew.fe.database.databases;
+import org.apache.tomcat.jdbc.pool.DataSource;
+import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.bukkit.configuration.ConfigurationSection;
import org.melonbrew.fe.Fe;
+import org.melonbrew.fe.database.Account;
+import org.melonbrew.fe.database.Database;
import java.sql.Connection;
-import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MySQLDB extends Database {
+ private final Fe plugin;
+ private DataSource pool;
+ private String table;
+ private String usernameField;
+ private String balanceField;
+ private String uuidField;
-public class MySQLDB extends SQLDB {
public MySQLDB(Fe plugin) {
- super(plugin, true);
+ super(plugin);
+ this.plugin = plugin;
}
- protected Connection getNewConnection() {
- ConfigurationSection config = getConfigSection();
+ public void getConfigDefaults(ConfigurationSection section) {
+ section.addDefault("host", "localhost");
- setAccountTable(config.getString("tables.accounts"));
+ section.addDefault("port", 3306);
- setAccountsColumnUser(config.getString("columns.accounts.username"));
+ section.addDefault("user", "root");
- setAccountsColumnMoney(config.getString("columns.accounts.money"));
+ section.addDefault("password", "minecraft");
- setAccountsColumnUUID(config.getString("columns.accounts.uuid"));
+ section.addDefault("database", "Fe");
- try {
- Class.forName("com.mysql.jdbc.Driver");
+ ConfigurationSection tables = getSection(section, "tables");
- String url = "jdbc:mysql://" + config.getString("host") + ":" + config.getString("port") + "/" + config.getString("database");
+ tables.addDefault("accounts", "fe_accounts");
- return DriverManager.getConnection(url, config.getString("user"), config.getString("password"));
- } catch (Exception e) {
- return null;
- }
+ ConfigurationSection columns = getSection(section, "columns");
+
+ ConfigurationSection columnsAccounts = getSection(columns, "accounts");
+
+ columnsAccounts.addDefault("username", "name");
+
+ columnsAccounts.addDefault("money", "money");
+
+ columnsAccounts.addDefault("uuid", "uuid");
}
private ConfigurationSection getSection(ConfigurationSection parent, String childName) {
@@ -43,33 +63,253 @@ private ConfigurationSection getSection(ConfigurationSection parent, String chil
return child;
}
- public void getConfigDefaults(ConfigurationSection section) {
- section.addDefault("host", "localhost");
+ public boolean init() {
+ ConfigurationSection config = getConfigSection();
+ String connectionString = "jdbc:mysql://" + config.getString("host") + ":" + config.getString("port") + "/" + config.getString("database");
- section.addDefault("port", 3306);
+ try {
+ // Force driver to load if not yet loaded
+ Class.forName("com.mysql.jdbc.Driver");
+ }
+ catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ return false;
+ }
- section.addDefault("user", "root");
+ table = config.getString("tables.accounts");
- section.addDefault("password", "minecraft");
+ usernameField = config.getString("columns.accounts.username");
- section.addDefault("database", "Fe");
+ balanceField = config.getString("columns.accounts.money");
- ConfigurationSection tables = getSection(section, "tables");
+ uuidField = config.getString("columns.accounts.uuid");
+
+ PoolProperties poolProperties = new PoolProperties();
+ poolProperties.setDriverClassName("com.mysql.jdbc.Driver");
+ poolProperties.setUrl(connectionString);
+ poolProperties.setUsername(config.getString("user"));
+ poolProperties.setPassword(config.getString("password"));
+ poolProperties.setMaxIdle(5);
+ poolProperties.setMaxActive(5);
+ poolProperties.setInitialSize(0);
+ poolProperties.setMaxWait(-1);
+ poolProperties.setRemoveAbandoned(true);
+ poolProperties.setRemoveAbandonedTimeout(60);
+ poolProperties.setTestOnBorrow(true);
+ poolProperties.setValidationQuery("SELECT 1");
+ poolProperties.setValidationInterval(30000);
+ pool = new DataSource(poolProperties);
+ Connection connection = null;
+ PreparedStatement statement = null;
+ ResultSet rs = null;
+ try {
+ connection = pool.getConnection();
+ statement = connection.prepareStatement("SHOW TABLES LIKE '" + table + "'");
+ rs = statement.executeQuery();
- tables.addDefault("accounts", "fe_accounts");
+ if (rs.next()) {
+ return true;
+ }
- ConfigurationSection columns = getSection(section, "columns");
+ rs.close();
+ statement.close();
- ConfigurationSection columnsAccounts = getSection(columns, "accounts");
+ statement = connection.prepareStatement("CREATE TABLE IF NOT EXISTS " + table + " (" + usernameField + " varchar(64) NOT NULL, " + uuidField + " varchar(36) PRIMARY KEY, " + balanceField + " double NOT NULL)");
+ statement.executeUpdate();
+ return true;
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ tryClose(rs);
+ tryClose(statement);
+ tryClose(connection);
+ }
+ return false;
+ }
- columnsAccounts.addDefault("username", "name");
+ private void tryClose(AutoCloseable closeable) {
+ try {
+ closeable.close();
+ } catch (Exception e) {
+ }
+ }
- columnsAccounts.addDefault("money", "money");
+ public void close() {
+ super.close();
+ pool.close(true);
+ }
- columnsAccounts.addDefault("uuid", "uuid");
+ public List loadTopAccounts(int size) {
+ List topAccounts = new ArrayList();
+
+ Connection connection = null;
+ PreparedStatement statement = null;
+ ResultSet rs = null;
+ try {
+ connection = pool.getConnection();
+ statement = connection.prepareStatement("SELECT " + usernameField + ", " + uuidField + ", " + balanceField + " FROM " + table + " ORDER BY " + balanceField + " DESC limit " + size);
+ rs = statement.executeQuery();
+ while (rs.next()) {
+ Account account = new Account(plugin, rs.getString(1), rs.getString(2), this);
+
+ account.setMoney(rs.getDouble(3));
+
+ topAccounts.add(account);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ tryClose(rs);
+ tryClose(statement);
+ tryClose(connection);
+ }
+
+ return topAccounts;
+ }
+
+ public List getAccounts() {
+ List accounts = new ArrayList();
+
+ Connection connection = null;
+ PreparedStatement statement = null;
+ ResultSet rs = null;
+ try {
+ connection = pool.getConnection();
+ statement = connection.prepareStatement("SELECT " + usernameField + ", " + uuidField + ", " + balanceField + " from " + table + "");
+ rs = statement.executeQuery();
+ while (rs.next()) {
+ Account account = new Account(plugin, rs.getString(1), rs.getString(2), this);
+
+ account.setMoney(rs.getDouble(3));
+
+ accounts.add(account);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ tryClose(rs);
+ tryClose(statement);
+ tryClose(connection);
+ }
+
+ return accounts;
+ }
+
+ public Double loadAccountMoney(String name, String uuid) {
+ Connection connection = null;
+ PreparedStatement statement = null;
+ ResultSet rs = null;
+ try {
+ connection = pool.getConnection();
+ statement = connection.prepareStatement("SELECT " + balanceField + " from " + table + " WHERE UPPER(" + uuidField + ") = UPPER(?) OR (? IS NULL AND UPPER(" + usernameField + ") = UPPER(?))");
+ statement.setString(1, uuid);
+ statement.setString(2, uuid);
+ statement.setString(3, name);
+ rs = statement.executeQuery();
+
+ if (rs.next()) {
+ return rs.getDouble(1);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ tryClose(rs);
+ tryClose(statement);
+ tryClose(connection);
+ }
+ return null;
+ }
+
+ public void removeAccount(String name, String uuid) {
+ super.removeAccount(name, uuid);
+
+ Connection connection = null;
+ PreparedStatement statement = null;
+ try {
+ connection = pool.getConnection();
+ statement = connection.prepareStatement("DELETE FROM " + table + " WHERE UPPER(" + uuidField + ") = UPPER(?) OR (? IS NULL AND UPPER(" + usernameField + ") = UPPER(?))");
+ statement.setString(1, uuid);
+ statement.setString(2, uuid);
+ statement.setString(3, name);
+
+ statement.executeUpdate();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ tryClose(statement);
+ tryClose(connection);
+ }
+ }
+
+ protected void saveAccount(String name, String uuid, double money) {
+ Connection connection = null;
+ PreparedStatement statement = null;
+ try {
+ connection = pool.getConnection();
+ statement = connection.prepareStatement("UPDATE " + table + " SET " + balanceField + "=?, " + usernameField + "=? WHERE UPPER(" + uuidField + ") = UPPER(?) OR (? IS NULL AND UPPER(" + usernameField + ") = UPPER(?))");
+
+ statement.setDouble(1, money);
+ statement.setString(2, name);
+ statement.setString(3, uuid);
+ statement.setString(4, uuid);
+ statement.setString(5, name);
+
+ if (statement.executeUpdate() == 0) {
+ statement.close();
+ statement = connection.prepareStatement("INSERT INTO " + table + " (" + usernameField + ", " + uuidField + ", " + balanceField + ") VALUES (?, ?, ?)");
+ statement.setString(1, name);
+ statement.setString(2, uuid);
+ statement.setDouble(3, money);
+ statement.executeUpdate();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ tryClose(statement);
+ tryClose(connection);
+ }
+ }
+
+ public void clean() {
+ Connection connection = null;
+ PreparedStatement statement = null;
+ try {
+ connection = pool.getConnection();
+ statement = connection.prepareStatement("DELETE FROM " + table + " WHERE " + balanceField + " = " + plugin.getAPI().getDefaultHoldings());
+ statement.executeUpdate();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ tryClose(statement);
+ tryClose(connection);
+ }
+ }
+
+ public void removeAllAccounts() {
+ super.removeAllAccounts();
+ Connection connection = null;
+ PreparedStatement statement = null;
+ try {
+ connection = pool.getConnection();
+ statement = connection.prepareStatement("DELETE FROM " + table);
+ statement.executeUpdate();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ tryClose(statement);
+ tryClose(connection);
+ }
}
public String getName() {
return "MySQL";
}
+
+ @Override
+ public int getVersion() {
+ return 2;
+ }
+
+ @Override
+ public void setVersion(int version) { }
}