PlotSquared/src/main/java/com/plotsquared/bukkit/uuid/SQLUUIDHandler.java

296 lines
15 KiB
Java
Raw Normal View History

2015-07-30 19:24:01 +02:00
package com.plotsquared.bukkit.uuid;
2015-07-24 16:06:58 +02:00
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.HashMap;
import java.util.UUID;
2015-07-24 16:06:58 +02:00
2016-02-10 19:59:51 +01:00
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.google.common.collect.HashBiMap;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.database.SQLite;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
2015-09-13 06:04:31 +02:00
public class SQLUUIDHandler extends UUIDHandlerImplementation {
2015-11-28 12:46:10 +01:00
final String PROFILE_URL = "https://sessionserver.mojang.com/session/minecraft/profile/";
final int MAX_REQUESTS = 500;
final int INTERVAL = 12000;
final JSONParser jsonParser = new JSONParser();
2015-09-13 06:04:31 +02:00
public SQLUUIDHandler(final UUIDWrapper wrapper) {
2015-07-27 09:26:50 +02:00
super(wrapper);
2015-07-24 16:06:58 +02:00
_sqLite = new SQLite("./plugins/PlotSquared/usercache.db");
2015-09-13 06:04:31 +02:00
try {
2015-07-24 16:06:58 +02:00
_sqLite.openConnection();
2015-09-13 06:04:31 +02:00
} catch (final Exception e) {
2015-07-24 16:06:58 +02:00
e.printStackTrace();
}
2015-09-13 06:04:31 +02:00
try {
final PreparedStatement stmt = getConnection().prepareStatement(
"CREATE TABLE IF NOT EXISTS `usercache` (uuid VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL, PRIMARY KEY (uuid, username))");
2015-07-24 16:06:58 +02:00
stmt.execute();
stmt.close();
2015-09-13 06:04:31 +02:00
} catch (final SQLException e) {
2015-07-24 16:06:58 +02:00
e.printStackTrace();
}
2015-07-27 15:10:14 +02:00
startCaching(null);
2015-07-24 16:06:58 +02:00
}
2015-09-13 06:04:31 +02:00
private class SQLUUIDHandlerException extends RuntimeException {
SQLUUIDHandlerException(final String s, final Throwable c) {
2015-07-27 09:26:50 +02:00
super("SQLUUIDHandler caused an exception: " + s, c);
}
2015-07-24 16:06:58 +02:00
}
2015-09-13 06:04:31 +02:00
2015-07-27 09:26:50 +02:00
private final SQLite _sqLite;
2015-09-13 06:04:31 +02:00
private Connection getConnection() {
synchronized (_sqLite) {
2015-07-27 09:26:50 +02:00
return _sqLite.getConnection();
}
2015-07-24 16:06:58 +02:00
}
2015-09-13 06:04:31 +02:00
2015-07-24 16:06:58 +02:00
@Override
2015-09-13 06:04:31 +02:00
public boolean startCaching(final Runnable whenDone) {
if (!super.startCaching(whenDone)) {
return false;
}
TaskManager.runTaskAsync(new Runnable() {
2015-07-24 16:06:58 +02:00
@Override
2015-09-13 06:04:31 +02:00
public void run() {
try {
2015-07-27 15:10:14 +02:00
final HashBiMap<StringWrapper, UUID> toAdd = HashBiMap.create(new HashMap<StringWrapper, UUID>());
2015-09-11 12:09:22 +02:00
final PreparedStatement statement = getConnection().prepareStatement("SELECT `uuid`, `username` FROM `usercache`");
final ResultSet resultSet = statement.executeQuery();
2015-07-24 16:06:58 +02:00
StringWrapper username;
UUID uuid;
2015-09-13 06:04:31 +02:00
while (resultSet.next()) {
2015-07-24 16:06:58 +02:00
username = new StringWrapper(resultSet.getString("username"));
uuid = UUID.fromString(resultSet.getString("uuid"));
2015-07-27 15:10:14 +02:00
toAdd.put(new StringWrapper(username.value), uuid);
2015-07-24 16:06:58 +02:00
}
statement.close();
2015-07-27 15:10:14 +02:00
add(toAdd);
add(new StringWrapper("*"), DBFunc.everyone);
2015-09-13 06:04:31 +02:00
2015-07-27 15:10:14 +02:00
// This should be called as long as there are some unknown plots
2015-11-28 12:46:10 +01:00
final ArrayDeque<UUID> toFetch = new ArrayDeque<>();
2015-09-13 06:04:31 +02:00
for (final UUID u : UUIDHandler.getAllUUIDS()) {
if (!uuidExists(u)) {
2015-07-27 15:10:14 +02:00
toFetch.add(u);
2015-07-24 16:06:58 +02:00
}
2015-07-27 15:10:14 +02:00
}
2015-09-13 06:04:31 +02:00
if (toFetch.isEmpty()) {
if (whenDone != null) {
2015-09-11 12:09:22 +02:00
whenDone.run();
}
2015-07-27 15:10:14 +02:00
return;
}
2015-09-11 12:09:22 +02:00
final FileUUIDHandler fileHandler = new FileUUIDHandler(SQLUUIDHandler.this.uuidWrapper);
2015-09-13 06:04:31 +02:00
fileHandler.startCaching(new Runnable() {
2015-07-27 15:10:14 +02:00
@Override
2015-09-13 06:04:31 +02:00
public void run() {
2015-07-27 15:10:14 +02:00
// If the file based UUID handler didn't cache it, then we can't cache offline mode
// Also, trying to cache based on files again, is useless as that's what the file based uuid cacher does
2015-09-13 06:04:31 +02:00
if (Settings.OFFLINE_MODE) {
if (whenDone != null) {
2015-09-11 12:09:22 +02:00
whenDone.run();
}
2015-07-24 16:06:58 +02:00
return;
}
2015-11-28 12:46:10 +01:00
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
2015-09-13 06:04:31 +02:00
try {
2015-11-28 12:46:10 +01:00
if (toFetch.size() == 0) {
if (whenDone != null) {
whenDone.run();
}
return;
2015-07-27 15:10:14 +02:00
}
2015-11-28 12:46:10 +01:00
for (int i = 0; i < Math.min(500, toFetch.size()); i++) {
UUID uuid = toFetch.pop();
HttpURLConnection connection = (HttpURLConnection) new URL(PROFILE_URL + uuid.toString().replace("-", "")).openConnection();
InputStreamReader reader = new InputStreamReader(connection.getInputStream());
JSONObject response = (JSONObject) jsonParser.parse(reader);
String name = (String) response.get("name");
if (name != null) {
add(new StringWrapper(name), uuid);
2015-07-27 15:10:14 +02:00
}
2015-07-24 16:06:58 +02:00
}
2015-11-28 12:46:10 +01:00
} catch (Exception e) {
2015-07-27 15:10:14 +02:00
e.printStackTrace();
2015-07-24 16:06:58 +02:00
}
2015-11-28 12:46:10 +01:00
TaskManager.runTaskLaterAsync(this, INTERVAL);
2015-07-24 16:06:58 +02:00
}
2015-11-28 12:46:10 +01:00
});
/*
* This API is no longer accessible.
*/
// if (!Settings.OFFLINE_MODE) {
// PS.debug(C.PREFIX.s() + "&cWill fetch &6" + toFetch.size() + "&c from mojang!");
//
// int i = 0;
// final Iterator<UUID> iterator = toFetch.iterator();
// while (iterator.hasNext()) {
// final StringBuilder url = new StringBuilder("http://api.intellectualsites.com/uuid/?user=");
// final List<UUID> currentIteration = new ArrayList<>();
// while ((i++ <= 15) && iterator.hasNext()) {
// final UUID _uuid = iterator.next();
// url.append(_uuid.toString());
// if (iterator.hasNext()) {
// url.append(",");
// }
// currentIteration.add(_uuid);
// }
// PS.debug(C.PREFIX.s() + "&cWill attempt to fetch &6" + currentIteration.size() + "&c uuids from: &6" + url.toString());
// try {
// final HttpURLConnection connection = (HttpURLConnection) new URL(url.toString()).openConnection();
// connection.setRequestProperty("User-Agent", "Mozilla/5.0");
// final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
// String line;
// final StringBuilder rawJSON = new StringBuilder();
// while ((line = reader.readLine()) != null) {
// rawJSON.append(line);
// }
// reader.close();
// final JSONObject object = new JSONObject(rawJSON.toString());
// for (final UUID _u : currentIteration) {
// final Object o = object.getJSONObject(_u.toString().replace("-", "")).get("username");
// if ((o == null) || !(o instanceof String)) {
// continue;
// }
// add(new StringWrapper(o.toString()), _u);
// }
// } catch (final Exception e) {
// e.printStackTrace();
// }
// i = 0;
// }
// }
// if (whenDone != null) {
// whenDone.run();
// }
2015-07-24 16:06:58 +02:00
}
2015-07-27 15:10:14 +02:00
});
2015-09-13 06:04:31 +02:00
} catch (final SQLException e) {
2015-07-24 16:06:58 +02:00
throw new SQLUUIDHandlerException("Couldn't select :s", e);
}
}
});
2015-07-27 09:26:50 +02:00
return true;
2015-07-24 16:06:58 +02:00
}
2015-09-13 06:04:31 +02:00
2015-07-24 16:06:58 +02:00
@Override
2015-09-13 06:04:31 +02:00
public void fetchUUID(final String name, final RunnableVal<UUID> ifFetch) {
2015-07-30 16:25:16 +02:00
PS.debug(C.PREFIX.s() + "UUID for '" + name + "' was null. We'll cache this from the mojang servers!");
2015-11-28 12:46:10 +01:00
if (ifFetch == null) {
return;
}
2015-09-13 06:04:31 +02:00
TaskManager.runTaskAsync(new Runnable() {
2015-07-24 16:06:58 +02:00
@Override
2015-09-13 06:04:31 +02:00
public void run() {
try {
2015-11-28 12:46:10 +01:00
URL url = new URL(PROFILE_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
String body = JSONArray.toJSONString(Collections.singletonList(name));
2015-11-28 12:46:10 +01:00
OutputStream stream = connection.getOutputStream();
stream.write(body.getBytes());
stream.flush();
stream.close();
JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream()));
JSONObject jsonProfile = (JSONObject) array.get(0);
String id = (String) jsonProfile.get("id");
String name = (String) jsonProfile.get("name");
ifFetch.value = UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32));
} catch (Exception e) {
2015-07-24 16:06:58 +02:00
e.printStackTrace();
}
2015-07-27 09:26:50 +02:00
TaskManager.runTask(ifFetch);
2015-07-24 16:06:58 +02:00
}
});
}
2015-09-13 06:04:31 +02:00
2015-07-24 16:06:58 +02:00
@Override
2015-09-13 06:04:31 +02:00
public void handleShutdown() {
2015-07-27 09:26:50 +02:00
super.handleShutdown();
2015-09-13 06:04:31 +02:00
try {
2015-07-27 09:26:50 +02:00
getConnection().close();
2015-09-13 06:04:31 +02:00
} catch (final SQLException e) {
2015-07-27 09:26:50 +02:00
throw new SQLUUIDHandlerException("Couldn't close database connection", e);
2015-07-24 16:06:58 +02:00
}
}
2015-09-13 06:04:31 +02:00
2015-07-24 16:06:58 +02:00
@Override
2015-09-13 06:04:31 +02:00
public boolean add(final StringWrapper name, final UUID uuid) {
2015-07-27 09:26:50 +02:00
// Ignoring duplicates
2015-09-13 06:04:31 +02:00
if (super.add(name, uuid)) {
TaskManager.runTaskAsync(new Runnable() {
2015-07-24 16:06:58 +02:00
@Override
2015-09-13 06:04:31 +02:00
public void run() {
try {
2015-11-28 12:46:10 +01:00
final PreparedStatement statement = getConnection().prepareStatement("REPLACE INTO usercache (`uuid`, `username`) VALUES(?, ?)");
2015-07-27 09:26:50 +02:00
statement.setString(1, uuid.toString());
statement.setString(2, name.toString());
statement.execute();
2015-07-30 16:25:16 +02:00
PS.debug(C.PREFIX.s() + "&cAdded '&6" + uuid + "&c' - '&6" + name + "&c'");
2015-09-13 06:04:31 +02:00
} catch (final SQLException e) {
2015-07-24 16:06:58 +02:00
e.printStackTrace();
}
}
});
2015-07-27 15:10:14 +02:00
return true;
2015-07-24 16:06:58 +02:00
}
2015-07-27 15:10:14 +02:00
return false;
2015-07-24 16:06:58 +02:00
}
2015-09-13 06:04:31 +02:00
2015-07-27 09:26:50 +02:00
/**
2015-11-28 12:46:10 +01:00
* This is useful for name changes
2015-07-27 09:26:50 +02:00
*/
2015-07-27 15:10:14 +02:00
@Override
2015-09-13 06:04:31 +02:00
public void rename(final UUID uuid, final StringWrapper name) {
2015-07-27 15:10:14 +02:00
super.rename(uuid, name);
2015-09-13 06:04:31 +02:00
TaskManager.runTaskAsync(new Runnable() {
2015-07-27 15:10:14 +02:00
@Override
2015-09-13 06:04:31 +02:00
public void run() {
try {
2015-09-11 12:09:22 +02:00
final PreparedStatement statement = getConnection().prepareStatement("UPDATE usercache SET `username`=? WHERE `uuid`=?");
2015-07-27 15:10:14 +02:00
statement.setString(1, name.value);
statement.setString(2, uuid.toString());
statement.execute();
2015-07-30 16:25:16 +02:00
PS.debug(C.PREFIX.s() + "Name change for '" + uuid + "' to '" + name.value + "'");
2015-09-13 06:04:31 +02:00
} catch (final SQLException e) {
2015-07-27 15:10:14 +02:00
e.printStackTrace();
}
}
});
}
2015-07-24 16:06:58 +02:00
}