PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/worldguard-legacy/src/main/java/com/sk89q/worldguard/protection/managers/migration/UUIDMigration.java

https://gitlab.com/igserfurtmcschulserver/CustomWorldGuard
Java | 241 lines | 142 code | 31 blank | 68 comment | 13 complexity | d7d4ba394068e2968a593c7979ace39f 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.migration;
  20. import com.google.common.base.Predicate;
  21. import com.sk89q.squirrelid.Profile;
  22. import com.sk89q.squirrelid.resolver.ProfileService;
  23. import com.sk89q.worldguard.domains.DefaultDomain;
  24. import com.sk89q.worldguard.domains.PlayerDomain;
  25. import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
  26. import com.sk89q.worldguard.protection.managers.storage.RegionDatabase;
  27. import com.sk89q.worldguard.protection.managers.storage.RegionDriver;
  28. import com.sk89q.worldguard.protection.managers.storage.StorageException;
  29. import com.sk89q.worldguard.protection.regions.ProtectedRegion;
  30. import java.io.IOException;
  31. import java.util.*;
  32. import java.util.concurrent.ConcurrentHashMap;
  33. import java.util.concurrent.ConcurrentMap;
  34. import java.util.logging.Level;
  35. import java.util.logging.Logger;
  36. import static com.google.common.base.Preconditions.checkNotNull;
  37. /**
  38. * Migrates names to UUIDs for all the worlds in a region store.
  39. */
  40. public class UUIDMigration extends AbstractMigration {
  41. private static final Logger log = Logger.getLogger(UUIDMigration.class.getCanonicalName());
  42. private static final int LOG_DELAY = 5000;
  43. private final Timer timer = new Timer();
  44. private final ProfileService profileService;
  45. private final FlagRegistry flagRegistry;
  46. private final ConcurrentMap<String, UUID> resolvedNames = new ConcurrentHashMap<String, UUID>();
  47. private final Set<String> unresolvedNames = new HashSet<String>();
  48. private boolean keepUnresolvedNames = true;
  49. /**
  50. * Create a new instance.
  51. *
  52. * @param driver the storage driver
  53. * @param profileService the profile service
  54. * @param flagRegistry the flag registry
  55. */
  56. public UUIDMigration(RegionDriver driver, ProfileService profileService, FlagRegistry flagRegistry) {
  57. super(driver);
  58. checkNotNull(profileService);
  59. checkNotNull(flagRegistry, "flagRegistry");
  60. this.profileService = profileService;
  61. this.flagRegistry = flagRegistry;
  62. }
  63. @Override
  64. protected void migrate(RegionDatabase store) throws MigrationException {
  65. log.log(Level.INFO, "Migrating regions in '" + store.getName() + "' to convert names -> UUIDs...");
  66. Set<ProtectedRegion> regions;
  67. try {
  68. regions = store.loadAll(flagRegistry);
  69. } catch (StorageException e) {
  70. throw new MigrationException("Failed to load region data for the world '" + store.getName() + "'", e);
  71. }
  72. migrate(regions);
  73. try {
  74. store.saveAll(regions);
  75. } catch (StorageException e) {
  76. throw new MigrationException("Failed to save region data after migration of the world '" + store.getName() + "'", e);
  77. }
  78. }
  79. private boolean migrate(Collection<ProtectedRegion> regions) throws MigrationException {
  80. // Name scan pass
  81. Set<String> names = getNames(regions);
  82. if (!names.isEmpty()) {
  83. // This task logs the progress of conversion (% converted...)
  84. // periodically
  85. TimerTask task = new ResolvedNamesTimerTask();
  86. try {
  87. timer.schedule(task, LOG_DELAY, LOG_DELAY);
  88. log.log(Level.INFO, "Resolving " + names.size() + " name(s) into UUIDs... this may take a while.");
  89. // Don't lookup names that we already looked up for previous
  90. // worlds -- note: all names are lowercase in these collections
  91. Set<String> lookupNames = new HashSet<String>(names);
  92. lookupNames.removeAll(resolvedNames.keySet());
  93. // Ask Mojang for names
  94. profileService.findAllByName(lookupNames, new Predicate<Profile>() {
  95. @Override
  96. public boolean apply(Profile profile) {
  97. resolvedNames.put(profile.getName().toLowerCase(), profile.getUniqueId());
  98. return true;
  99. }
  100. });
  101. } catch (IOException e) {
  102. throw new MigrationException("The name -> UUID service failed", e);
  103. } catch (InterruptedException e) {
  104. throw new MigrationException("The migration was interrupted");
  105. } finally {
  106. // Stop showing the % converted messages
  107. task.cancel();
  108. }
  109. // Name -> UUID in all regions
  110. log.log(Level.INFO, "UUIDs resolved... now migrating all regions to UUIDs where possible...");
  111. convert(regions);
  112. return true;
  113. } else {
  114. return false;
  115. }
  116. }
  117. @Override
  118. protected void postMigration() {
  119. if (!unresolvedNames.isEmpty()) {
  120. if (keepUnresolvedNames) {
  121. log.log(Level.WARNING,
  122. "Some member and owner names do not seem to exist or own Minecraft so they " +
  123. "could not be converted into UUIDs. They have been left as names, but the conversion can " +
  124. "be re-run with 'keep-names-that-lack-uuids' set to false in the configuration in " +
  125. "order to remove these names. Leaving the names means that someone can register with one of " +
  126. "these names in the future and become that player.");
  127. } else {
  128. log.log(Level.WARNING,
  129. "Some member and owner names do not seem to exist or own Minecraft so they " +
  130. "could not be converted into UUIDs. These names have been removed.");
  131. }
  132. }
  133. }
  134. /**
  135. * Grab all the player names from all the regions in the given collection.
  136. *
  137. * @param regions a collection of regions
  138. * @return a set of names
  139. */
  140. private static Set<String> getNames(Collection<ProtectedRegion> regions) {
  141. Set<String> names = new HashSet<String>();
  142. for (ProtectedRegion region : regions) {
  143. // Names are already lower case
  144. names.addAll(region.getOwners().getPlayers());
  145. names.addAll(region.getMembers().getPlayers());
  146. }
  147. return names;
  148. }
  149. /**
  150. * Convert all the names to UUIDs.
  151. *
  152. * @param regions a collection of regions
  153. */
  154. private void convert(Collection<ProtectedRegion> regions) {
  155. for (ProtectedRegion region : regions) {
  156. convert(region.getOwners());
  157. convert(region.getMembers());
  158. }
  159. }
  160. /**
  161. * Convert all the names to UUIDs.
  162. *
  163. * @param domain the domain
  164. */
  165. private void convert(DefaultDomain domain) {
  166. PlayerDomain playerDomain = new PlayerDomain();
  167. for (UUID uuid : domain.getUniqueIds()) {
  168. playerDomain.addPlayer(uuid);
  169. }
  170. for (String name : domain.getPlayers()) {
  171. UUID uuid = resolvedNames.get(name.toLowerCase());
  172. if (uuid != null) {
  173. playerDomain.addPlayer(uuid);
  174. } else {
  175. if (keepUnresolvedNames) {
  176. playerDomain.addPlayer(name);
  177. }
  178. unresolvedNames.add(name);
  179. }
  180. }
  181. domain.setPlayerDomain(playerDomain);
  182. }
  183. /**
  184. * Get whether names that have no UUID equivalent (i.e. name that is not
  185. * owned) should be kept as names and not removed.
  186. *
  187. * @return true to keep names
  188. */
  189. public boolean getKeepUnresolvedNames() {
  190. return keepUnresolvedNames;
  191. }
  192. /**
  193. * Set whether names that have no UUID equivalent (i.e. name that is not
  194. * owned) should be kept as names and not removed.
  195. *
  196. * @param keepUnresolvedNames true to keep names
  197. */
  198. public void setKeepUnresolvedNames(boolean keepUnresolvedNames) {
  199. this.keepUnresolvedNames = keepUnresolvedNames;
  200. }
  201. /**
  202. * A task to periodically say how many names have been resolved.
  203. */
  204. private class ResolvedNamesTimerTask extends TimerTask {
  205. @Override
  206. public void run() {
  207. log.info("UUIDs have been found for " + resolvedNames.size() + " name(s)...");
  208. }
  209. }
  210. }