Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ public class UserConverter {
if (baseUser == null) {
return null;
}
return baseUser.toUser(uuid, key);
try {
return baseUser.toUser(uuid, key);
} catch (IllegalStateException e) {
// 插件不存在时返回null
return null;
}
}

public static byte @NotNull [] toJson(@NotNull User user) {
Expand Down
76 changes: 54 additions & 22 deletions paper/src/main/java/net/sabafly/mailBox/database/impl/Base.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public abstract class Base implements Database {
CREATE TABLE IF NOT EXISTS mailbox_users (
uuid VARCHAR(36) PRIMARY KEY,
user_data LONGBLOB DEFAULT NULL,
address TEXT DEFAULT NULL UNIQUE
address VARCHAR(255) DEFAULT NULL UNIQUE
)
""";

Expand Down Expand Up @@ -122,6 +122,9 @@ public void setup() {
runner = new QueryRunner();

try (Connection conn = getConnection()) {
if (conn == null) {
throw new SQLException("Failed to get database connection");
}
runner.execute(conn, CREATE_TABLE_USERS);
runner.execute(conn, CREATE_TABLE_MAILS);
runner.execute(conn, CREATE_TABLE_MAIL_ATTACHMENTS);
Expand All @@ -131,6 +134,7 @@ public void setup() {
runner.execute(conn, CREATE_TABLE_USER_NOTIFICATION);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("Failed to setup database tables", e);
}
reload();
}
Expand All @@ -140,39 +144,55 @@ public void setup() {
public void reload() {
try (Connection conn = getConnection()) {
var fallbackPreview = ItemStack.of(Material.STONE).serializeAsBytes();
Comment on lines 144 to 146

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In reload(), if getConnection() returns null (for example, if the database connection fails), a NullPointerException will be thrown when addColumnIfNotExists attempts to call conn.getMetaData(). Adding a null check for conn in reload(), similar to the one in setup(), will handle connection failures gracefully.

Suggested change
public void reload() {
try (Connection conn = getConnection()) {
var fallbackPreview = ItemStack.of(Material.STONE).serializeAsBytes();
public void reload() {
try (Connection conn = getConnection()) {
if (conn == null) {
throw new SQLException("Failed to get database connection");
}
var fallbackPreview = ItemStack.of(Material.STONE).serializeAsBytes();

runner.execute(conn, """
ALTER TABLE mailbox_mail_attachments ADD COLUMN IF NOT EXISTS preview_item LONGBLOB DEFAULT NULL
""");
runner.execute(conn, """
ALTER TABLE mailbox_mail_attachments DROP COLUMN IF EXISTS item_type
""");

// 检查列是否存在,不存在则添加
addColumnIfNotExists(conn, "mailbox_mail_attachments", "preview_item", "LONGBLOB DEFAULT NULL");
dropColumnIfExists(conn, "mailbox_mail_attachments", "item_type");
runner.execute(conn, """
UPDATE mailbox_mail_attachments SET preview_item = ? WHERE preview_item IS NULL
""", fallbackPreview);
runner.execute(conn, """
ALTER TABLE mailbox_template_attachments ADD COLUMN IF NOT EXISTS preview_item LONGBLOB DEFAULT NULL
""");
runner.execute(conn, """
ALTER TABLE mailbox_template_attachments DROP COLUMN IF EXISTS item_type
""");

addColumnIfNotExists(conn, "mailbox_template_attachments", "preview_item", "LONGBLOB DEFAULT NULL");
dropColumnIfExists(conn, "mailbox_template_attachments", "item_type");
runner.execute(conn, """
UPDATE mailbox_template_attachments SET preview_item = ? WHERE preview_item IS NULL
""", fallbackPreview);

runner.execute(conn, """
ALTER TABLE mailbox_users ADD COLUMN IF NOT EXISTS user_data LONGBLOB DEFAULT NULL
""");

runner.execute(conn, """
ALTER TABLE mailbox_users ADD COLUMN IF NOT EXISTS address TEXT DEFAULT NULL UNIQUE
""");
addColumnIfNotExists(conn, "mailbox_users", "user_data", "LONGBLOB DEFAULT NULL");
addColumnIfNotExists(conn, "mailbox_users", "address", "VARCHAR(255) DEFAULT NULL UNIQUE");

getOrCreateUser(DummyMailUser.SYSTEM_USER);
} catch (SQLException e) {
e.printStackTrace();
}
}

private void addColumnIfNotExists(Connection conn, String table, String column, String definition) throws SQLException {
try {
// 检查列是否存在(H2 默认大写存储标识符)
var rs = conn.getMetaData().getColumns(null, null, table.toUpperCase(), column.toUpperCase());
if (!rs.next()) {
runner.execute(conn, "ALTER TABLE " + table + " ADD COLUMN " + column + " " + definition);
}
rs.close();
} catch (SQLException e) {
// 如果表不存在或其他错误,忽略
e.printStackTrace();
}
}

private void dropColumnIfExists(Connection conn, String table, String column) {
try {
var rs = conn.getMetaData().getColumns(null, null, table.toUpperCase(), column.toUpperCase());
if (rs.next()) {
runner.execute(conn, "ALTER TABLE " + table + " DROP COLUMN " + column);
}
rs.close();
} catch (SQLException e) {
// 忽略错误
}
}
Comment on lines +170 to +194

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In both addColumnIfNotExists and dropColumnIfExists, the ResultSet rs is opened but not closed using a try-with-resources block. If an exception is thrown during runner.execute, the ResultSet will leak. Additionally, addColumnIfNotExists declares throws SQLException in its signature, but it already catches SQLException internally and does not rethrow it, making the throws clause redundant. Refactoring both methods to use try-with-resources ensures resources are always closed properly and cleans up the redundant throws clause.

    private void addColumnIfNotExists(Connection conn, String table, String column, String definition) {
        try (var rs = conn.getMetaData().getColumns(null, null, table.toUpperCase(), column.toUpperCase())) {
            if (!rs.next()) {
                runner.execute(conn, "ALTER TABLE " + table + " ADD COLUMN " + column + " " + definition);
            }
        } catch (SQLException e) {
            // 如果表不存在或其他错误,忽略
            e.printStackTrace();
        }
    }

    private void dropColumnIfExists(Connection conn, String table, String column) {
        try (var rs = conn.getMetaData().getColumns(null, null, table.toUpperCase(), column.toUpperCase())) {
            if (rs.next()) {
                runner.execute(conn, "ALTER TABLE " + table + " DROP COLUMN " + column);
            }
        } catch (SQLException e) {
            // 忽略错误
        }
    }


@Override
public boolean isUserExists(@NotNull UUID uuid) {
try (Connection conn = getConnection()) {
Expand Down Expand Up @@ -329,7 +349,13 @@ INSERT INTO mailbox_users (uuid, user_data, address) VALUES (?, ?, ?)
String content = rs.getString("content");
boolean isRead = rs.getBoolean("is_read");
LocalDateTime sentTime = rs.getTimestamp("sentTime").toLocalDateTime();
Mail mail = new Mail(id, Objects.requireNonNull(sender), Objects.requireNonNull(receiver), title, content, List.of(), isRead, sentTime);
if (sender == null) {
sender = DummyMailUser.createUser(senderId, "Unknown Sender", "unknown", null);
}
if (receiver == null) {
receiver = DummyMailUser.createUser(receiverId, "Unknown Receiver", "unknown", null);
}
Mail mail = new Mail(id, sender, receiver, title, content, List.of(), isRead, sentTime);
mail.attachments(getMailAttachments(mail));
mails.add(mail);
}
Expand All @@ -350,7 +376,13 @@ INSERT INTO mailbox_users (uuid, user_data, address) VALUES (?, ?, ?)
String content = rs.getString("content");
boolean isRead = rs.getBoolean("is_read");
LocalDateTime sentTime = rs.getTimestamp("sentTime").toLocalDateTime();
Mail mail = new Mail(id, Objects.requireNonNull(sender), Objects.requireNonNull(receiver), title, content, List.of(), isRead, sentTime);
if (sender == null) {
sender = DummyMailUser.createUser(senderId, "Unknown Sender", "unknown", null);
}
if (receiver == null) {
receiver = DummyMailUser.createUser(receiverId, "Unknown Receiver", "unknown", null);
}
Mail mail = new Mail(id, sender, receiver, title, content, List.of(), isRead, sentTime);
mail.attachments(getMailAttachments(mail));
mails.add(mail);
}
Expand Down