From 4dedc10763fcd04ad2106052bc80f25ca1ecce79 Mon Sep 17 00:00:00 2001
From: Ollie <75035364+obfuscatedgenerated@users.noreply.github.com>
Date: Sat, 27 May 2023 22:30:41 +0100
Subject: [PATCH] fix a potential memory leak in playerdb
---
pom.xml | 2 +-
.../java/codes/ollieg/magicmotd/PlayerDB.java | 96 +++++++++++--------
2 files changed, 58 insertions(+), 40 deletions(-)
diff --git a/pom.xml b/pom.xml
index 86134b4..80183fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
codes.ollieg
MagicMOTD
- 1.0.2
+ 1.0.3
jar
MagicMOTD
diff --git a/src/main/java/codes/ollieg/magicmotd/PlayerDB.java b/src/main/java/codes/ollieg/magicmotd/PlayerDB.java
index 0cadd89..a72d165 100644
--- a/src/main/java/codes/ollieg/magicmotd/PlayerDB.java
+++ b/src/main/java/codes/ollieg/magicmotd/PlayerDB.java
@@ -20,6 +20,7 @@ public class PlayerDB {
/**
* Constructs a new {@link PlayerDB}.
+ *
* @param plugin the plugin
* @throws IllegalArgumentException if the plugin is null
*/
@@ -34,7 +35,8 @@ public PlayerDB(@NotNull MagicMOTD plugin) {
/**
* Creates a connection pool to the database.
- * @throws RuntimeException if the H2 database driver cannot be found
+ *
+ * @throws RuntimeException if the H2 database driver cannot be found
* @throws IllegalStateException if the database is already ready
*/
public void readyConnections() {
@@ -59,6 +61,7 @@ public void readyConnections() {
/**
* Returns whether the database is ready to be used.
+ *
* @return whether the database is ready
*/
public boolean isReady() {
@@ -67,6 +70,7 @@ public boolean isReady() {
/**
* Destroys the connection pool.
+ *
* @throws IllegalStateException if the database is not ready
*/
public void destroyConnections() {
@@ -81,8 +85,9 @@ public void destroyConnections() {
/**
* Creates the database and its table if they don't exist.
- * @throws SQLException if an error occurs while creating the database or table
- * @throws RuntimeException if the connection fails
+ *
+ * @throws SQLException if an error occurs while creating the database or table
+ * @throws RuntimeException if the connection fails
* @throws IllegalStateException if the database is not ready
*/
public void createIfNotExists() throws SQLException {
@@ -108,12 +113,12 @@ public void createIfNotExists() throws SQLException {
/**
* Updates the player name for the given IP address.
*
- * @param ip the player's IP address
- * @param name the player name
- * @throws SQLException if an error occurs while updating the player name
+ * @param ip the player's IP address
+ * @param name the player name
+ * @throws SQLException if an error occurs while updating the player name
* @throws IllegalArgumentException if the IP or name is null
- * @throws IllegalStateException if the database is not ready
- * @throws RuntimeException if the connection fails
+ * @throws IllegalStateException if the database is not ready
+ * @throws RuntimeException if the connection fails
*/
public void setNameForIP(@NotNull String ip, @NotNull String name) throws SQLException {
if (ip == null) {
@@ -134,16 +139,18 @@ public void setNameForIP(@NotNull String ip, @NotNull String name) throws SQLExc
throw new RuntimeException("Connection is null!");
}
- PreparedStatement statement = conn.prepareStatement("INSERT INTO PLAYERS (ip, name) VALUES (?, ?) ON DUPLICATE KEY UPDATE name = ?");
- statement.setString(1, ip);
- statement.setString(2, name);
- statement.setString(3, name);
- statement.execute();
+ try (PreparedStatement statement = conn.prepareStatement("INSERT INTO PLAYERS (ip, name) VALUES (?, ?) ON DUPLICATE KEY UPDATE name = ?")) {
+ statement.setString(1, ip);
+ statement.setString(2, name);
+ statement.setString(3, name);
+ statement.execute();
+ }
}
}
/**
* Returns the player name for the given IP address, or null if the IP address is not in the database.
+ *
* @param ip the player's IP address
* @return the player name, or null if the IP address is not in the database
*/
@@ -161,12 +168,14 @@ public void setNameForIP(@NotNull String ip, @NotNull String name) throws SQLExc
throw new RuntimeException("Connection is null!");
}
- PreparedStatement statement = conn.prepareStatement("SELECT name FROM PLAYERS WHERE ip = ?");
- statement.setString(1, ip);
- ResultSet result = statement.executeQuery();
+ try (PreparedStatement statement = conn.prepareStatement("SELECT name FROM PLAYERS WHERE ip = ?")) {
+ statement.setString(1, ip);
- if (result.next()) {
- return result.getString("name");
+ try (ResultSet result = statement.executeQuery()) {
+ if (result.next()) {
+ return result.getString("name");
+ }
+ }
}
} catch (SQLException e) {
throw new RuntimeException(e);
@@ -177,11 +186,12 @@ public void setNameForIP(@NotNull String ip, @NotNull String name) throws SQLExc
/**
* Returns a list of IPs known for the given player name.
+ *
* @param name the player name
* @return a list of IPs for the given player name
* @throws IllegalArgumentException if the name is null
- * @throws IllegalStateException if the database is not ready
- * @throws RuntimeException if the connection fails
+ * @throws IllegalStateException if the database is not ready
+ * @throws RuntimeException if the connection fails
*/
public @NotNull List getIPsForName(@NotNull String name) {
if (name == null) {
@@ -192,22 +202,26 @@ public void setNameForIP(@NotNull String ip, @NotNull String name) throws SQLExc
throw new IllegalStateException("Database is not ready!");
}
+ // TODO: the try-with chaining kinda sucks, perhaps we could encapsulate the process in a method?
try (Connection conn = this.pool.getConnection()) {
if (conn == null) {
throw new RuntimeException("Connection is null!");
}
- PreparedStatement statement = conn.prepareStatement("SELECT ip FROM PLAYERS WHERE name = ?");
- statement.setString(1, name);
- ResultSet result = statement.executeQuery();
+ try (PreparedStatement statement = conn.prepareStatement("SELECT ip FROM PLAYERS WHERE name = ?")) {
+ statement.setString(1, name);
- // convert result set to list
- List ips = new ArrayList<>();
- while (result.next()) {
- ips.add(result.getString("ip"));
- }
+ try (ResultSet result = statement.executeQuery()) {
+
+ // convert result set to list
+ List ips = new ArrayList<>();
+ while (result.next()) {
+ ips.add(result.getString("ip"));
+ }
- return ips;
+ return ips;
+ }
+ }
} catch (SQLException e) {
throw new RuntimeException(e);
}
@@ -215,10 +229,11 @@ public void setNameForIP(@NotNull String ip, @NotNull String name) throws SQLExc
/**
* Erases the given IP address from the database.
+ *
* @param ip the IP address to erase
* @throws IllegalArgumentException if the IP is null
- * @throws IllegalStateException if the database is not ready
- * @throws RuntimeException if the connection fails
+ * @throws IllegalStateException if the database is not ready
+ * @throws RuntimeException if the connection fails
*/
public void eraseIP(@NotNull String ip) {
if (ip == null) {
@@ -234,9 +249,10 @@ public void eraseIP(@NotNull String ip) {
throw new RuntimeException("Connection is null!");
}
- PreparedStatement statement = conn.prepareStatement("DELETE FROM PLAYERS WHERE ip = ?");
- statement.setString(1, ip);
- statement.execute();
+ try (PreparedStatement statement = conn.prepareStatement("DELETE FROM PLAYERS WHERE ip = ?")) {
+ statement.setString(1, ip);
+ statement.execute();
+ }
} catch (SQLException e) {
throw new RuntimeException(e);
}
@@ -244,10 +260,11 @@ public void eraseIP(@NotNull String ip) {
/**
* Erases all records (IP addresses) for the given player name.
+ *
* @param name the player name
* @throws IllegalArgumentException if the name is null
- * @throws IllegalStateException if the database is not ready
- * @throws RuntimeException if the connection fails
+ * @throws IllegalStateException if the database is not ready
+ * @throws RuntimeException if the connection fails
*/
public void eraseName(@NotNull String name) {
if (name == null) {
@@ -263,9 +280,10 @@ public void eraseName(@NotNull String name) {
throw new RuntimeException("Connection is null!");
}
- PreparedStatement statement = conn.prepareStatement("DELETE FROM PLAYERS WHERE name = ?");
- statement.setString(1, name);
- statement.execute();
+ try (PreparedStatement statement = conn.prepareStatement("DELETE FROM PLAYERS WHERE name = ?")) {
+ statement.setString(1, name);
+ statement.execute();
+ }
} catch (SQLException e) {
throw new RuntimeException(e);
}