PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/talmor/worldguard
Java | 348 lines | 196 code | 43 blank | 109 comment | 47 complexity | 0a8bd41b572bc9ca31bb9789bcfc50ab 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.FileReader;
  22. import java.io.IOException;
  23. import java.util.HashMap;
  24. import java.util.LinkedHashMap;
  25. import java.util.Map;
  26. import java.util.logging.Logger;
  27. import java.util.regex.Matcher;
  28. import java.util.regex.Pattern;
  29. import au.com.bytecode.opencsv.CSVReader;
  30. import com.sk89q.worldedit.BlockVector;
  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.StateFlag;
  35. import com.sk89q.worldguard.protection.flags.StateFlag.State;
  36. import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
  37. import com.sk89q.worldguard.protection.regions.ProtectedRegion;
  38. import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException;
  39. import com.sk89q.worldguard.util.ArrayReader;
  40. /**
  41. * Represents a protected area database that uses CSV files.
  42. *
  43. * @author sk89q
  44. */
  45. public class CSVDatabase extends AbstractProtectionDatabase {
  46. private static Logger logger = Logger.getLogger("Minecraft.WorldGuard");
  47. /**
  48. * References the CSV file.
  49. */
  50. private File file;
  51. /**
  52. * Holds the list of regions.
  53. */
  54. private Map<String,ProtectedRegion> regions;
  55. /**
  56. * Construct the database with a path to a file. No file is read or
  57. * written at this time.
  58. *
  59. * @param file
  60. */
  61. public CSVDatabase(File file) {
  62. this.file = file;
  63. }
  64. /**
  65. * Saves the database.
  66. */
  67. public void save() throws IOException {
  68. throw new UnsupportedOperationException("CSV format is no longer implemented");
  69. }
  70. /**
  71. * Load the database from file.
  72. */
  73. public void load() throws IOException {
  74. Map<String,ProtectedRegion> regions =
  75. new HashMap<String,ProtectedRegion>();
  76. Map<ProtectedRegion,String> parentSets =
  77. new LinkedHashMap<ProtectedRegion, String>();
  78. CSVReader reader = new CSVReader(new FileReader(file));
  79. try {
  80. String[] line;
  81. while ((line = reader.readNext()) != null) {
  82. if (line.length < 2) {
  83. logger.warning("Invalid region definition: " + line);
  84. continue;
  85. }
  86. String id = line[0].toLowerCase().replace(".", "");
  87. String type = line[1];
  88. ArrayReader<String> entries = new ArrayReader<String>(line);
  89. if (type.equalsIgnoreCase("cuboid")) {
  90. if (line.length < 8) {
  91. logger.warning("Invalid region definition: " + line);
  92. continue;
  93. }
  94. Vector pt1 = new Vector(
  95. Integer.parseInt(line[2]),
  96. Integer.parseInt(line[3]),
  97. Integer.parseInt(line[4]));
  98. Vector pt2 = new Vector(
  99. Integer.parseInt(line[5]),
  100. Integer.parseInt(line[6]),
  101. Integer.parseInt(line[7]));
  102. BlockVector min = Vector.getMinimum(pt1, pt2).toBlockVector();
  103. BlockVector max = Vector.getMaximum(pt1, pt2).toBlockVector();
  104. int priority = entries.get(8) == null ? 0 : Integer.parseInt(entries.get(8));
  105. String ownersData = entries.get(9);
  106. String flagsData = entries.get(10);
  107. //String enterMessage = nullEmptyString(entries.get(11));
  108. ProtectedRegion region = new ProtectedCuboidRegion(id, min, max);
  109. region.setPriority(priority);
  110. parseFlags(region, flagsData);
  111. region.setOwners(this.parseDomains(ownersData));
  112. regions.put(id, region);
  113. } else if (type.equalsIgnoreCase("cuboid.2")) {
  114. Vector pt1 = new Vector(
  115. Integer.parseInt(line[2]),
  116. Integer.parseInt(line[3]),
  117. Integer.parseInt(line[4]));
  118. Vector pt2 = new Vector(
  119. Integer.parseInt(line[5]),
  120. Integer.parseInt(line[6]),
  121. Integer.parseInt(line[7]));
  122. BlockVector min = Vector.getMinimum(pt1, pt2).toBlockVector();
  123. BlockVector max = Vector.getMaximum(pt1, pt2).toBlockVector();
  124. int priority = entries.get(8) == null ? 0 : Integer.parseInt(entries.get(8));
  125. String parentId = entries.get(9);
  126. String ownersData = entries.get(10);
  127. String membersData = entries.get(11);
  128. String flagsData = entries.get(12);
  129. //String enterMessage = nullEmptyString(entries.get(13));
  130. //String leaveMessage = nullEmptyString(entries.get(14));
  131. ProtectedRegion region = new ProtectedCuboidRegion(id, min, max);
  132. region.setPriority(priority);
  133. parseFlags(region, flagsData);
  134. region.setOwners(this.parseDomains(ownersData));
  135. region.setMembers(this.parseDomains(membersData));
  136. regions.put(id, region);
  137. // Link children to parents later
  138. if (parentId.length() > 0) {
  139. parentSets.put(region, parentId);
  140. }
  141. }
  142. }
  143. } finally {
  144. try {
  145. reader.close();
  146. } catch (IOException e) {
  147. }
  148. }
  149. for (Map.Entry<ProtectedRegion, String> entry : parentSets.entrySet()) {
  150. ProtectedRegion parent = regions.get(entry.getValue());
  151. if (parent != null) {
  152. try {
  153. entry.getKey().setParent(parent);
  154. } catch (CircularInheritanceException e) {
  155. logger.warning("Circular inheritance detect with '"
  156. + entry.getValue() + "' detected as a parent");
  157. }
  158. } else {
  159. logger.warning("Unknown region parent: " + entry.getValue());
  160. }
  161. }
  162. this.regions = regions;
  163. }
  164. /**
  165. * Used to parse the specified domain in the CSV file.
  166. *
  167. * @param data
  168. * @return
  169. */
  170. private DefaultDomain parseDomains(String data) {
  171. if (data == null) {
  172. return new DefaultDomain();
  173. }
  174. DefaultDomain domain = new DefaultDomain();
  175. Pattern pattern = Pattern.compile("^([A-Za-z]):(.*)$");
  176. String[] parts = data.split(",");
  177. for (String part : parts) {
  178. if (part.trim().length() == 0) {
  179. continue;
  180. }
  181. Matcher matcher = pattern.matcher(part);
  182. if (!matcher.matches()) {
  183. logger.warning("Invalid owner specification: " + part);
  184. continue;
  185. }
  186. String type = matcher.group(1);
  187. String id = matcher.group(2);
  188. if (type.equals("u")) {
  189. domain.addPlayer(id);
  190. } else if (type.equals("g")) {
  191. domain.addGroup(id);
  192. } else {
  193. logger.warning("Unknown owner specification: " + type);
  194. }
  195. }
  196. return domain;
  197. }
  198. /**
  199. * Used to parse the list of flags.
  200. *
  201. * @param data
  202. */
  203. private void parseFlags(ProtectedRegion region, String data) {
  204. if (data == null) {
  205. return;
  206. }
  207. State curState = State.ALLOW;
  208. for (int i = 0; i < data.length(); i++) {
  209. char k = data.charAt(i);
  210. if (k == '+') {
  211. curState = State.ALLOW;
  212. } else if (k == '-') {
  213. curState = State.DENY;
  214. } else {
  215. String flagStr;
  216. if (k == '_') {
  217. if (i == data.length() - 1) {
  218. logger.warning("_ read ahead fail");
  219. break;
  220. }
  221. flagStr = "_" + data.charAt(i + 1);
  222. i++;
  223. logger.warning("_? custom flags are no longer supported");
  224. continue;
  225. } else {
  226. flagStr = String.valueOf(k);
  227. }
  228. StateFlag flag = DefaultFlag.getLegacyFlag(flagStr);
  229. if (flag != null) {
  230. region.setFlag(flag, curState);
  231. } else {
  232. logger.warning("Legacy flag '" + flagStr + "' is unsupported");
  233. }
  234. }
  235. }
  236. }
  237. /**
  238. * Used to write the list of domains.
  239. *
  240. * @param domain
  241. * @return
  242. */
  243. /* private String writeDomains(DefaultDomain domain) {
  244. StringBuilder str = new StringBuilder();
  245. for (String player : domain.getPlayers()) {
  246. str.append("u:" + player + ",");
  247. }
  248. for (String group : domain.getGroups()) {
  249. str.append("g:" + group + ",");
  250. }
  251. return str.length() > 0 ?
  252. str.toString().substring(0, str.length() - 1) : "";
  253. }*/
  254. /**
  255. * Helper method to prepend '+' or '-' in front of a flag according
  256. * to the flag's state.
  257. *
  258. * @param state
  259. * @param flag
  260. * @return
  261. */
  262. /*
  263. private String writeFlag(State state, String flag) {
  264. if (state == State.ALLOW) {
  265. return "+" + flag;
  266. } else if (state == State.DENY) {
  267. return "-" + flag;
  268. }
  269. return "";
  270. }
  271. */
  272. /**
  273. * Returns a null if a string is null or empty.
  274. *
  275. * @param str
  276. * @return
  277. */
  278. protected String nullEmptyString(String str) {
  279. if (str == null) {
  280. return null;
  281. } else if (str.length() == 0) {
  282. return null;
  283. } else {
  284. return str;
  285. }
  286. }
  287. /**
  288. * Get a list of protected regions.
  289. *
  290. * @return
  291. */
  292. public Map<String,ProtectedRegion> getRegions() {
  293. return regions;
  294. }
  295. /**
  296. * Get a list of protected regions.
  297. */
  298. public void setRegions(Map<String,ProtectedRegion> regions) {
  299. this.regions = regions;
  300. }
  301. }