PageRenderTime 45ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/worldguard-legacy/src/main/java/com/sk89q/worldguard/protection/managers/storage/sql/RegionUpdater.java

https://gitlab.com/igserfurtmcschulserver/CustomWorldGuard
Java | 341 lines | 262 code | 52 blank | 27 comment | 35 complexity | 64471097645f2768d236cc1098493571 MD5 | raw file
  1. /*
  2. * WorldGuard, a suite of tools for Minecraft
  3. * Copyright (C) sk89q <http://www.sk89q.com>
  4. * Copyright (C) WorldGuard team and contributors
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU Lesser General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
  14. * for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.sk89q.worldguard.protection.managers.storage.sql;
  20. import com.google.common.collect.Lists;
  21. import com.sk89q.worldguard.domains.DefaultDomain;
  22. import com.sk89q.worldguard.protection.flags.Flag;
  23. import com.sk89q.worldguard.protection.regions.ProtectedRegion;
  24. import com.sk89q.worldguard.util.io.Closer;
  25. import com.sk89q.worldguard.util.sql.DataSourceConfig;
  26. import org.yaml.snakeyaml.Yaml;
  27. import java.sql.Connection;
  28. import java.sql.PreparedStatement;
  29. import java.sql.SQLException;
  30. import java.util.ArrayList;
  31. import java.util.HashSet;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.Set;
  35. import java.util.UUID;
  36. import java.util.logging.Level;
  37. import java.util.logging.Logger;
  38. /**
  39. * Updates region data that needs to be updated for both inserts and updates.
  40. */
  41. class RegionUpdater {
  42. private static final Logger log = Logger.getLogger(RegionUpdater.class.getCanonicalName());
  43. private final DataSourceConfig config;
  44. private final Connection conn;
  45. private final int worldId;
  46. private final DomainTableCache domainTableCache;
  47. private final Set<String> userNames = new HashSet<String>();
  48. private final Set<UUID> userUuids = new HashSet<UUID>();
  49. private final Set<String> groupNames = new HashSet<String>();
  50. private final Yaml yaml = SQLRegionDatabase.createYaml();
  51. private final List<ProtectedRegion> typesToUpdate = new ArrayList<ProtectedRegion>();
  52. private final List<ProtectedRegion> parentsToSet = new ArrayList<ProtectedRegion>();
  53. private final List<ProtectedRegion> flagsToReplace = new ArrayList<ProtectedRegion>();
  54. private final List<ProtectedRegion> domainsToReplace = new ArrayList<ProtectedRegion>();
  55. RegionUpdater(DataUpdater updater) {
  56. this.config = updater.config;
  57. this.conn = updater.conn;
  58. this.worldId = updater.worldId;
  59. this.domainTableCache = updater.domainTableCache;
  60. }
  61. public void updateRegionType(ProtectedRegion region) {
  62. typesToUpdate.add(region);
  63. }
  64. public void updateRegionProperties(ProtectedRegion region) {
  65. if (region.getParent() != null) {
  66. parentsToSet.add(region);
  67. }
  68. flagsToReplace.add(region);
  69. domainsToReplace.add(region);
  70. addDomain(region.getOwners());
  71. addDomain(region.getMembers());
  72. }
  73. private void addDomain(DefaultDomain domain) {
  74. //noinspection deprecation
  75. for (String name : domain.getPlayers()) {
  76. userNames.add(name.toLowerCase());
  77. }
  78. for (UUID uuid : domain.getUniqueIds()) {
  79. userUuids.add(uuid);
  80. }
  81. for (String name : domain.getGroups()) {
  82. groupNames.add(name.toLowerCase());
  83. }
  84. }
  85. private void setParents() throws SQLException {
  86. Closer closer = Closer.create();
  87. try {
  88. PreparedStatement stmt = closer.register(conn.prepareStatement(
  89. "UPDATE " + config.getTablePrefix() + "region " +
  90. "SET parent = ? " +
  91. "WHERE id = ? AND world_id = " + worldId));
  92. for (List<ProtectedRegion> partition : Lists.partition(parentsToSet, StatementBatch.MAX_BATCH_SIZE)) {
  93. for (ProtectedRegion region : partition) {
  94. ProtectedRegion parent = region.getParent();
  95. if (parent != null) { // Parent would be null due to a race condition
  96. stmt.setString(1, parent.getId());
  97. stmt.setString(2, region.getId());
  98. stmt.addBatch();
  99. }
  100. }
  101. stmt.executeBatch();
  102. }
  103. } finally {
  104. closer.closeQuietly();
  105. }
  106. }
  107. private void replaceFlags() throws SQLException {
  108. Closer closer = Closer.create();
  109. try {
  110. PreparedStatement stmt = closer.register(conn.prepareStatement(
  111. "DELETE FROM " + config.getTablePrefix() + "region_flag " +
  112. "WHERE region_id = ? " +
  113. "AND world_id = " + worldId));
  114. for (List<ProtectedRegion> partition : Lists.partition(flagsToReplace, StatementBatch.MAX_BATCH_SIZE)) {
  115. for (ProtectedRegion region : partition) {
  116. stmt.setString(1, region.getId());
  117. stmt.addBatch();
  118. }
  119. stmt.executeBatch();
  120. }
  121. } finally {
  122. closer.closeQuietly();
  123. }
  124. closer = Closer.create();
  125. try {
  126. PreparedStatement stmt = closer.register(conn.prepareStatement(
  127. "INSERT INTO " + config.getTablePrefix() + "region_flag " +
  128. "(id, region_id, world_id, flag, value) " +
  129. "VALUES " +
  130. "(null, ?, " + worldId + ", ?, ?)"));
  131. StatementBatch batch = new StatementBatch(stmt, StatementBatch.MAX_BATCH_SIZE);
  132. for (ProtectedRegion region : flagsToReplace) {
  133. for (Map.Entry<Flag<?>, Object> entry : region.getFlags().entrySet()) {
  134. if (entry.getValue() == null) continue;
  135. Object flag = marshalFlagValue(entry.getKey(), entry.getValue());
  136. stmt.setString(1, region.getId());
  137. stmt.setString(2, entry.getKey().getName());
  138. stmt.setObject(3, flag);
  139. batch.addBatch();
  140. }
  141. }
  142. batch.executeRemaining();
  143. } finally {
  144. closer.closeQuietly();
  145. }
  146. }
  147. private void replaceDomainUsers() throws SQLException {
  148. // Remove users
  149. Closer closer = Closer.create();
  150. try {
  151. PreparedStatement stmt = closer.register(conn.prepareStatement(
  152. "DELETE FROM " + config.getTablePrefix() + "region_players " +
  153. "WHERE region_id = ? " +
  154. "AND world_id = " + worldId));
  155. for (List<ProtectedRegion> partition : Lists.partition(domainsToReplace, StatementBatch.MAX_BATCH_SIZE)) {
  156. for (ProtectedRegion region : partition) {
  157. stmt.setString(1, region.getId());
  158. stmt.addBatch();
  159. }
  160. stmt.executeBatch();
  161. }
  162. } finally {
  163. closer.closeQuietly();
  164. }
  165. // Add users
  166. closer = Closer.create();
  167. try {
  168. PreparedStatement stmt = closer.register(conn.prepareStatement(
  169. "INSERT INTO " + config.getTablePrefix() + "region_players " +
  170. "(region_id, world_id, user_id, owner) " +
  171. "VALUES (?, " + worldId + ", ?, ?)"));
  172. StatementBatch batch = new StatementBatch(stmt, StatementBatch.MAX_BATCH_SIZE);
  173. for (ProtectedRegion region : domainsToReplace) {
  174. insertDomainUsers(stmt, batch, region, region.getMembers(), false); // owner = false
  175. insertDomainUsers(stmt, batch, region, region.getOwners(), true); // owner = true
  176. }
  177. batch.executeRemaining();
  178. } finally {
  179. closer.closeQuietly();
  180. }
  181. }
  182. private void insertDomainUsers(PreparedStatement stmt, StatementBatch batch, ProtectedRegion region, DefaultDomain domain, boolean owner) throws SQLException {
  183. //noinspection deprecation
  184. for (String name : domain.getPlayers()) {
  185. Integer id = domainTableCache.getUserNameCache().find(name);
  186. if (id != null) {
  187. stmt.setString(1, region.getId());
  188. stmt.setInt(2, id);
  189. stmt.setBoolean(3, owner);
  190. batch.addBatch();
  191. } else {
  192. log.log(Level.WARNING, "Did not find an ID for the user identified as '" + name + "'");
  193. }
  194. }
  195. for (UUID uuid : domain.getUniqueIds()) {
  196. Integer id = domainTableCache.getUserUuidCache().find(uuid);
  197. if (id != null) {
  198. stmt.setString(1, region.getId());
  199. stmt.setInt(2, id);
  200. stmt.setBoolean(3, owner);
  201. batch.addBatch();
  202. } else {
  203. log.log(Level.WARNING, "Did not find an ID for the user identified by '" + uuid + "'");
  204. }
  205. }
  206. }
  207. private void replaceDomainGroups() throws SQLException {
  208. // Remove groups
  209. Closer closer = Closer.create();
  210. try {
  211. PreparedStatement stmt = closer.register(conn.prepareStatement(
  212. "DELETE FROM " + config.getTablePrefix() + "region_groups " +
  213. "WHERE region_id = ? " +
  214. "AND world_id = " + worldId));
  215. for (List<ProtectedRegion> partition : Lists.partition(domainsToReplace, StatementBatch.MAX_BATCH_SIZE)) {
  216. for (ProtectedRegion region : partition) {
  217. stmt.setString(1, region.getId());
  218. stmt.addBatch();
  219. }
  220. stmt.executeBatch();
  221. }
  222. } finally {
  223. closer.closeQuietly();
  224. }
  225. // Add groups
  226. closer = Closer.create();
  227. try {
  228. PreparedStatement stmt = closer.register(conn.prepareStatement(
  229. "INSERT INTO " + config.getTablePrefix() + "region_groups " +
  230. "(region_id, world_id, group_id, owner) " +
  231. "VALUES (?, " + worldId + ", ?, ?)"));
  232. StatementBatch batch = new StatementBatch(stmt, StatementBatch.MAX_BATCH_SIZE);
  233. for (ProtectedRegion region : domainsToReplace) {
  234. insertDomainGroups(stmt, batch, region, region.getMembers(), false); // owner = false
  235. insertDomainGroups(stmt, batch, region, region.getOwners(), true); // owner = true
  236. }
  237. batch.executeRemaining();
  238. } finally {
  239. closer.closeQuietly();
  240. }
  241. }
  242. private void insertDomainGroups(PreparedStatement stmt, StatementBatch batch, ProtectedRegion region, DefaultDomain domain, boolean owner) throws SQLException {
  243. for (String name : domain.getGroups()) {
  244. Integer id = domainTableCache.getGroupNameCache().find(name);
  245. if (id != null) {
  246. stmt.setString(1, region.getId());
  247. stmt.setInt(2, id);
  248. stmt.setBoolean(3, owner);
  249. batch.addBatch();
  250. } else {
  251. log.log(Level.WARNING, "Did not find an ID for the group identified as '" + name + "'");
  252. }
  253. }
  254. }
  255. private void updateRegionTypes() throws SQLException {
  256. Closer closer = Closer.create();
  257. try {
  258. PreparedStatement stmt = closer.register(conn.prepareStatement(
  259. "UPDATE " + config.getTablePrefix() + "region " +
  260. "SET type = ?, priority = ?, parent = NULL " +
  261. "WHERE id = ? AND world_id = " + worldId));
  262. for (List<ProtectedRegion> partition : Lists.partition(typesToUpdate, StatementBatch.MAX_BATCH_SIZE)) {
  263. for (ProtectedRegion region : partition) {
  264. stmt.setString(1, SQLRegionDatabase.getRegionTypeName(region));
  265. stmt.setInt(2, region.getPriority());
  266. stmt.setString(3, region.getId());
  267. stmt.addBatch();
  268. }
  269. stmt.executeBatch();
  270. }
  271. } finally {
  272. closer.closeQuietly();
  273. }
  274. }
  275. public void apply() throws SQLException {
  276. domainTableCache.getUserNameCache().fetch(userNames);
  277. domainTableCache.getUserUuidCache().fetch(userUuids);
  278. domainTableCache.getGroupNameCache().fetch(groupNames);
  279. updateRegionTypes();
  280. setParents();
  281. replaceFlags();
  282. replaceDomainUsers();
  283. replaceDomainGroups();
  284. }
  285. @SuppressWarnings("unchecked")
  286. private <V> Object marshalFlagValue(Flag<V> flag, Object val) {
  287. return yaml.dump(flag.marshal((V) val));
  288. }
  289. }