summaryrefslogtreecommitdiffstats
path: root/EssentialsGroupManager/src/org/anjocaido/groupmanager/GlobalGroups.java
blob: ea0e5bc7cdd8463feb91e3dc03b93213ced6dd2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
package org.anjocaido.groupmanager;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import org.anjocaido.groupmanager.data.Group;
import org.anjocaido.groupmanager.events.GMGroupEvent;
import org.anjocaido.groupmanager.utils.PermissionCheckResult;
import org.anjocaido.groupmanager.utils.Tasks;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.reader.UnicodeReader;

/**
 * @author ElgarL
 * 
 */
public class GlobalGroups {

	private GroupManager plugin;
	//private Yaml GGroups;

	private final Map<String, Group> groups = Collections.synchronizedMap(new HashMap<String, Group>());

	protected long timeStampGroups = 0;
	protected boolean haveGroupsChanged = false;
	protected File GlobalGroupsFile = null;

	public GlobalGroups(GroupManager plugin) {

		this.plugin = plugin;
		load();
	}

	/**
	 * @return the haveGroupsChanged
	 */
	public boolean haveGroupsChanged() {

		if (this.haveGroupsChanged) {
			return true;
		}
		synchronized(groups) {
		for (Group g : groups.values()) {
			if (g.isChanged()) {
				return true;
			}
		}
		}
		return false;
	}

	/**
	 * @return the timeStampGroups
	 */
	public long getTimeStampGroups() {

		return timeStampGroups;
	}

	/**
	 * @param timeStampGroups the timeStampGroups to set
	 */
	protected void setTimeStampGroups(long timeStampGroups) {

		this.timeStampGroups = timeStampGroups;
	}

	/**
	 * @param haveGroupsChanged
	 *            the haveGroupsChanged to set
	 */
	public void setGroupsChanged(boolean haveGroupsChanged) {

		this.haveGroupsChanged = haveGroupsChanged;
	}

	@SuppressWarnings("unchecked")
	public void load() {

		Yaml GGroupYAML = new Yaml(new SafeConstructor());
		Map<String, Object> GGroups;
		
		GroupManager.setLoaded(false);

		// READ globalGroups FILE
		if (GlobalGroupsFile == null)
			GlobalGroupsFile = new File(plugin.getDataFolder(), "globalgroups.yml");

		if (!GlobalGroupsFile.exists()) {
			try {
				// Create a new file if it doesn't exist.
				Tasks.copy(plugin.getResourceAsStream("globalgroups.yml"), GlobalGroupsFile);
			} catch (IOException ex) {
				GroupManager.logger.log(Level.SEVERE, null, ex);
			}
		}

		/*
		 * Load the YAML file.
		 */
		try {
			FileInputStream groupsInputStream = new FileInputStream(GlobalGroupsFile);
			GGroups = (Map<String, Object>) GGroupYAML.load(new UnicodeReader(groupsInputStream));
			groupsInputStream.close();
		} catch (Exception ex) {
			throw new IllegalArgumentException("The following file couldn't pass on Parser.\n" + GlobalGroupsFile.getPath(), ex);
		}

		// Clear out old groups
		resetGlobalGroups();

		if (!GGroups.keySet().isEmpty()) {
			// Read all global groups
			Map<String, Object> allGroups = new HashMap<String, Object>();

			try {
				allGroups = (Map<String, Object>) GGroups.get("groups");
			} catch (Exception ex) {
				// ex.printStackTrace();
				throw new IllegalArgumentException("Your " + GlobalGroupsFile.getPath() + " file is invalid. See console for details.", ex);
			}

			// Load each groups permissions list.
			if (allGroups != null) {

				Iterator<String> groupItr = allGroups.keySet().iterator();
				String groupName;
				Integer groupCount = 0;

				/*
				 * loop each group entry
				 * and read it's data.
				 */
				while (groupItr.hasNext()) {
					try {
						groupCount++;
						// Attempt to fetch the next group name.
						groupName = groupItr.next();
					} catch (Exception ex) {
						throw new IllegalArgumentException("Invalid group name for GlobalGroup entry (" + groupCount + ") in file: " + GlobalGroupsFile.getPath(), ex);
					}

					/*
					 * Create a new group with this name.
					 */
					Group newGroup = new Group(groupName.toLowerCase());
					Object element;

					// Permission nodes
					try {
						element = ((Map<String, Object>)allGroups.get(groupName)).get("permissions");
					} catch ( Exception ex) {
						throw new IllegalArgumentException("The GlobalGroup ' " + groupName + "' is formatted incorrectly: ", ex);
					}

					if (element != null)
						if (element instanceof List) {
							try {
								for (String node : (List<String>) element) {
									if ((node != null) && !node.isEmpty())
										newGroup.addPermission(node);
								}
							} catch (ClassCastException ex) {
								throw new IllegalArgumentException("Invalid permission node for global group:  " + groupName, ex);
							}
						} else if (element instanceof String) {
							if ((element != null) && !((String)element).isEmpty())
							newGroup.addPermission((String) element);
						} else
							throw new IllegalArgumentException("Unknown type of permission node for global group:  " + groupName);

//					// Info nodes
//					try {
//						element = ((Map<String, Object>)allGroups.get(groupName)).get("info");
//					} catch ( Exception ex) {
//						throw new IllegalArgumentException("The GlobalGroup ' " + groupName + "' is formatted incorrectly: ", ex);
//					}
//
//					if (element != null)
//						if (element instanceof MemorySection) {
//							Map<String, Object> vars = new HashMap<String, Object>();
//							for (String key : ((MemorySection) element).getKeys(false)) {
//								vars.put(key, ((MemorySection) element).get(key));
//							}
//							newGroup.setVariables(vars);
//						} else
//							throw new IllegalArgumentException("Unknown type of info node for global group:  " + groupName);

					// Push a new group
					addGroup(newGroup);
				}
			}

			removeGroupsChangedFlag();
		}

		setTimeStampGroups(GlobalGroupsFile.lastModified());
		GroupManager.setLoaded(true);
		// GlobalGroupsFile = null;
	}

	/**
	 * Write the globalgroups.yml file
	 */

	public void writeGroups(boolean overwrite) {

		// File GlobalGroupsFile = new File(plugin.getDataFolder(), "globalgroups.yml");

		if (haveGroupsChanged()) {
			if (overwrite || (!overwrite && (getTimeStampGroups() >= GlobalGroupsFile.lastModified()))) {
				Map<String, Object> root = new HashMap<String, Object>();

				Map<String, Object> groupsMap = new HashMap<String, Object>();
				root.put("groups", groupsMap);
				synchronized(groups) {
				for (String groupKey : groups.keySet()) {
					Group group = groups.get(groupKey);

					// Group header
					Map<String, Object> aGroupMap = new HashMap<String, Object>();
					groupsMap.put(group.getName(), aGroupMap);

//					// Info nodes
//					Map<String, Object> infoMap = new HashMap<String, Object>();
//					aGroupMap.put("info", infoMap);
//
//					for (String infoKey : group.getVariables().getVarKeyList()) {
//						infoMap.put(infoKey, group.getVariables().getVarObject(infoKey));
//					}

					// Permission nodes
					aGroupMap.put("permissions", group.getPermissionList());
				}
				}

				if (!root.isEmpty()) {
					DumperOptions opt = new DumperOptions();
					opt.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
					final Yaml yaml = new Yaml(opt);
					try {
						yaml.dump(root, new OutputStreamWriter(new FileOutputStream(GlobalGroupsFile), "UTF-8"));
					} catch (UnsupportedEncodingException ex) {
					} catch (FileNotFoundException ex) {
					}
				}
				setTimeStampGroups(GlobalGroupsFile.lastModified());
			} else {
				// Newer file found.
				GroupManager.logger.log(Level.WARNING, "Newer GlobalGroups file found, but we have local changes!");
				throw new IllegalStateException("Unable to save unless you issue a '/mansave force'");
			}
			removeGroupsChangedFlag();
		} else {
			// Check for newer file as no local changes.
			if (getTimeStampGroups() < GlobalGroupsFile.lastModified()) {
				System.out.print("Newer GlobalGroups file found (Loading changes)!");
				// Backup GlobalGroups file
				backupFile();
				load();
			}
		}

	}

	/**
	 * Backup the BlobalGroups file
	 * 
	 * @param w
	 */
	private void backupFile() {

		File backupFile = new File(plugin.getBackupFolder(), "bkp_ggroups_" + Tasks.getDateString() + ".yml");
		try {
			Tasks.copy(GlobalGroupsFile, backupFile);
		} catch (IOException ex) {
			GroupManager.logger.log(Level.SEVERE, null, ex);
		}
	}

	/**
	 * Adds a group, or replaces an existing one.
	 * 
	 * @param groupToAdd
	 */
	public void addGroup(Group groupToAdd) {

		// Create a new group if it already exists
		if (hasGroup(groupToAdd.getName())) {
			groupToAdd = groupToAdd.clone();
			removeGroup(groupToAdd.getName());
		}

		newGroup(groupToAdd);
		haveGroupsChanged = true;
		if (GroupManager.isLoaded())
			GroupManager.getGMEventHandler().callEvent(groupToAdd, GMGroupEvent.Action.GROUP_ADDED);
	}

	/**
	 * Creates a new group if it doesn't already exist.
	 * 
	 * @param newGroup
	 */
	public Group newGroup(Group newGroup) {

		// Push a new group
		if (!groups.containsKey(newGroup.getName().toLowerCase())) {
			groups.put(newGroup.getName().toLowerCase(), newGroup);
			this.setGroupsChanged(true);
			return newGroup;
		}
		return null;
	}

	/**
	 * Delete a group if it exist.
	 * 
	 * @param groupName
	 */
	public boolean removeGroup(String groupName) {

		// Push a new group
		if (groups.containsKey(groupName.toLowerCase())) {
			groups.remove(groupName.toLowerCase());
			this.setGroupsChanged(true);
			if (GroupManager.isLoaded())
				GroupManager.getGMEventHandler().callEvent(groupName.toLowerCase(), GMGroupEvent.Action.GROUP_REMOVED);
			return true;
		}
		return false;
	}

	/**
	 * Returns true if the Global Group exists in the globalgroups.yml
	 * 
	 * @param groupName
	 * @return true if the group exists
	 */
	public boolean hasGroup(String groupName) {

		return groups.containsKey(groupName.toLowerCase());
	}

	/**
	 * Returns true if the group has the correct permission node.
	 * 
	 * @param groupName
	 * @param permissionNode
	 * @return true if node exists
	 */
	public boolean hasPermission(String groupName, String permissionNode) {

		if (!hasGroup(groupName))
			return false;

		return groups.get(groupName.toLowerCase()).hasSamePermissionNode(permissionNode);

	}

	/**
	 * Returns a PermissionCheckResult of the permission node for the group to
	 * be tested against.
	 * 
	 * @param groupName
	 * @param permissionNode
	 * @return PermissionCheckResult object
	 */
	public PermissionCheckResult checkPermission(String groupName, String permissionNode) {

		PermissionCheckResult result = new PermissionCheckResult();
		result.askedPermission = permissionNode;
		result.resultType = PermissionCheckResult.Type.NOTFOUND;

		if (!hasGroup(groupName))
			return result;

		Group tempGroup = groups.get(groupName.toLowerCase());

		if (tempGroup.hasSamePermissionNode(permissionNode))
			result.resultType = PermissionCheckResult.Type.FOUND;
		if (tempGroup.hasSamePermissionNode("-" + permissionNode))
			result.resultType = PermissionCheckResult.Type.NEGATION;
		if (tempGroup.hasSamePermissionNode("+" + permissionNode))
			result.resultType = PermissionCheckResult.Type.EXCEPTION;

		return result;
	}

	/**
	 * Returns a List of all permission nodes for this group null if none
	 * 
	 * @param groupName
	 * @return List of all group names
	 */
	public List<String> getGroupsPermissions(String groupName) {

		if (!hasGroup(groupName))
			return null;

		return groups.get(groupName.toLowerCase()).getPermissionList();
	}

	/**
	 * Returns a Set of all global group names.
	 * 
	 * @return Set containing all group names.
	 */
	/*public Set<String> getGlobalGroups() {

		return groups.keySet();
	}*/

	/**
	 * Resets GlobalGroups.
	 */
	public void resetGlobalGroups() {
		this.groups.clear();
	}

	/**
	 * 
	 * @return a collection of the groups
	 */
	public Group[] getGroupList() {
		synchronized(groups) {
			return groups.values().toArray(new Group[0]);
		}
	}

	/**
	 * Returns the Global Group or null if it doesn't exist.
	 * 
	 * @param groupName
	 * @return Group object
	 */
	public Group getGroup(String groupName) {

		if (!hasGroup(groupName))
			return null;

		return groups.get(groupName.toLowerCase());

	}

	/**
	 * @return the globalGroupsFile
	 */
	public File getGlobalGroupsFile() {

		return GlobalGroupsFile;
	}

	/**
    *
    */
	public void removeGroupsChangedFlag() {

		setGroupsChanged(false);
		synchronized(groups) {
		for (Group g : groups.values()) {
			g.flagAsSaved();
		}
		}
	}

}