PageRenderTime 107ms CodeModel.GetById 59ms RepoModel.GetById 5ms app.codeStats 0ms

/src/main/java/com/sk89q/worldguard/protection/databases/YAMLDatabase.java

https://github.com/HaxtorMoogle/worldguard
Java | 295 lines | 246 code | 30 blank | 19 comment | 14 complexity | 34925228838238dea12d393e307a2553 MD5 | raw file
  1. // $Id$
  2. /*
  3. * WorldGuard
  4. * Copyright (C) 2010 sk89q <http://www.sk89q.com>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the 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,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.sk89q.worldguard.protection.databases;
  20. import java.io.File;
  21. import java.io.IOException;
  22. import java.util.ArrayList;
  23. import java.util.HashMap;
  24. import java.util.LinkedHashMap;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Set;
  28. import java.util.logging.Logger;
  29. import com.sk89q.worldedit.BlockVector;
  30. import com.sk89q.worldedit.BlockVector2D;
  31. import com.sk89q.worldedit.Vector;
  32. import com.sk89q.worldguard.domains.DefaultDomain;
  33. import com.sk89q.worldguard.protection.flags.DefaultFlag;
  34. import com.sk89q.worldguard.protection.flags.Flag;
  35. import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
  36. import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
  37. import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
  38. import com.sk89q.worldguard.protection.regions.ProtectedRegion;
  39. import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException;
  40. import com.sk89q.worldguard.util.yaml.Configuration;
  41. import com.sk89q.worldguard.util.yaml.ConfigurationNode;
  42. public class YAMLDatabase extends AbstractProtectionDatabase {
  43. private static Logger logger = Logger.getLogger("Minecraft.WorldGuard");
  44. private Configuration config;
  45. private Map<String, ProtectedRegion> regions;
  46. public YAMLDatabase(File file) {
  47. config = new Configuration(file);
  48. }
  49. public void load() throws IOException {
  50. config.load();
  51. Map<String, ConfigurationNode> regionData = config.getNodes("regions");
  52. // No regions are even configured
  53. if (regionData == null) {
  54. this.regions = new HashMap<String, ProtectedRegion>();
  55. return;
  56. }
  57. Map<String,ProtectedRegion> regions =
  58. new HashMap<String,ProtectedRegion>();
  59. Map<ProtectedRegion,String> parentSets =
  60. new LinkedHashMap<ProtectedRegion, String>();
  61. for (Map.Entry<String, ConfigurationNode> entry : regionData.entrySet()) {
  62. String id = entry.getKey().toLowerCase().replace(".", "");
  63. ConfigurationNode node = entry.getValue();
  64. String type = node.getString("type");
  65. ProtectedRegion region;
  66. try {
  67. if (type == null) {
  68. logger.warning("Undefined region type for region '" + id + '"');
  69. continue;
  70. } else if (type.equals("cuboid")) {
  71. Vector pt1 = checkNonNull(node.getVector("min"));
  72. Vector pt2 = checkNonNull(node.getVector("max"));
  73. BlockVector min = Vector.getMinimum(pt1, pt2).toBlockVector();
  74. BlockVector max = Vector.getMaximum(pt1, pt2).toBlockVector();
  75. region = new ProtectedCuboidRegion(id, min, max);
  76. } else if (type.equals("poly2d")) {
  77. Integer minY = checkNonNull(node.getInt("min-y"));
  78. Integer maxY = checkNonNull(node.getInt("max-y"));
  79. List<BlockVector2D> points = node.getBlockVector2dList("points", null);
  80. region = new ProtectedPolygonalRegion(id, points, minY, maxY);
  81. } else if (type.equals("global")) {
  82. region = new GlobalProtectedRegion(id);
  83. } else {
  84. logger.warning("Unknown region type for region '" + id + '"');
  85. continue;
  86. }
  87. Integer priority = checkNonNull(node.getInt("priority"));
  88. region.setPriority(priority);
  89. setFlags(region, node.getNode("flags"));
  90. region.setOwners(parseDomain(node.getNode("owners")));
  91. region.setMembers(parseDomain(node.getNode("members")));
  92. regions.put(id, region);
  93. String parentId = node.getString("parent");
  94. if (parentId != null) {
  95. parentSets.put(region, parentId);
  96. }
  97. } catch (NullPointerException e) {
  98. logger.warning("Missing data for region '" + id + '"');
  99. }
  100. }
  101. // Relink parents
  102. for (Map.Entry<ProtectedRegion, String> entry : parentSets.entrySet()) {
  103. ProtectedRegion parent = regions.get(entry.getValue());
  104. if (parent != null) {
  105. try {
  106. entry.getKey().setParent(parent);
  107. } catch (CircularInheritanceException e) {
  108. logger.warning("Circular inheritance detect with '"
  109. + entry.getValue() + "' detected as a parent");
  110. }
  111. } else {
  112. logger.warning("Unknown region parent: " + entry.getValue());
  113. }
  114. }
  115. this.regions = regions;
  116. }
  117. private <V> V checkNonNull(V val) throws NullPointerException {
  118. if (val == null) {
  119. throw new NullPointerException();
  120. }
  121. return val;
  122. }
  123. private void setFlags(ProtectedRegion region, ConfigurationNode flagsData) {
  124. if (flagsData == null) {
  125. return;
  126. }
  127. // @TODO: Make this better
  128. for (Flag<?> flag : DefaultFlag.getFlags()) {
  129. Object o = flagsData.getProperty(flag.getName());
  130. if (o != null) {
  131. setFlag(region, flag, o);
  132. }
  133. }
  134. }
  135. private <T> void setFlag(ProtectedRegion region, Flag<T> flag, Object rawValue) {
  136. T val = flag.unmarshal(rawValue);
  137. if (val == null) {
  138. logger.warning("Failed to parse flag '" + flag.getName()
  139. + "' with value '" + rawValue.toString() + "'");
  140. return;
  141. }
  142. region.setFlag(flag, val);
  143. }
  144. private DefaultDomain parseDomain(ConfigurationNode node) {
  145. if (node == null) {
  146. return new DefaultDomain();
  147. }
  148. DefaultDomain domain = new DefaultDomain();
  149. for (String name : node.getStringList("players", null)) {
  150. domain.addPlayer(name);
  151. }
  152. for (String name : node.getStringList("groups", null)) {
  153. domain.addGroup(name);
  154. }
  155. return domain;
  156. }
  157. public void save() throws IOException {
  158. config.clear();
  159. for (Map.Entry<String, ProtectedRegion> entry : regions.entrySet()) {
  160. ProtectedRegion region = entry.getValue();
  161. ConfigurationNode node = config.addNode("regions." + entry.getKey());
  162. if (region instanceof ProtectedCuboidRegion) {
  163. ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
  164. node.setProperty("type", "cuboid");
  165. node.setProperty("min", cuboid.getMinimumPoint());
  166. node.setProperty("max", cuboid.getMaximumPoint());
  167. } else if (region instanceof ProtectedPolygonalRegion) {
  168. ProtectedPolygonalRegion poly = (ProtectedPolygonalRegion) region;
  169. node.setProperty("type", "poly2d");
  170. node.setProperty("min-y", poly.getMinimumPoint().getBlockY());
  171. node.setProperty("max-y", poly.getMaximumPoint().getBlockY());
  172. List<Map<String, Object>> points = new ArrayList<Map<String,Object>>();
  173. for (BlockVector2D point : poly.getPoints()) {
  174. Map<String, Object> data = new HashMap<String, Object>();
  175. data.put("x", point.getBlockX());
  176. data.put("z", point.getBlockZ());
  177. points.add(data);
  178. }
  179. node.setProperty("points", points);
  180. } else if (region instanceof GlobalProtectedRegion) {
  181. node.setProperty("type", "global");
  182. } else {
  183. node.setProperty("type", region.getClass().getCanonicalName());
  184. }
  185. node.setProperty("priority", region.getPriority());
  186. node.setProperty("flags", getFlagData(region));
  187. node.setProperty("owners", getDomainData(region.getOwners()));
  188. node.setProperty("members", getDomainData(region.getMembers()));
  189. ProtectedRegion parent = region.getParent();
  190. if (parent != null) {
  191. node.setProperty("parent", parent.getId());
  192. }
  193. }
  194. config.setHeader("#\r\n" +
  195. "# WorldGuard regions file\r\n" +
  196. "#\r\n" +
  197. "# WARNING: THIS FILE IS AUTOMATICALLY GENERATED. If you modify this file by\r\n" +
  198. "# hand, be aware that A SINGLE MISTYPED CHARACTER CAN CORRUPT THE FILE. If\r\n" +
  199. "# WorldGuard is unable to parse the file, your regions will FAIL TO LOAD and\r\n" +
  200. "# the contents of this file will reset. Please use a YAML validator such as\r\n" +
  201. "# http://yaml-online-parser.appspot.com (for smaller files).\r\n" +
  202. "#\r\n" +
  203. "# REMEMBER TO KEEP PERIODICAL BACKUPS.\r\n" +
  204. "#");
  205. config.save();
  206. }
  207. private Map<String, Object> getFlagData(ProtectedRegion region) {
  208. Map<String, Object> flagData = new HashMap<String, Object>();
  209. for (Map.Entry<Flag<?>, Object> entry : region.getFlags().entrySet()) {
  210. Flag<?> flag = entry.getKey();
  211. addMarshalledFlag(flagData, flag, entry.getValue());
  212. }
  213. return flagData;
  214. }
  215. @SuppressWarnings("unchecked")
  216. private <V> void addMarshalledFlag(Map<String, Object> flagData,
  217. Flag<V> flag, Object val) {
  218. if (val == null) {
  219. return;
  220. }
  221. flagData.put(flag.getName(), flag.marshal((V) val));
  222. }
  223. private Map<String, Object> getDomainData(DefaultDomain domain) {
  224. Map<String, Object> domainData = new HashMap<String, Object>();
  225. setDomainData(domainData, "players", domain.getPlayers());
  226. setDomainData(domainData, "groups", domain.getGroups());
  227. return domainData;
  228. }
  229. private void setDomainData(Map<String, Object> domainData,
  230. String key, Set<String> domain) {
  231. if (domain.size() == 0) {
  232. return;
  233. }
  234. List<String> list = new ArrayList<String>();
  235. for (String str : domain) {
  236. list.add(str);
  237. }
  238. domainData.put(key, list);
  239. }
  240. public Map<String, ProtectedRegion> getRegions() {
  241. return regions;
  242. }
  243. public void setRegions(Map<String, ProtectedRegion> regions) {
  244. this.regions = regions;
  245. }
  246. }