Commits
sk89q authored 0d2adc57075
12 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 14 | * GNU General Public License for more details. |
15 15 | * |
16 16 | * You should have received a copy of the GNU General Public License |
17 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 18 | */ |
19 19 | |
20 20 | package com.sk89q.worldguard.protection.databases; |
21 21 | |
22 - | import java.io.File; |
23 - | import java.io.IOException; |
24 - | import java.io.FileNotFoundException; |
25 - | import java.util.ArrayList; |
26 - | import java.util.HashMap; |
27 - | import java.util.LinkedHashMap; |
28 - | import java.util.List; |
29 - | import java.util.Map; |
30 - | import java.util.Set; |
31 - | import java.util.logging.Logger; |
32 - | |
33 22 | import com.sk89q.util.yaml.YAMLFormat; |
34 23 | import com.sk89q.util.yaml.YAMLNode; |
35 24 | import com.sk89q.util.yaml.YAMLProcessor; |
36 25 | import com.sk89q.worldedit.BlockVector; |
37 26 | import com.sk89q.worldedit.BlockVector2D; |
38 27 | import com.sk89q.worldedit.Vector; |
39 28 | import com.sk89q.worldguard.domains.DefaultDomain; |
40 29 | import com.sk89q.worldguard.protection.flags.DefaultFlag; |
41 30 | import com.sk89q.worldguard.protection.flags.Flag; |
42 31 | import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion; |
43 32 | import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; |
44 33 | import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion; |
45 34 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; |
46 35 | import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException; |
36 + | import org.yaml.snakeyaml.DumperOptions; |
37 + | import org.yaml.snakeyaml.DumperOptions.FlowStyle; |
38 + | import org.yaml.snakeyaml.Yaml; |
39 + | import org.yaml.snakeyaml.constructor.SafeConstructor; |
40 + | import org.yaml.snakeyaml.representer.Representer; |
41 + | |
42 + | import java.io.File; |
43 + | import java.io.FileNotFoundException; |
44 + | import java.io.IOException; |
45 + | import java.util.ArrayList; |
46 + | import java.util.HashMap; |
47 + | import java.util.LinkedHashMap; |
48 + | import java.util.List; |
49 + | import java.util.Map; |
50 + | import java.util.Set; |
51 + | import java.util.logging.Level; |
52 + | import java.util.logging.Logger; |
47 53 | |
48 54 | public class YAMLDatabase extends AbstractProtectionDatabase { |
49 - | |
55 + | |
56 + | /** |
57 + | * Used to dump YAML when an error occurs |
58 + | */ |
59 + | private static Yaml yaml; |
60 + | |
50 61 | private YAMLProcessor config; |
51 62 | private Map<String, ProtectedRegion> regions; |
52 63 | private final Logger logger; |
53 64 | |
54 65 | public YAMLDatabase(File file, Logger logger) throws ProtectionDatabaseException, FileNotFoundException { |
55 66 | this.logger = logger; |
56 67 | if (!file.exists()) { // shouldn't be necessary, but check anyways |
57 68 | try { |
58 69 | file.createNewFile(); |
59 70 | } catch (IOException e) { |
71 82 | } |
72 83 | |
73 84 | Map<String, YAMLNode> regionData = config.getNodes("regions"); |
74 85 | |
75 86 | // No regions are even configured |
76 87 | if (regionData == null) { |
77 88 | this.regions = new HashMap<String, ProtectedRegion>(); |
78 89 | return; |
79 90 | } |
80 91 | |
81 - | Map<String,ProtectedRegion> regions = |
82 - | new HashMap<String,ProtectedRegion>(); |
83 - | Map<ProtectedRegion,String> parentSets = |
84 - | new LinkedHashMap<ProtectedRegion, String>(); |
92 + | Map<String,ProtectedRegion> regions = new HashMap<String,ProtectedRegion>(); |
93 + | Map<ProtectedRegion,String> parentSets = new LinkedHashMap<ProtectedRegion, String>(); |
85 94 | |
86 95 | for (Map.Entry<String, YAMLNode> entry : regionData.entrySet()) { |
87 96 | String id = entry.getKey().toLowerCase().replace(".", ""); |
88 97 | YAMLNode node = entry.getValue(); |
89 - | |
98 + | |
90 99 | String type = node.getString("type"); |
91 100 | ProtectedRegion region; |
92 101 | |
93 102 | try { |
94 103 | if (type == null) { |
95 - | logger.warning("Undefined region type for region '" + id + '"'); |
104 + | logger.warning("Undefined region type for region '" + id + "'!\n" + |
105 + | "Here is what the region data looks like:\n\n" + dumpAsYaml(entry.getValue().getMap()) + "\n"); |
96 106 | continue; |
97 107 | } else if (type.equals("cuboid")) { |
98 108 | Vector pt1 = checkNonNull(node.getVector("min")); |
99 109 | Vector pt2 = checkNonNull(node.getVector("max")); |
100 110 | BlockVector min = Vector.getMinimum(pt1, pt2).toBlockVector(); |
101 111 | BlockVector max = Vector.getMaximum(pt1, pt2).toBlockVector(); |
102 112 | region = new ProtectedCuboidRegion(id, min, max); |
103 113 | } else if (type.equals("poly2d")) { |
104 114 | Integer minY = checkNonNull(node.getInt("min-y")); |
105 115 | Integer maxY = checkNonNull(node.getInt("max-y")); |
106 116 | List<BlockVector2D> points = node.getBlockVector2dList("points", null); |
107 117 | region = new ProtectedPolygonalRegion(id, points, minY, maxY); |
108 118 | } else if (type.equals("global")) { |
109 119 | region = new GlobalProtectedRegion(id); |
110 120 | } else { |
111 - | logger.warning("Unknown region type for region '" + id + '"'); |
121 + | logger.warning("Unknown region type for region '" + id + "'!\n" + |
122 + | "Here is what the region data looks like:\n\n" + dumpAsYaml(entry.getValue().getMap()) + "\n"); |
112 123 | continue; |
113 124 | } |
114 125 | |
115 126 | Integer priority = checkNonNull(node.getInt("priority")); |
116 127 | region.setPriority(priority); |
117 128 | setFlags(region, node.getNode("flags")); |
118 129 | region.setOwners(parseDomain(node.getNode("owners"))); |
119 130 | region.setMembers(parseDomain(node.getNode("members"))); |
120 131 | regions.put(id, region); |
121 132 | |
122 133 | String parentId = node.getString("parent"); |
123 134 | if (parentId != null) { |
124 135 | parentSets.put(region, parentId); |
125 136 | } |
126 137 | } catch (NullPointerException e) { |
127 - | logger.warning("Missing data for region '" + id + '"'); |
138 + | logger.log(Level.WARNING, |
139 + | "Unexpected NullPointerException encountered during parsing for the region '" + id + "'!\n" + |
140 + | "Here is what the region data looks like:\n\n" + dumpAsYaml(entry.getValue().getMap()) + |
141 + | "\n\nNote: This region will disappear as a result!", e); |
128 142 | } |
129 143 | } |
130 144 | |
131 145 | // Relink parents |
132 146 | for (Map.Entry<ProtectedRegion, String> entry : parentSets.entrySet()) { |
133 147 | ProtectedRegion parent = regions.get(entry.getValue()); |
134 148 | if (parent != null) { |
135 149 | try { |
136 150 | entry.getKey().setParent(parent); |
137 151 | } catch (CircularInheritanceException e) { |
138 - | logger.warning("Circular inheritance detect with '" |
139 - | + entry.getValue() + "' detected as a parent"); |
152 + | logger.warning("Circular inheritance detect with '" + entry.getValue() + "' detected as a parent"); |
140 153 | } |
141 154 | } else { |
142 155 | logger.warning("Unknown region parent: " + entry.getValue()); |
143 156 | } |
144 157 | } |
145 158 | |
146 159 | this.regions = regions; |
147 160 | } |
148 161 | |
149 162 | private <V> V checkNonNull(V val) throws NullPointerException { |
304 317 | domainData.put(key, list); |
305 318 | } |
306 319 | |
307 320 | public Map<String, ProtectedRegion> getRegions() { |
308 321 | return regions; |
309 322 | } |
310 323 | |
311 324 | public void setRegions(Map<String, ProtectedRegion> regions) { |
312 325 | this.regions = regions; |
313 326 | } |
327 + | |
328 + | /** |
329 + | * Dump the given object as YAML for debugging purposes. |
330 + | * |
331 + | * @param object the object |
332 + | * @return the YAML string or an error string if dumping fals |
333 + | */ |
334 + | private static String dumpAsYaml(Object object) { |
335 + | if (yaml == null) { |
336 + | DumperOptions options = new DumperOptions(); |
337 + | options.setIndent(4); |
338 + | options.setDefaultFlowStyle(FlowStyle.AUTO); |
339 + | |
340 + | yaml = new Yaml(new SafeConstructor(), new Representer(), options); |
341 + | } |
342 + | |
343 + | try { |
344 + | return yaml.dump(object).replaceAll("(?m)^", "\t"); |
345 + | } catch (Throwable t) { |
346 + | return "<error while dumping object>"; |
347 + | } |
348 + | } |
314 349 | |
315 350 | } |