001/*
002 * PlotSquared, a land and world management plugin for Minecraft.
003 * Copyright (C) IntellectualSites <https://intellectualsites.com>
004 * Copyright (C) IntellectualSites team and contributors
005 *
006 * This program is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
018 */
019package com.plotsquared.bukkit.uuid;
020
021import com.plotsquared.core.PlotSquared;
022import com.plotsquared.core.database.SQLite;
023import com.plotsquared.core.util.FileUtils;
024import com.plotsquared.core.uuid.UUIDMapping;
025import com.plotsquared.core.uuid.UUIDService;
026import org.checkerframework.checker.nullness.qual.NonNull;
027
028import java.sql.Connection;
029import java.sql.PreparedStatement;
030import java.sql.ResultSet;
031import java.sql.SQLException;
032import java.util.ArrayList;
033import java.util.LinkedList;
034import java.util.List;
035import java.util.UUID;
036import java.util.function.Consumer;
037
038/**
039 * UUID service that uses the (legacy) SQL UUID cache
040 */
041public class SQLiteUUIDService implements UUIDService, Consumer<List<UUIDMapping>> {
042
043    private final SQLite sqlite;
044
045    public SQLiteUUIDService(final String fileName) {
046        this.sqlite =
047                new SQLite(FileUtils.getFile(PlotSquared.platform().getDirectory(), fileName));
048        try {
049            this.sqlite.openConnection();
050        } catch (ClassNotFoundException | SQLException e) {
051            e.printStackTrace();
052        }
053
054        try (PreparedStatement stmt = getConnection().prepareStatement(
055                "CREATE TABLE IF NOT EXISTS `usercache` (uuid VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL, PRIMARY KEY (uuid))")) {
056            stmt.execute();
057        } catch (SQLException e) {
058            e.printStackTrace();
059        }
060    }
061
062    private Connection getConnection() {
063        synchronized (this.sqlite) {
064            return this.sqlite.getConnection();
065        }
066    }
067
068    @Override
069    public @NonNull List<UUIDMapping> getNames(final @NonNull List<UUID> uuids) {
070        final List<UUIDMapping> mappings = new ArrayList<>(uuids.size());
071        try (final PreparedStatement statement = getConnection()
072                .prepareStatement("SELECT `username` FROM `usercache` WHERE `uuid` = ?")) {
073            for (final UUID uuid : uuids) {
074                statement.setString(1, uuid.toString());
075                try (final ResultSet resultSet = statement.executeQuery()) {
076                    if (resultSet.next()) {
077                        mappings.add(new UUIDMapping(uuid, resultSet.getString("username")));
078                    }
079                }
080            }
081        } catch (final Exception e) {
082            e.printStackTrace();
083        }
084        return mappings;
085    }
086
087    @Override
088    public @NonNull List<UUIDMapping> getUUIDs(@NonNull List<String> usernames) {
089        final List<UUIDMapping> mappings = new ArrayList<>(usernames.size());
090        try (final PreparedStatement statement = getConnection()
091                .prepareStatement("SELECT `uuid` FROM `usercache` WHERE `username` = ?")) {
092            for (final String username : usernames) {
093                statement.setString(1, username);
094                try (final ResultSet resultSet = statement.executeQuery()) {
095                    if (resultSet.next()) {
096                        mappings.add(new UUIDMapping(
097                                UUID.fromString(resultSet.getString("uuid")),
098                                username
099                        ));
100                    }
101                }
102            }
103        } catch (final Exception e) {
104            e.printStackTrace();
105        }
106        return mappings;
107    }
108
109    @Override
110    public void accept(final List<UUIDMapping> uuidWrappers) {
111        try (final PreparedStatement statement = getConnection()
112                .prepareStatement("INSERT OR REPLACE INTO `usercache` (`uuid`, `username`) VALUES(?, ?)")) {
113            for (final UUIDMapping mapping : uuidWrappers) {
114                statement.setString(1, mapping.getUuid().toString());
115                statement.setString(2, mapping.getUsername());
116                statement.executeUpdate();
117            }
118        } catch (SQLException e) {
119            e.printStackTrace();
120        }
121    }
122
123    /**
124     * Read the entire cache at once
125     *
126     * @return All read mappings
127     */
128    public @NonNull List<UUIDMapping> getAll() {
129        final List<UUIDMapping> mappings = new LinkedList<>();
130        try (final PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM `usercache`")) {
131            try (final ResultSet resultSet = statement.executeQuery()) {
132                while (resultSet.next()) {
133                    mappings.add(new UUIDMapping(UUID.fromString(resultSet.getString("uuid")), resultSet.getString("username")));
134                }
135            }
136        } catch (final Exception e) {
137            e.printStackTrace();
138        }
139        return mappings;
140    }
141
142
143}