PageRenderTime 155ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/talmor/worldguard
Java | 301 lines | 251 code | 30 blank | 20 comment | 15 complexity | d46e4dc47c3ad524ec78625e8e68e294 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. if (!file.exists()) { // shouldn't be necessary, but check anyways
  48. try {
  49. file.createNewFile();
  50. } catch (IOException e) {}
  51. // if this is thrown, we can't do anything (caught elsewhere anyway)
  52. }
  53. config = new Configuration(file);
  54. }
  55. public void load() throws IOException {
  56. config.load();
  57. Map<String, ConfigurationNode> regionData = config.getNodes("regions");
  58. // No regions are even configured
  59. if (regionData == null) {
  60. this.regions = new HashMap<String, ProtectedRegion>();
  61. return;
  62. }
  63. Map<String,ProtectedRegion> regions =
  64. new HashMap<String,ProtectedRegion>();
  65. Map<ProtectedRegion,String> parentSets =
  66. new LinkedHashMap<ProtectedRegion, String>();
  67. for (Map.Entry<String, ConfigurationNode> entry : regionData.entrySet()) {
  68. String id = entry.getKey().toLowerCase().replace(".", "");
  69. ConfigurationNode node = entry.getValue();
  70. String type = node.getString("type");
  71. ProtectedRegion region;
  72. try {
  73. if (type == null) {
  74. logger.warning("Undefined region type for region '" + id + '"');
  75. continue;
  76. } else if (type.equals("cuboid")) {
  77. Vector pt1 = checkNonNull(node.getVector("min"));
  78. Vector pt2 = checkNonNull(node.getVector("max"));
  79. BlockVector min = Vector.getMinimum(pt1, pt2).toBlockVector();
  80. BlockVector max = Vector.getMaximum(pt1, pt2).toBlockVector();
  81. region = new ProtectedCuboidRegion(id, min, max);
  82. } else if (type.equals("poly2d")) {
  83. Integer minY = checkNonNull(node.getInt("min-y"));
  84. Integer maxY = checkNonNull(node.getInt("max-y"));
  85. List<BlockVector2D> points = node.getBlockVector2dList("points", null);
  86. region = new ProtectedPolygonalRegion(id, points, minY, maxY);
  87. } else if (type.equals("global")) {
  88. region = new GlobalProtectedRegion(id);
  89. } else {
  90. logger.warning("Unknown region type for region '" + id + '"');
  91. continue;
  92. }
  93. Integer priority = checkNonNull(node.getInt("priority"));
  94. region.setPriority(priority);
  95. setFlags(region, node.getNode("flags"));
  96. region.setOwners(parseDomain(node.getNode("owners")));
  97. region.setMembers(parseDomain(node.getNode("members")));
  98. regions.put(id, region);
  99. String parentId = node.getString("parent");
  100. if (parentId != null) {
  101. parentSets.put(region, parentId);
  102. }
  103. } catch (NullPointerException e) {
  104. logger.warning("Missing data for region '" + id + '"');
  105. }
  106. }
  107. // Relink parents
  108. for (Map.Entry<ProtectedRegion, String> entry : parentSets.entrySet()) {
  109. ProtectedRegion parent = regions.get(entry.getValue());
  110. if (parent != null) {
  111. try {
  112. entry.getKey().setParent(parent);
  113. } catch (CircularInheritanceException e) {
  114. logger.warning("Circular inheritance detect with '"
  115. + entry.getValue() + "' detected as a parent");
  116. }
  117. } else {
  118. logger.warning("Unknown region parent: " + entry.getValue());
  119. }
  120. }
  121. this.regions = regions;
  122. }
  123. private <V> V checkNonNull(V val) throws NullPointerException {
  124. if (val == null) {
  125. throw new NullPointerException();
  126. }
  127. return val;
  128. }
  129. private void setFlags(ProtectedRegion region, ConfigurationNode flagsData) {
  130. if (flagsData == null) {
  131. return;
  132. }
  133. // @TODO: Make this better
  134. for (Flag<?> flag : DefaultFlag.getFlags()) {
  135. Object o = flagsData.getProperty(flag.getName());
  136. if (o != null) {
  137. setFlag(region, flag, o);
  138. }
  139. }
  140. }
  141. private <T> void setFlag(ProtectedRegion region, Flag<T> flag, Object rawValue) {
  142. T val = flag.unmarshal(rawValue);
  143. if (val == null) {
  144. logger.warning("Failed to parse flag '" + flag.getName()
  145. + "' with value '" + rawValue.toString() + "'");
  146. return;
  147. }
  148. region.setFlag(flag, val);
  149. }
  150. private DefaultDomain parseDomain(ConfigurationNode node) {
  151. if (node == null) {
  152. return new DefaultDomain();
  153. }
  154. DefaultDomain domain = new DefaultDomain();
  155. for (String name : node.getStringList("players", null)) {
  156. domain.addPlayer(name);
  157. }
  158. for (String name : node.getStringList("groups", null)) {
  159. domain.addGroup(name);
  160. }
  161. return domain;
  162. }
  163. public void save() throws IOException {
  164. config.clear();
  165. for (Map.Entry<String, ProtectedRegion> entry : regions.entrySet()) {
  166. ProtectedRegion region = entry.getValue();
  167. ConfigurationNode node = config.addNode("regions." + entry.getKey());
  168. if (region instanceof ProtectedCuboidRegion) {
  169. ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
  170. node.setProperty("type", "cuboid");
  171. node.setProperty("min", cuboid.getMinimumPoint());
  172. node.setProperty("max", cuboid.getMaximumPoint());
  173. } else if (region instanceof ProtectedPolygonalRegion) {
  174. ProtectedPolygonalRegion poly = (ProtectedPolygonalRegion) region;
  175. node.setProperty("type", "poly2d");
  176. node.setProperty("min-y", poly.getMinimumPoint().getBlockY());
  177. node.setProperty("max-y", poly.getMaximumPoint().getBlockY());
  178. List<Map<String, Object>> points = new ArrayList<Map<String,Object>>();
  179. for (BlockVector2D point : poly.getPoints()) {
  180. Map<String, Object> data = new HashMap<String, Object>();
  181. data.put("x", point.getBlockX());
  182. data.put("z", point.getBlockZ());
  183. points.add(data);
  184. }
  185. node.setProperty("points", points);
  186. } else if (region instanceof GlobalProtectedRegion) {
  187. node.setProperty("type", "global");
  188. } else {
  189. node.setProperty("type", region.getClass().getCanonicalName());
  190. }
  191. node.setProperty("priority", region.getPriority());
  192. node.setProperty("flags", getFlagData(region));
  193. node.setProperty("owners", getDomainData(region.getOwners()));
  194. node.setProperty("members", getDomainData(region.getMembers()));
  195. ProtectedRegion parent = region.getParent();
  196. if (parent != null) {
  197. node.setProperty("parent", parent.getId());
  198. }
  199. }
  200. config.setHeader("#\r\n" +
  201. "# WorldGuard regions file\r\n" +
  202. "#\r\n" +
  203. "# WARNING: THIS FILE IS AUTOMATICALLY GENERATED. If you modify this file by\r\n" +
  204. "# hand, be aware that A SINGLE MISTYPED CHARACTER CAN CORRUPT THE FILE. If\r\n" +
  205. "# WorldGuard is unable to parse the file, your regions will FAIL TO LOAD and\r\n" +
  206. "# the contents of this file will reset. Please use a YAML validator such as\r\n" +
  207. "# http://yaml-online-parser.appspot.com (for smaller files).\r\n" +
  208. "#\r\n" +
  209. "# REMEMBER TO KEEP PERIODICAL BACKUPS.\r\n" +
  210. "#");
  211. config.save();
  212. }
  213. private Map<String, Object> getFlagData(ProtectedRegion region) {
  214. Map<String, Object> flagData = new HashMap<String, Object>();
  215. for (Map.Entry<Flag<?>, Object> entry : region.getFlags().entrySet()) {
  216. Flag<?> flag = entry.getKey();
  217. addMarshalledFlag(flagData, flag, entry.getValue());
  218. }
  219. return flagData;
  220. }
  221. @SuppressWarnings("unchecked")
  222. private <V> void addMarshalledFlag(Map<String, Object> flagData,
  223. Flag<V> flag, Object val) {
  224. if (val == null) {
  225. return;
  226. }
  227. flagData.put(flag.getName(), flag.marshal((V) val));
  228. }
  229. private Map<String, Object> getDomainData(DefaultDomain domain) {
  230. Map<String, Object> domainData = new HashMap<String, Object>();
  231. setDomainData(domainData, "players", domain.getPlayers());
  232. setDomainData(domainData, "groups", domain.getGroups());
  233. return domainData;
  234. }
  235. private void setDomainData(Map<String, Object> domainData,
  236. String key, Set<String> domain) {
  237. if (domain.size() == 0) {
  238. return;
  239. }
  240. List<String> list = new ArrayList<String>();
  241. for (String str : domain) {
  242. list.add(str);
  243. }
  244. domainData.put(key, list);
  245. }
  246. public Map<String, ProtectedRegion> getRegions() {
  247. return regions;
  248. }
  249. public void setRegions(Map<String, ProtectedRegion> regions) {
  250. this.regions = regions;
  251. }
  252. }