diff options
author | Iaccidentally <coryhuckaby@gmail.com> | 2013-01-11 19:59:22 -0500 |
---|---|---|
committer | Iaccidentally <coryhuckaby@gmail.com> | 2013-01-11 19:59:22 -0500 |
commit | eb7cedd6fd5dae2353bdd47b2ce09942460fd8a6 (patch) | |
tree | 4c8a85944a28daeffd50b47b8646aaa71b10e71d /EssentialsGroupManager/src/org | |
parent | 859ca6e9199b2fe3ce652d3cb56a76559c2b4aca (diff) | |
download | Essentials-eb7cedd6fd5dae2353bdd47b2ce09942460fd8a6.tar Essentials-eb7cedd6fd5dae2353bdd47b2ce09942460fd8a6.tar.gz Essentials-eb7cedd6fd5dae2353bdd47b2ce09942460fd8a6.tar.lz Essentials-eb7cedd6fd5dae2353bdd47b2ce09942460fd8a6.tar.xz Essentials-eb7cedd6fd5dae2353bdd47b2ce09942460fd8a6.zip |
Revert "Remove GM from 3.0"
This reverts commit a4c93fef05493e6210e8d3d72af7b6d492f4e121.
Diffstat (limited to 'EssentialsGroupManager/src/org')
28 files changed, 8772 insertions, 0 deletions
diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GMConfiguration.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GMConfiguration.java new file mode 100644 index 000000000..0832000f2 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GMConfiguration.java @@ -0,0 +1,101 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager; + +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.logging.Level; + +import org.anjocaido.groupmanager.utils.Tasks; +import org.bukkit.configuration.file.YamlConfiguration; + +/** + * + * @author gabrielcouto + */ +public class GMConfiguration { + + private GroupManager plugin; + private File configFile; + private YamlConfiguration GMconfig; + + public GMConfiguration(GroupManager plugin) { + + this.plugin = plugin; + load(); + } + + public void load() { + + if (!plugin.getDataFolder().exists()) { + plugin.getDataFolder().mkdirs(); + } + configFile = new File(plugin.getDataFolder(), "config.yml"); + + if (!configFile.exists()) { + try { + Tasks.copy(plugin.getResourceAsStream("config.yml"), configFile); + } catch (IOException ex) { + GroupManager.logger.log(Level.SEVERE, null, ex); + } + } + + GMconfig = new YamlConfiguration(); + + try { + GMconfig.load(configFile); + } catch (Exception ex) { + throw new IllegalArgumentException("The following file couldn't pass on Parser.\n" + configFile.getPath(), ex); + } + + // Setup defaults + adjustLoggerLevel(); + plugin.setValidateOnlinePlayer(isToggleValidate()); + } + + public boolean isOpOverride() { + + return GMconfig.getBoolean("settings.config.opOverrides", true); + } + + public boolean isToggleValidate() { + + return GMconfig.getBoolean("settings.config.validate_toggle", true); + } + + public Map<String, Object> getMirrorsMap() { + + // Try to fetch the old mirror path first + if (GMconfig.isConfigurationSection("settings.permission.world.mirror")) { + return (Map<String, Object>) GMconfig.getConfigurationSection("settings.permission.world.mirror").getValues(false); + } else if (GMconfig.isConfigurationSection("settings.mirrors")) { + return (Map<String, Object>) GMconfig.getConfigurationSection("settings.mirrors").getValues(false); + } + return null; + + } + + public Integer getSaveInterval() { + + return GMconfig.getInt("settings.data.save.minutes", 10); + } + + public Integer getBackupDuration() { + + return GMconfig.getInt("settings.data.save.hours", 24); + } + + public void adjustLoggerLevel() { + + try { + GroupManager.logger.setLevel(Level.parse(GMconfig.getString("settings.logging.level", "INFO"))); + return; + } catch (Exception e) { + } + + GroupManager.logger.setLevel(Level.INFO); + } +}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GlobalGroups.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GlobalGroups.java new file mode 100644 index 000000000..04d9e86be --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GlobalGroups.java @@ -0,0 +1,461 @@ +package org.anjocaido.groupmanager;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+
+import org.anjocaido.groupmanager.data.Group;
+import org.anjocaido.groupmanager.events.GMGroupEvent;
+import org.anjocaido.groupmanager.events.GroupManagerEventHandler;
+import org.anjocaido.groupmanager.utils.PermissionCheckResult;
+import org.anjocaido.groupmanager.utils.Tasks;
+import org.bukkit.configuration.MemorySection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * @author ElgarL
+ *
+ */
+public class GlobalGroups {
+
+ private GroupManager plugin;
+ private YamlConfiguration GGroups;
+
+ private Map<String, Group> groups;
+
+ 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;
+ }
+ 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() {
+
+ GGroups = new YamlConfiguration();
+
+ 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);
+ }
+ }
+
+ try {
+ GGroups.load(GlobalGroupsFile);
+ } 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.getKeys(false).isEmpty()) {
+ // Read all global groups
+ Map<String, Object> allGroups = new HashMap<String, Object>();
+
+ try {
+ allGroups = (Map<String, Object>) GGroups.getConfigurationSection("groups").getValues(false);
+ } 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
+ element = GGroups.get("groups." + groupName + ".permissions");
+
+ 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
+ element = GGroups.get("groups." + groupName + ".info");
+
+ 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);
+ 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())
+ GroupManagerEventHandler.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())
+ GroupManagerEventHandler.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 = new HashMap<String, Group>();
+ }
+
+ /**
+ *
+ * @return a collection of the groups
+ */
+ public Collection<Group> getGroupList() {
+
+ return groups.values();
+ }
+
+ /**
+ * 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);
+ for (Group g : groups.values()) {
+ g.flagAsSaved();
+ }
+ }
+
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java new file mode 100644 index 000000000..5f357641a --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java @@ -0,0 +1,2038 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager; + +import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler; +import org.anjocaido.groupmanager.permissions.BukkitPermissions; +import org.anjocaido.groupmanager.utils.GroupManagerPermissions; +import org.anjocaido.groupmanager.Tasks.BukkitPermsUpdateTask; +import org.anjocaido.groupmanager.data.Variables; +import org.anjocaido.groupmanager.data.User; +import org.anjocaido.groupmanager.data.Group; +import org.anjocaido.groupmanager.dataholder.OverloadedWorldHolder; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.anjocaido.groupmanager.dataholder.worlds.WorldsHolder; +import org.anjocaido.groupmanager.events.GMSystemEvent; +import org.anjocaido.groupmanager.events.GMWorldListener; +import org.anjocaido.groupmanager.events.GroupManagerEventHandler; +import org.anjocaido.groupmanager.utils.GMLoggerHandler; +import org.anjocaido.groupmanager.utils.PermissionCheckResult; +import org.anjocaido.groupmanager.utils.Tasks; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.ServicePriority; +import org.bukkit.plugin.java.JavaPlugin; + + +/** + * + * @author gabrielcouto, ElgarL + */ +public class GroupManager extends JavaPlugin { + + private File backupFolder; + private Runnable commiter; + private ScheduledThreadPoolExecutor scheduler; + private Map<String, ArrayList<User>> overloadedUsers = new HashMap<String, ArrayList<User>>(); + private Map<CommandSender, String> selectedWorlds = new HashMap<CommandSender, String>(); + private WorldsHolder worldsHolder; + private boolean validateOnlinePlayer = true; + + private static boolean isLoaded = false; + protected GMConfiguration config; + + protected static GlobalGroups globalGroups; + + private GMLoggerHandler ch; + public static BukkitPermissions BukkitPermissions; + private static GMWorldListener WorldEvents; + public static final Logger logger = Logger.getLogger(GroupManager.class.getName()); + + // PERMISSIONS FOR COMMAND BEING LOADED + private OverloadedWorldHolder dataHolder = null; + private AnjoPermissionsHandler permissionHandler = null; + + private String lastError = ""; + + @Override + public void onDisable() { + + onDisable(false); + } + + @Override + public void onEnable() { + + onEnable(false); + } + + public void onDisable(boolean restarting) { + + setLoaded(false); + + if (!restarting) { + // Unregister this service if we are shutting down. + this.getServer().getServicesManager().unregister(this.worldsHolder); + } + + disableScheduler(); // Shutdown before we save, so it doesn't interfere. + if (worldsHolder != null) { + try { + worldsHolder.saveChanges(false); + } catch (IllegalStateException ex) { + GroupManager.logger.log(Level.WARNING, ex.getMessage()); + } + } + + + + // Remove all attachments before clearing + if (BukkitPermissions != null) { + BukkitPermissions.removeAllAttachments(); + } + + if (!restarting) { + + if (WorldEvents != null) + WorldEvents = null; + + BukkitPermissions = null; + + } + + // EXAMPLE: Custom code, here we just output some info so we can check that all is well + PluginDescriptionFile pdfFile = this.getDescription(); + System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " is disabled!"); + + if (!restarting) + GroupManager.logger.removeHandler(ch); + } + + public void onEnable(boolean restarting) { + + try { + /* + * reset local variables. + */ + overloadedUsers = new HashMap<String, ArrayList<User>>(); + selectedWorlds = new HashMap<CommandSender, String>(); + lastError = ""; + + /* + * Setup our logger if we are not restarting. + */ + if (!restarting) { + GroupManager.logger.setUseParentHandlers(false); + ch = new GMLoggerHandler(); + GroupManager.logger.addHandler(ch); + } + logger.setLevel(Level.ALL); + + // Create the backup folder, if it doesn't exist. + prepareFileFields(); + // Load the config.yml + prepareConfig(); + // Load the global groups + globalGroups = new GlobalGroups(this); + + /* + * Configure the worlds holder. + */ + if (!restarting) + worldsHolder = new WorldsHolder(this); + else + worldsHolder.resetWorldsHolder(); + + /* + * This should NEVER happen. No idea why it's still here. + */ + PluginDescriptionFile pdfFile = this.getDescription(); + if (worldsHolder == null) { + GroupManager.logger.severe("Can't enable " + pdfFile.getName() + " version " + pdfFile.getVersion() + ", bad loading!"); + this.getServer().getPluginManager().disablePlugin(this); + throw new IllegalStateException("An error ocurred while loading GroupManager"); + } + + /* + * Prevent our registered events from triggering + * updates as we are not fully loaded. + */ + setLoaded(false); + + /* + * Initialize the world listener and bukkit permissions + * to handle events if this is a fresh start + * + * else + * + * Reset bukkit perms. + */ + if (!restarting) { + WorldEvents = new GMWorldListener(this); + BukkitPermissions = new BukkitPermissions(this); + } else { + BukkitPermissions.reset(); + } + + /* + * Start the scheduler for data saving. + */ + enableScheduler(); + + /* + * Schedule a Bukkit Permissions update for 1 tick later. + * All plugins will be loaded by then + */ + + if (getServer().getScheduler().scheduleSyncDelayedTask(this, new BukkitPermsUpdateTask(), 1) == -1) { + GroupManager.logger.severe("Could not schedule superperms Update."); + /* + * Flag that we are now loaded and should start processing events. + */ + setLoaded(true); + } + + System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " is enabled!"); + + // Register as a service + if (!restarting) + this.getServer().getServicesManager().register(WorldsHolder.class, this.worldsHolder, this, ServicePriority.Lowest); + + } catch (Exception ex) { + + /* + * Store the error and write to the log. + */ + saveErrorLog(ex); + + /* + * Throw an error so Bukkit knows about it. + */ + throw new IllegalArgumentException(ex.getMessage(), ex); + + } + } + + /** + * Write an error.log + * + * @param ex + */ + private void saveErrorLog(Exception ex) { + + if (!getDataFolder().exists()) { + getDataFolder().mkdirs(); + } + + lastError = ex.getMessage(); + + GroupManager.logger.severe("==================================================="); + GroupManager.logger.severe("= ERROR REPORT START ="); + GroupManager.logger.severe("==================================================="); + GroupManager.logger.severe("=== PLEASE COPY AND PASTE THE ERROR.LOG FROM THE =="); + GroupManager.logger.severe("= GROUPMANAGER FOLDER TO AN ESSENTIALS DEVELOPER ="); + GroupManager.logger.severe("==================================================="); + GroupManager.logger.severe(lastError); + GroupManager.logger.severe("==================================================="); + GroupManager.logger.severe("= ERROR REPORT ENDED ="); + GroupManager.logger.severe("==================================================="); + + // Append this error to the error log. + try { + String error = "=============================== GM ERROR LOG ===============================\n\n"; + error += Tasks.getStackTraceAsString(ex); + error += "\n============================================================================\n"; + + Tasks.appendStringToFile(error, (getDataFolder() + System.getProperty("file.separator") + "ERROR.LOG")); + } catch (IOException e) { + // Failed to write file. + e.printStackTrace(); + } + + } + + /** + * @return the validateOnlinePlayer + */ + public boolean isValidateOnlinePlayer() { + + return validateOnlinePlayer; + } + + /** + * @param validateOnlinePlayer the validateOnlinePlayer to set + */ + public void setValidateOnlinePlayer(boolean validateOnlinePlayer) { + + this.validateOnlinePlayer = validateOnlinePlayer; + } + + public static boolean isLoaded() { + + return isLoaded; + } + + public static void setLoaded(boolean isLoaded) { + + GroupManager.isLoaded = isLoaded; + } + + public InputStream getResourceAsStream(String fileName) { + + return this.getClassLoader().getResourceAsStream(fileName); + } + + private void prepareFileFields() { + + backupFolder = new File(this.getDataFolder(), "backup"); + if (!backupFolder.exists()) { + getBackupFolder().mkdirs(); + } + } + + private void prepareConfig() { + + config = new GMConfiguration(this); + } + + public void enableScheduler() { + + if (worldsHolder != null) { + disableScheduler(); + commiter = new Runnable() { + + @Override + public void run() { + + try { + worldsHolder.saveChanges(false); + GroupManager.logger.log(Level.INFO, " Data files refreshed."); + } catch (IllegalStateException ex) { + GroupManager.logger.log(Level.WARNING, ex.getMessage()); + } + } + }; + scheduler = new ScheduledThreadPoolExecutor(1); + long minutes = (long) getGMConfig().getSaveInterval(); + if (minutes > 0) { + scheduler.scheduleAtFixedRate(commiter, minutes, minutes, TimeUnit.MINUTES); + GroupManager.logger.info("Scheduled Data Saving is set for every " + minutes + " minutes!"); + } else + GroupManager.logger.info("Scheduled Data Saving is Disabled!"); + + GroupManager.logger.info("Backups will be retained for " + getGMConfig().getBackupDuration() + " hours!"); + } + } + + public void disableScheduler() { + + if (scheduler != null) { + try { + scheduler.setContinueExistingPeriodicTasksAfterShutdownPolicy(false); + scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); + scheduler.shutdown(); + } catch (Exception e) { + } + scheduler = null; + GroupManager.logger.info("Scheduled Data Saving is disabled!"); + } + } + + public WorldsHolder getWorldsHolder() { + + return worldsHolder; + } + + /** + * Called when a command registered by this plugin is received. + * + * @param sender + * @param cmd + * @param args + */ + @Override + public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { + + boolean playerCanDo = false; + boolean isConsole = false; + Player senderPlayer = null, targetPlayer = null; + Group senderGroup = null; + User senderUser = null; + boolean isOpOverride = config.isOpOverride(); + + // DETERMINING PLAYER INFORMATION + if (sender instanceof Player) { + senderPlayer = (Player) sender; + + if (!lastError.isEmpty() && !commandLabel.equalsIgnoreCase("manload")) { + sender.sendMessage(ChatColor.RED + "All commands are locked due to an error. Check the log and then try a '/manload'.)"); + return true; + } + + senderUser = worldsHolder.getWorldData(senderPlayer).getUser(senderPlayer.getName()); + senderGroup = senderUser.getGroup(); + isOpOverride = (isOpOverride && (senderPlayer.isOp() || worldsHolder.getWorldPermissions(senderPlayer).has(senderPlayer, "groupmanager.op"))); + + System.out.println("[PLAYER_COMMAND] " + senderPlayer.getName() + ": /" + commandLabel + " " + Tasks.join(args, " ")); + if (isOpOverride || worldsHolder.getWorldPermissions(senderPlayer).has(senderPlayer, "groupmanager." + cmd.getName())) { + playerCanDo = true; + } + } else if (sender instanceof ConsoleCommandSender) { + + if (!lastError.isEmpty() && !commandLabel.equalsIgnoreCase("manload")) { + sender.sendMessage(ChatColor.RED + "All commands are locked due to an error. Check the log and then try a '/manload'.)"); + return true; + } + + isConsole = true; + } + + // PERMISSIONS FOR COMMAND BEING LOADED + dataHolder = null; + permissionHandler = null; + + if (senderPlayer != null) { + dataHolder = worldsHolder.getWorldData(senderPlayer); + } + + String selectedWorld = selectedWorlds.get(sender); + if (selectedWorld != null) { + dataHolder = worldsHolder.getWorldData(selectedWorld); + } + + if (dataHolder != null) { + permissionHandler = dataHolder.getPermissionsHandler(); + } + + // VARIABLES USED IN COMMANDS + + int count; + PermissionCheckResult permissionResult = null; + ArrayList<User> removeList = null; + String auxString = null; + List<String> match = null; + User auxUser = null; + Group auxGroup = null; + Group auxGroup2 = null; + + GroupManagerPermissions execCmd = null; + try { + execCmd = GroupManagerPermissions.valueOf(cmd.getName()); + } catch (Exception e) { + // this error happened once with someone. now im prepared... i think + GroupManager.logger.severe("==================================================="); + GroupManager.logger.severe("= ERROR REPORT START ="); + GroupManager.logger.severe("==================================================="); + GroupManager.logger.severe("= COPY AND PASTE THIS TO A GROUPMANAGER DEVELOPER ="); + GroupManager.logger.severe("==================================================="); + GroupManager.logger.severe(this.getDescription().getName()); + GroupManager.logger.severe(this.getDescription().getVersion()); + GroupManager.logger.severe("An error occured while trying to execute command:"); + GroupManager.logger.severe(cmd.getName()); + GroupManager.logger.severe("With " + args.length + " arguments:"); + for (String ar : args) { + GroupManager.logger.severe(ar); + } + GroupManager.logger.severe("The field '" + cmd.getName() + "' was not found in enum."); + GroupManager.logger.severe("And could not be parsed."); + GroupManager.logger.severe("FIELDS FOUND IN ENUM:"); + for (GroupManagerPermissions val : GroupManagerPermissions.values()) { + GroupManager.logger.severe(val.name()); + } + GroupManager.logger.severe("==================================================="); + GroupManager.logger.severe("= ERROR REPORT ENDED ="); + GroupManager.logger.severe("==================================================="); + sender.sendMessage("An error occurred. Ask the admin to take a look at the console."); + } + + if (isConsole || playerCanDo) { + switch (execCmd) { + case manuadd: + + // Validating arguments + if ((args.length != 2) && (args.length != 3)) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player> <group> | optional [world])"); + return false; + } + + // Select the relevant world (if specified) + if (args.length == 3) { + dataHolder = worldsHolder.getWorldData(args[2]); + permissionHandler = dataHolder.getPermissionsHandler(); + } + + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + auxGroup = dataHolder.getGroup(args[1]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "Group not found!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "Players may not be members of GlobalGroups directly."); + return false; + } + + // Validating permissions + if (!isConsole && !isOpOverride && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "Can't modify a player with the same permissions as you, or higher."); + return false; + } + if (!isConsole && !isOpOverride && (permissionHandler.hasGroupInInheritance(auxGroup, senderGroup.getName()))) { + sender.sendMessage(ChatColor.RED + "The destination group can't be the same as yours, or higher."); + return false; + } + if (!isConsole && !isOpOverride && (!permissionHandler.inGroup(senderUser.getName(), auxUser.getGroupName()) || !permissionHandler.inGroup(senderUser.getName(), auxGroup.getName()))) { + sender.sendMessage(ChatColor.RED + "You can't modify a player involving a group that you don't inherit."); + return false; + } + + // Seems OK + auxUser.setGroup(auxGroup); + if (!sender.hasPermission("groupmanager.notify.other") || (isConsole)) + sender.sendMessage(ChatColor.YELLOW + "You changed player '" + auxUser.getName() + "' group to '" + auxGroup.getName() + "' in world '" + dataHolder.getName() + "'."); + + return true; + + case manudel: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating permission + if (!isConsole && !isOpOverride && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "You can't modify a player with same permissions as you, or higher."); + return false; + } + // Seems OK + dataHolder.removeUser(auxUser.getName()); + sender.sendMessage(ChatColor.YELLOW + "You changed player '" + auxUser.getName() + "' to default settings."); + + // If the player is online, this will create new data for the user. + targetPlayer = this.getServer().getPlayer(auxUser.getName()); + if (targetPlayer != null) + BukkitPermissions.updatePermissions(targetPlayer); + + return true; + + case manuaddsub: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) { + sender.sendMessage(ChatColor.RED + "Couldn't retrieve your world. World selection is needed."); + sender.sendMessage(ChatColor.RED + "Use /manselect <world>"); + return true; + } + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player> <group>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + auxGroup = dataHolder.getGroup(args[1]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "Group not found!"); + return false; + } + // Validating permission + if (!isConsole && !isOpOverride && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "You can't modify a player with same permissions as you, or higher."); + return false; + } + // Seems OK + if (auxUser.addSubGroup(auxGroup)) + sender.sendMessage(ChatColor.YELLOW + "You added subgroup '" + auxGroup.getName() + "' to player '" + auxUser.getName() + "'."); + else + sender.sendMessage(ChatColor.RED + "The subgroup '" + auxGroup.getName() + "' is already available to '" + auxUser.getName() + "'."); + + return true; + + case manudelsub: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/manudelsub <user> <group>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + auxGroup = dataHolder.getGroup(args[1]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "Group not found!"); + return false; + } + + // Validating permission + if (!isConsole && !isOpOverride && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "You can't modify a player with same permissions as you, or higher."); + return false; + } + // Seems OK + auxUser.removeSubGroup(auxGroup); + sender.sendMessage(ChatColor.YELLOW + "You removed subgroup '" + auxGroup.getName() + "' from player '" + auxUser.getName() + "' list."); + + // targetPlayer = this.getServer().getPlayer(auxUser.getName()); + // if (targetPlayer != null) + // BukkitPermissions.updatePermissions(targetPlayer); + + return true; + + case mangadd: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup != null) { + sender.sendMessage(ChatColor.RED + "Group already exists!"); + return false; + } + // Seems OK + auxGroup = dataHolder.createGroup(args[0]); + sender.sendMessage(ChatColor.YELLOW + "You created a group named: " + auxGroup.getName()); + + return true; + + case mangdel: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "Group not exists!"); + return false; + } + // Seems OK + dataHolder.removeGroup(auxGroup.getName()); + sender.sendMessage(ChatColor.YELLOW + "You deleted a group named " + auxGroup.getName() + ", it's users are default group now."); + + BukkitPermissions.updateAllPlayers(); + + return true; + + case manuaddp: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player> <permission>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating your permissions + if (!isConsole && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "Can't modify player with same group than you, or higher."); + return false; + } + permissionResult = permissionHandler.checkFullUserPermission(senderUser, args[1]); + if (!isConsole && !isOpOverride && (permissionResult.resultType.equals(PermissionCheckResult.Type.NOTFOUND) || permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION))) { + sender.sendMessage(ChatColor.RED + "You can't add a permission you don't have."); + return false; + } + // Validating permissions of user + permissionResult = permissionHandler.checkUserOnlyPermission(auxUser, args[1]); + if (args[1].startsWith("+")) { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.EXCEPTION)) { + sender.sendMessage(ChatColor.RED + "The user already has direct access to that permission."); + sender.sendMessage(ChatColor.RED + "Node: " + permissionResult.accessLevel); + return false; + } + } else if (args[1].startsWith("-")) { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.EXCEPTION)) { + sender.sendMessage(ChatColor.RED + "The user already has an exception for this node."); + sender.sendMessage(ChatColor.RED + "Node: " + permissionResult.accessLevel); + return false; + } else if (permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION)) { + sender.sendMessage(ChatColor.RED + "The user already has a matching node "); + sender.sendMessage(ChatColor.RED + "Node: " + permissionResult.accessLevel); + return false; + } + } else { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.FOUND)) { + sender.sendMessage(ChatColor.RED + "The user already has direct access to that permission."); + sender.sendMessage(ChatColor.RED + "Node: " + permissionResult.accessLevel); + return false; + } + } + // Seems OK + auxUser.addPermission(args[1]); + sender.sendMessage(ChatColor.YELLOW + "You added '" + args[1] + "' to player '" + auxUser.getName() + "' permissions."); + + targetPlayer = this.getServer().getPlayer(auxUser.getName()); + if (targetPlayer != null) + BukkitPermissions.updatePermissions(targetPlayer); + + return true; + + case manudelp: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player> <permission>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating your permissions + if (!isConsole && !isOpOverride && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "You can't modify a player with same group as you, or higher."); + return false; + } + permissionResult = permissionHandler.checkFullUserPermission(senderUser, args[1]); + if (!isConsole && !isOpOverride && (permissionResult.resultType.equals(PermissionCheckResult.Type.NOTFOUND) || permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION))) { + sender.sendMessage(ChatColor.RED + "You can't remove a permission you don't have."); + return false; + } + // Validating permissions of user + permissionResult = permissionHandler.checkUserOnlyPermission(auxUser, args[1]); + if (permissionResult.resultType.equals(PermissionCheckResult.Type.NOTFOUND)) { + sender.sendMessage(ChatColor.RED + "The user doesn't have direct access to that permission."); + return false; + } + if (!auxUser.hasSamePermissionNode(args[1])) { + sender.sendMessage(ChatColor.RED + "This permission node doesn't match any node."); + sender.sendMessage(ChatColor.RED + "But might match node: " + permissionResult.accessLevel); + return false; + } + // Seems OK + auxUser.removePermission(args[1]); + sender.sendMessage(ChatColor.YELLOW + "You removed '" + args[1] + "' from player '" + auxUser.getName() + "' permissions."); + + targetPlayer = this.getServer().getPlayer(auxUser.getName()); + if (targetPlayer != null) + BukkitPermissions.updatePermissions(targetPlayer); + + return true; + + case manulistp: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if ((args.length == 0) || (args.length > 2)) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player> (+))"); + return false; + } + + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating permission + // Seems OK + auxString = ""; + for (String perm : auxUser.getPermissionList()) { + auxString += perm + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + sender.sendMessage(ChatColor.YELLOW + "The player '" + auxUser.getName() + "' has following permissions: " + ChatColor.WHITE + auxString); + sender.sendMessage(ChatColor.YELLOW + "And all permissions from group: " + auxUser.getGroupName()); + auxString = ""; + for (String subGroup : auxUser.subGroupListStringCopy()) { + auxString += subGroup + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + sender.sendMessage(ChatColor.YELLOW + "And all permissions from subgroups: " + auxString); + } + } else { + sender.sendMessage(ChatColor.YELLOW + "The player '" + auxUser.getName() + "' has no specific permissions."); + sender.sendMessage(ChatColor.YELLOW + "Only all permissions from group: " + auxUser.getGroupName()); + auxString = ""; + for (String subGroup : auxUser.subGroupListStringCopy()) { + auxString += subGroup + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + sender.sendMessage(ChatColor.YELLOW + "And all permissions from subgroups: " + auxString); + } + } + + // bukkit perms + if ((args.length == 2) && (args[1].equalsIgnoreCase("+"))) { + targetPlayer = this.getServer().getPlayer(auxUser.getName()); + if (targetPlayer != null) { + sender.sendMessage(ChatColor.YELLOW + "Superperms reports: "); + for (String line : BukkitPermissions.listPerms(targetPlayer)) + sender.sendMessage(ChatColor.YELLOW + line); + + } + } + + return true; + + case manucheckp: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player> <permission>)"); + return false; + } + + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + targetPlayer = this.getServer().getPlayer(auxUser.getName()); + // Validating permission + permissionResult = permissionHandler.checkFullGMPermission(auxUser, args[1], false); + + if (permissionResult.resultType.equals(PermissionCheckResult.Type.NOTFOUND)) { + // No permissions found in GM so fall through and check Bukkit. + sender.sendMessage(ChatColor.RED + "The player doesn't have access to that permission"); + + } else { + // This permission was found in groupmanager. + if (permissionResult.owner instanceof User) { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION)) { + sender.sendMessage(ChatColor.RED + "The user has directly a negation node for that permission."); + } else { + sender.sendMessage(ChatColor.YELLOW + "The user has directly this permission."); + } + sender.sendMessage(ChatColor.YELLOW + "Permission Node: " + permissionResult.accessLevel); + } else if (permissionResult.owner instanceof Group) { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION)) { + sender.sendMessage(ChatColor.RED + "The user inherits a negation permission from group: " + permissionResult.owner.getName()); + } else { + sender.sendMessage(ChatColor.YELLOW + "The user inherits the permission from group: " + permissionResult.owner.getName()); + } + sender.sendMessage(ChatColor.YELLOW + "Permission Node: " + permissionResult.accessLevel); + } + } + + // superperms + if (targetPlayer != null) { + sender.sendMessage(ChatColor.YELLOW + "SuperPerms reports Node: " + targetPlayer.hasPermission(args[1]) + ((!targetPlayer.hasPermission(args[1]) && targetPlayer.isPermissionSet(args[1])) ? " (Negated)": "")); + } + + return true; + + case mangaddp: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group> <permission>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "The specified group does not exist!"); + return false; + } + // Validating your permissions + permissionResult = permissionHandler.checkFullUserPermission(senderUser, args[1]); + if (!isConsole && (permissionResult.resultType.equals(PermissionCheckResult.Type.NOTFOUND) || permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION))) { + sender.sendMessage(ChatColor.RED + "You can't add a permission you don't have."); + return false; + } + // Validating permissions of user + permissionResult = permissionHandler.checkGroupOnlyPermission(auxGroup, args[1]); + if (args[1].startsWith("+")) { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.EXCEPTION)) { + sender.sendMessage(ChatColor.RED + "The group already has direct access to that permission."); + sender.sendMessage(ChatColor.RED + "Node: " + permissionResult.accessLevel); + return false; + } + } else if (args[1].startsWith("-")) { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.EXCEPTION)) { + sender.sendMessage(ChatColor.RED + "The group already has an exception for this node."); + sender.sendMessage(ChatColor.RED + "Node: " + permissionResult.accessLevel); + return false; + } else if (permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION)) { + sender.sendMessage(ChatColor.RED + "The group already has a matching node."); + sender.sendMessage(ChatColor.RED + "Node: " + permissionResult.accessLevel); + return false; + } + } else { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.FOUND)) { + sender.sendMessage(ChatColor.RED + "The group already has direct access to that permission."); + sender.sendMessage(ChatColor.RED + "Node: " + permissionResult.accessLevel); + return false; + } + } + // Seems OK + auxGroup.addPermission(args[1]); + sender.sendMessage(ChatColor.YELLOW + "You added '" + args[1] + "' to group '" + auxGroup.getName() + "' permissions."); + + BukkitPermissions.updateAllPlayers(); + + return true; + + case mangdelp: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group> <permission>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "The specified group does not exist!"); + return false; + } + // Validating your permissions + permissionResult = permissionHandler.checkFullUserPermission(senderUser, args[1]); + if (!isConsole && (permissionResult.resultType.equals(PermissionCheckResult.Type.NOTFOUND) || permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION))) { + sender.sendMessage(ChatColor.RED + "Can't remove a permission you don't have."); + return false; + } + // Validating permissions of user + permissionResult = permissionHandler.checkGroupOnlyPermission(auxGroup, args[1]); + if (permissionResult.resultType.equals(PermissionCheckResult.Type.NOTFOUND)) { + sender.sendMessage(ChatColor.RED + "The group doesn't have direct access to that permission."); + return false; + } + if (!auxGroup.hasSamePermissionNode(args[1])) { + sender.sendMessage(ChatColor.RED + "This permission node doesn't match any node."); + sender.sendMessage(ChatColor.RED + "But might match node: " + permissionResult.accessLevel); + return false; + } + // Seems OK + auxGroup.removePermission(args[1]); + sender.sendMessage(ChatColor.YELLOW + "You removed '" + args[1] + "' from group '" + auxGroup.getName() + "' permissions."); + + BukkitPermissions.updateAllPlayers(); + + return true; + + case manglistp: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "The specified group does not exist!"); + return false; + } + // Validating permission + + // Seems OK + auxString = ""; + for (String perm : auxGroup.getPermissionList()) { + auxString += perm + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + sender.sendMessage(ChatColor.YELLOW + "The group '" + auxGroup.getName() + "' has following permissions: " + ChatColor.WHITE + auxString); + auxString = ""; + for (String grp : auxGroup.getInherits()) { + auxString += grp + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + sender.sendMessage(ChatColor.YELLOW + "And all permissions from groups: " + auxString); + } + + } else { + sender.sendMessage(ChatColor.YELLOW + "The group '" + auxGroup.getName() + "' has no specific permissions."); + auxString = ""; + for (String grp : auxGroup.getInherits()) { + auxString += grp + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + sender.sendMessage(ChatColor.YELLOW + "Only all permissions from groups: " + auxString); + } + + } + return true; + + case mangcheckp: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group> <permission>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "The specified group does not exist!"); + return false; + } + // Validating permission + permissionResult = permissionHandler.checkGroupPermissionWithInheritance(auxGroup, args[1]); + if (permissionResult.resultType.equals(PermissionCheckResult.Type.NOTFOUND)) { + sender.sendMessage(ChatColor.RED + "The group doesn't have access to that permission"); + return false; + } + // Seems OK + // auxString = permissionHandler.checkUserOnlyPermission(auxUser, args[1]); + if (permissionResult.owner instanceof Group) { + if (permissionResult.resultType.equals(PermissionCheckResult.Type.NEGATION)) { + sender.sendMessage(ChatColor.RED + "The group inherits the a negation permission from group: " + permissionResult.owner.getName()); + } else { + sender.sendMessage(ChatColor.YELLOW + "The user inherits the permission from group: " + permissionResult.owner.getName()); + } + sender.sendMessage(ChatColor.YELLOW + "Permission Node: " + permissionResult.accessLevel); + + } + return true; + + case mangaddi: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group1> <group2>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "Group 1 does not exist!"); + return false; + } + auxGroup2 = dataHolder.getGroup(args[1]); + if (auxGroup2 == null) { + sender.sendMessage(ChatColor.RED + "Group 2 does not exist!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "GlobalGroups do NOT support inheritance."); + return false; + } + + // Validating permission + if (permissionHandler.hasGroupInInheritance(auxGroup, auxGroup2.getName())) { + sender.sendMessage(ChatColor.RED + "Group " + auxGroup.getName() + " already inherits " + auxGroup2.getName() + " (might not be directly)"); + return false; + } + // Seems OK + auxGroup.addInherits(auxGroup2); + sender.sendMessage(ChatColor.RED + "Group " + auxGroup2.getName() + " is now in " + auxGroup.getName() + " inheritance list."); + + BukkitPermissions.updateAllPlayers(); + + return true; + + case mangdeli: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group1> <group2>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "Group 1 does not exist!"); + return false; + } + auxGroup2 = dataHolder.getGroup(args[1]); + if (auxGroup2 == null) { + sender.sendMessage(ChatColor.RED + "Group 2 does not exist!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "GlobalGroups do NOT support inheritance."); + return false; + } + + // Validating permission + if (!permissionHandler.hasGroupInInheritance(auxGroup, auxGroup2.getName())) { + sender.sendMessage(ChatColor.RED + "Group " + auxGroup.getName() + " does not inherits " + auxGroup2.getName() + "."); + return false; + } + if (!auxGroup.getInherits().contains(auxGroup2.getName())) { + sender.sendMessage(ChatColor.RED + "Group " + auxGroup.getName() + " does not inherits " + auxGroup2.getName() + " directly."); + return false; + } + // Seems OK + auxGroup.removeInherits(auxGroup2.getName()); + sender.sendMessage(ChatColor.RED + "Group " + auxGroup2.getName() + " was removed from " + auxGroup.getName() + " inheritance list."); + + BukkitPermissions.updateAllPlayers(); + + return true; + + case manuaddv: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length < 3) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <user> <variable> <value>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating permission + // Seems OK + auxString = ""; + for (int i = 2; i < args.length; i++) { + auxString += args[i]; + if ((i + 1) < args.length) { + auxString += " "; + } + } + auxUser.getVariables().addVar(args[1], Variables.parseVariableValue(auxString)); + sender.sendMessage(ChatColor.YELLOW + "Variable " + ChatColor.GOLD + args[1] + ChatColor.YELLOW + ":'" + ChatColor.GREEN + auxString + ChatColor.YELLOW + "' added to the user " + auxUser.getName()); + + return true; + + case manudelv: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <user> <variable>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating permission + if (!auxUser.getVariables().hasVar(args[1])) { + sender.sendMessage(ChatColor.RED + "The user doesn't have directly that variable!"); + } + // Seems OK + auxUser.getVariables().removeVar(args[1]); + sender.sendMessage(ChatColor.YELLOW + "Variable " + ChatColor.GOLD + args[1] + ChatColor.YELLOW + " removed from the user " + ChatColor.GREEN + auxUser.getName()); + + return true; + + case manulistv: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <user>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating permission + // Seems OK + auxString = ""; + for (String varKey : auxUser.getVariables().getVarKeyList()) { + Object o = auxUser.getVariables().getVarObject(varKey); + auxString += ChatColor.GOLD + varKey + ChatColor.WHITE + ":'" + ChatColor.GREEN + o.toString() + ChatColor.WHITE + "', "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + } + sender.sendMessage(ChatColor.YELLOW + "Variables of user " + auxUser.getName() + ": "); + sender.sendMessage(auxString + "."); + sender.sendMessage(ChatColor.YELLOW + "Plus all variables from group: " + auxUser.getGroupName()); + + return true; + + case manucheckv: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <user> <variable>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating permission + auxGroup = auxUser.getGroup(); + auxGroup2 = permissionHandler.nextGroupWithVariable(auxGroup, args[1]); + + if (!auxUser.getVariables().hasVar(args[1])) { + // Check sub groups + if (!auxUser.isSubGroupsEmpty() && auxGroup2 == null) + for (Group subGroup : auxUser.subGroupListCopy()) { + auxGroup2 = permissionHandler.nextGroupWithVariable(subGroup, args[1]); + if (auxGroup2 != null) + continue; + } + if (auxGroup2 == null) { + sender.sendMessage(ChatColor.RED + "The user doesn't have access to that variable!"); + return false; + } + } + // Seems OK + if (auxUser.getVariables().hasVar(auxString)) { + sender.sendMessage(ChatColor.YELLOW + "The value of variable '" + ChatColor.GOLD + args[1] + ChatColor.YELLOW + "' is: '" + ChatColor.GREEN + auxUser.getVariables().getVarObject(args[1]).toString() + ChatColor.WHITE + "'"); + sender.sendMessage(ChatColor.YELLOW + "This user own directly the variable"); + } + sender.sendMessage(ChatColor.YELLOW + "The value of variable '" + ChatColor.GOLD + args[1] + ChatColor.YELLOW + "' is: '" + ChatColor.GREEN + auxGroup2.getVariables().getVarObject(args[1]).toString() + ChatColor.WHITE + "'"); + if (!auxGroup.equals(auxGroup2)) { + sender.sendMessage(ChatColor.YELLOW + "And the value was inherited from group: " + ChatColor.GREEN + auxGroup2.getName()); + } + + return true; + + case mangaddv: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length < 3) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group> <variable> <value>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "The specified group does not exist!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "GlobalGroups do NOT support Info Nodes."); + return false; + } + // Validating permission + // Seems OK + auxString = ""; + for (int i = 2; i < args.length; i++) { + auxString += args[i]; + if ((i + 1) < args.length) { + auxString += " "; + } + } + auxGroup.getVariables().addVar(args[1], Variables.parseVariableValue(auxString)); + sender.sendMessage(ChatColor.YELLOW + "Variable " + ChatColor.GOLD + args[1] + ChatColor.YELLOW + ":'" + ChatColor.GREEN + auxString + ChatColor.YELLOW + "' added to the group " + auxGroup.getName()); + + return true; + + case mangdelv: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group> <variable>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "The specified group does not exist!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "GlobalGroups do NOT support Info Nodes."); + return false; + } + // Validating permission + if (!auxGroup.getVariables().hasVar(args[1])) { + sender.sendMessage(ChatColor.RED + "The group doesn't have directly that variable!"); + } + // Seems OK + auxGroup.getVariables().removeVar(args[1]); + sender.sendMessage(ChatColor.YELLOW + "Variable " + ChatColor.GOLD + args[1] + ChatColor.YELLOW + " removed from the group " + ChatColor.GREEN + auxGroup.getName()); + + return true; + + case manglistv: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "The specified group does not exist!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "GlobalGroups do NOT support Info Nodes."); + return false; + } + // Validating permission + // Seems OK + auxString = ""; + for (String varKey : auxGroup.getVariables().getVarKeyList()) { + Object o = auxGroup.getVariables().getVarObject(varKey); + auxString += ChatColor.GOLD + varKey + ChatColor.WHITE + ":'" + ChatColor.GREEN + o.toString() + ChatColor.WHITE + "', "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + } + sender.sendMessage(ChatColor.YELLOW + "Variables of group " + auxGroup.getName() + ": "); + sender.sendMessage(auxString + "."); + auxString = ""; + for (String grp : auxGroup.getInherits()) { + auxString += grp + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + sender.sendMessage(ChatColor.YELLOW + "Plus all variables from groups: " + auxString); + } + + return true; + + case mangcheckv: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <group> <variable>)"); + return false; + } + auxGroup = dataHolder.getGroup(args[0]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "The specified group does not exist!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "GlobalGroups do NOT support Info Nodes."); + return false; + } + // Validating permission + auxGroup2 = permissionHandler.nextGroupWithVariable(auxGroup, args[1]); + if (auxGroup2 == null) { + sender.sendMessage(ChatColor.RED + "The group doesn't have access to that variable!"); + } + // Seems OK + sender.sendMessage(ChatColor.YELLOW + "The value of variable '" + ChatColor.GOLD + args[1] + ChatColor.YELLOW + "' is: '" + ChatColor.GREEN + auxGroup2.getVariables().getVarObject(args[1]).toString() + ChatColor.WHITE + "'"); + if (!auxGroup.equals(auxGroup2)) { + sender.sendMessage(ChatColor.YELLOW + "And the value was inherited from group: " + ChatColor.GREEN + auxGroup2.getName()); + } + + return true; + + case manwhois: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Seems OK + sender.sendMessage(ChatColor.YELLOW + "Name: " + ChatColor.GREEN + auxUser.getName()); + sender.sendMessage(ChatColor.YELLOW + "Group: " + ChatColor.GREEN + auxUser.getGroup().getName()); + // Compile a list of subgroups + auxString = ""; + for (String subGroup : auxUser.subGroupListStringCopy()) { + auxString += subGroup + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + sender.sendMessage(ChatColor.YELLOW + "subgroups: " + auxString); + } + + sender.sendMessage(ChatColor.YELLOW + "Overloaded: " + ChatColor.GREEN + dataHolder.isOverloaded(auxUser.getName())); + auxGroup = dataHolder.surpassOverload(auxUser.getName()).getGroup(); + if (!auxGroup.equals(auxUser.getGroup())) { + sender.sendMessage(ChatColor.YELLOW + "Original Group: " + ChatColor.GREEN + auxGroup.getName()); + } + // victim.permissions.add(args[1]); + return true; + + case tempadd: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating permission + if (!isConsole && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "Can't modify player with same permissions than you, or higher."); + return false; + } + // Seems OK + if (overloadedUsers.get(dataHolder.getName().toLowerCase()) == null) { + overloadedUsers.put(dataHolder.getName().toLowerCase(), new ArrayList<User>()); + } + dataHolder.overloadUser(auxUser.getName()); + overloadedUsers.get(dataHolder.getName().toLowerCase()).add(dataHolder.getUser(auxUser.getName())); + sender.sendMessage(ChatColor.YELLOW + "Player overloaded!"); + + return true; + + case tempdel: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + // Validating permission + if (!isConsole && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "You can't modify a player with same permissions as you, or higher."); + return false; + } + // Seems OK + if (overloadedUsers.get(dataHolder.getName().toLowerCase()) == null) { + overloadedUsers.put(dataHolder.getName().toLowerCase(), new ArrayList<User>()); + } + dataHolder.removeOverload(auxUser.getName()); + if (overloadedUsers.get(dataHolder.getName().toLowerCase()).contains(auxUser)) { + overloadedUsers.get(dataHolder.getName().toLowerCase()).remove(auxUser); + } + sender.sendMessage(ChatColor.YELLOW + "You removed that player's overload. He's back to normal!"); + + return true; + + case templist: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // WORKING + auxString = ""; + removeList = new ArrayList<User>(); + count = 0; + for (User u : overloadedUsers.get(dataHolder.getName().toLowerCase())) { + if (!dataHolder.isOverloaded(u.getName())) { + removeList.add(u); + } else { + auxString += u.getName() + ", "; + count++; + } + } + if (count == 0) { + sender.sendMessage(ChatColor.YELLOW + "There are no users in overload mode."); + return true; + } + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + if (overloadedUsers.get(dataHolder.getName().toLowerCase()) == null) { + overloadedUsers.put(dataHolder.getName().toLowerCase(), new ArrayList<User>()); + } + overloadedUsers.get(dataHolder.getName().toLowerCase()).removeAll(removeList); + sender.sendMessage(ChatColor.YELLOW + " " + count + " Users in overload mode: " + ChatColor.WHITE + auxString); + + return true; + + case tempdelall: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // WORKING + removeList = new ArrayList<User>(); + count = 0; + for (User u : overloadedUsers.get(dataHolder.getName().toLowerCase())) { + if (dataHolder.isOverloaded(u.getName())) { + dataHolder.removeOverload(u.getName()); + count++; + } + } + if (count == 0) { + sender.sendMessage(ChatColor.YELLOW + "There are no users in overload mode."); + return true; + } + if (overloadedUsers.get(dataHolder.getName().toLowerCase()) == null) { + overloadedUsers.put(dataHolder.getName().toLowerCase(), new ArrayList<User>()); + } + overloadedUsers.get(dataHolder.getName().toLowerCase()).clear(); + sender.sendMessage(ChatColor.YELLOW + " " + count + "All users in overload mode are now normal again."); + + return true; + + case mansave: + + boolean forced = false; + + if ((args.length == 1) && (args[0].equalsIgnoreCase("force"))) + forced = true; + + try { + worldsHolder.saveChanges(forced); + sender.sendMessage(ChatColor.YELLOW + " All changes were saved."); + } catch (IllegalStateException ex) { + sender.sendMessage(ChatColor.RED + ex.getMessage()); + } + return true; + + case manload: + + /** + * Attempt to reload a specific world + */ + if (args.length > 0) { + + if (!lastError.isEmpty()) { + sender.sendMessage(ChatColor.RED + "All commands are locked due to an error. Check the log and then try a '/manload'.)"); + return true; + } + + auxString = ""; + for (int i = 0; i < args.length; i++) { + auxString += args[i]; + if ((i + 1) < args.length) { + auxString += " "; + } + } + + isLoaded = false; // Disable Bukkit Perms update and event triggers + + globalGroups.load(); + worldsHolder.loadWorld(auxString); + + sender.sendMessage("The request to reload world '" + auxString + "' was attempted."); + + isLoaded = true; + + BukkitPermissions.updateAllPlayers(); + + } else { + + /** + * Reload all settings and data as no world was specified. + */ + + /* + * Attempting a fresh load. + */ + onDisable(true); + onEnable(true); + + sender.sendMessage("All settings and worlds were reloaded!"); + } + + /** + * Fire an event as none will have been triggered in the reload. + */ + if (GroupManager.isLoaded()) + GroupManagerEventHandler.callEvent(GMSystemEvent.Action.RELOADED); + + return true; + + case listgroups: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // WORKING + auxString = ""; + for (Group g : dataHolder.getGroupList()) { + auxString += g.getName() + ", "; + } + for (Group g : getGlobalGroups().getGroupList()) { + auxString += g.getName() + ", "; + } + if (auxString.lastIndexOf(",") > 0) { + auxString = auxString.substring(0, auxString.lastIndexOf(",")); + } + sender.sendMessage(ChatColor.YELLOW + " Groups Available: " + ChatColor.WHITE + auxString); + + return true; + + case manpromote: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player> <group>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + auxGroup = dataHolder.getGroup(args[1]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "Group not found!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "Players may not be members of GlobalGroups directly."); + return false; + } + // Validating permission + if (!isConsole && !isOpOverride && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "You can't modify a player with same permissions as you, or higher."); + return false; + } + if (!isConsole && !isOpOverride && (permissionHandler.hasGroupInInheritance(auxGroup, senderGroup.getName()))) { + sender.sendMessage(ChatColor.RED + "The destination group can't be the same as yours, or higher."); + return false; + } + if (!isConsole && !isOpOverride && (!permissionHandler.inGroup(senderUser.getName(), auxUser.getGroupName()) || !permissionHandler.inGroup(senderUser.getName(), auxGroup.getName()))) { + sender.sendMessage(ChatColor.RED + "You can't modify a player involving a group that you don't inherit."); + return false; + } + if (!isConsole && !isOpOverride && (!permissionHandler.hasGroupInInheritance(auxUser.getGroup(), auxGroup.getName()) && !permissionHandler.hasGroupInInheritance(auxGroup, auxUser.getGroupName()))) { + sender.sendMessage(ChatColor.RED + "You can't modify a player using groups with different heritage line."); + return false; + } + if (!isConsole && !isOpOverride && (!permissionHandler.hasGroupInInheritance(auxGroup, auxUser.getGroupName()))) { + sender.sendMessage(ChatColor.RED + "The new group must be a higher rank."); + return false; + } + // Seems OK + auxUser.setGroup(auxGroup); + if (!sender.hasPermission("groupmanager.notify.other") || (isConsole)) + sender.sendMessage(ChatColor.YELLOW + "You changed " + auxUser.getName() + " group to " + auxGroup.getName() + "."); + + return true; + + case mandemote: + // Validating state of sender + if (dataHolder == null || permissionHandler == null) { + if (!setDefaultWorldHandler(sender)) + return true; + } + // Validating arguments + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <player> <group>)"); + return false; + } + if ((validateOnlinePlayer) && ((match = validatePlayer(args[0], sender)) == null)) { + return false; + } + if (match != null) { + auxUser = dataHolder.getUser(match.get(0)); + } else { + auxUser = dataHolder.getUser(args[0]); + } + auxGroup = dataHolder.getGroup(args[1]); + if (auxGroup == null) { + sender.sendMessage(ChatColor.RED + "Group not found!"); + return false; + } + if (auxGroup.isGlobal()) { + sender.sendMessage(ChatColor.RED + "Players may not be members of GlobalGroups directly."); + return false; + } + // Validating permission + if (!isConsole && !isOpOverride && (senderGroup != null ? permissionHandler.inGroup(auxUser.getName(), senderGroup.getName()) : false)) { + sender.sendMessage(ChatColor.RED + "You can't modify a player with same permissions as you, or higher."); + return false; + } + if (!isConsole && !isOpOverride && (permissionHandler.hasGroupInInheritance(auxGroup, senderGroup.getName()))) { + sender.sendMessage(ChatColor.RED + "The destination group can't be the same as yours, or higher."); + return false; + } + if (!isConsole && !isOpOverride && (!permissionHandler.inGroup(senderUser.getName(), auxUser.getGroupName()) || !permissionHandler.inGroup(senderUser.getName(), auxGroup.getName()))) { + sender.sendMessage(ChatColor.RED + "You can't modify a player involving a group that you don't inherit."); + return false; + } + if (!isConsole && !isOpOverride && (!permissionHandler.hasGroupInInheritance(auxUser.getGroup(), auxGroup.getName()) && !permissionHandler.hasGroupInInheritance(auxGroup, auxUser.getGroupName()))) { + sender.sendMessage(ChatColor.RED + "You can't modify a player using groups with different heritage line."); + return false; + } + if (!isConsole && !isOpOverride && (permissionHandler.hasGroupInInheritance(auxGroup, auxUser.getGroupName()))) { + sender.sendMessage(ChatColor.RED + "The new group must be a lower rank."); + return false; + } + // Seems OK + auxUser.setGroup(auxGroup); + if (!sender.hasPermission("groupmanager.notify.other") || (isConsole)) + sender.sendMessage(ChatColor.YELLOW + "You changed " + auxUser.getName() + " group to " + auxGroup.getName() + "."); + + return true; + + case mantogglevalidate: + validateOnlinePlayer = !validateOnlinePlayer; + sender.sendMessage(ChatColor.YELLOW + "Validade if player is online, now set to: " + Boolean.toString(validateOnlinePlayer)); + if (!validateOnlinePlayer) { + sender.sendMessage(ChatColor.GOLD + "From now on you can edit players not connected... BUT:"); + sender.sendMessage(ChatColor.LIGHT_PURPLE + "From now on you should type the whole name of the player, correctly."); + } + return true; + case mantogglesave: + if (scheduler == null) { + enableScheduler(); + sender.sendMessage(ChatColor.YELLOW + "The auto-saving is enabled!"); + } else { + disableScheduler(); + sender.sendMessage(ChatColor.YELLOW + "The auto-saving is disabled!"); + } + return true; + case manworld: + auxString = selectedWorlds.get(sender); + if (auxString != null) { + sender.sendMessage(ChatColor.YELLOW + "You have the world '" + dataHolder.getName() + "' in your selection."); + } else { + if (dataHolder == null) { + sender.sendMessage(ChatColor.YELLOW + "There is no world selected. And no world is available now."); + } else { + sender.sendMessage(ChatColor.YELLOW + "You don't have a world in your selection.."); + sender.sendMessage(ChatColor.YELLOW + "Working with the direct world where your player is."); + sender.sendMessage(ChatColor.YELLOW + "Your world now uses permissions of world name: '" + dataHolder.getName() + "' "); + } + } + + return true; + + case manselect: + if (args.length < 1) { + sender.sendMessage(ChatColor.RED + "Review your arguments count! (/<command> <world>)"); + sender.sendMessage(ChatColor.YELLOW + "Worlds available: "); + ArrayList<OverloadedWorldHolder> worlds = worldsHolder.allWorldsDataList(); + auxString = ""; + for (int i = 0; i < worlds.size(); i++) { + auxString += worlds.get(i).getName(); + if ((i + 1) < worlds.size()) { + auxString += ", "; + } + } + sender.sendMessage(ChatColor.YELLOW + auxString); + return false; + } + auxString = ""; + for (int i = 0; i < args.length; i++) { + if (args[i] == null) { + logger.warning("Bukkit gave invalid arguments array! Cmd: " + cmd.getName() + " args.length: " + args.length); + return false; + } + auxString += args[i]; + if (i < (args.length - 1)) { + auxString += " "; + } + } + dataHolder = worldsHolder.getWorldData(auxString); + permissionHandler = dataHolder.getPermissionsHandler(); + selectedWorlds.put(sender, dataHolder.getName()); + sender.sendMessage(ChatColor.YELLOW + "You have selected world '" + dataHolder.getName() + "'."); + + return true; + + case manclear: + if (args.length != 0) { + sender.sendMessage(ChatColor.RED + "Review your arguments count!"); + return false; + } + selectedWorlds.remove(sender); + sender.sendMessage(ChatColor.YELLOW + "You have removed your world selection. Working with current world(if possible)."); + + return true; + + default: + break; + } + } + sender.sendMessage(ChatColor.RED + "You are not allowed to use that command."); + return false; + } + + /** + * Sets up the default world for use. + */ + private boolean setDefaultWorldHandler(CommandSender sender) { + + dataHolder = worldsHolder.getWorldData(worldsHolder.getDefaultWorld().getName()); + permissionHandler = dataHolder.getPermissionsHandler(); + + if ((dataHolder != null) && (permissionHandler != null)) { + selectedWorlds.put(sender, dataHolder.getName()); + sender.sendMessage(ChatColor.RED + "Couldn't retrieve your world. Default world '" + worldsHolder.getDefaultWorld().getName() + "' selected."); + return true; + } + + sender.sendMessage(ChatColor.RED + "Couldn't retrieve your world. World selection is needed."); + sender.sendMessage(ChatColor.RED + "Use /manselect <world>"); + return false; + + } + + /** + * Send confirmation of a group change. using permission nodes... + * + * groupmanager.notify.self groupmanager.notify.other + * + * @param name + * @param msg + */ + public static void notify(String name, String msg) { + + Player player = Bukkit.getServer().getPlayerExact(name); + + for (Player test : Bukkit.getServer().getOnlinePlayers()) { + if (!test.equals(player)) { + if (test.hasPermission("groupmanager.notify.other")) + test.sendMessage(ChatColor.YELLOW + name + " was" + msg); + } else if ((player != null) && ((player.hasPermission("groupmanager.notify.self")) || (player.hasPermission("groupmanager.notify.other")))) + player.sendMessage(ChatColor.YELLOW + "You were" + msg); + } + + } + + /** + * Load a List of players matching the name given. If none online, check + * Offline. + * + * @param playerName, sender + * @return true if a single match is found + */ + private List<String> validatePlayer(String playerName, CommandSender sender) { + + List<Player> players = new ArrayList<Player>(); + List<String> match = new ArrayList<String>(); + + players = this.getServer().matchPlayer(playerName); + if (players.isEmpty()) { + // Check for an offline player (exact match). + if (Arrays.asList(this.getServer().getOfflinePlayers()).contains(Bukkit.getOfflinePlayer(playerName))) { + match.add(playerName); + } else { + // look for partial matches + for (OfflinePlayer offline : this.getServer().getOfflinePlayers()) { + if (offline.getName().toLowerCase().startsWith(playerName.toLowerCase())) + match.add(offline.getName()); + } + } + + } else { + for (Player player : players) { + match.add(player.getName()); + } + } + + if (match.isEmpty() || match == null) { + sender.sendMessage(ChatColor.RED + "Player not found!"); + return null; + } else if (match.size() > 1) { + sender.sendMessage(ChatColor.RED + "Too many matches found! (" + match.toString() + ")"); + return null; + } + + return match; + + } + + /** + * @return the config + */ + public GMConfiguration getGMConfig() { + + return config; + } + + /** + * @return the backupFolder + */ + public File getBackupFolder() { + + return backupFolder; + } + + public static GlobalGroups getGlobalGroups() { + + return globalGroups; + + } +}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/Tasks/BukkitPermsUpdateTask.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/Tasks/BukkitPermsUpdateTask.java new file mode 100644 index 000000000..1a0fc2369 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/Tasks/BukkitPermsUpdateTask.java @@ -0,0 +1,29 @@ +package org.anjocaido.groupmanager.Tasks;
+
+import org.anjocaido.groupmanager.GroupManager;
+
+/*
+ *
+ * Created by ElgarL
+ */
+
+public class BukkitPermsUpdateTask implements Runnable {
+
+ public BukkitPermsUpdateTask() {
+
+ super();
+ }
+
+ @Override
+ public void run() {
+
+ // Signal loaded and update BukkitPermissions.
+ GroupManager.setLoaded(true);
+ GroupManager.BukkitPermissions.collectPermissions();
+ GroupManager.BukkitPermissions.updateAllPlayers();
+
+ GroupManager.logger.info("Bukkit Permissions Updated!");
+
+ }
+
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java new file mode 100644 index 000000000..bb04fa3d7 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java @@ -0,0 +1,181 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.data; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.anjocaido.groupmanager.GroupManager; +import org.anjocaido.groupmanager.dataholder.WorldDataHolder; +import org.anjocaido.groupmanager.utils.StringPermissionComparator; + +/** + * + * @author gabrielcouto + */ +public abstract class DataUnit { + + private WorldDataHolder dataSource; + private String name; + private boolean changed, sorted = false; + private ArrayList<String> permissions = new ArrayList<String>(); + + public DataUnit(WorldDataHolder dataSource, String name) { + + this.dataSource = dataSource; + this.name = name; + } + + public DataUnit(String name) { + + this.name = name; + } + + /** + * Every group is matched only by their names and DataSources names. + * + * @param o + * @return true if they are equal. false if not. + */ + @Override + public boolean equals(Object o) { + + if (o instanceof DataUnit) { + DataUnit go = (DataUnit) o; + if (this.getName().equalsIgnoreCase(go.getName())) { + // Global Group match. + if (this.dataSource == null && go.getDataSource() == null) + return true; + // This is a global group, the object to test isn't. + if (this.dataSource == null && go.getDataSource() != null) + return false; + // This is not a global group, but the object to test is. + if (this.dataSource != null && go.getDataSource() == null) + return false; + // Match on group name and world name. + if (this.dataSource.getName().equalsIgnoreCase(go.getDataSource().getName())) + return true; + } + } + return false; + } + + @Override + public int hashCode() { + + int hash = 5; + hash = 71 * hash + (this.name != null ? this.name.toLowerCase().hashCode() : 0); + return hash; + } + + /** + * Set the data source to point to a different worldDataHolder + * + * @param source + */ + public void setDataSource(WorldDataHolder source) { + + this.dataSource = source; + } + + /** + * Get the current worldDataHolder this object is pointing to + * + * @return the dataSource + */ + public WorldDataHolder getDataSource() { + + return dataSource; + } + + /** + * @return the name + */ + public String getName() { + + return name; + } + + public void flagAsChanged() { + + WorldDataHolder testSource = getDataSource(); + String source = ""; + + if (testSource == null) + source = "GlobalGroups"; + else + source = testSource.getName(); + + GroupManager.logger.finest("DataSource: " + source + " - DataUnit: " + getName() + " flagged as changed!"); + // for(StackTraceElement st: Thread.currentThread().getStackTrace()){ + // GroupManager.logger.finest(st.toString()); + // } + sorted = false; + changed = true; + } + + public boolean isChanged() { + + return changed; + } + + public void flagAsSaved() { + + WorldDataHolder testSource = getDataSource(); + String source = ""; + + if (testSource == null) + source = "GlobalGroups"; + else + source = testSource.getName(); + + GroupManager.logger.finest("DataSource: " + source + " - DataUnit: " + getName() + " flagged as saved!"); + changed = false; + } + + public boolean hasSamePermissionNode(String permission) { + + return permissions.contains(permission); + } + + public void addPermission(String permission) { + + if (!hasSamePermissionNode(permission)) { + permissions.add(permission); + } + flagAsChanged(); + } + + public boolean removePermission(String permission) { + + flagAsChanged(); + return permissions.remove(permission); + } + + /** + * Use this only to list permissions. + * You can't edit the permissions using the returned ArrayList instance + * + * @return a copy of the permission list + */ + public List<String> getPermissionList() { + + return Collections.unmodifiableList(permissions); + } + + public boolean isSorted() { + + return this.sorted; + } + + public void sortPermissions() { + + if (!isSorted()) { + Collections.sort(permissions, StringPermissionComparator.getInstance()); + sorted = true; + } + } +}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/Group.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/Group.java new file mode 100644 index 000000000..751dc8fd6 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/Group.java @@ -0,0 +1,187 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.data; + +import org.anjocaido.groupmanager.GroupManager; +import org.anjocaido.groupmanager.dataholder.WorldDataHolder; +import org.anjocaido.groupmanager.events.GMGroupEvent.Action; +import org.anjocaido.groupmanager.events.GroupManagerEventHandler; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * + * @author gabrielcouto/ElgarL + */ +public class Group extends DataUnit implements Cloneable { + + /** + * The group it inherits DIRECTLY! + */ + private ArrayList<String> inherits = new ArrayList<String>(); + /** + * This one holds the fields in INFO node. + * like prefix = 'c' + * or build = false + */ + private GroupVariables variables = new GroupVariables(this); + + /** + * Constructor for individual World Groups. + * + * @param name + */ + public Group(WorldDataHolder source, String name) { + + super(source, name); + } + + /** + * Constructor for Global Groups. + * + * @param name + */ + public Group(String name) { + + super(name); + } + + /** + * Is this a GlobalGroup + * + * @return true if this is a global group + */ + public boolean isGlobal() { + + return (getDataSource() == null); + } + + /** + * Clone this group + * + * @return a clone of this group + */ + @Override + public Group clone() { + + Group clone; + + if (isGlobal()) { + clone = new Group(this.getName()); + } else { + clone = new Group(getDataSource(), this.getName()); + clone.inherits = new ArrayList<String>(this.getInherits()); + } + + for (String perm : this.getPermissionList()) { + clone.addPermission(perm); + } + clone.variables = ((GroupVariables) variables).clone(clone); + //clone.flagAsChanged(); + return clone; + } + + /** + * Use this to deliver a group from a different dataSource to another + * + * @param dataSource + * @return Null or Clone + */ + public Group clone(WorldDataHolder dataSource) { + + if (dataSource.groupExists(this.getName())) { + return null; + } + + Group clone = dataSource.createGroup(this.getName()); + + // Don't add inheritance for GlobalGroups + if (!isGlobal()) { + clone.inherits = new ArrayList<String>(this.getInherits()); + } + for (String perm : this.getPermissionList()) { + clone.addPermission(perm); + } + clone.variables = variables.clone(clone); + clone.flagAsChanged(); //use this to make the new dataSource save the new group + return clone; + } + + /** + * an unmodifiable list of inherits list + * You can't manage the list by here + * Lol... version 0.6 had a problem because this. + * + * @return the inherits + */ + public List<String> getInherits() { + + return Collections.unmodifiableList(inherits); + } + + /** + * @param inherit the inherits to set + */ + public void addInherits(Group inherit) { + + if (!isGlobal()) { + if (!this.getDataSource().groupExists(inherit.getName())) { + getDataSource().addGroup(inherit); + } + if (!inherits.contains(inherit.getName().toLowerCase())) { + inherits.add(inherit.getName().toLowerCase()); + } + flagAsChanged(); + if (GroupManager.isLoaded()) { + GroupManager.BukkitPermissions.updateAllPlayers(); + GroupManagerEventHandler.callEvent(this, Action.GROUP_INHERITANCE_CHANGED); + } + } + } + + public boolean removeInherits(String inherit) { + + if (!isGlobal()) { + if (this.inherits.contains(inherit.toLowerCase())) { + this.inherits.remove(inherit.toLowerCase()); + flagAsChanged(); + GroupManagerEventHandler.callEvent(this, Action.GROUP_INHERITANCE_CHANGED); + return true; + } + } + return false; + } + + /** + * @return the variables + */ + public GroupVariables getVariables() { + + return variables; + } + + /** + * + * @param varList + */ + public void setVariables(Map<String, Object> varList) { + + if (!isGlobal()) { + GroupVariables temp = new GroupVariables(this, varList); + variables.clearVars(); + for (String key : temp.getVarKeyList()) { + variables.addVar(key, temp.getVarObject(key)); + } + flagAsChanged(); + if (GroupManager.isLoaded()) { + GroupManager.BukkitPermissions.updateAllPlayers(); + GroupManagerEventHandler.callEvent(this, Action.GROUP_INFO_CHANGED); + } + } + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/GroupVariables.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/GroupVariables.java new file mode 100644 index 000000000..e08d1db7d --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/GroupVariables.java @@ -0,0 +1,94 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.data; + +import java.util.Map; + +/** + * + * @author gabrielcouto + */ +public class GroupVariables extends Variables implements Cloneable { + + private Group owner; + + public GroupVariables(Group owner) { + + super(owner); + this.owner = owner; + addVar("prefix", ""); + addVar("suffix", ""); + addVar("build", false); + } + + public GroupVariables(Group owner, Map<String, Object> varList) { + + super(owner); + variables = varList; + if (variables.get("prefix") == null) { + variables.put("prefix", ""); + owner.flagAsChanged(); + } + //thisGrp.prefix = infoNode.get("prefix").toString(); + + if (variables.get("suffix") == null) { + variables.put("suffix", ""); + owner.flagAsChanged(); + } + //thisGrp.suffix = infoNode.get("suffix").toString(); + + if (variables.get("build") == null) { + variables.put("build", false); + owner.flagAsChanged(); + } + this.owner = owner; + } + + /** + * A clone of all vars here. + * + * @return GroupVariables clone + */ + protected GroupVariables clone(Group newOwner) { + + GroupVariables clone = new GroupVariables(newOwner); + for (String key : variables.keySet()) { + clone.variables.put(key, variables.get(key)); + } + newOwner.flagAsChanged(); + return clone; + } + + /** + * Remove a var from the list + * + * @param name + */ + @Override + public void removeVar(String name) { + + try { + this.variables.remove(name); + } catch (Exception e) { + } + if (name.equals("prefix")) { + addVar("prefix", ""); + } else if (name.equals("suffix")) { + addVar("suffix", ""); + } else if (name.equals("build")) { + addVar("build", false); + } + owner.flagAsChanged(); + } + + /** + * @return the owner + */ + @Override + public Group getOwner() { + + return owner; + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/User.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/User.java new file mode 100644 index 000000000..6c74c2e50 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/User.java @@ -0,0 +1,273 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.data; + +//import com.sun.org.apache.bcel.internal.generic.AALOAD; +import java.util.ArrayList; + +import org.anjocaido.groupmanager.GroupManager; +import org.anjocaido.groupmanager.dataholder.WorldDataHolder; +import org.anjocaido.groupmanager.events.GMUserEvent.Action; +import org.anjocaido.groupmanager.events.GroupManagerEventHandler; + +import java.util.Map; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +/** + * + * @author gabrielcouto/ElgarL + */ +public class User extends DataUnit implements Cloneable { + + /** + * + */ + private String group = null; + private ArrayList<String> subGroups = new ArrayList<String>(); + /** + * This one holds the fields in INFO node. like prefix = 'c' or build = + * false + */ + private UserVariables variables = new UserVariables(this); + private transient Player bukkitPlayer = null; + + /** + * + * @param name + */ + public User(WorldDataHolder source, String name) { + + super(source, name); + this.group = source.getDefaultGroup().getName(); + } + + /** + * + * @return User clone + */ + @Override + public User clone() { + + User clone = new User(getDataSource(), this.getName()); + clone.group = this.group; + for (String perm : this.getPermissionList()) { + clone.addPermission(perm); + } + // clone.variables = this.variables.clone(); + // clone.flagAsChanged(); + return clone; + } + + /** + * Use this to deliver a user from one WorldDataHolder to another + * + * @param dataSource + * @return null if given dataSource already contains the same user + */ + public User clone(WorldDataHolder dataSource) { + + if (dataSource.isUserDeclared(this.getName())) { + return null; + } + User clone = dataSource.createUser(this.getName()); + if (dataSource.getGroup(group) == null) { + clone.setGroup(dataSource.getDefaultGroup()); + } else { + clone.setGroup(dataSource.getGroup(this.getGroupName())); + } + for (String perm : this.getPermissionList()) { + clone.addPermission(perm); + } + clone.variables = this.variables.clone(this); + clone.flagAsChanged(); + return clone; + } + + public Group getGroup() { + + Group result = getDataSource().getGroup(group); + if (result == null) { + this.setGroup(getDataSource().getDefaultGroup()); + result = getDataSource().getDefaultGroup(); + } + return result; + } + + /** + * @return the group + */ + public String getGroupName() { + + Group result = getDataSource().getGroup(group); + if (result == null) { + group = getDataSource().getDefaultGroup().getName(); + } + return group; + } + + + /** + * @param group + * the group to set + */ + public void setGroup(Group group) { + + setGroup(group, true); + } + + /** + * @param group the group to set + * @param updatePerms if we are to trigger a superperms update. + * + */ + public void setGroup(Group group, Boolean updatePerms) { + + if (!this.getDataSource().groupExists(group.getName())) { + getDataSource().addGroup(group); + } + group = getDataSource().getGroup(group.getName()); + String oldGroup = this.group; + this.group = group.getName(); + flagAsChanged(); + if (GroupManager.isLoaded()) { + if (!GroupManager.BukkitPermissions.isPlayer_join() && (updatePerms)) + GroupManager.BukkitPermissions.updatePlayer(getBukkitPlayer()); + + // Do we notify of the group change? + String defaultGroupName = getDataSource().getDefaultGroup().getName(); + // if we were not in the default group + // or we were in the default group and the move is to a different + // group. + boolean notify = (!oldGroup.equalsIgnoreCase(defaultGroupName)) || ((oldGroup.equalsIgnoreCase(defaultGroupName)) && (!this.group.equalsIgnoreCase(defaultGroupName))); + + if (notify) + GroupManager.notify(this.getName(), String.format(" moved to the group %s.", group.getName())); + + GroupManagerEventHandler.callEvent(this, Action.USER_GROUP_CHANGED); + } + } + + public boolean addSubGroup(Group subGroup) { + + // Don't allow adding a subgroup if it's already set as the primary. + if (this.group.equalsIgnoreCase(subGroup.getName())) { + return false; + } + // User already has this subgroup + if (containsSubGroup(subGroup)) + return false; + + // If the group doesn't exists add it + if (!this.getDataSource().groupExists(subGroup.getName())) { + getDataSource().addGroup(subGroup); + } + + subGroups.add(subGroup.getName()); + flagAsChanged(); + if (GroupManager.isLoaded()) { + if (!GroupManager.BukkitPermissions.isPlayer_join()) + GroupManager.BukkitPermissions.updatePlayer(getBukkitPlayer()); + GroupManagerEventHandler.callEvent(this, Action.USER_SUBGROUP_CHANGED); + } + return true; + + //subGroup = getDataSource().getGroup(subGroup.getName()); + //removeSubGroup(subGroup); + //subGroups.add(subGroup.getName()); + } + + public int subGroupsSize() { + + return subGroups.size(); + } + + public boolean isSubGroupsEmpty() { + + return subGroups.isEmpty(); + } + + public boolean containsSubGroup(Group subGroup) { + + return subGroups.contains(subGroup.getName()); + } + + public boolean removeSubGroup(Group subGroup) { + + try { + if (subGroups.remove(subGroup.getName())) { + flagAsChanged(); + if (GroupManager.isLoaded()) + if (!GroupManager.BukkitPermissions.isPlayer_join()) + GroupManager.BukkitPermissions.updatePlayer(getBukkitPlayer()); + GroupManagerEventHandler.callEvent(this, Action.USER_SUBGROUP_CHANGED); + return true; + } + } catch (Exception e) { + } + return false; + } + + public ArrayList<Group> subGroupListCopy() { + + ArrayList<Group> val = new ArrayList<Group>(); + for (String gstr : subGroups) { + Group g = getDataSource().getGroup(gstr); + if (g == null) { + removeSubGroup(g); + continue; + } + val.add(g); + } + return val; + } + + public ArrayList<String> subGroupListStringCopy() { + + return new ArrayList<String>(subGroups); + } + + /** + * @return the variables + */ + public UserVariables getVariables() { + + return variables; + } + + /** + * + * @param varList + */ + public void setVariables(Map<String, Object> varList) { + + //UserVariables temp = new UserVariables(this, varList); + variables.clearVars(); + for (String key : varList.keySet()) { + variables.addVar(key, varList.get(key)); + } + flagAsChanged(); + if (GroupManager.isLoaded()) { + //if (!GroupManager.BukkitPermissions.isPlayer_join()) + // GroupManager.BukkitPermissions.updatePlayer(this.getName()); + GroupManagerEventHandler.callEvent(this, Action.USER_INFO_CHANGED); + } + } + + + public User updatePlayer(Player player) { + + bukkitPlayer = player; + return this; + } + + public Player getBukkitPlayer() { + + if (bukkitPlayer == null) { + bukkitPlayer = Bukkit.getPlayer(this.getName()); + } + return bukkitPlayer; + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/UserVariables.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/UserVariables.java new file mode 100644 index 000000000..f994595c1 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/UserVariables.java @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.data; + +import java.util.Map; + +/** + * + * @author gabrielcouto + */ +public class UserVariables extends Variables { + + private User owner; + + public UserVariables(User owner) { + + super(owner); + this.owner = owner; + } + + public UserVariables(User owner, Map<String, Object> varList) { + + super(owner); + this.variables = varList; + this.owner = owner; + } + + /** + * A clone of all vars here. + * + * @return UserVariables clone + */ + protected UserVariables clone(User newOwner) { + + UserVariables clone = new UserVariables(newOwner); + for (String key : variables.keySet()) { + clone.variables.put(key, variables.get(key)); + } + newOwner.flagAsChanged(); + return clone; + } + + /** + * @return the owner + */ + @Override + public User getOwner() { + + return owner; + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/Variables.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/Variables.java new file mode 100644 index 000000000..42ceba7e4 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/Variables.java @@ -0,0 +1,208 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.data; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * A class that holds variables of a user/group. + * In groups, it holds the contents of INFO node. + * Like: + * prefix + * suffix + * build + * + * @author gabrielcouto + */ +public abstract class Variables implements Cloneable { + + private DataUnit owner; + protected Map<String, Object> variables = new HashMap<String, Object>(); + + public Variables(DataUnit owner) { + + this.owner = owner; + } + + /** + * Add var to the the INFO node. + * examples: + * addVar("build",true); + * addVar("prefix","c"); + * + * @param name key name of the var + * @param o the object value of the var + */ + public void addVar(String name, Object o) { + + if (o == null) { + return; + } + if (variables.containsKey(name)) { + variables.remove(name); + } + variables.put(name, o); + owner.flagAsChanged(); + } + + /** + * Returns the object inside the var + * + * @param name + * @return a Object if exists. null if doesn't exists + */ + public Object getVarObject(String name) { + + return variables.get(name); + } + + /** + * Get the String value for the given var name + * + * @param name the var key name + * @return "" if null. or the toString() value of object + */ + public String getVarString(String name) { + + Object o = variables.get(name); + try { + return o == null ? "" : o.toString(); + } catch (Exception e) { + return ""; + } + } + + /** + * + * @param name + * @return false if null. or a Boolean.parseBoolean of the string + */ + public Boolean getVarBoolean(String name) { + + Object o = variables.get(name); + try { + return o == null ? false : Boolean.parseBoolean(o.toString()); + } catch (Exception e) { + return false; + } + } + + /** + * + * @param name + * @return -1 if null. or a parseInt of the string + */ + public Integer getVarInteger(String name) { + + Object o = variables.get(name); + try { + return o == null ? -1 : Integer.parseInt(o.toString()); + } catch (Exception e) { + return -1; + } + } + + /** + * + * @param name + * @return -1 if null. or a parseDouble of the string + */ + public Double getVarDouble(String name) { + + Object o = variables.get(name); + try { + return o == null ? -1.0D : Double.parseDouble(o.toString()); + } catch (Exception e) { + return -1.0D; + } + } + + /** + * All variable keys this is holding + * + * @return Set of all variable names. + */ + public Set<String> getVarKeyList() { + + return variables.keySet(); + } + + /** + * verify is a var exists + * + * @param name the key name of the var + * @return true if that var exists + */ + public boolean hasVar(String name) { + + return variables.containsKey(name); + } + + /** + * Returns the quantity of vars this is holding + * + * @return the number of vars + */ + public int getSize() { + + return variables.size(); + } + + /** + * Remove a var from the list + * + * @param name + */ + public void removeVar(String name) { + + try { + variables.remove(name); + } catch (Exception e) { + } + owner.flagAsChanged(); + } + + public static Object parseVariableValue(String value) { + + try { + Integer i = Integer.parseInt(value); + return i; + } catch (NumberFormatException e) { + } + try { + Double d = Double.parseDouble(value); + return d; + } catch (NumberFormatException e) { + } + if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("on")) { + return true; + } else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no") || value.equalsIgnoreCase("off")) { + return false; + } + return value; + + } + + public void clearVars() { + + variables.clear(); + owner.flagAsChanged(); + } + + /** + * @return the owner + */ + public DataUnit getOwner() { + + return owner; + } + + public boolean isEmpty() { + + return variables.isEmpty(); + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java new file mode 100644 index 000000000..eaaaace74 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java @@ -0,0 +1,123 @@ +package org.anjocaido.groupmanager.dataholder;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.anjocaido.groupmanager.data.Group;
+
+/**
+ * This container holds all Groups loaded from the relevant groupsFile.
+ *
+ * @author ElgarL
+ *
+ */
+public class GroupsDataHolder {
+
+ private WorldDataHolder dataSource;
+ private Group defaultGroup = null;
+ private File groupsFile;
+ private boolean haveGroupsChanged = false;
+ private long timeStampGroups = 0;
+
+ /**
+ * The actual groups holder
+ */
+ private Map<String, Group> groups = new HashMap<String, Group>();
+
+ /**
+ * Constructor
+ */
+ protected GroupsDataHolder() {
+
+ }
+
+ public void setDataSource(WorldDataHolder dataSource) {
+
+ this.dataSource = dataSource;
+ //push this data source to the users, so they pull the correct groups data.
+ for (Group group : groups.values())
+ group.setDataSource(this.dataSource);
+ }
+
+ /**
+ * @return the defaultGroup
+ */
+ public Group getDefaultGroup() {
+
+ return defaultGroup;
+ }
+
+ /**
+ * @param defaultGroup the defaultGroup to set
+ */
+ public void setDefaultGroup(Group defaultGroup) {
+
+ this.defaultGroup = defaultGroup;
+ }
+
+ /**
+ * @return the groups
+ */
+ public Map<String, Group> getGroups() {
+
+ return groups;
+ }
+
+ /**
+ * @param groups the groups to set
+ */
+ public void setGroups(Map<String, Group> groups) {
+
+ this.groups = groups;
+ }
+
+ /**
+ * @return the groupsFile
+ */
+ public File getGroupsFile() {
+
+ return groupsFile;
+ }
+
+ /**
+ * @param groupsFile the groupsFile to set
+ */
+ public void setGroupsFile(File groupsFile) {
+
+ this.groupsFile = groupsFile;
+ }
+
+ /**
+ * @return the haveGroupsChanged
+ */
+ public boolean HaveGroupsChanged() {
+
+ return haveGroupsChanged;
+ }
+
+ /**
+ * @param haveGroupsChanged the haveGroupsChanged to set
+ */
+ public void setGroupsChanged(boolean haveGroupsChanged) {
+
+ this.haveGroupsChanged = haveGroupsChanged;
+ }
+
+ /**
+ * @return the timeStampGroups
+ */
+ public long getTimeStampGroups() {
+
+ return timeStampGroups;
+ }
+
+ /**
+ * @param timeStampGroups the timeStampGroups to set
+ */
+ public void setTimeStampGroups(long timeStampGroups) {
+
+ this.timeStampGroups = timeStampGroups;
+ }
+
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/OverloadedWorldHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/OverloadedWorldHolder.java new file mode 100644 index 000000000..84561b6e5 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/OverloadedWorldHolder.java @@ -0,0 +1,214 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.dataholder; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.anjocaido.groupmanager.data.User; + +/** + * + * @author gabrielcouto + */ +public class OverloadedWorldHolder extends WorldDataHolder { + + /** + * + */ + protected Map<String, User> overloadedUsers = new HashMap<String, User>(); + + /** + * + * @param ph + */ + public OverloadedWorldHolder(WorldDataHolder ph) { + + super(ph.getName()); + this.setGroupsFile(ph.getGroupsFile()); + this.setUsersFile(ph.getUsersFile()); + this.groups = ph.groups; + this.users = ph.users; + } + + /** + * + * @param userName + * @return user object or a new user if none exists. + */ + @Override + public User getUser(String userName) { + + //OVERLOADED CODE + String userNameLowered = userName.toLowerCase(); + if (overloadedUsers.containsKey(userNameLowered)) { + return overloadedUsers.get(userNameLowered); + } + //END CODE + if (getUsers().containsKey(userNameLowered)) { + return getUsers().get(userNameLowered); + } + User newUser = createUser(userName); + setUsersChanged(true); + return newUser; + } + + /** + * + * @param theUser + */ + @Override + public void addUser(User theUser) { + + if (theUser.getDataSource() != this) { + theUser = theUser.clone(this); + } + if (theUser == null) { + return; + } + if ((theUser.getGroup() == null) || (!getGroups().containsKey(theUser.getGroupName().toLowerCase()))) { + theUser.setGroup(getDefaultGroup()); + } + //OVERLOADED CODE + if (overloadedUsers.containsKey(theUser.getName().toLowerCase())) { + overloadedUsers.remove(theUser.getName().toLowerCase()); + overloadedUsers.put(theUser.getName().toLowerCase(), theUser); + return; + } + //END CODE + removeUser(theUser.getName()); + getUsers().put(theUser.getName().toLowerCase(), theUser); + setUsersChanged(true); + } + + /** + * + * @param userName + * @return true if removed/false if not found. + */ + @Override + public boolean removeUser(String userName) { + + //OVERLOADED CODE + if (overloadedUsers.containsKey(userName.toLowerCase())) { + overloadedUsers.remove(userName.toLowerCase()); + return true; + } + //END CODE + if (getUsers().containsKey(userName.toLowerCase())) { + getUsers().remove(userName.toLowerCase()); + setUsersChanged(true); + return true; + } + return false; + } + + @Override + public boolean removeGroup(String groupName) { + + if (groupName.equals(getDefaultGroup())) { + return false; + } + for (String key : getGroups().keySet()) { + if (groupName.equalsIgnoreCase(key)) { + getGroups().remove(key); + for (String userKey : getUsers().keySet()) { + User user = getUsers().get(userKey); + if (user.getGroupName().equalsIgnoreCase(key)) { + user.setGroup(getDefaultGroup()); + } + + } + //OVERLOADED CODE + for (String userKey : overloadedUsers.keySet()) { + User user = overloadedUsers.get(userKey); + if (user.getGroupName().equalsIgnoreCase(key)) { + user.setGroup(getDefaultGroup()); + } + + } + //END OVERLOAD + setGroupsChanged(true); + return true; + } + } + return false; + } + + /** + * + * @return Collection of all users + */ + @Override + public Collection<User> getUserList() { + + Collection<User> overloadedList = new ArrayList<User>(); + Collection<User> normalList = getUsers().values(); + for (User u : normalList) { + if (overloadedUsers.containsKey(u.getName().toLowerCase())) { + overloadedList.add(overloadedUsers.get(u.getName().toLowerCase())); + } else { + overloadedList.add(u); + } + } + return overloadedList; + } + + /** + * + * @param userName + * @return true if user is overloaded. + */ + public boolean isOverloaded(String userName) { + + return overloadedUsers.containsKey(userName.toLowerCase()); + } + + /** + * + * @param userName + */ + public void overloadUser(String userName) { + + if (!isOverloaded(userName)) { + User theUser = getUser(userName); + theUser = theUser.clone(); + if (overloadedUsers.containsKey(theUser.getName().toLowerCase())) { + overloadedUsers.remove(theUser.getName().toLowerCase()); + } + overloadedUsers.put(theUser.getName().toLowerCase(), theUser); + } + } + + /** + * + * @param userName + */ + public void removeOverload(String userName) { + + overloadedUsers.remove(userName.toLowerCase()); + } + + /** + * Gets the user in normal state. Surpassing the overload state. + * It doesn't affect permissions. But it enables plugins change the + * actual user permissions even in overload mode. + * + * @param userName + * @return user object + */ + public User surpassOverload(String userName) { + + if (!isOverloaded(userName)) { + return getUser(userName); + } + if (getUsers().containsKey(userName.toLowerCase())) { + return getUsers().get(userName.toLowerCase()); + } + User newUser = createUser(userName); + return newUser; + } +}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java new file mode 100644 index 000000000..665fe227d --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java @@ -0,0 +1,107 @@ +package org.anjocaido.groupmanager.dataholder;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.anjocaido.groupmanager.data.User;
+
+/**
+ * This container holds all Users loaded from the relevant usersFile.
+ *
+ * @author ElgarL
+ *
+ */
+public class UsersDataHolder {
+
+ private WorldDataHolder dataSource;
+ private File usersFile;
+ private boolean haveUsersChanged = false;
+ private long timeStampUsers = 0;
+
+ /**
+ * The actual groups holder
+ */
+ private Map<String, User> users = new HashMap<String, User>();
+
+ /**
+ * Constructor
+ */
+ protected UsersDataHolder() {
+
+ }
+
+ public void setDataSource(WorldDataHolder dataSource) {
+
+ this.dataSource = dataSource;
+ //push this data source to the users, so they pull the correct groups data.
+ for (User user : users.values())
+ user.setDataSource(this.dataSource);
+
+ }
+
+ /**
+ * @return the users
+ */
+ public Map<String, User> getUsers() {
+
+ return users;
+ }
+
+ /**
+ * @param users the users to set
+ */
+ public void setUsers(Map<String, User> users) {
+
+ this.users = users;
+ }
+
+ /**
+ * @return the usersFile
+ */
+ public File getUsersFile() {
+
+ return usersFile;
+ }
+
+ /**
+ * @param usersFile the usersFile to set
+ */
+ public void setUsersFile(File usersFile) {
+
+ this.usersFile = usersFile;
+ }
+
+ /**
+ * @return the haveUsersChanged
+ */
+ public boolean HaveUsersChanged() {
+
+ return haveUsersChanged;
+ }
+
+ /**
+ * @param haveUsersChanged the haveUsersChanged to set
+ */
+ public void setUsersChanged(boolean haveUsersChanged) {
+
+ this.haveUsersChanged = haveUsersChanged;
+ }
+
+ /**
+ * @return the timeStampUsers
+ */
+ public long getTimeStampUsers() {
+
+ return timeStampUsers;
+ }
+
+ /**
+ * @param timeStampUsers the timeStampUsers to set
+ */
+ public void setTimeStampUsers(long timeStampUsers) {
+
+ this.timeStampUsers = timeStampUsers;
+ }
+
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java new file mode 100644 index 000000000..fefc698f9 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java @@ -0,0 +1,1348 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.dataholder; + +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.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.anjocaido.groupmanager.GroupManager; +import org.anjocaido.groupmanager.data.Group; +import org.anjocaido.groupmanager.data.User; +import org.anjocaido.groupmanager.events.GMGroupEvent; +import org.anjocaido.groupmanager.events.GMSystemEvent; +import org.anjocaido.groupmanager.events.GMUserEvent; +import org.anjocaido.groupmanager.events.GMUserEvent.Action; +import org.anjocaido.groupmanager.events.GroupManagerEventHandler; +import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler; +import org.bukkit.Server; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.reader.UnicodeReader; + +/** + * One instance of this should exist per world/mirror + * it contains all functions to manage these data sets + * and points to the relevant users and groups objects. + * + * @author gabrielcouto, ElgarL + */ +public class WorldDataHolder { + + /** + * World name + */ + protected String name; + /** + * The actual groups holder + */ + protected GroupsDataHolder groups = new GroupsDataHolder(); + /** + * The actual users holder + */ + protected UsersDataHolder users = new UsersDataHolder(); + /** + * + */ + protected AnjoPermissionsHandler permissionsHandler; + + /** + * Prevent direct instantiation + * + * @param worldName + */ + public WorldDataHolder(String worldName) { + + name = worldName; + } + + /** + * The main constructor for a new WorldDataHolder + * + * @param worldName + * @param groups + * @param users + */ + public WorldDataHolder(String worldName, GroupsDataHolder groups, UsersDataHolder users) { + + this.name = worldName; + this.groups = groups; + this.users = users; + + // this.defaultGroup = defaultGroup; + } + + /** + * update the dataSource to point to this object. + * + * This should be called whenever a set of world data is fetched. + */ + public void updateDataSource() { + + this.groups.setDataSource(this); + this.users.setDataSource(this); + } + + /** + * Search for a user. If it doesn't exist, create a new one with + * default group. + * + * @param userName the name of the user + * @return class that manage that user permission + */ + public User getUser(String userName) { + + if (getUsers().containsKey(userName.toLowerCase())) { + return getUsers().get(userName.toLowerCase()); + } + User newUser = createUser(userName); + return newUser; + } + + /** + * Add a user to the list. If it already exists, overwrite the old. + * + * @param theUser the user you want to add to the permission list + */ + public void addUser(User theUser) { + + if (theUser.getDataSource() != this) { + theUser = theUser.clone(this); + } + if (theUser == null) { + return; + } + if ((theUser.getGroup() == null)) { + theUser.setGroup(groups.getDefaultGroup()); + } + removeUser(theUser.getName()); + getUsers().put(theUser.getName().toLowerCase(), theUser); + setUsersChanged(true); + if (GroupManager.isLoaded()) + GroupManagerEventHandler.callEvent(theUser, Action.USER_ADDED); + } + + /** + * Removes the user from the list. (he might become a default user) + * + * @param userName the username from the user to remove + * @return true if it had something to remove + */ + public boolean removeUser(String userName) { + + if (getUsers().containsKey(userName.toLowerCase())) { + getUsers().remove(userName.toLowerCase()); + setUsersChanged(true); + if (GroupManager.isLoaded()) + GroupManagerEventHandler.callEvent(userName, GMUserEvent.Action.USER_REMOVED); + return true; + } + return false; + } + + /** + * + * @param userName + * @return true if we have data for this player. + */ + public boolean isUserDeclared(String userName) { + + return getUsers().containsKey(userName.toLowerCase()); + } + + /** + * Change the default group of the file. + * + * @param group the group you want make default. + */ + public void setDefaultGroup(Group group) { + + if (!getGroups().containsKey(group.getName().toLowerCase()) || (group.getDataSource() != this)) { + addGroup(group); + } + groups.setDefaultGroup(getGroup(group.getName())); + setGroupsChanged(true); + if (GroupManager.isLoaded()) + GroupManagerEventHandler.callEvent(GMSystemEvent.Action.DEFAULT_GROUP_CHANGED); + } + + /** + * Returns the default group of the file + * + * @return the default group + */ + public Group getDefaultGroup() { + + return groups.getDefaultGroup(); + } + + /** + * Returns a group of the given name + * + * @param groupName the name of the group + * @return a group if it is found. null if not found. + */ + public Group getGroup(String groupName) { + + if (groupName.toLowerCase().startsWith("g:")) + return GroupManager.getGlobalGroups().getGroup(groupName); + else + return getGroups().get(groupName.toLowerCase()); + } + + /** + * Check if a group exists. + * Its the same of getGroup, but check if it is null. + * + * @param groupName the name of the group + * @return true if exists. false if not. + */ + public boolean groupExists(String groupName) { + + if (groupName.toLowerCase().startsWith("g:")) + return GroupManager.getGlobalGroups().hasGroup(groupName); + else + return getGroups().containsKey(groupName.toLowerCase()); + } + + /** + * Add a group to the list + * + * @param groupToAdd + */ + public void addGroup(Group groupToAdd) { + + if (groupToAdd.getName().toLowerCase().startsWith("g:")) { + GroupManager.getGlobalGroups().addGroup(groupToAdd); + GroupManagerEventHandler.callEvent(groupToAdd, GMGroupEvent.Action.GROUP_ADDED); + return; + } + + if (groupToAdd.getDataSource() != this) { + groupToAdd = groupToAdd.clone(this); + } + removeGroup(groupToAdd.getName()); + getGroups().put(groupToAdd.getName().toLowerCase(), groupToAdd); + setGroupsChanged(true); + if (GroupManager.isLoaded()) + GroupManagerEventHandler.callEvent(groupToAdd, GMGroupEvent.Action.GROUP_ADDED); + } + + /** + * Remove the group from the list + * + * @param groupName + * @return true if had something to remove. false the group was default or + * non-existant + */ + public boolean removeGroup(String groupName) { + + if (groupName.toLowerCase().startsWith("g:")) { + return GroupManager.getGlobalGroups().removeGroup(groupName); + } + + if (getDefaultGroup() != null && groupName.equalsIgnoreCase(getDefaultGroup().getName())) { + return false; + } + if (getGroups().containsKey(groupName.toLowerCase())) { + getGroups().remove(groupName.toLowerCase()); + setGroupsChanged(true); + if (GroupManager.isLoaded()) + GroupManagerEventHandler.callEvent(groupName.toLowerCase(), GMGroupEvent.Action.GROUP_REMOVED); + return true; + } + return false; + + } + + /** + * Creates a new User with the given name + * and adds it to this holder. + * + * @param userName the username you want + * @return null if user already exists. or new User + */ + public User createUser(String userName) { + + if (getUsers().containsKey(userName.toLowerCase())) { + return null; + } + User newUser = new User(this, userName); + newUser.setGroup(groups.getDefaultGroup(), false); + addUser(newUser); + setUsersChanged(true); + return newUser; + } + + /** + * Creates a new Group with the given name + * and adds it to this holder + * + * @param groupName the groupname you want + * @return null if group already exists. or new Group + */ + public Group createGroup(String groupName) { + + if (groupName.toLowerCase().startsWith("g:")) { + Group newGroup = new Group(groupName); + return GroupManager.getGlobalGroups().newGroup(newGroup); + } + + if (getGroups().containsKey(groupName.toLowerCase())) { + return null; + } + + Group newGroup = new Group(this, groupName); + addGroup(newGroup); + setGroupsChanged(true); + return newGroup; + } + + /** + * + * @return a collection of the groups + */ + public Collection<Group> getGroupList() { + + return getGroups().values(); + } + + /** + * + * @return a collection of the users + */ + public Collection<User> getUserList() { + + return getUsers().values(); + } + + /** + * reads the file again + */ + public void reload() { + + try { + reloadGroups(); + reloadUsers(); + } catch (Exception ex) { + Logger.getLogger(WorldDataHolder.class.getName()).log(Level.SEVERE, null, ex); + } + } + + /** + * Refresh Group data from file + */ + public void reloadGroups() { + + GroupManager.setLoaded(false); + try { + // temporary holder in case the load fails. + WorldDataHolder ph = new WorldDataHolder(this.getName()); + + loadGroups(ph, getGroupsFile()); + // transfer new data + resetGroups(); + for (Group tempGroup : ph.getGroupList()) { + tempGroup.clone(this); + } + this.setDefaultGroup(getGroup(ph.getDefaultGroup().getName())); + this.removeGroupsChangedFlag(); + this.setTimeStampGroups(getGroupsFile().lastModified()); + + ph = null; + } catch (Exception ex) { + Logger.getLogger(WorldDataHolder.class.getName()).log(Level.WARNING, null, ex); + } + GroupManager.setLoaded(true); + GroupManagerEventHandler.callEvent(GMSystemEvent.Action.RELOADED); + } + + /** + * Refresh Users data from file + */ + public void reloadUsers() { + + GroupManager.setLoaded(false); + try { + // temporary holder in case the load fails. + WorldDataHolder ph = new WorldDataHolder(this.getName()); + // copy groups for reference + for (Group tempGroup : this.getGroupList()) { + tempGroup.clone(ph); + } + // setup the default group before loading user data. + ph.setDefaultGroup(ph.getGroup(getDefaultGroup().getName())); + loadUsers(ph, getUsersFile()); + // transfer new data + resetUsers(); + for (User tempUser : ph.getUserList()) { + tempUser.clone(this); + } + this.removeUsersChangedFlag(); + this.setTimeStampUsers(getUsersFile().lastModified()); + + ph = null; + } catch (Exception ex) { + Logger.getLogger(WorldDataHolder.class.getName()).log(Level.WARNING, null, ex); + } + GroupManager.setLoaded(true); + GroupManagerEventHandler.callEvent(GMSystemEvent.Action.RELOADED); + } + + public void loadGroups(File groupsFile) { + + GroupManager.setLoaded(false); + try { + setGroupsFile(groupsFile); + loadGroups(this, groupsFile); + } catch (FileNotFoundException e) { + e.printStackTrace(); + throw new IllegalArgumentException("The file which should contain groups does not exist!\n" + groupsFile.getPath()); + } catch (IOException e) { + e.printStackTrace(); + throw new IllegalArgumentException("Error access the groups file!\n" + groupsFile.getPath()); + } + + GroupManager.setLoaded(true); + } + + public void loadUsers(File usersFile) { + + GroupManager.setLoaded(false); + try { + setUsersFile(usersFile); + loadUsers(this, usersFile); + } catch (FileNotFoundException e) { + e.printStackTrace(); + throw new IllegalArgumentException("The file which should contain users does not exist!\n" + usersFile.getPath()); + } catch (IOException e) { + e.printStackTrace(); + throw new IllegalArgumentException("Error access the users file!\n" + usersFile.getPath()); + } + + GroupManager.setLoaded(true); + } + + /** + * Returns a NEW data holder containing data read from the files + * + * @param worldName + * @param groupsFile + * @param usersFile + * + * @throws FileNotFoundException + * @throws IOException + */ + public static WorldDataHolder load(String worldName, File groupsFile, File usersFile) throws FileNotFoundException, IOException { + + WorldDataHolder ph = new WorldDataHolder(worldName); + + GroupManager.setLoaded(false); + if (groupsFile != null) + loadGroups(ph, groupsFile); + if (usersFile != null) + loadUsers(ph, usersFile); + GroupManager.setLoaded(true); + + return ph; + } + + /** + * Updates the WorldDataHolder from the Groups file + * + * @param ph + * @param groupsFile + * + * @throws FileNotFoundException + * @throws IOException + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected static void loadGroups(WorldDataHolder ph, File groupsFile) throws FileNotFoundException, IOException { + + // READ GROUPS FILE + + Yaml yamlGroups = new Yaml(new SafeConstructor()); + Map<String, Object> groupsRootDataNode; + + if (!groupsFile.exists()) { + throw new IllegalArgumentException("The file which should contain groups does not exist!\n" + groupsFile.getPath()); + } + FileInputStream groupsInputStream = new FileInputStream(groupsFile); + try { + groupsRootDataNode = (Map<String, Object>) yamlGroups.load(new UnicodeReader(groupsInputStream)); + if (groupsRootDataNode == null) { + throw new NullPointerException(); + } + } catch (Exception ex) { + throw new IllegalArgumentException("The following file couldn't pass on Parser.\n" + groupsFile.getPath(), ex); + } finally { + groupsInputStream.close(); + } + + // PROCESS GROUPS FILE + + Map<String, List<String>> inheritance = new HashMap<String, List<String>>(); + Map<String, Object> allGroupsNode = null; + + /* + * Fetch all groups under the 'groups' entry. + */ + try { + allGroupsNode = (Map<String, Object>) groupsRootDataNode.get("groups"); + } catch (Exception ex) { + throw new IllegalArgumentException("Your " + groupsFile.getPath() + " file is invalid. See console for details.", ex); + } + + Iterator<String> groupItr = allGroupsNode.keySet().iterator(); + String groupKey; + Integer groupCount = 0; + + /* + * loop each group entry + * and process it's data. + */ + while (groupItr.hasNext()) { + + try { + groupCount++; + // Attempt to fetch the next group name. + groupKey = groupItr.next(); + } catch (Exception ex) { + throw new IllegalArgumentException("Invalid group name for group entry (" + groupCount + ") in file: " + groupsFile.getPath(), ex); + } + + /* + * Fetch this groups child nodes + */ + Map<String, Object> thisGroupNode = null; + + try { + thisGroupNode = (Map<String, Object>) allGroupsNode.get(groupKey); + } catch (Exception ex) { + throw new IllegalArgumentException("Invalid child nodes for group '" + groupKey + "' in file: " + groupsFile.getPath(), ex); + } + + /* + * Create a new group with this name + * in the assigned data source. + */ + Group thisGrp = ph.createGroup(groupKey); + + if (thisGrp == null) { + throw new IllegalArgumentException("I think this Group was declared more than once: " + groupKey + " in file: " + groupsFile.getPath()); + } + + // DEFAULT NODE + + Object nodeData = null; + try { + nodeData = thisGroupNode.get("default"); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found in 'permissions' for group: " + groupKey + " in file: " + groupsFile.getPath()); + } + + if (nodeData == null) { + /* + * If no 'default' node is found do nothing. + */ + } else if ((Boolean.parseBoolean(nodeData.toString()))) { + /* + * Set this as the default group. + * Warn if some other group has already claimed that position. + */ + if (ph.getDefaultGroup() != null) { + GroupManager.logger.warning("The group '" + thisGrp.getName() + "' is claiming to be default where '" + ph.getDefaultGroup().getName() + "' already was."); + GroupManager.logger.warning("Overriding first default request in file: " + groupsFile.getPath()); + } + ph.setDefaultGroup(thisGrp); + } + + // PERMISSIONS NODE + + nodeData = null; + try { + nodeData = thisGroupNode.get("permissions"); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found in 'permissions' for '" + groupKey + "' in file: " + groupsFile.getPath()); + } + + if (nodeData == null) { + /* + * If no permissions node is found, or it's empty + * do nothing. + */ + } else { + /* + * There is a permission list Which seems to hold some data + */ + if (nodeData instanceof List) { + /* + * Check each entry and add it as a new permission. + */ + try { + for (Object o : ((List) nodeData)) { + try { + /* + * Only add this permission if it's not empty. + */ + if (!o.toString().isEmpty()) + thisGrp.addPermission(o.toString()); + + } catch (NullPointerException ex) { + // Ignore this entry as it's null. It can be + // safely dropped + } + } + } catch (Exception ex) { + throw new IllegalArgumentException("Invalid formatting found in 'permissions' section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath(), ex); + } + + } else if (nodeData instanceof String) { + /* + * Only add this permission if it's not empty. + */ + if (!nodeData.toString().isEmpty()) + thisGrp.addPermission((String) nodeData); + + } else { + throw new IllegalArgumentException("Unknown type of 'permissions' node(Should be String or List<String>) for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } + /* + * Sort all permissions so they are in the correct order for + * checking. + */ + thisGrp.sortPermissions(); + } + + // INFO NODE + + nodeData = null; + try { + nodeData = thisGroupNode.get("info"); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found in 'info' section for group: " + groupKey + " in file: " + groupsFile.getPath()); + } + + if (nodeData == null) { + /* + * No info section was found, so leave all variables as + * defaults. + */ + GroupManager.logger.warning("The group '" + thisGrp.getName() + "' has no 'info' section!"); + GroupManager.logger.warning("Using default values: " + groupsFile.getPath()); + + } else if (nodeData instanceof Map) { + try { + if (nodeData != null) { + thisGrp.setVariables((Map<String, Object>) nodeData); + } + } catch (Exception ex) { + throw new IllegalArgumentException("Invalid formatting found in 'info' section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath(), ex); + } + + } else + throw new IllegalArgumentException("Unknown entry found in 'info' section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + + // INHERITANCE NODE + + nodeData = null; + try { + nodeData = thisGroupNode.get("inheritance"); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found in 'inheritance' section for group: " + groupKey + " in file: " + groupsFile.getPath()); + } + + if (nodeData == null || nodeData instanceof List) { + if (nodeData == null) { + /* + * If no inheritance node is found, or it's empty + * do nothing. + */ + } else if (nodeData instanceof List) { + + try { + for (String grp : (List<String>) nodeData) { + if (inheritance.get(groupKey) == null) { + inheritance.put(groupKey, new ArrayList<String>()); + } + inheritance.get(groupKey).add(grp); + } + + } catch (Exception ex) { + throw new IllegalArgumentException("Invalid formatting found in 'inheritance' section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath(), ex); + } + + } + } else + throw new IllegalArgumentException("Unknown entry found in 'inheritance' section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + + // END GROUP + + } + + if (ph.getDefaultGroup() == null) { + throw new IllegalArgumentException("There was no Default Group declared in file: " + groupsFile.getPath()); + } + + /* + * Build the inheritance map and recored any errors + */ + for (String group : inheritance.keySet()) { + List<String> inheritedList = inheritance.get(group); + Group thisGroup = ph.getGroup(group); + if (thisGroup != null) + for (String inheritedKey : inheritedList) { + if (inheritedKey != null) { + Group inheritedGroup = ph.getGroup(inheritedKey); + if (inheritedGroup != null) { + thisGroup.addInherits(inheritedGroup); + } else + GroupManager.logger.warning("Inherited group '" + inheritedKey + "' not found for group " + thisGroup.getName() + ". Ignoring entry in file: " + groupsFile.getPath()); + } + } + } + + ph.removeGroupsChangedFlag(); + // Update the LastModified time. + ph.setGroupsFile(groupsFile); + ph.setTimeStampGroups(groupsFile.lastModified()); + + // return ph; + } + + /** + * Updates the WorldDataHolder from the Users file + * + * @param ph + * @param usersFile + * + * @throws FileNotFoundException + * @throws IOException + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected static void loadUsers(WorldDataHolder ph, File usersFile) throws FileNotFoundException, IOException { + + // READ USERS FILE + Yaml yamlUsers = new Yaml(new SafeConstructor()); + Map<String, Object> usersRootDataNode; + if (!usersFile.exists()) { + throw new IllegalArgumentException("The file which should contain users does not exist!\n" + usersFile.getPath()); + } + FileInputStream usersInputStream = new FileInputStream(usersFile); + try { + usersRootDataNode = (Map<String, Object>) yamlUsers.load(new UnicodeReader(usersInputStream)); + if (usersRootDataNode == null) { + throw new NullPointerException(); + } + } catch (Exception ex) { + throw new IllegalArgumentException("The following file couldn't pass on Parser.\n" + usersFile.getPath(), ex); + } finally { + usersInputStream.close(); + } + + // PROCESS USERS FILE + + Map<String, Object> allUsersNode = null; + + /* + * Fetch all child nodes under the 'users' entry. + */ + try { + allUsersNode = (Map<String, Object>) usersRootDataNode.get("users"); + } catch (Exception ex) { + throw new IllegalArgumentException("Your " + usersFile.getPath() + " file is invalid. See console for details.", ex); + } + + // Load users if the file is NOT empty + + if (allUsersNode != null) { + + Iterator<String> usersItr = allUsersNode.keySet().iterator(); + String usersKey; + Integer userCount = 0; + + while (usersItr.hasNext()) { + try { + userCount++; + // Attempt to fetch the next user name. + usersKey = usersItr.next(); + } catch (Exception ex) { + throw new IllegalArgumentException("Invalid node type for user entry (" + userCount + ") in file: " + usersFile.getPath(), ex); + } + + Map<String, Object> thisUserNode = null; + try { + thisUserNode = (Map<String, Object>) allUsersNode.get(usersKey); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found for user: " + usersKey + " in file: " + usersFile.getPath()); + } + + User thisUser = ph.createUser(usersKey); + if (thisUser == null) { + throw new IllegalArgumentException("I think this user was declared more than once: " + usersKey + " in file: " + usersFile.getPath()); + } + + // USER PERMISSIONS NODES + + Object nodeData = null; + try { + nodeData = thisUserNode.get("permissions"); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found in 'permissions' for user: " + usersKey + " in file: " + usersFile.getPath()); + } + + if (nodeData == null) { + /* + * If no permissions node is found, or it's empty + * do nothing. + */ + } else { + if (nodeData instanceof List) { + for (Object o : ((List) nodeData)) { + /* + * Only add this permission if it's not empty + */ + if (!o.toString().isEmpty()) + thisUser.addPermission(o.toString()); + } + } else if (nodeData instanceof String) { + try { + /* + * Only add this permission if it's not empty + */ + if (!nodeData.toString().isEmpty()) + thisUser.addPermission(nodeData.toString()); + } catch (NullPointerException e) { + // Ignore this entry as it's null. + } + } + thisUser.sortPermissions(); + } + + // SUBGROUPS NODES + + nodeData = null; + try { + nodeData = thisUserNode.get("subgroups"); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found in 'subgroups' for user: " + usersKey + " in file: " + usersFile.getPath()); + } + + if (nodeData == null) { + /* + * If no subgroups node is found, or it's empty + * do nothing. + */ + } else if (nodeData instanceof List) { + for (Object o : ((List) nodeData)) { + Group subGrp = ph.getGroup(o.toString()); + if (subGrp != null) { + thisUser.addSubGroup(subGrp); + } else { + GroupManager.logger.warning("Subgroup '" + o.toString() + "' not found for user: " + thisUser.getName() + ". Ignoring entry in file: " + usersFile.getPath()); + } + } + } else if (nodeData instanceof String) { + Group subGrp = ph.getGroup(nodeData.toString()); + if (subGrp != null) { + thisUser.addSubGroup(subGrp); + } else { + GroupManager.logger.warning("Subgroup '" + nodeData.toString() + "' not found for user: " + thisUser.getName() + ". Ignoring entry in file: " + usersFile.getPath()); + } + } + + // USER INFO NODE + + nodeData = null; + try { + nodeData = thisUserNode.get("info"); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found in 'info' section for user: " + usersKey + " in file: " + usersFile.getPath()); + } + + if (nodeData == null) { + /* + * If no info node is found, or it's empty + * do nothing. + */ + } else if (nodeData instanceof Map) { + thisUser.setVariables((Map<String, Object>) nodeData); + + } else + throw new IllegalArgumentException("Unknown entry found in 'info' section for user: " + thisUser.getName() + " in file: " + usersFile.getPath()); + + // END INFO NODE + + // PRIMARY GROUP + + nodeData = null; + try { + nodeData = thisUserNode.get("group"); + } catch (Exception ex) { + throw new IllegalArgumentException("Bad format found in 'group' section for user: " + usersKey + " in file: " + usersFile.getPath()); + } + + if (nodeData != null) { + Group hisGroup = ph.getGroup(nodeData.toString()); + if (hisGroup == null) { + GroupManager.logger.warning("There is no group " + thisUserNode.get("group").toString() + ", as stated for player " + thisUser.getName() + ": Set to '" + ph.getDefaultGroup().getName() + "' for file: " + usersFile.getPath()); + hisGroup = ph.getDefaultGroup(); + } + thisUser.setGroup(hisGroup); + } else { + thisUser.setGroup(ph.getDefaultGroup()); + } + } + } + + ph.removeUsersChangedFlag(); + // Update the LastModified time. + ph.setUsersFile(usersFile); + ph.setTimeStampUsers(usersFile.lastModified()); + } + + /** + * Write a dataHolder in a specified file + * + * @param ph + * @param groupsFile + */ + public static void writeGroups(WorldDataHolder ph, File groupsFile) { + + Map<String, Object> root = new HashMap<String, Object>(); + + Map<String, Object> groupsMap = new HashMap<String, Object>(); + + root.put("groups", groupsMap); + for (String groupKey : ph.getGroups().keySet()) { + Group group = ph.getGroups().get(groupKey); + + Map<String, Object> aGroupMap = new HashMap<String, Object>(); + groupsMap.put(group.getName(), aGroupMap); + + if (ph.getDefaultGroup() == null) { + GroupManager.logger.severe("There is no default group for world: " + ph.getName()); + } + aGroupMap.put("default", group.equals(ph.getDefaultGroup())); + + 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)); + } + + aGroupMap.put("inheritance", group.getInherits()); + + aGroupMap.put("permissions", group.getPermissionList()); + } + + if (!root.isEmpty()) { + DumperOptions opt = new DumperOptions(); + opt.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + final Yaml yaml = new Yaml(opt); + try { + OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(groupsFile), "UTF-8"); + + String newLine = System.getProperty("line.separator"); + + out.write("# Group inheritance" + newLine); + out.write("#" + newLine); + out.write("# Any inherited groups prefixed with a g: are global groups" + newLine); + out.write("# and are inherited from the GlobalGroups.yml." + newLine); + out.write("#" + newLine); + out.write("# Groups without the g: prefix are groups local to this world" + newLine); + out.write("# and are defined in the this groups.yml file." + newLine); + out.write("#" + newLine); + out.write("# Local group inheritances define your promotion tree when using 'manpromote/mandemote'" + newLine); + out.write(newLine); + + yaml.dump(root, out); + out.close(); + } catch (UnsupportedEncodingException ex) { + } catch (FileNotFoundException ex) { + } catch (IOException e) { + } + } + + // Update the LastModified time. + ph.setGroupsFile(groupsFile); + ph.setTimeStampGroups(groupsFile.lastModified()); + ph.removeGroupsChangedFlag(); + + if (GroupManager.isLoaded()) + GroupManagerEventHandler.callEvent(GMSystemEvent.Action.SAVED); + + /* + * FileWriter tx = null; + * try { + * tx = new FileWriter(groupsFile, false); + * tx.write(yaml.dump(root)); + * tx.flush(); + * } catch (Exception e) { + * } finally { + * try { + * tx.close(); + * } catch (IOException ex) { + * } + * } + */ + } + + /** + * Write a dataHolder in a specified file + * + * @param ph + * @param usersFile + */ + public static void writeUsers(WorldDataHolder ph, File usersFile) { + + Map<String, Object> root = new HashMap<String, Object>(); + + Map<String, Object> usersMap = new HashMap<String, Object>(); + root.put("users", usersMap); + for (String userKey : ph.getUsers().keySet()) { + User user = ph.getUsers().get(userKey); + if ((user.getGroup() == null || user.getGroup().equals(ph.getDefaultGroup())) && user.getPermissionList().isEmpty() && user.getVariables().isEmpty() && user.isSubGroupsEmpty()) { + continue; + } + + Map<String, Object> aUserMap = new HashMap<String, Object>(); + usersMap.put(user.getName(), aUserMap); + + if (user.getGroup() == null) { + aUserMap.put("group", ph.getDefaultGroup().getName()); + } else { + aUserMap.put("group", user.getGroup().getName()); + } + // USER INFO NODE - BETA + if (user.getVariables().getSize() > 0) { + Map<String, Object> infoMap = new HashMap<String, Object>(); + aUserMap.put("info", infoMap); + for (String infoKey : user.getVariables().getVarKeyList()) { + infoMap.put(infoKey, user.getVariables().getVarObject(infoKey)); + } + } + // END USER INFO NODE - BETA + aUserMap.put("permissions", user.getPermissionList()); + + // SUBGROUPS NODE - BETA + aUserMap.put("subgroups", user.subGroupListStringCopy()); + // END SUBGROUPS NODE - BETA + } + + if (!root.isEmpty()) { + DumperOptions opt = new DumperOptions(); + opt.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + final Yaml yaml = new Yaml(opt); + try { + OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(usersFile), "UTF-8"); + yaml.dump(root, out); + out.close(); + } catch (UnsupportedEncodingException ex) { + } catch (FileNotFoundException ex) { + } catch (IOException e) { + } + } + + // Update the LastModified time. + ph.setUsersFile(usersFile); + ph.setTimeStampUsers(usersFile.lastModified()); + ph.removeUsersChangedFlag(); + + if (GroupManager.isLoaded()) + GroupManagerEventHandler.callEvent(GMSystemEvent.Action.SAVED); + + /* + * FileWriter tx = null; + * try { + * tx = new FileWriter(usersFile, false); + * tx.write(yaml.dump(root)); + * tx.flush(); + * } catch (Exception e) { + * } finally { + * try { + * tx.close(); + * } catch (IOException ex) { + * } + * } + */ + } + + /** + * Don't use this. Unless you want to make this plugin to interact with + * original Nijikokun Permissions + * This method is supposed to make the original one reload the file, and + * propagate the changes made here. + * + * Prefer to use the AnjoCaido's fake version of Nijikokun's Permission + * plugin. + * The AnjoCaido's Permission can propagate the changes made on this plugin + * instantly, + * without need to save the file. + * + * @param server the server that holds the plugin + * @deprecated it is not used anymore... unless if you use original + * Permissions + */ + @Deprecated + public static void reloadOldPlugins(Server server) { + + // Only reload permissions + PluginManager pm = server.getPluginManager(); + Plugin[] plugins = pm.getPlugins(); + for (int i = 0; i < plugins.length; i++) { + // plugins[i].getConfiguration().load(); + try { + plugins[i].getClass().getMethod("setupPermissions").invoke(plugins[i]); + } catch (Exception ex) { + continue; + } + } + } + + /** + * @return the permissionsHandler + */ + public AnjoPermissionsHandler getPermissionsHandler() { + + if (permissionsHandler == null) { + permissionsHandler = new AnjoPermissionsHandler(this); + } + return permissionsHandler; + } + + /** + * @param haveUsersChanged the haveUsersChanged to set + */ + public void setUsersChanged(boolean haveUsersChanged) { + + users.setUsersChanged(haveUsersChanged); + } + + /** + * + * @return true if any user data has changed + */ + public boolean haveUsersChanged() { + + if (users.HaveUsersChanged()) { + return true; + } + for (User u : users.getUsers().values()) { + if (u.isChanged()) { + return true; + } + } + return false; + } + + /** + * @param setGroupsChanged the haveGroupsChanged to set + */ + public void setGroupsChanged(boolean setGroupsChanged) { + + groups.setGroupsChanged(setGroupsChanged); + } + + /** + * + * @return true if any group data has changed. + */ + public boolean haveGroupsChanged() { + + if (groups.HaveGroupsChanged()) { + return true; + } + for (Group g : groups.getGroups().values()) { + if (g.isChanged()) { + return true; + } + } + return false; + } + + /** + * + */ + public void removeUsersChangedFlag() { + + setUsersChanged(false); + for (User u : getUsers().values()) { + u.flagAsSaved(); + } + } + + /** + * + */ + public void removeGroupsChangedFlag() { + + setGroupsChanged(false); + for (Group g : getGroups().values()) { + g.flagAsSaved(); + } + } + + /** + * @return the usersFile + */ + public File getUsersFile() { + + return users.getUsersFile(); + } + + /** + * @param file the usersFile to set + */ + public void setUsersFile(File file) { + + users.setUsersFile(file); + } + + /** + * @return the groupsFile + */ + public File getGroupsFile() { + + return groups.getGroupsFile(); + } + + /** + * @param file the groupsFile to set + */ + public void setGroupsFile(File file) { + + groups.setGroupsFile(file); + } + + /** + * @return the name + */ + public String getName() { + + return name; + } + + /** + * Resets Groups. + */ + public void resetGroups() { + + // setDefaultGroup(null); + groups.setGroups(new HashMap<String, Group>()); + } + + /** + * Resets Users + */ + public void resetUsers() { + + users.setUsers(new HashMap<String, User>()); + } + + /** + * @return the groups + */ + public Map<String, Group> getGroups() { + + return groups.getGroups(); + } + + /** + * @return the users + */ + public Map<String, User> getUsers() { + + return users.getUsers(); + } + + /** + * @return the groups + */ + public GroupsDataHolder getGroupsObject() { + + return groups; + } + + /** + * @param groupsDataHolder the GroupsDataHolder to set + */ + public void setGroupsObject(GroupsDataHolder groupsDataHolder) { + + groups = groupsDataHolder; + } + + /** + * @return the users + */ + public UsersDataHolder getUsersObject() { + + return users; + } + + /** + * @param usersDataHolder the UsersDataHolder to set + */ + public void setUsersObject(UsersDataHolder usersDataHolder) { + + users = usersDataHolder; + } + + /** + * @return the timeStampGroups + */ + public long getTimeStampGroups() { + + return groups.getTimeStampGroups(); + } + + /** + * @return the timeStampUsers + */ + public long getTimeStampUsers() { + + return users.getTimeStampUsers(); + } + + /** + * @param timeStampGroups the timeStampGroups to set + */ + protected void setTimeStampGroups(long timeStampGroups) { + + groups.setTimeStampGroups(timeStampGroups); + } + + /** + * @param timeStampUsers the timeStampUsers to set + */ + protected void setTimeStampUsers(long timeStampUsers) { + + users.setTimeStampUsers(timeStampUsers); + } + + public void setTimeStamps() { + + if (getGroupsFile() != null) + setTimeStampGroups(getGroupsFile().lastModified()); + if (getUsersFile() != null) + setTimeStampUsers(getUsersFile().lastModified()); + } + +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java new file mode 100644 index 000000000..27a7d9a59 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java @@ -0,0 +1,719 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.dataholder.worlds; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.anjocaido.groupmanager.GroupManager; +import org.anjocaido.groupmanager.dataholder.WorldDataHolder; +import org.anjocaido.groupmanager.dataholder.OverloadedWorldHolder; +import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler; +import org.anjocaido.groupmanager.utils.Tasks; +import org.bukkit.World; +import org.bukkit.configuration.MemorySection; +import org.bukkit.entity.Player; + +/** + * + * @author gabrielcouto + */ +public class WorldsHolder { + + /** + * Map with instances of loaded worlds. + */ + private Map<String, OverloadedWorldHolder> worldsData = new HashMap<String, OverloadedWorldHolder>(); + + /** + * Map of mirrors: <nonExistingWorldName, existingAndLoadedWorldName> + * The key is the mirror. + * The object is the mirrored. + * + * Mirror shows the same data of mirrored. + */ + private Map<String, String> mirrorsGroup = new HashMap<String, String>(); + private Map<String, String> mirrorsUser = new HashMap<String, String>(); + + private String serverDefaultWorldName; + private GroupManager plugin; + private File worldsFolder; + + /** + * + * @param plugin + */ + public WorldsHolder(GroupManager plugin) { + + this.plugin = plugin; + resetWorldsHolder(); + } + + public void resetWorldsHolder() { + + worldsData = new HashMap<String, OverloadedWorldHolder>(); + mirrorsGroup = new HashMap<String, String>(); + mirrorsUser = new HashMap<String, String>(); + + // Setup folders and check files exist for the primary world + verifyFirstRun(); + initialLoad(); + if (serverDefaultWorldName == null) + throw new IllegalStateException("There is no default group! OMG!"); + } + + private void initialLoad() { + + // load the initial world + initialWorldLoading(); + // Configure and load any mirrors and additional worlds as defined in config.yml + mirrorSetUp(); + // search the worlds folder for any manually created worlds (not listed in config.yml) + loadAllSearchedWorlds(); + } + + private void initialWorldLoading() { + + //Load the default world + loadWorld(serverDefaultWorldName); + //defaultWorld = getUpdatedWorldData(serverDefaultWorldName); + } + + private void loadAllSearchedWorlds() { + + /* + * Read all known worlds from Bukkit + * Create the data files if they don't already exist, + * and they are not mirrored. + */ + for (World world : plugin.getServer().getWorlds()) + if ((!worldsData.containsKey(world.getName().toLowerCase())) && ((!mirrorsGroup.containsKey(world.getName().toLowerCase())) || (!mirrorsUser.containsKey(world.getName().toLowerCase())))) + setupWorldFolder(world.getName()); + /* + * Loop over all folders within the worlds folder + * and attempt to load the world data + */ + for (File folder : worldsFolder.listFiles()) { + if (folder.isDirectory()) { + GroupManager.logger.info("World Found: " + folder.getName()); + + /* + * don't load any worlds which are already loaded + * or fully mirrored worlds that don't need data. + */ + if (!worldsData.containsKey(folder.getName().toLowerCase()) && ((!mirrorsGroup.containsKey(folder.getName().toLowerCase())) || (!mirrorsUser.containsKey(folder.getName().toLowerCase())))) { + /* + * Call setupWorldFolder to check case sensitivity + * and convert to lower case, before we attempt to load this + * world. + */ + setupWorldFolder(folder.getName()); + loadWorld(folder.getName().toLowerCase()); + } + + } + } + } + + @SuppressWarnings("rawtypes") + public void mirrorSetUp() { + + mirrorsGroup.clear(); + mirrorsUser.clear(); + Map<String, Object> mirrorsMap = plugin.getGMConfig().getMirrorsMap(); + + HashSet<String> mirroredWorlds = new HashSet<String>(); + + if (mirrorsMap != null) { + for (String source : mirrorsMap.keySet()) { + // Make sure all non mirrored worlds have a set of data files. + setupWorldFolder(source); + // Load the world data + if (!worldsData.containsKey(source.toLowerCase())) + loadWorld(source); + + if (mirrorsMap.get(source) instanceof ArrayList) { + ArrayList mirrorList = (ArrayList) mirrorsMap.get(source); + + // These worlds fully mirror their parent + for (Object o : mirrorList) { + String world = o.toString().toLowerCase(); + if (world != serverDefaultWorldName) { + try { + mirrorsGroup.remove(world); + mirrorsUser.remove(world); + } catch (Exception e) { + } + mirrorsGroup.put(world, getWorldData(source).getName()); + mirrorsUser.put(world, getWorldData(source).getName()); + + // Track this world so we can create a datasource for it later + mirroredWorlds.add(o.toString()); + + } else + GroupManager.logger.log(Level.WARNING, "Mirroring error with " + o.toString() + ". Recursive loop detected!"); + } + } else if (mirrorsMap.get(source) instanceof MemorySection) { + MemorySection subSection = (MemorySection) mirrorsMap.get(source); + + for (String key : subSection.getKeys(true)) { + + if (key.toLowerCase() != serverDefaultWorldName) { + + if (subSection.get(key) instanceof ArrayList) { + ArrayList mirrorList = (ArrayList) subSection.get(key); + + // These worlds have defined mirroring + for (Object o : mirrorList) { + String type = o.toString().toLowerCase(); + try { + if (type.equals("groups")) + mirrorsGroup.remove(key.toLowerCase()); + + if (type.equals("users")) + mirrorsUser.remove(key.toLowerCase()); + + } catch (Exception e) { + } + if (type.equals("groups")) + mirrorsGroup.put(key.toLowerCase(), getWorldData(source).getName()); + + if (type.equals("users")) + mirrorsUser.put(key.toLowerCase(), getWorldData(source).getName()); + } + + // Track this world so we can create a datasource for it later + mirroredWorlds.add(key); + + } else + GroupManager.logger.log(Level.WARNING, "Mirroring error with " + key + ". Recursive loop detected!"); + + } else { + throw new IllegalStateException("Unknown mirroring format for " + key); + } + + } + } + } + + // Create a datasource for any worlds not already loaded + for (String world : mirroredWorlds) { + if (!worldsData.containsKey(world.toLowerCase())) { + setupWorldFolder(world); + loadWorld(world, true); + } + } + } + } + + /** + * + */ + public void reloadAll() { + + // Load global groups + GroupManager.getGlobalGroups().load(); + + ArrayList<WorldDataHolder> alreadyDone = new ArrayList<WorldDataHolder>(); + for (WorldDataHolder w : worldsData.values()) { + if (alreadyDone.contains(w)) { + continue; + } + if (!mirrorsGroup.containsKey(w.getName().toLowerCase())) + w.reloadGroups(); + if (!mirrorsUser.containsKey(w.getName().toLowerCase())) + w.reloadUsers(); + + alreadyDone.add(w); + } + + } + + /** + * + * @param worldName + */ + public void reloadWorld(String worldName) { + + if (!mirrorsGroup.containsKey(worldName.toLowerCase())) + getWorldData(worldName).reloadGroups(); + if (!mirrorsUser.containsKey(worldName.toLowerCase())) + getWorldData(worldName).reloadUsers(); + } + + /** + * Wrapper to retain backwards compatibility + * (call this function to auto overwrite files) + */ + public void saveChanges() { + + saveChanges(true); + } + + /** + * + */ + public void saveChanges(boolean overwrite) { + + ArrayList<WorldDataHolder> alreadyDone = new ArrayList<WorldDataHolder>(); + Tasks.removeOldFiles(plugin, plugin.getBackupFolder()); + + // Write Global Groups + if (GroupManager.getGlobalGroups().haveGroupsChanged()) { + GroupManager.getGlobalGroups().writeGroups(overwrite); + } else { + if (GroupManager.getGlobalGroups().getTimeStampGroups() < GroupManager.getGlobalGroups().getGlobalGroupsFile().lastModified()) { + System.out.print("Newer GlobalGroups file found (Loading changes)!"); + GroupManager.getGlobalGroups().load(); + } + } + + for (OverloadedWorldHolder w : worldsData.values()) { + if (alreadyDone.contains(w)) { + continue; + } + if (w == null) { + GroupManager.logger.severe("WHAT HAPPENED?"); + continue; + } + if (!mirrorsGroup.containsKey(w.getName().toLowerCase())) + if (w.haveGroupsChanged()) { + if (overwrite || (!overwrite && (w.getTimeStampGroups() >= w.getGroupsFile().lastModified()))) { + // Backup Groups file + backupFile(w, true); + + WorldDataHolder.writeGroups(w, w.getGroupsFile()); + //w.removeGroupsChangedFlag(); + } else { + // Newer file found. + GroupManager.logger.log(Level.WARNING, "Newer Groups file found for " + w.getName() + ", but we have local changes!"); + throw new IllegalStateException("Unable to save unless you issue a '/mansave force'"); + } + } else { + //Check for newer file as no local changes. + if (w.getTimeStampGroups() < w.getGroupsFile().lastModified()) { + System.out.print("Newer Groups file found (Loading changes)!"); + // Backup Groups file + backupFile(w, true); + w.reloadGroups(); + } + } + if (!mirrorsUser.containsKey(w.getName().toLowerCase())) + if (w.haveUsersChanged()) { + if (overwrite || (!overwrite && (w.getTimeStampUsers() >= w.getUsersFile().lastModified()))) { + // Backup Users file + backupFile(w, false); + + WorldDataHolder.writeUsers(w, w.getUsersFile()); + //w.removeUsersChangedFlag(); + } else { + // Newer file found. + GroupManager.logger.log(Level.WARNING, "Newer Users file found for " + w.getName() + ", but we have local changes!"); + throw new IllegalStateException("Unable to save unless you issue a '/mansave force'"); + } + } else { + //Check for newer file as no local changes. + if (w.getTimeStampUsers() < w.getUsersFile().lastModified()) { + System.out.print("Newer Users file found (Loading changes)!"); + // Backup Users file + backupFile(w, false); + w.reloadUsers(); + } + } + alreadyDone.add(w); + } + } + + /** + * Backup the Groups/Users file + * + * @param w + * @param groups + */ + private void backupFile(OverloadedWorldHolder w, Boolean groups) { + + File backupFile = new File(plugin.getBackupFolder(), "bkp_" + w.getName() + (groups ? "_g_" : "_u_") + Tasks.getDateString() + ".yml"); + try { + Tasks.copy((groups ? w.getGroupsFile() : w.getUsersFile()), backupFile); + } catch (IOException ex) { + GroupManager.logger.log(Level.SEVERE, null, ex); + } + } + + /** + * Returns the dataHolder for the given world. + * If the world is not on the worlds list, returns the default world + * holder. + * + * Mirrors return their parent world data. + * If no mirroring data it returns the default world. + * + * @param worldName + * @return OverloadedWorldHolder + */ + public OverloadedWorldHolder getWorldData(String worldName) { + + String worldNameLowered = worldName.toLowerCase(); + + // Find this worlds data + if (worldsData.containsKey(worldNameLowered)) + return getUpdatedWorldData(worldNameLowered); + + // Oddly no data source was found for this world so return the default. + GroupManager.logger.finest("Requested world " + worldName + " not found or badly mirrored. Returning default world..."); + return getDefaultWorld(); + } + + /** + * Get the requested world data and update it's dataSource to be relevant + * for this world + * + * @param worldName + * @return updated world holder + */ + private OverloadedWorldHolder getUpdatedWorldData(String worldName) { + + String worldNameLowered = worldName.toLowerCase(); + + if (worldsData.containsKey(worldNameLowered)) { + OverloadedWorldHolder data = worldsData.get(worldNameLowered); + data.updateDataSource(); + return data; + } + return null; + + } + + /** + * Do a matching of playerName, if its found only one player, do + * getWorldData(player) + * + * @param playerName + * @return null if matching returned no player, or more than one. + */ + public OverloadedWorldHolder getWorldDataByPlayerName(String playerName) { + + List<Player> matchPlayer = plugin.getServer().matchPlayer(playerName); + if (matchPlayer.size() == 1) { + return getWorldData(matchPlayer.get(0)); + } + return null; + } + + /** + * Retrieves the field player.getWorld().getName() and do + * getWorld(worldName) + * + * @param player + * @return OverloadedWorldHolder + */ + public OverloadedWorldHolder getWorldData(Player player) { + + return getWorldData(player.getWorld().getName()); + } + + /** + * It does getWorld(worldName).getPermissionsHandler() + * + * @param worldName + * @return AnjoPermissionsHandler + */ + public AnjoPermissionsHandler getWorldPermissions(String worldName) { + + return getWorldData(worldName).getPermissionsHandler(); + } + + /** + * Returns the PermissionsHandler for this player data + * + * @param player + * @return AnjoPermissionsHandler + */ + public AnjoPermissionsHandler getWorldPermissions(Player player) { + + return getWorldData(player).getPermissionsHandler(); + } + + /** + * Id does getWorldDataByPlayerName(playerName). + * If it doesnt return null, it will return result.getPermissionsHandler() + * + * @param playerName + * @return null if the player matching gone wrong. + */ + public AnjoPermissionsHandler getWorldPermissionsByPlayerName(String playerName) { + + WorldDataHolder dh = getWorldDataByPlayerName(playerName); + if (dh != null) { + return dh.getPermissionsHandler(); + } + return null; + } + + private void verifyFirstRun() { + + Properties server = new Properties(); + try { + server.load(new FileInputStream(new File("server.properties"))); + serverDefaultWorldName = server.getProperty("level-name").toLowerCase(); + setupWorldFolder(serverDefaultWorldName); + } catch (IOException ex) { + GroupManager.logger.log(Level.SEVERE, null, ex); + } + + } + + public void setupWorldFolder(String worldName) { + + String worldNameLowered = worldName.toLowerCase(); + + worldsFolder = new File(plugin.getDataFolder(), "worlds"); + if (!worldsFolder.exists()) { + worldsFolder.mkdirs(); + } + + File defaultWorldFolder = new File(worldsFolder, worldNameLowered); + if ((!defaultWorldFolder.exists()) && ((!mirrorsGroup.containsKey(worldNameLowered))) || (!mirrorsUser.containsKey(worldNameLowered))) { + + /* + * check and convert all old case sensitive folders to lower case + */ + File casedWorldFolder = new File(worldsFolder, worldName); + if ((casedWorldFolder.exists()) && (casedWorldFolder.getName().toLowerCase().equals(worldNameLowered))) { + /* + * Rename the old folder to the new lower cased format + */ + casedWorldFolder.renameTo(new File(worldsFolder, worldNameLowered)); + } else { + /* + * Else we just create the folder + */ + defaultWorldFolder.mkdirs(); + } + } + if (defaultWorldFolder.exists()) { + if (!mirrorsGroup.containsKey(worldNameLowered)) { + File groupsFile = new File(defaultWorldFolder, "groups.yml"); + if (!groupsFile.exists() || groupsFile.length() == 0) { + + InputStream template = plugin.getResourceAsStream("groups.yml"); + try { + Tasks.copy(template, groupsFile); + } catch (IOException ex) { + GroupManager.logger.log(Level.SEVERE, null, ex); + } + } + } + + if (!mirrorsUser.containsKey(worldNameLowered)) { + File usersFile = new File(defaultWorldFolder, "users.yml"); + if (!usersFile.exists() || usersFile.length() == 0) { + + InputStream template = plugin.getResourceAsStream("users.yml"); + try { + Tasks.copy(template, usersFile); + } catch (IOException ex) { + GroupManager.logger.log(Level.SEVERE, null, ex); + } + + } + } + } + } + + /** + * Copies the specified world data to another world + * + * @param fromWorld + * @param toWorld + * @return true if successfully copied. + */ + public boolean cloneWorld(String fromWorld, String toWorld) { + + File fromWorldFolder = new File(worldsFolder, fromWorld.toLowerCase()); + File toWorldFolder = new File(worldsFolder, toWorld.toLowerCase()); + if (toWorldFolder.exists() || !fromWorldFolder.exists()) { + return false; + } + File fromWorldGroups = new File(fromWorldFolder, "groups.yml"); + File fromWorldUsers = new File(fromWorldFolder, "users.yml"); + if (!fromWorldGroups.exists() || !fromWorldUsers.exists()) { + return false; + } + File toWorldGroups = new File(toWorldFolder, "groups.yml"); + File toWorldUsers = new File(toWorldFolder, "users.yml"); + toWorldFolder.mkdirs(); + try { + Tasks.copy(fromWorldGroups, toWorldGroups); + Tasks.copy(fromWorldUsers, toWorldUsers); + } catch (IOException ex) { + Logger.getLogger(WorldsHolder.class.getName()).log(Level.SEVERE, null, ex); + return false; + } + return true; + } + + /** + * Wrapper for LoadWorld(String,Boolean) for backwards compatibility + * + * Load a world from file. + * If it already been loaded, summon reload method from dataHolder. + * + * @param worldName + */ + public void loadWorld(String worldName) { + + loadWorld(worldName, false); + } + + /** + * Load a world from file. + * If it already been loaded, summon reload method from dataHolder. + * + * @param worldName + */ + public void loadWorld(String worldName, Boolean isMirror) { + + String worldNameLowered = worldName.toLowerCase(); + + if (worldsData.containsKey(worldNameLowered)) { + worldsData.get(worldNameLowered).reload(); + return; + } + GroupManager.logger.finest("Trying to load world " + worldName + "..."); + File thisWorldFolder = new File(worldsFolder, worldNameLowered); + if ((isMirror) || (thisWorldFolder.exists() && thisWorldFolder.isDirectory())) { + + // Setup file handles, if not mirrored + File groupsFile = (mirrorsGroup.containsKey(worldNameLowered)) ? null : new File(thisWorldFolder, "groups.yml"); + File usersFile = (mirrorsUser.containsKey(worldNameLowered)) ? null : new File(thisWorldFolder, "users.yml"); + + if ((groupsFile != null) && (!groupsFile.exists())) { + throw new IllegalArgumentException("Groups file for world '" + worldName + "' doesnt exist: " + groupsFile.getPath()); + } + if ((usersFile != null) && (!usersFile.exists())) { + throw new IllegalArgumentException("Users file for world '" + worldName + "' doesnt exist: " + usersFile.getPath()); + } + + WorldDataHolder tempHolder = new WorldDataHolder(worldName); + + // Map the group object for any mirror + if (mirrorsGroup.containsKey(worldNameLowered)) + tempHolder.setGroupsObject(this.getWorldData(mirrorsGroup.get(worldNameLowered)).getGroupsObject()); + else + tempHolder.loadGroups(groupsFile); + + // Map the user object for any mirror + if (mirrorsUser.containsKey(worldNameLowered)) + tempHolder.setUsersObject(this.getWorldData(mirrorsUser.get(worldNameLowered)).getUsersObject()); + else + tempHolder.loadUsers(usersFile); + + OverloadedWorldHolder thisWorldData = new OverloadedWorldHolder(tempHolder); + + // null the object so we don't keep file handles open where we shouldn't + tempHolder = null; + + // Set the file TimeStamps as it will be default from the initial load. + thisWorldData.setTimeStamps(); + + if (thisWorldData != null) { + GroupManager.logger.finest("Successful load of world " + worldName + "..."); + worldsData.put(worldNameLowered, thisWorldData); + return; + } + + //GroupManager.logger.severe("Failed to load world " + worldName + "..."); + } + } + + /** + * Tells if the such world has been mapped. + * + * It will return true if world is a mirror. + * + * @param worldName + * @return true if world is loaded or mirrored. false if not listed + */ + public boolean isInList(String worldName) { + + if (worldsData.containsKey(worldName.toLowerCase()) || mirrorsGroup.containsKey(worldName.toLowerCase()) || mirrorsUser.containsKey(worldName.toLowerCase())) { + return true; + } + return false; + } + + /** + * Verify if world has it's own file permissions. + * + * @param worldName + * @return true if it has its own holder. false if not. + */ + public boolean hasOwnData(String worldName) { + + if (worldsData.containsKey(worldName.toLowerCase()) && (!mirrorsGroup.containsKey(worldName.toLowerCase()) || !mirrorsUser.containsKey(worldName.toLowerCase()))) { + return true; + } + return false; + } + + /** + * @return the defaultWorld + */ + public OverloadedWorldHolder getDefaultWorld() { + + return getUpdatedWorldData(serverDefaultWorldName); + } + + /** + * Returns all physically loaded worlds which have at least + * one of their own data sets for users or groups. + * + * @return ArrayList<OverloadedWorldHolder> of all loaded worlds + */ + public ArrayList<OverloadedWorldHolder> allWorldsDataList() { + + ArrayList<OverloadedWorldHolder> list = new ArrayList<OverloadedWorldHolder>(); + for (OverloadedWorldHolder data : worldsData.values()) { + if ((!list.contains(data)) && (!mirrorsGroup.containsKey(data.getName().toLowerCase()) || !mirrorsUser.containsKey(data.getName().toLowerCase()))) { + + String worldNameLowered = data.getName().toLowerCase(); + String usersMirror = mirrorsUser.get(worldNameLowered); + String groupsMirror = mirrorsGroup.get(worldNameLowered); + + // is users mirrored? + if (usersMirror != null) { + + // If both are mirrored + if (groupsMirror != null) { + + // if the data sources are the same, return the parent + if (usersMirror == groupsMirror) { + if (!list.contains(usersMirror.toLowerCase())) + list.add(worldsData.get(usersMirror.toLowerCase())); + continue; + } + // Both data sources are mirrors, but they are from different parents + // so fall through to add the actual data object. + } + // Groups isn't a mirror so fall through to add this this worlds data source + } + + // users isn't mirrored so we need to add this worlds data source + list.add(data); + } + } + return list; + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMGroupEvent.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMGroupEvent.java new file mode 100644 index 000000000..af3fb6135 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMGroupEvent.java @@ -0,0 +1,87 @@ +package org.anjocaido.groupmanager.events;
+
+import org.anjocaido.groupmanager.GroupManager;
+import org.anjocaido.groupmanager.data.Group;
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * @author ElgarL
+ *
+ */
+public class GMGroupEvent extends Event {
+
+ /**
+ *
+ */
+ private static final HandlerList handlers = new HandlerList();
+
+ @Override
+ public HandlerList getHandlers() {
+
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList() {
+
+ return handlers;
+ }
+
+ //////////////////////////////
+
+ protected Group group;
+
+ protected String groupName;
+
+ protected Action action;
+
+ public GMGroupEvent(Group group, Action action) {
+
+ super();
+
+ this.group = group;
+ this.action = action;
+ this.groupName = group.getName();
+ }
+
+ public GMGroupEvent(String groupName, Action action) {
+
+ super();
+
+ this.groupName = groupName;
+ this.action = action;
+ }
+
+ public Action getAction() {
+
+ return this.action;
+ }
+
+ public Group getGroup() {
+
+ return group;
+ }
+
+ public String getGroupName() {
+
+ return groupName;
+ }
+
+ public enum Action {
+ GROUP_PERMISSIONS_CHANGED, GROUP_INHERITANCE_CHANGED, GROUP_INFO_CHANGED, GROUP_ADDED, GROUP_REMOVED,
+ }
+
+ public void schedule(final GMGroupEvent event) {
+
+ if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(Bukkit.getPluginManager().getPlugin("GroupManager"), new Runnable() {
+
+ @Override
+ public void run() {
+
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ }
+ }, 1) == -1)
+ GroupManager.logger.warning("Could not schedule GM Event.");
+ }
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMSystemEvent.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMSystemEvent.java new file mode 100644 index 000000000..d11581356 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMSystemEvent.java @@ -0,0 +1,62 @@ +package org.anjocaido.groupmanager.events;
+
+import org.anjocaido.groupmanager.GroupManager;
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * @author ElgarL
+ *
+ */
+public class GMSystemEvent extends Event {
+
+ /**
+ *
+ */
+ private static final HandlerList handlers = new HandlerList();
+
+ @Override
+ public HandlerList getHandlers() {
+
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList() {
+
+ return handlers;
+ }
+
+ //////////////////////////////
+
+ protected Action action;
+
+ public GMSystemEvent(Action action) {
+
+ super();
+
+ this.action = action;
+ }
+
+ public Action getAction() {
+
+ return this.action;
+ }
+
+ public enum Action {
+ RELOADED, SAVED, DEFAULT_GROUP_CHANGED, VALIDATE_TOGGLE,
+ }
+
+ public void schedule(final GMSystemEvent event) {
+
+ if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(Bukkit.getPluginManager().getPlugin("GroupManager"), new Runnable() {
+
+ @Override
+ public void run() {
+
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ }
+ }, 1) == -1)
+ GroupManager.logger.warning("Could not schedule GM Event.");
+ }
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMUserEvent.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMUserEvent.java new file mode 100644 index 000000000..361e7d4cc --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMUserEvent.java @@ -0,0 +1,87 @@ +package org.anjocaido.groupmanager.events;
+
+import org.anjocaido.groupmanager.GroupManager;
+import org.anjocaido.groupmanager.data.User;
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * @author ElgarL
+ *
+ */
+public class GMUserEvent extends Event {
+
+ /**
+ *
+ */
+ private static final HandlerList handlers = new HandlerList();
+
+ @Override
+ public HandlerList getHandlers() {
+
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList() {
+
+ return handlers;
+ }
+
+ //////////////////////////////
+
+ protected User user;
+
+ protected String userName;
+
+ protected Action action;
+
+ public GMUserEvent(User user, Action action) {
+
+ super();
+
+ this.user = user;
+ this.action = action;
+ this.userName = user.getName();
+ }
+
+ public GMUserEvent(String userName, Action action) {
+
+ super();
+
+ this.userName = userName;
+ this.action = action;
+ }
+
+ public Action getAction() {
+
+ return this.action;
+ }
+
+ public User getUser() {
+
+ return user;
+ }
+
+ public String getUserName() {
+
+ return userName;
+ }
+
+ public enum Action {
+ USER_PERMISSIONS_CHANGED, USER_INHERITANCE_CHANGED, USER_INFO_CHANGED, USER_GROUP_CHANGED, USER_SUBGROUP_CHANGED, USER_ADDED, USER_REMOVED,
+ }
+
+ public void schedule(final GMUserEvent event) {
+
+ if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(Bukkit.getPluginManager().getPlugin("GroupManager"), new Runnable() {
+
+ @Override
+ public void run() {
+
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ }
+ }, 1) == -1)
+ GroupManager.logger.warning("Could not schedule GM Event.");
+ }
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMWorldListener.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMWorldListener.java new file mode 100644 index 000000000..f7a7109ab --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GMWorldListener.java @@ -0,0 +1,46 @@ +package org.anjocaido.groupmanager.events;
+
+import org.anjocaido.groupmanager.GroupManager;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.world.WorldInitEvent;
+
+/**
+ * @author ElgarL
+ *
+ * Handle new world creation from other plugins
+ *
+ */
+public class GMWorldListener implements Listener {
+
+ private final GroupManager plugin;
+
+ public GMWorldListener(GroupManager instance) {
+
+ plugin = instance;
+ registerEvents();
+ }
+
+ private void registerEvents() {
+
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onWorldInit(WorldInitEvent event) {
+
+ String worldName = event.getWorld().getName();
+
+ if (GroupManager.isLoaded() && !plugin.getWorldsHolder().isInList(worldName)) {
+ GroupManager.logger.info("New world detected...");
+ GroupManager.logger.info("Creating data for: " + worldName);
+ plugin.getWorldsHolder().setupWorldFolder(worldName);
+ plugin.getWorldsHolder().loadWorld(worldName);
+ if (plugin.getWorldsHolder().isInList(worldName)) {
+ GroupManager.logger.info("Don't forget to configure/mirror this world in config.yml.");
+ } else
+ GroupManager.logger.severe("Failed to configure this world.");
+ }
+ }
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GroupManagerEventHandler.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GroupManagerEventHandler.java new file mode 100644 index 000000000..5fc555cc4 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/events/GroupManagerEventHandler.java @@ -0,0 +1,53 @@ +package org.anjocaido.groupmanager.events;
+
+import org.anjocaido.groupmanager.data.Group;
+import org.anjocaido.groupmanager.data.User;
+
+/**
+ * @author ElgarL
+ *
+ * Handles all Event generation.
+ *
+ */
+public class GroupManagerEventHandler {
+
+ protected static void callEvent(GMGroupEvent event) {
+
+ event.schedule(event);
+ }
+
+ protected static void callEvent(GMUserEvent event) {
+
+ event.schedule(event);
+ }
+
+ protected static void callEvent(GMSystemEvent event) {
+
+ event.schedule(event);
+ }
+
+ public static void callEvent(Group group, GMGroupEvent.Action action) {
+
+ callEvent(new GMGroupEvent(group, action));
+ }
+
+ public static void callEvent(String groupName, GMGroupEvent.Action action) {
+
+ callEvent(new GMGroupEvent(groupName, action));
+ }
+
+ public static void callEvent(User user, GMUserEvent.Action action) {
+
+ callEvent(new GMUserEvent(user, action));
+ }
+
+ public static void callEvent(String userName, GMUserEvent.Action action) {
+
+ callEvent(new GMUserEvent(userName, action));
+ }
+
+ public static void callEvent(GMSystemEvent.Action action) {
+
+ callEvent(new GMSystemEvent(action));
+ }
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java new file mode 100644 index 000000000..efad11df4 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java @@ -0,0 +1,1184 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.permissions; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.anjocaido.groupmanager.GroupManager; +import org.anjocaido.groupmanager.data.Group; +import org.anjocaido.groupmanager.dataholder.WorldDataHolder; +import org.anjocaido.groupmanager.data.User; +import org.anjocaido.groupmanager.utils.PermissionCheckResult; +import org.bukkit.entity.Player; + +/** + * Everything here maintains the model created by Nijikokun + * + * But implemented to use GroupManager system. Which provides instant changes, + * without file access. + * + * It holds permissions only for one single world. + * + * @author gabrielcouto, ElgarL + */ +public class AnjoPermissionsHandler extends PermissionsReaderInterface { + + WorldDataHolder ph = null; + + /** + * It needs a WorldDataHolder to work with. + * + * @param holder + */ + public AnjoPermissionsHandler(WorldDataHolder holder) { + + ph = holder; + } + + /** + * A short name method, for permission method. + * + * @param player + * @param permission + * @return true if the player has the permission + */ + @Override + public boolean has(Player player, String permission) { + + return permission(player, permission); + } + + /** + * Checks if a player can use that permission node. + * + * @param player + * @param permission + * @return true if the player has the permission + */ + @Override + public boolean permission(Player player, String permission) { + + return checkUserPermission(ph.getUser(player.getName()).updatePlayer(player), permission); + } + + /** + * Checks if a player can use that permission node. + * + * @param playerName + * @param permission + * @return true if the player has the permission + */ + public boolean permission(String playerName, String permission) { + + return checkUserPermission(ph.getUser(playerName), permission); + } + + /** + * Returns the name of the group of that player name. + * + * @param userName + * @return String of players group name. + */ + @Override + public String getGroup(String userName) { + + return ph.getUser(userName).getGroup().getName(); + } + + /** + * Returns All permissions (including inheritance and sub groups) for the + * player, including child nodes from Bukkit. + * + * @param userName + * @return List<String> of all players permissions. + */ + @Override + public List<String> getAllPlayersPermissions(String userName) { + + List<String> perms = new ArrayList<String>(); + + perms.addAll(getAllPlayersPermissions(userName, true)); + + return perms; + } + + /** + * Returns All permissions (including inheritance and sub groups) for the + * player. With or without Bukkit child nodes. + * + * @param userName + * @return Set<String> of all players permissions. + */ + @Override + public Set<String> getAllPlayersPermissions(String userName, Boolean includeChildren) { + + Set<String> playerPermArray = new HashSet<String>(); + + // Add the players own permissions. + playerPermArray.addAll(populatePerms(ph.getUser(userName).getPermissionList(), includeChildren)); + + ArrayList<String> alreadyProcessed = new ArrayList<String>(); + + // fetch all group permissions + for (String group : getGroups(userName)) { + // Don't process a group more than once. + if (!alreadyProcessed.contains(group)) { + alreadyProcessed.add(group); + + Set<String> groupPermArray = new HashSet<String>(); + + if (group.startsWith("g:") && GroupManager.getGlobalGroups().hasGroup(group)) { + // GlobalGroups + groupPermArray = populatePerms(GroupManager.getGlobalGroups().getGroupsPermissions(group), includeChildren); + + } else { + // World Groups + groupPermArray = populatePerms(ph.getGroup(group).getPermissionList(), includeChildren); + } + + // Add all group permissions, unless negated by earlier permissions. + for (String perm : groupPermArray) { + boolean negated = (perm.startsWith("-")); + // Perm doesn't already exists and there is no negation for it + // or It's a negated perm where a normal perm doesn't exists (don't allow inheritance to negate higher perms) + if ((!negated && !playerPermArray.contains(perm) && !playerPermArray.contains("-" + perm)) || (negated && !playerPermArray.contains(perm.substring(1)) && !playerPermArray.contains("-" + perm))) + playerPermArray.add(perm); + } + } + + } + // Collections.sort(playerPermArray, StringPermissionComparator.getInstance()); + + return playerPermArray; + } + + private Set<String> populatePerms(List<String> permsList, boolean includeChildren) { + + // Create a new array so it's modifiable. + List<String> perms = new ArrayList<String>(permsList); + Set<String> permArray = new HashSet<String>(); + Boolean allPerms = false; + + // Allow * node to populate ALL permissions to Bukkit. + if (perms.contains("*")) { + permArray.addAll(GroupManager.BukkitPermissions.getAllRegisteredPermissions(includeChildren)); + allPerms = true; + perms.remove("*"); + } + + for (String perm : perms) { + + /** + * all permission sets are passed here pre-sorted, alphabetically. + * This means negated nodes will be processed before all permissions + * other than *. + */ + boolean negated = perm.startsWith("-"); + + if (!permArray.contains(perm)) { + permArray.add(perm); + + if ((negated) && (permArray.contains(perm.substring(1)))) + permArray.remove(perm.substring(1)); + + /** + * Process child nodes if required, + * or this is a negated node AND we used * to include all + * permissions, + * in which case we need to remove all children of that node. + */ + if ((includeChildren) || (negated && allPerms)) { + + Map<String, Boolean> children = GroupManager.BukkitPermissions.getAllChildren((negated ? perm.substring(1) : perm), new HashSet<String>()); + + if (children != null) { + if (negated) + if (allPerms) { + + // Remove children of negated nodes + for (String child : children.keySet()) + if (children.get(child)) + if (permArray.contains(child)) + permArray.remove(child); + + } else { + + // Add child nodes + for (String child : children.keySet()) + if (children.get(child)) + if ((!permArray.contains(child)) && (!permArray.contains("-" + child))) + permArray.add(child); + } + } + } + } + } + + return permArray; + } + + /** + * Verify if player is in such group. It will check it's groups inheritance. + * + * So if you have a group Admin > Moderator + * + * And verify the player 'MyAdmin', which is Admin, it will return true for + * both Admin or Moderator groups. + * + * If you have a player 'MyModerator', which is Moderator, it will give + * false if you pass Admin in group parameter. + * + * @param name + * @param group + * @return true if in group (with inheritance) + */ + @Override + public boolean inGroup(String name, String group) { + + if (hasGroupInInheritance(ph.getUser(name).getGroup(), group)) { + return true; + } + for (Group subGroup : ph.getUser(name).subGroupListCopy()) { + if (hasGroupInInheritance(subGroup, group)) { + return true; + } + } + return false; + } + + /** + * Gets the appropriate prefix for the user. This method is a utility method + * for chat plugins to get the user's prefix without having to look at every + * one of the user's ancestors. Returns an empty string if user has no + * parent groups. + * + * @param user + * Player's name + * @return Player's prefix + */ + @Override + public String getUserPrefix(String user) { + + String prefix = ph.getUser(user).getVariables().getVarString("prefix"); + if (prefix.length() != 0) { + return prefix; + } + + return getGroupPrefix(getGroup(user)); + } + + /** + * Gets the appropriate prefix for the user. This method is a utility method + * for chat plugins to get the user's prefix without having to look at every + * one of the user's ancestors. Returns an empty string if user has no + * parent groups. + * + * @param user + * Player's name + * @return Player's prefix + */ + @Override + public String getUserSuffix(String user) { + + String suffix = ph.getUser(user).getVariables().getVarString("suffix"); + if (suffix.length() != 0) { + return suffix; + } + + return getGroupSuffix(getGroup(user)); + + } + + /** + * Gets name of the primary group of the user. Returns the name of the + * default group if user has no parent groups, or "Default" if there is no + * default group for that world. + * + * @param user + * Player's name + * @return Name of player's primary group + */ + public String getPrimaryGroup(String user) { + + return getGroup(user); + + } + + /** + * Check if user can build. Checks inheritance and subgroups. + * + * @param userName + * Player's name + * @return true if the user can build + */ + public boolean canUserBuild(String userName) { + + return getPermissionBoolean(userName, "build"); + + } + + /** + * Returns the String prefix for the given group + * + * @param groupName + * @return empty string if found none. + */ + @Override + public String getGroupPrefix(String groupName) { + + Group g = ph.getGroup(groupName); + if (g == null) { + return ""; + } + return g.getVariables().getVarString("prefix"); + } + + /** + * Return the suffix for the given group name + * + * @param groupName + * @return empty string if not found. + */ + @Override + public String getGroupSuffix(String groupName) { + + Group g = ph.getGroup(groupName); + if (g == null) { + return ""; + } + return g.getVariables().getVarString("suffix"); + } + + /** + * Checks the specified group for the Info Build node. Does NOT check + * inheritance + * + * @param groupName + * @return true if can build + */ + @Override + public boolean canGroupBuild(String groupName) { + + Group g = ph.getGroup(groupName); + if (g == null) { + return false; + } + return g.getVariables().getVarBoolean("build"); + } + + /** + * It returns a string variable value, set in the INFO node of the group. It + * will harvest inheritance for value. + * + * @param groupName + * @param variable + * @return null if no group with that variable is found. + */ + @Override + public String getGroupPermissionString(String groupName, String variable) { + + Group start = ph.getGroup(groupName); + if (start == null) { + return null; + } + Group result = nextGroupWithVariable(start, variable); + if (result == null) { + return null; + } + return result.getVariables().getVarString(variable); + } + + /** + * It returns a Integer variable value It will harvest inheritance for + * value. + * + * @param groupName + * @param variable + * @return -1 if none found or not parseable. + */ + @Override + public int getGroupPermissionInteger(String groupName, String variable) { + + Group start = ph.getGroup(groupName); + if (start == null) { + return -1; + } + Group result = nextGroupWithVariable(start, variable); + if (result == null) { + return -1; + } + return result.getVariables().getVarInteger(variable); + } + + /** + * Returns a boolean for given variable in INFO node. It will harvest + * inheritance for value. + * + * @param group + * @param variable + * @return false if not found/not parseable. + */ + @Override + public boolean getGroupPermissionBoolean(String group, String variable) { + + Group start = ph.getGroup(group); + if (start == null) { + return false; + } + Group result = nextGroupWithVariable(start, variable); + if (result == null) { + return false; + } + return result.getVariables().getVarBoolean(variable); + } + + /** + * Returns a double value for the given variable name in INFO node. It will + * harvest inheritance for value. + * + * @param group + * @param variable + * @return -1 if not found / not parseable. + */ + @Override + public double getGroupPermissionDouble(String group, String variable) { + + Group start = ph.getGroup(group); + if (start == null) { + return -1; + } + Group result = nextGroupWithVariable(start, variable); + if (result == null) { + return -1; + } + return result.getVariables().getVarDouble(variable); + } + + /** + * Returns the variable value of the user, in INFO node. + * + * @param user + * @param variable + * @return empty string if not found + */ + @Override + public String getUserPermissionString(String user, String variable) { + + User auser = ph.getUser(user); + if (auser == null) { + return ""; + } + return auser.getVariables().getVarString(variable); + } + + /** + * Returns the variable value of the user, in INFO node. + * + * @param user + * @param variable + * @return -1 if not found + */ + @Override + public int getUserPermissionInteger(String user, String variable) { + + User auser = ph.getUser(user); + if (auser == null) { + return -1; + } + return auser.getVariables().getVarInteger(variable); + } + + /** + * Returns the variable value of the user, in INFO node. + * + * @param user + * @param variable + * @return boolean value + */ + @Override + public boolean getUserPermissionBoolean(String user, String variable) { + + User auser = ph.getUser(user); + if (auser == null) { + return false; + } + return auser.getVariables().getVarBoolean(variable); + } + + /** + * Returns the variable value of the user, in INFO node. + * + * @param user + * @param variable + * @return -1 if not found + */ + @Override + public double getUserPermissionDouble(String user, String variable) { + + User auser = ph.getUser(user); + if (auser == null) { + return -1; + } + return auser.getVariables().getVarDouble(variable); + } + + /** + * Returns the variable value of the user, in INFO node. If not found, it + * will search for his Group variables. It will harvest the inheritance and + * subgroups. + * + * @param user + * @param variable + * @return empty string if not found + */ + @Override + public String getPermissionString(String user, String variable) { + + User auser = ph.getUser(user); + if (auser == null) { + return ""; + } + if (auser.getVariables().hasVar(variable)) { + return auser.getVariables().getVarString(variable); + } + Group start = auser.getGroup(); + if (start == null) { + return ""; + } + Group result = nextGroupWithVariable(start, variable); + if (result == null) { + // Check sub groups + if (!auser.isSubGroupsEmpty()) + for (Group subGroup : auser.subGroupListCopy()) { + result = nextGroupWithVariable(subGroup, variable); + // Found value? + if (result != null) + continue; + } + if (result == null) + return ""; + } + return result.getVariables().getVarString(variable); + // return getUserPermissionString(user, variable); + } + + /** + * Returns the variable value of the user, in INFO node. If not found, it + * will search for his Group variables. It will harvest the inheritance and + * subgroups. + * + * @param user + * @param variable + * @return -1 if not found + */ + @Override + public int getPermissionInteger(String user, String variable) { + + User auser = ph.getUser(user); + if (auser == null) { + return -1; + } + if (auser.getVariables().hasVar(variable)) { + return auser.getVariables().getVarInteger(variable); + } + Group start = auser.getGroup(); + if (start == null) { + return -1; + } + Group result = nextGroupWithVariable(start, variable); + if (result == null) { + // Check sub groups + if (!auser.isSubGroupsEmpty()) + for (Group subGroup : auser.subGroupListCopy()) { + result = nextGroupWithVariable(subGroup, variable); + // Found value? + if (result != null) + continue; + } + if (result == null) + return -1; + } + return result.getVariables().getVarInteger(variable); + // return getUserPermissionInteger(string, string1); + } + + /** + * Returns the variable value of the user, in INFO node. If not found, it + * will search for his Group variables. It will harvest the inheritance and + * subgroups. + * + * @param user + * @param variable + * @return false if not found or not parseable to true. + */ + @Override + public boolean getPermissionBoolean(String user, String variable) { + + User auser = ph.getUser(user); + if (auser == null) { + return false; + } + if (auser.getVariables().hasVar(variable)) { + return auser.getVariables().getVarBoolean(variable); + } + Group start = auser.getGroup(); + if (start == null) { + return false; + } + Group result = nextGroupWithVariable(start, variable); + if (result == null) { + // Check sub groups + if (!auser.isSubGroupsEmpty()) + for (Group subGroup : auser.subGroupListCopy()) { + result = nextGroupWithVariable(subGroup, variable); + // Found value? + if (result != null) + continue; + } + if (result == null) + return false; + } + return result.getVariables().getVarBoolean(variable); + // return getUserPermissionBoolean(user, string1); + } + + /** + * Returns the variable value of the user, in INFO node. If not found, it + * will search for his Group variables. It will harvest the inheritance and + * subgroups. + * + * @param user + * @param variable + * @return -1 if not found. + */ + @Override + public double getPermissionDouble(String user, String variable) { + + User auser = ph.getUser(user); + if (auser == null) { + return -1.0D; + } + if (auser.getVariables().hasVar(variable)) { + return auser.getVariables().getVarDouble(variable); + } + Group start = auser.getGroup(); + if (start == null) { + return -1.0D; + } + Group result = nextGroupWithVariable(start, variable); + if (result == null) { + // Check sub groups + if (!auser.isSubGroupsEmpty()) + for (Group subGroup : auser.subGroupListCopy()) { + result = nextGroupWithVariable(subGroup, variable); + // Found value? + if (result != null) + continue; + } + if (result == null) + return -1.0D; + } + return result.getVariables().getVarDouble(variable); + // return getUserPermissionDouble(string, string1); + } + + /** + * Does not include User's group permission + * + * @param user + * @param permission + * @return PermissionCheckResult + */ + public PermissionCheckResult checkUserOnlyPermission(User user, String permission) { + + user.sortPermissions(); + PermissionCheckResult result = new PermissionCheckResult(); + result.askedPermission = permission; + result.owner = user; + for (String access : user.getPermissionList()) { + result.resultType = comparePermissionString(access, permission); + if (result.resultType != PermissionCheckResult.Type.NOTFOUND) { + return result; + } + } + result.resultType = PermissionCheckResult.Type.NOTFOUND; + return result; + } + + /** + * Returns the node responsible for that permission. Does not include User's + * group permission. + * + * @param group + * @param permission + * @return the node if permission is found. if not found, return null + */ + public PermissionCheckResult checkGroupOnlyPermission(Group group, String permission) { + + group.sortPermissions(); + PermissionCheckResult result = new PermissionCheckResult(); + result.owner = group; + result.askedPermission = permission; + for (String access : group.getPermissionList()) { + result.resultType = comparePermissionString(access, permission); + if (result.resultType != PermissionCheckResult.Type.NOTFOUND) { + return result; + } + } + result.resultType = PermissionCheckResult.Type.NOTFOUND; + return result; + } + + /** + * Check permissions, including it's group and inheritance. + * + * @param user + * @param permission + * @return true if permission was found. false if not, or was negated. + */ + public boolean checkUserPermission(User user, String permission) { + + PermissionCheckResult result = checkFullGMPermission(user, permission, true); + if (result.resultType == PermissionCheckResult.Type.EXCEPTION || result.resultType == PermissionCheckResult.Type.FOUND) { + return true; + } + + return false; + } + + /** + * Do what checkUserPermission did before. But now returning a + * PermissionCheckResult. + * + * @param user + * @param targetPermission + * @return PermissionCheckResult + */ + public PermissionCheckResult checkFullUserPermission(User user, String targetPermission) { + + return checkFullGMPermission(user, targetPermission, true); + } + + /** + * Check user and groups with inheritance and Bukkit if bukkit = true return + * a PermissionCheckResult. + * + * @param user + * @param targetPermission + * @param checkBukkit + * @return PermissionCheckResult + */ + public PermissionCheckResult checkFullGMPermission(User user, String targetPermission, Boolean checkBukkit) { + + PermissionCheckResult result = new PermissionCheckResult(); + result.accessLevel = targetPermission; + result.resultType = PermissionCheckResult.Type.NOTFOUND; + + if (user == null || targetPermission == null || targetPermission.isEmpty()) { + return result; + } + + if (checkBukkit) { + // Check Bukkit perms to support plugins which add perms via code + // (Heroes). + final Player player = user.getBukkitPlayer(); + //final Permission bukkitPerm = Bukkit.getPluginManager().getPermission(targetPermission); + if ((player != null) && player.hasPermission(targetPermission)) { + result.resultType = PermissionCheckResult.Type.FOUND; + result.owner = user; + return result; + } + } + + PermissionCheckResult resultUser = checkUserOnlyPermission(user, targetPermission); + if (resultUser.resultType != PermissionCheckResult.Type.NOTFOUND) { + resultUser.accessLevel = targetPermission; + return resultUser; + } + + // IT ONLY CHECKS GROUPS PERMISSIONS IF RESULT FOR USER IS NOT FOUND + PermissionCheckResult resultGroup = checkGroupPermissionWithInheritance(user.getGroup(), targetPermission); + if (resultGroup.resultType != PermissionCheckResult.Type.NOTFOUND) { + resultGroup.accessLevel = targetPermission; + return resultGroup; + } + + // SUBGROUPS CHECK + for (Group subGroup : user.subGroupListCopy()) { + PermissionCheckResult resultSubGroup = checkGroupPermissionWithInheritance(subGroup, targetPermission); + if (resultSubGroup.resultType != PermissionCheckResult.Type.NOTFOUND) { + resultSubGroup.accessLevel = targetPermission; + return resultSubGroup; + } + } + + // THEN IT RETURNS A NOT FOUND + return result; + } + + /** + * Returns the next group, including inheritance, which contains that + * variable name. + * + * It does Breadth-first search + * + * @param start the starting group to look for + * @param targetVariable the variable name + * @return The group if found. Null if not. + */ + public Group nextGroupWithVariable(Group start, String targetVariable) { + + if (start == null || targetVariable == null) { + return null; + } + LinkedList<Group> stack = new LinkedList<Group>(); + ArrayList<Group> alreadyVisited = new ArrayList<Group>(); + stack.push(start); + alreadyVisited.add(start); + while (!stack.isEmpty()) { + Group now = stack.pop(); + if (now.getVariables().hasVar(targetVariable)) { + return now; + } + for (String sonName : now.getInherits()) { + Group son = ph.getGroup(sonName); + if (son != null && !alreadyVisited.contains(son)) { + stack.push(son); + alreadyVisited.add(son); + } + } + } + return null; + } + + + /** + * Check if given group inherits another group. + * + * It does Breadth-first search + * + * @param start The group to start the search. + * @param askedGroup Name of the group you're looking for + * @return true if it inherits the group. + */ + public boolean hasGroupInInheritance(Group start, String askedGroup) { + + if (start == null || askedGroup == null) { + return false; + } + LinkedList<Group> stack = new LinkedList<Group>(); + ArrayList<Group> alreadyVisited = new ArrayList<Group>(); + stack.push(start); + alreadyVisited.add(start); + while (!stack.isEmpty()) { + Group now = stack.pop(); + if (now.getName().equalsIgnoreCase(askedGroup)) { + return true; + } + for (String sonName : now.getInherits()) { + Group son = ph.getGroup(sonName); + if (son != null && !alreadyVisited.contains(son)) { + stack.push(son); + alreadyVisited.add(son); + } + } + } + return false; + } + + /** + * Returns the result of permission check. Including inheritance. If found + * anything, the PermissionCheckResult that retuns will include the Group + * name, and the result type. Result types will be EXCEPTION, NEGATION, + * FOUND. + * + * If returned type NOTFOUND, the owner will be null, and ownerType too. + * + * It does Breadth-first search + * + * @param start + * @param targetPermission + * @return PermissionCheckResult + */ + public PermissionCheckResult checkGroupPermissionWithInheritance(Group start, String targetPermission) { + + if (start == null || targetPermission == null) { + return null; + } + LinkedList<Group> stack = new LinkedList<Group>(); + List<Group> alreadyVisited = new ArrayList<Group>(); + stack.push(start); + alreadyVisited.add(start); + while (!stack.isEmpty()) { + Group now = stack.pop(); + PermissionCheckResult resultNow = checkGroupOnlyPermission(now, targetPermission); + if (!resultNow.resultType.equals(PermissionCheckResult.Type.NOTFOUND)) { + return resultNow; + } + for (String sonName : now.getInherits()) { + Group son = ph.getGroup(sonName); + if (son != null && !alreadyVisited.contains(son)) { + // Add rather than push to retain inheritance order. + stack.add(son); + alreadyVisited.add(son); + } + } + } + PermissionCheckResult result = new PermissionCheckResult(); + result.askedPermission = targetPermission; + result.resultType = PermissionCheckResult.Type.NOTFOUND; + return result; + } + + /** + * Return whole list of names of groups in a inheritance chain. Including a + * starting group. + * + * It does Breadth-first search. So closer groups will appear first in list. + * + * @param start + * @return the group that passed on test. null if no group passed. + */ + public ArrayList<String> listAllGroupsInherited(Group start) { + + if (start == null) { + return null; + } + LinkedList<Group> stack = new LinkedList<Group>(); + ArrayList<String> alreadyVisited = new ArrayList<String>(); + stack.push(start); + alreadyVisited.add(start.getName()); + while (!stack.isEmpty()) { + Group now = stack.pop(); + for (String sonName : now.getInherits()) { + Group son = ph.getGroup(sonName); + if (son != null && !alreadyVisited.contains(son.getName())) { + stack.push(son); + alreadyVisited.add(son.getName()); + } + } + } + return alreadyVisited; + } + + /** + * Compare a user permission like 'myplugin.*' against a full plugin + * permission name, like 'myplugin.dosomething'. As the example above, will + * return true. + * + * Please sort permissions before sending them here. So negative tokens get + * priority. + * + * You must test if it start with negative outside this method. It will only + * tell if the nodes are matching or not. + * + * Every '-' or '+' in the beginning is ignored. It will match only node + * names. + * + * @param userAccessLevel + * @param fullPermissionName + * @return PermissionCheckResult.Type + */ + public PermissionCheckResult.Type comparePermissionString(String userAccessLevel, String fullPermissionName) { + + int userAccessLevelLength; + if (userAccessLevel == null || fullPermissionName == null || fullPermissionName.length() == 0 || (userAccessLevelLength = userAccessLevel.length()) == 0) { + return PermissionCheckResult.Type.NOTFOUND; + } + + PermissionCheckResult.Type result = PermissionCheckResult.Type.FOUND; + int userAccessLevelOffset = 0; + if (userAccessLevel.charAt(0) == '+') { + userAccessLevelOffset = 1; + result = PermissionCheckResult.Type.EXCEPTION; + } else if (userAccessLevel.charAt(0) == '-') { + userAccessLevelOffset = 1; + result = PermissionCheckResult.Type.NEGATION; + } + if ("*".regionMatches(0, userAccessLevel, userAccessLevelOffset, userAccessLevelLength - userAccessLevelOffset)) { + return result; + } + int fullPermissionNameOffset; + if (fullPermissionName.charAt(0) == '+' || fullPermissionName.charAt(0) == '-') { + fullPermissionNameOffset = 1; + } else { + fullPermissionNameOffset = 0; + } + + if (userAccessLevel.charAt(userAccessLevel.length() - 1) == '*') { + return userAccessLevel.regionMatches(true, userAccessLevelOffset, fullPermissionName, fullPermissionNameOffset, userAccessLevelLength - userAccessLevelOffset - 1) ? result : PermissionCheckResult.Type.NOTFOUND; + } else { + return userAccessLevel.regionMatches(true, userAccessLevelOffset, fullPermissionName, fullPermissionNameOffset, Math.max(userAccessLevelLength - userAccessLevelOffset, fullPermissionName.length() - fullPermissionNameOffset)) ? result : PermissionCheckResult.Type.NOTFOUND; + } + } + + /** + * Returns a list of all groups. + * + * Including subgroups. + * + * @param userName + * @return String[] of all group names. + */ + @Override + public String[] getGroups(String userName) { + + ArrayList<String> allGroups = listAllGroupsInherited(ph.getUser(userName).getGroup()); + for (Group subg : ph.getUser(userName).subGroupListCopy()) { + allGroups.addAll(listAllGroupsInherited(subg)); + } + + String[] arr = new String[allGroups.size()]; + return allGroups.toArray(arr); + } + + /** + * A Breadth-first search thru inheritance model. + * + * Just a model to copy and paste. This will guarantee the closer groups + * will be checked first. + * + * @param start + * @param targerPermission + * @return + */ + @SuppressWarnings("unused") + private Group breadthFirstSearch(Group start, String targerPermission) { + + if (start == null || targerPermission == null) { + return null; + } + LinkedList<Group> stack = new LinkedList<Group>(); + ArrayList<Group> alreadyVisited = new ArrayList<Group>(); + stack.push(start); + alreadyVisited.add(start); + while (!stack.isEmpty()) { + Group now = stack.pop(); + PermissionCheckResult resultNow = checkGroupOnlyPermission(now, targerPermission); + if (resultNow.resultType.equals(PermissionCheckResult.Type.EXCEPTION) || resultNow.resultType.equals(PermissionCheckResult.Type.FOUND)) { + return now; + } + if (resultNow.resultType.equals(PermissionCheckResult.Type.NEGATION)) { + return null; + } + for (String sonName : now.getInherits()) { + Group son = ph.getGroup(sonName); + if (son != null && !alreadyVisited.contains(son)) { + stack.push(son); + alreadyVisited.add(son); + } + } + } + return null; + } + + @Override + public Group getDefaultGroup() { + + return ph.getDefaultGroup(); + } + + @Override + public String getInfoString(String entryName, String path, boolean isGroup) { + + if (isGroup) { + Group data = ph.getGroup(entryName); + if (data == null) { + return null; + } + return data.getVariables().getVarString(path); + } else { + User data = ph.getUser(entryName); + if (data == null) { + return null; + } + return data.getVariables().getVarString(path); + } + } + + @Override + public int getInfoInteger(String entryName, String path, boolean isGroup) { + + if (isGroup) { + Group data = ph.getGroup(entryName); + if (data == null) { + return -1; + } + return data.getVariables().getVarInteger(path); + } else { + User data = ph.getUser(entryName); + if (data == null) { + return -1; + } + return data.getVariables().getVarInteger(path); + } + } + + @Override + public double getInfoDouble(String entryName, String path, boolean isGroup) { + + if (isGroup) { + Group data = ph.getGroup(entryName); + if (data == null) { + return -1; + } + return data.getVariables().getVarDouble(path); + } else { + User data = ph.getUser(entryName); + if (data == null) { + return -1; + } + return data.getVariables().getVarDouble(path); + } + + } + + @Override + public boolean getInfoBoolean(String entryName, String path, boolean isGroup) { + + if (isGroup) { + Group data = ph.getGroup(entryName); + if (data == null) { + return false; + } + return data.getVariables().getVarBoolean(path); + } else { + User data = ph.getUser(entryName); + if (data == null) { + return false; + } + return data.getVariables().getVarBoolean(path); + } + } + + @Override + public void addUserInfo(String name, String path, Object data) { + + ph.getUser(name).getVariables().addVar(path, data); + } + + @Override + public void removeUserInfo(String name, String path) { + + ph.getUser(name).getVariables().removeVar(path); + } + + @Override + public void addGroupInfo(String name, String path, Object data) { + + ph.getGroup(name).getVariables().addVar(path, data); + } + + @Override + public void removeGroupInfo(String name, String path) { + + ph.getGroup(name).getVariables().removeVar(path); + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java new file mode 100644 index 000000000..05e152286 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java @@ -0,0 +1,491 @@ +/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+package org.anjocaido.groupmanager.permissions;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.anjocaido.groupmanager.GroupManager;
+import org.anjocaido.groupmanager.data.User;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerChangedWorldEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerKickEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.event.server.PluginDisableEvent;
+import org.bukkit.event.server.PluginEnableEvent;
+import org.bukkit.permissions.Permission;
+import org.bukkit.permissions.PermissionAttachment;
+import org.bukkit.permissions.PermissionAttachmentInfo;
+import org.bukkit.plugin.PluginManager;
+
+/**
+ *
+ * BukkitPermissions overrides to force GM reponses to Superperms
+ *
+ * @author ElgarL
+ */
+public class BukkitPermissions {
+
+ protected WeakHashMap<Player, PermissionAttachment> attachments = new WeakHashMap<Player, PermissionAttachment>();
+ protected LinkedHashMap<String, Permission> registeredPermissions = new LinkedHashMap<String, Permission>();
+ protected GroupManager plugin;
+ protected boolean dumpAllPermissions = true;
+ protected boolean dumpMatchedPermissions = true;
+ private boolean player_join = false;
+
+ /**
+ * @return the player_join
+ */
+ public boolean isPlayer_join() {
+
+ return player_join;
+ }
+
+ /**
+ * @param player_join the player_join to set
+ */
+ public void setPlayer_join(boolean player_join) {
+
+ this.player_join = player_join;
+ }
+
+ private static Field permissions;
+
+ // Setup reflection (Thanks to Codename_B for the reflection source)
+ static {
+ try {
+ permissions = PermissionAttachment.class.getDeclaredField("permissions");
+ permissions.setAccessible(true);
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public BukkitPermissions(GroupManager plugin) {
+
+ this.plugin = plugin;
+ this.reset();
+ this.registerEvents();
+
+
+ GroupManager.logger.info("Superperms support enabled.");
+ }
+
+ public void reset() {
+ this.collectPermissions();
+ this.updateAllPlayers();
+ }
+
+ private void registerEvents() {
+
+ PluginManager manager = plugin.getServer().getPluginManager();
+
+ manager.registerEvents(new PlayerEvents(), plugin);
+ manager.registerEvents(new BukkitEvents(), plugin);
+ }
+
+ public void collectPermissions() {
+
+ registeredPermissions.clear();
+
+ for (Permission perm : Bukkit.getPluginManager().getPermissions()) {
+ registeredPermissions.put(perm.getName().toLowerCase(), perm);
+ }
+
+ }
+
+ public void updatePermissions(Player player) {
+
+ this.updatePermissions(player, null);
+ }
+
+ /**
+ * Push all permissions which are registered with GM for this player, on
+ * this world to Bukkit
+ * and make it update for the child nodes.
+ *
+ * @param player
+ * @param world
+ */
+ public void updatePermissions(Player player, String world) {
+
+ if (player == null || !GroupManager.isLoaded()) {
+ return;
+ }
+
+ // Reset the User objects player reference.
+ User user = plugin.getWorldsHolder().getWorldData(player.getWorld().getName()).getUser(player.getName());
+ if (user != null)
+ user.updatePlayer(player);
+
+ PermissionAttachment attachment;
+
+ // Find the players current attachment, or add a new one.
+ if (this.attachments.containsKey(player)) {
+ attachment = this.attachments.get(player);
+ } else {
+ attachment = player.addAttachment(plugin);
+ this.attachments.put(player, attachment);
+ }
+
+ if (world == null) {
+ world = player.getWorld().getName();
+ }
+
+ // Add all permissions for this player (GM only)
+ // child nodes will be calculated by Bukkit.
+ List<String> playerPermArray = new ArrayList<String>(plugin.getWorldsHolder().getWorldData(world).getPermissionsHandler().getAllPlayersPermissions(player.getName(), false));
+ LinkedHashMap<String, Boolean> newPerms = new LinkedHashMap<String, Boolean>();
+
+ // Sort the perm list by parent/child, so it will push to superperms correctly.
+ playerPermArray = sort(playerPermArray);
+
+ Boolean value = false;
+ for (String permission : playerPermArray) {
+ value = (!permission.startsWith("-"));
+ newPerms.put((value ? permission : permission.substring(1)), value);
+ }
+
+ /**
+ * This is put in place until such a time as Bukkit pull 466 is
+ * implemented
+ * https://github.com/Bukkit/Bukkit/pull/466
+ */
+ try { // Codename_B source
+ @SuppressWarnings("unchecked")
+ Map<String, Boolean> orig = (Map<String, Boolean>) permissions.get(attachment);
+ // Clear the map (faster than removing the attachment and recalculating)
+ orig.clear();
+ // Then whack our map into there
+ orig.putAll(newPerms);
+ // That's all folks!
+ //attachment.getPermissible().recalculatePermissions();
+ player.recalculatePermissions();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Sort a permission node list by parent/child
+ *
+ * @param permList
+ * @return List sorted for priority
+ */
+ private List<String> sort(List<String> permList) {
+
+ List<String> result = new ArrayList<String>();
+
+ for (String key : permList) {
+ String a = key.charAt(0) == '-' ? key.substring(1) : key;
+ Map<String, Boolean> allchildren = GroupManager.BukkitPermissions.getAllChildren(a, new HashSet<String>());
+ if (allchildren != null) {
+
+ ListIterator<String> itr = result.listIterator();
+
+ while (itr.hasNext()) {
+ String node = (String) itr.next();
+ String b = node.charAt(0) == '-' ? node.substring(1) : node;
+
+ // Insert the parent node before the child
+ if (allchildren.containsKey(b)) {
+ itr.set(key);
+ itr.add(node);
+ break;
+ }
+ }
+ }
+ if (!result.contains(key))
+ result.add(key);
+ }
+
+ return result;
+ }
+
+ /**
+ * Fetch all permissions which are registered with superperms.
+ * {can include child nodes)
+ *
+ * @param includeChildren
+ * @return List of all permission nodes
+ */
+ public List<String> getAllRegisteredPermissions(boolean includeChildren) {
+
+ List<String> perms = new ArrayList<String>();
+
+ for (String key : registeredPermissions.keySet()) {
+ if (!perms.contains(key)) {
+ perms.add(key);
+
+ if (includeChildren) {
+ Map<String, Boolean> children = getAllChildren(key, new HashSet<String>());
+ if (children != null) {
+ for (String node : children.keySet())
+ if (!perms.contains(node))
+ perms.add(node);
+ }
+ }
+ }
+
+ }
+ return perms;
+ }
+
+ /**
+ * Returns a map of ALL child permissions registered with bukkit
+ * null is empty
+ *
+ * @param node
+ * @param playerPermArray current list of perms to check against for
+ * negations
+ * @return Map of child permissions
+ */
+ public Map<String, Boolean> getAllChildren(String node, Set<String> playerPermArray) {
+
+ LinkedList<String> stack = new LinkedList<String>();
+ Map<String, Boolean> alreadyVisited = new HashMap<String, Boolean>();
+ stack.push(node);
+ alreadyVisited.put(node, true);
+
+ while (!stack.isEmpty()) {
+ String now = stack.pop();
+
+ Map<String, Boolean> children = getChildren(now);
+
+ if ((children != null) && (!playerPermArray.contains("-" + now))) {
+ for (String childName : children.keySet()) {
+ if (!alreadyVisited.containsKey(childName)) {
+ stack.push(childName);
+ alreadyVisited.put(childName, children.get(childName));
+ }
+ }
+ }
+ }
+ alreadyVisited.remove(node);
+ if (!alreadyVisited.isEmpty())
+ return alreadyVisited;
+
+ return null;
+ }
+
+ /**
+ * Returns a map of the child permissions (1 node deep) as registered with
+ * Bukkit.
+ * null is empty
+ *
+ * @param node
+ * @return Map of child permissions
+ */
+ public Map<String, Boolean> getChildren(String node) {
+
+ Permission perm = registeredPermissions.get(node.toLowerCase());
+ if (perm == null)
+ return null;
+
+ return perm.getChildren();
+
+ }
+
+ /**
+ * List all effective permissions for this player.
+ *
+ * @param player
+ * @return List<String> of permissions
+ */
+ public List<String> listPerms(Player player) {
+
+ List<String> perms = new ArrayList<String>();
+
+ /*
+ * // All permissions registered with Bukkit for this player
+ * PermissionAttachment attachment = this.attachments.get(player);
+ *
+ * // List perms for this player perms.add("Attachment Permissions:");
+ * for(Map.Entry<String, Boolean> entry :
+ * attachment.getPermissions().entrySet()){ perms.add(" " +
+ * entry.getKey() + " = " + entry.getValue()); }
+ */
+
+ perms.add("Effective Permissions:");
+ for (PermissionAttachmentInfo info : player.getEffectivePermissions()) {
+ if (info.getValue() == true)
+ perms.add(" " + info.getPermission() + " = " + info.getValue());
+ }
+ return perms;
+ }
+
+ /**
+ * force Bukkit to update every OnlinePlayers permissions.
+ */
+ public void updateAllPlayers() {
+
+ for (Player player : Bukkit.getServer().getOnlinePlayers()) {
+ updatePermissions(player);
+ }
+ }
+
+ /**
+ * force Bukkit to update this Players permissions.
+ */
+ public void updatePlayer(Player player) {
+
+ if (player != null)
+ this.updatePermissions(player, null);
+ }
+
+ /**
+ * Force remove any attachments
+ *
+ * @param player
+ */
+ private void removeAttachment(Player player) {
+
+ if (attachments.containsKey(player)) {
+ try {
+ player.removeAttachment(attachments.get(player));
+ } catch (IllegalArgumentException e) {
+ /*
+ * Failed to remove attachment
+ * This usually means Bukkit no longer knows of it.
+ */
+ }
+ attachments.remove(player);
+ }
+ }
+
+ /**
+ * Remove all attachments in case of a restart or reload.
+ */
+ public void removeAllAttachments() {
+
+ Iterator<Player> itr = attachments.keySet().iterator();
+
+ while (itr.hasNext()) {
+ Player player = itr.next();
+ try {
+ player.removeAttachment(attachments.get(player));
+ } catch (IllegalArgumentException e) {
+ /*
+ * Failed to remove attachment
+ * This usually means Bukkit no longer knows of it.
+ */
+ }
+ }
+ attachments.clear();
+ }
+
+ /**
+ * Player events tracked to cause Superperms updates
+ *
+ * @author ElgarL
+ *
+ */
+ protected class PlayerEvents implements Listener {
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onPlayerJoin(PlayerJoinEvent event) {
+
+ setPlayer_join(true);
+ Player player = event.getPlayer();
+
+ /*
+ * Tidy up any lose ends
+ */
+ removeAttachment(player);
+
+ // force GM to create the player if they are not already listed.
+ if (plugin.getWorldsHolder().getWorldData(player.getWorld().getName()).getUser(player.getName()) != null) {
+ setPlayer_join(false);
+ updatePermissions(event.getPlayer());
+ }
+ setPlayer_join(false);
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onPlayerChangeWorld(PlayerChangedWorldEvent event) { // has changed worlds
+
+ updatePermissions(event.getPlayer(), event.getPlayer().getWorld().getName());
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onPlayerKick(PlayerKickEvent event) {
+
+ Player player = event.getPlayer();
+
+ /*
+ * force remove any attachments as bukkit may not
+ */
+ removeAttachment(player);
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onPlayerQuit(PlayerQuitEvent event) {
+
+ if (!GroupManager.isLoaded())
+ return;
+
+ Player player = event.getPlayer();
+
+ /*
+ * force remove any attachments as bukkit may not
+ */
+ removeAttachment(player);
+ }
+ }
+
+ protected class BukkitEvents implements Listener {
+
+ @EventHandler(priority = EventPriority.NORMAL)
+ public void onPluginEnable(PluginEnableEvent event) {
+
+ if (!GroupManager.isLoaded())
+ return;
+
+ collectPermissions();
+ updateAllPlayers();
+ }
+
+ @EventHandler(priority = EventPriority.NORMAL)
+ public void onPluginDisable(PluginDisableEvent event) {
+
+ collectPermissions();
+ // updateAllPlayers();
+ }
+ }
+
+}
\ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/PermissionsReaderInterface.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/PermissionsReaderInterface.java new file mode 100644 index 000000000..69f098949 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/PermissionsReaderInterface.java @@ -0,0 +1,252 @@ +package org.anjocaido.groupmanager.permissions; + +//import java.util.Collection; +//import java.util.Map; +//import java.util.Set; +import java.util.List; +import java.util.Set; + +import org.anjocaido.groupmanager.data.Group; +//import org.anjocaido.groupmanager.data.User; +import org.bukkit.entity.Player; + +/** + * Made by Nijikokun. Changed by Gabriel Couto + * + * This class is intended to *read* permissions from a single world. + * + * @author Nijikokun + * @author Gabriel Couto + * @author ElgarL + */ +public abstract class PermissionsReaderInterface { + + /** + * + * @param player + * @param string + * @return true if has permission + */ + public abstract boolean has(Player player, String string); + + /** + * + * @param player + * @param string + * @return true if has permission + */ + public abstract boolean permission(Player player, String string); + + /** + * + * @param userName + * @return group name for this player. + */ + public abstract String getGroup(String userName); + + /** + * + * @param userName + * @param groupName + * @return true if in group + */ + public abstract boolean inGroup(String userName, String groupName); + + /** + * + * @param groupName + * @return String of prefix + */ + public abstract String getGroupPrefix(String groupName); + + /** + * + * @param groupName + * @return String of suffix + */ + public abstract String getGroupSuffix(String groupName); + + /** + * + * @param groupName + * @return true if can build + */ + public abstract boolean canGroupBuild(String groupName); + + /** + * + * @param groupName + * @param node + * @return String value + */ + public abstract String getGroupPermissionString(String groupName, String node); + + /** + * + * @param groupName + * @param node + * @return integer value + */ + public abstract int getGroupPermissionInteger(String groupName, String node); + + /** + * + * @param groupName + * @param node + * @return boolean value + */ + public abstract boolean getGroupPermissionBoolean(String groupName, String node); + + /** + * + * @param groupName + * @param node + * @return double value + */ + public abstract double getGroupPermissionDouble(String groupName, String node); + + /** + * + * @param userName + * @param node + * @return String value + */ + public abstract String getUserPermissionString(String userName, String node); + + /** + * + * @param userName + * @param node + * @return integer value + */ + public abstract int getUserPermissionInteger(String userName, String node); + + /** + * + * @param userName + * @param node + * @return boolean value + */ + public abstract boolean getUserPermissionBoolean(String userName, String node); + + /** + * + * @param userName + * @param node + * @return double value + */ + public abstract double getUserPermissionDouble(String userName, String node); + + /** + * + * @param userName + * @param node + * @return String value + */ + public abstract String getPermissionString(String userName, String node); + + /** + * + * @param userName + * @param node + * @return integer value + */ + public abstract int getPermissionInteger(String userName, String node); + + /** + * + * @param userName + * @param node + * @return boolean value + */ + public abstract boolean getPermissionBoolean(String userName, String node); + + /** + * + * @param userName + * @param node + * @return double value + */ + public abstract double getPermissionDouble(String userName, String node); + + ///////////////////////////// + /** + * Gets the appropriate prefix for the user. + * This method is a utility method for chat plugins to get the user's prefix + * without having to look at every one of the user's ancestors. + * Returns an empty string if user has no parent groups. + * + * @param user Player's name + * @return Player's prefix + */ + public abstract String getUserPrefix(String user); + + /** + * Gets the appropriate suffix for the user. + * This method is a utility method for chat plugins to get the user's suffix + * without having to look at every one of the user's ancestors. + * Returns an empty string if user has no parent groups. + * + * @param user Player's name + * @return Player's suffix + */ + public abstract String getUserSuffix(String user); + + /** + * Returns the group object representing the default group of the given + * world. + * This method will return null if the object does not exist or the world + * has no default group. + * + * @return Group object representing default world, or null if it doesn't + * exist or is not defined. + */ + public abstract Group getDefaultGroup(); + + /** + * Gets a array of the names of all parent groups in the same world. + * + * @param name Target user's name + * @return An array containing the names of all parent groups (including + * ancestors) that are in the same world + */ + public abstract String[] getGroups(String name); + + public abstract String getInfoString(String entryName, String path, boolean isGroup); + + //public abstract String getInfoString(String entryName, String path, boolean isGroup, Comparator<String> comparator); + + public abstract int getInfoInteger(String entryName, String path, boolean isGroup); + + //public abstract int getInfoInteger(String entryName, String path, boolean isGroup, Comparator<Integer> comparator); + + /** + * Gets a double from the Info node without inheritance. + * + * @param entryName + * @param path + * @param isGroup + * @return -1 if not found + */ + public abstract double getInfoDouble(String entryName, String path, boolean isGroup); + + //public abstract double getInfoDouble(String entryName, String path, boolean isGroup, Comparator<Double> comparator); + + public abstract boolean getInfoBoolean(String entryName, String path, boolean isGroup); + + //public abstract boolean getInfoBoolean(String entryName, String path, boolean isGroup, Comparator<Boolean> comparator); + + public abstract void addUserInfo(String name, String path, Object data); + + public abstract void removeUserInfo(String name, String path); + + public abstract void addGroupInfo(String name, String path, Object data); + + public abstract void removeGroupInfo(String name, String path); + + ////////////////////////////// + + public abstract List<String> getAllPlayersPermissions(String userName); + + public abstract Set<String> getAllPlayersPermissions(String userName, Boolean includeChildren); +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/GMLoggerHandler.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/GMLoggerHandler.java new file mode 100644 index 000000000..de5348b17 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/GMLoggerHandler.java @@ -0,0 +1,27 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.utils; + +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +/** + * + * @author gabrielcouto + */ +public class GMLoggerHandler extends ConsoleHandler { + + @Override + public void publish(LogRecord record) { + + String message = "GroupManager - " + record.getLevel() + " - " + record.getMessage(); + if (record.getLevel().equals(Level.SEVERE) || record.getLevel().equals(Level.WARNING)) { + System.err.println(message); + } else { + System.out.println(message); + } + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/GroupManagerPermissions.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/GroupManagerPermissions.java new file mode 100644 index 000000000..4a7298b9c --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/GroupManagerPermissions.java @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.utils; + +/** + * Just a list of commands for this plugin + * + * @author gabrielcouto + */ +public enum GroupManagerPermissions { + + manuadd, + manudel, + manuaddsub, + manudelsub, + mangadd, + mangdel, + manuaddp, + manudelp, + manulistp, + manucheckp, + mangaddp, + mangdelp, + manglistp, + mangcheckp, + mangaddi, + mangdeli, + manuaddv, + manudelv, + manulistv, + manucheckv, + mangaddv, + mangdelv, + manglistv, + mangcheckv, + manwhois, + tempadd, + tempdel, + templist, + tempdelall, + mansave, + manload, + listgroups, + manpromote, + mandemote, + mantogglevalidate, + mantogglesave, + manworld, + manselect, + manclear +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/PermissionCheckResult.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/PermissionCheckResult.java new file mode 100644 index 000000000..eb6633863 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/PermissionCheckResult.java @@ -0,0 +1,67 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.utils; + +import org.anjocaido.groupmanager.data.DataUnit; + +/** + * + * @author gabrielcouto + */ +public class PermissionCheckResult { + + /** + * It should be the owner of the access level found. + * + * Use instanceof to find the owner type + */ + public DataUnit owner; + /** + * The permission node found in the DataUnit. + */ + public String accessLevel; + /** + * The full name of the permission you are looking for + */ + public String askedPermission; + /** + * The result conclusion of the search. + * It determines if the owner can do, or not. + * + * It even determines if it has an owner. + */ + public Type resultType = Type.NOTFOUND; + + /** + * The type of result the search can give. + */ + public enum Type { + + /** + * If found a matching node starting with '+'. + * It means the user CAN do the permission. + */ + EXCEPTION, + /** + * If found a matching node starting with '-'. + * It means the user CANNOT do the permission. + */ + NEGATION, + /** + * If just found a common matching node. + * IT means the user CAN do the permission. + */ + FOUND, + /** + * If no matchin node was found. + * It means the user CANNOT do the permission. + * + * owner field and accessLevel field should not be considered, + * when type is + * NOTFOUND + */ + NOTFOUND + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/StringPermissionComparator.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/StringPermissionComparator.java new file mode 100644 index 000000000..5a56cd9fc --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/StringPermissionComparator.java @@ -0,0 +1,52 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.utils; + +import java.util.Comparator; + +/** + * + * @author gabrielcouto + */ +public class StringPermissionComparator implements Comparator<String> { + + @Override + public int compare(String permA, String permB) { + + boolean ap = permA.startsWith("+"); + boolean bp = permB.startsWith("+"); + boolean am = permA.startsWith("-"); + boolean bm = permB.startsWith("-"); + if (ap && bp) { + return 0; + } + if (ap && !bp) { + return -1; + } + if (!ap && bp) { + return 1; + } + if (am && bm) { + return 0; + } + if (am && !bm) { + return -1; + } + if (!am && bm) { + return 1; + } + return permA.compareToIgnoreCase(permB); + } + + private static StringPermissionComparator instance; + + public static StringPermissionComparator getInstance() { + + if (instance == null) { + instance = new StringPermissionComparator(); + } + return instance; + } +} diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/Tasks.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/Tasks.java new file mode 100644 index 000000000..d75737c66 --- /dev/null +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/utils/Tasks.java @@ -0,0 +1,175 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.anjocaido.groupmanager.utils; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; + +import org.anjocaido.groupmanager.GroupManager; +import org.anjocaido.groupmanager.data.Group; + +/** + * + * @author gabrielcouto + */ +public abstract class Tasks { + + /** + * Gets the exception stack trace as a string. + * + * @param exception + * @return stack trace as a string + */ + public static String getStackTraceAsString(Exception exception) { + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + exception.printStackTrace(pw); + return sw.toString(); + } + + public static void copy(InputStream src, File dst) throws IOException { + + InputStream in = src; + OutputStream out = new FileOutputStream(dst); + + // Transfer bytes from in to out + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + out.close(); + try { + in.close(); + } catch (Exception e) { + } + } + + public static void copy(File src, File dst) throws IOException { + + InputStream in = new FileInputStream(src); + copy(in, dst); + } + + /** + * Appends a string to a file + * + * @param data + * @param file + */ + public static void appendStringToFile(String data, String file) throws IOException { + + FileWriter outStream = new FileWriter("." + System.getProperty("file.separator") + file, true); + + BufferedWriter out = new BufferedWriter(outStream); + + data.replaceAll("\n", System.getProperty("line.separator")); + + out.append(new SimpleDateFormat("yyyy-MM-dd HH-mm").format(System.currentTimeMillis())); + out.append(System.getProperty("line.separator")); + out.append(data); + out.append(System.getProperty("line.separator")); + + out.close(); + } + + public static void removeOldFiles(GroupManager gm, File folder) { + + if (folder.isDirectory()) { + long oldTime = System.currentTimeMillis() - (((long) gm.getGMConfig().getBackupDuration() * 60 * 60) * 1000); + for (File olds : folder.listFiles()) { + if (olds.isFile()) { + if (olds.lastModified() < oldTime) { + try { + olds.delete(); + } catch (Exception e) { + } + } + } + } + } + } + + public static String getDateString() { + + GregorianCalendar now = new GregorianCalendar(); + String date = ""; + date += now.get(Calendar.DAY_OF_MONTH); + date += "-"; + date += now.get(Calendar.HOUR); + date += "-"; + date += now.get(Calendar.MINUTE); + return date; + } + + public static String getStringListInString(List<String> list) { + + if (list == null) { + return ""; + } + String result = ""; + for (int i = 0; i < list.size(); i++) { + result += list.get(i); + if (i < list.size() - 1) { + result += ", "; + } + } + return result; + } + + public static String getStringArrayInString(String[] list) { + + if (list == null) { + return ""; + } + String result = ""; + for (int i = 0; i < list.length; i++) { + result += list[i]; + if (i < ((list.length) - 1)) { + result += ", "; + } + } + return result; + } + + public static String getGroupListInString(List<Group> list) { + + if (list == null) { + return ""; + } + String result = ""; + for (int i = 0; i < list.size(); i++) { + result += list.get(i).getName(); + if (i < list.size() - 1) { + result += ", "; + } + } + return result; + } + + public static String join(String[] arr, String separator) { + + if (arr.length == 0) + return ""; + String out = arr[0].toString(); + for (int i = 1; i < arr.length; i++) + out += separator + arr[i]; + return out; + } + +} |