From ca86ea1eb7cc4e86c5030585fd7eca9f098a93bb Mon Sep 17 00:00:00 2001 From: Dinnerbone Date: Wed, 20 Jul 2011 18:05:04 +0100 Subject: [PATCH] Made Permissions mutable, added methods to view which Permissibles are subscribed to which Permission --- pom.xml | 7 + .../bukkit/permissions/PermissibleBase.java | 17 ++- .../org/bukkit/permissions/Permission.java | 65 ++++++++- .../java/org/bukkit/plugin/PluginManager.java | 84 ++++++++++++ .../bukkit/plugin/SimplePluginManager.java | 125 ++++++++++++++++-- 5 files changed, 282 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index 72b2e44d..7e841f0b 100644 --- a/pom.xml +++ b/pom.xml @@ -100,5 +100,12 @@ jar compile + + com.google.guava + guava-collections + r03 + jar + compile + diff --git a/src/main/java/org/bukkit/permissions/PermissibleBase.java b/src/main/java/org/bukkit/permissions/PermissibleBase.java index 950cfc8b..fe2b9e3b 100644 --- a/src/main/java/org/bukkit/permissions/PermissibleBase.java +++ b/src/main/java/org/bukkit/permissions/PermissibleBase.java @@ -154,12 +154,14 @@ public class PermissibleBase implements Permissible { private synchronized void calculatePermissions() { if (dirtyPermissions) { - permissions.clear(); + clearPermissions(); Set defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp()); + Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), this); for (Permission perm : defaults) { String name = perm.getName().toLowerCase(); permissions.put(name, new PermissionAttachmentInfo(this, name, null, true)); + Bukkit.getServer().getPluginManager().subscribeToPermission(name, this); calculateChildPermissions(perm.getChildren(), false, null); } @@ -171,6 +173,18 @@ public class PermissibleBase implements Permissible { } } + private synchronized void clearPermissions() { + Set perms = permissions.keySet(); + + for (String name : perms) { + Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, this); + } + + Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(isOp(), this); + + permissions.clear(); + } + private void calculateChildPermissions(Map children, boolean invert, PermissionAttachment attachment) { Set keys = children.keySet(); @@ -180,6 +194,7 @@ public class PermissibleBase implements Permissible { String lname = name.toLowerCase(); permissions.put(lname, new PermissionAttachmentInfo(this, lname, attachment, value)); + Bukkit.getServer().getPluginManager().subscribeToPermission(name, this); if (perm != null) { calculateChildPermissions(perm.getChildren(), !value, attachment); diff --git a/src/main/java/org/bukkit/permissions/Permission.java b/src/main/java/org/bukkit/permissions/Permission.java index 5acbe220..ea6ade6b 100644 --- a/src/main/java/org/bukkit/permissions/Permission.java +++ b/src/main/java/org/bukkit/permissions/Permission.java @@ -5,6 +5,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.bukkit.Bukkit; /** * Represents a unique permission that may be attached to a {@link Permissible} @@ -51,6 +52,8 @@ public class Permission { if (children != null) { this.children.putAll(children); } + + recalculatePermissibles(); } /** @@ -65,12 +68,12 @@ public class Permission { /** * Gets the children of this permission. * - * This is a copy and changes will not be saved. + * If you change this map in any form, you must call {@link #recalculatePermissibles()} to recalculate all {@link Permissible}s * * @return Permission children */ public Map getChildren() { - return new LinkedHashMap(children); + return children; } /** @@ -82,6 +85,23 @@ public class Permission { return defaultValue; } + /** + * Sets the default value of this permission. + * + * This will not be saved to disk, and is a temporary operation until the server reloads permissions. + * Changing this default will cause all {@link Permissible}s that contain this permission to recalculate their permissions + * + * @param value The new default to set + */ + public void setDefault(PermissionDefault value) { + if (defaultValue == null) { + throw new IllegalArgumentException("Default value cannot be null"); + } + + defaultValue = value; + recalculatePermissibles(); + } + /** * Gets a brief description of this permission, if set * @@ -91,6 +111,47 @@ public class Permission { return description; } + /** + * Sets the description of this permission. + * + * This will not be saved to disk, and is a temporary operation until the server reloads permissions. + * + * @param value The new description to set + */ + public void setDescription(String value) { + if (value == null) { + description = ""; + } else { + description = value; + } + } + + /** + * Gets a set containing every {@link Permissible} that has this permission. + * + * This set cannot be modified. + * + * @return Set containing permissibles with this permission + */ + public Set getPermissibles() { + return Bukkit.getServer().getPluginManager().getPermissionSubscriptions(name); + } + + /** + * Recalculates all {@link Permissible}s that contain this permission. + * + * This should be called after modifying the children, and is automatically called after modifying the default value + */ + public void recalculatePermissibles() { + Set perms = getPermissibles(); + + Bukkit.getServer().getPluginManager().recalculatePermissionDefaults(this); + + for (Permissible p : perms) { + p.recalculatePermissions(); + } + } + /** * Loads a Permission from a map of data, usually used from retrieval from a yaml file. * diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java index b445f180..f2c407d3 100644 --- a/src/main/java/org/bukkit/plugin/PluginManager.java +++ b/src/main/java/org/bukkit/plugin/PluginManager.java @@ -6,6 +6,7 @@ import java.util.Set; import org.bukkit.event.Event; import org.bukkit.event.Event.Priority; import org.bukkit.event.Listener; +import org.bukkit.permissions.Permissible; import org.bukkit.permissions.Permission; /** @@ -152,10 +153,93 @@ public interface PluginManager { */ public void addPermission(Permission perm); + /** + * Removes a {@link Permission} registration from this plugin manager. + * + * If the specified permission does not exist in this plugin manager, nothing will happen. + * + * Removing a permission registration will not remove the permission from any {@link Permissible}s that have it. + * + * @param perm Permission to remove + */ + public void removePermission(Permission perm); + + /** + * Removes a {@link Permission} registration from this plugin manager. + * + * If the specified permission does not exist in this plugin manager, nothing will happen. + * + * Removing a permission registration will not remove the permission from any {@link Permissible}s that have it. + * + * @param name Permission to remove + */ + public void removePermission(String name); + /** * Gets the default permissions for the given op status * * @param op Which set of default permissions to get */ public Set getDefaultPermissions(boolean op); + + /** + * Recalculates the defaults for the given {@link Permission}. + * + * This will have no effect if the specified permission is not registered here. + * + * @param perm Permission to recalculate + */ + public void recalculatePermissionDefaults(Permission perm); + + /** + * Subscribes the given Permissible for information about the requested Permission, by name. + * + * If the specified Permission changes in any form, the Permissible will be asked to recalculate. + * + * @param permission Permission to subscribe to + * @param permissible Permissible subscribing + */ + public void subscribeToPermission(String permission, Permissible permissible); + + /** + * Unsubscribes the given Permissible for information about the requested Permission, by name. + * + * @param permission Permission to unsubscribe from + * @param permissible Permissible subscribing + */ + public void unsubscribeFromPermission(String permission, Permissible permissible); + + /** + * Gets a set containing all subscribed {@link Permissible}s to the given permission, by name + * + * @param permission Permission to query for + * @return Set containing all subscribed permissions + */ + public Set getPermissionSubscriptions(String permission); + + /** + * Subscribes to the given Default permissions by operator status + * + * If the specified defaults change in any form, the Permissible will be asked to recalculate. + * + * @param op Default list to subscribe to + * @param permissible Permissible subscribing + */ + public void subscribeToDefaultPerms(boolean op, Permissible permissible); + + /** + * Unsubscribes from the given Default permissions by operator status + * + * @param op Default list to unsubscribe from + * @param permissible Permissible subscribing + */ + public void unsubscribeFromDefaultPerms(boolean op, Permissible permissible); + + /** + * Gets a set containing all subscribed {@link Permissible}s to the given default list, by op status + * + * @param op Default list to query for + * @return Set containing all subscribed permissions + */ + public Set getDefaultPermSubscriptions(boolean op); } diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java index eaf3b671..7f37d29e 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -1,5 +1,7 @@ package org.bukkit.plugin; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.MapMaker; import java.io.File; import java.lang.reflect.Constructor; import java.util.ArrayList; @@ -27,7 +29,9 @@ import org.bukkit.command.SimpleCommandMap; import org.bukkit.event.Event; import org.bukkit.event.Event.Priority; import org.bukkit.event.Listener; +import org.bukkit.permissions.Permissible; import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; import org.bukkit.util.FileUtil; @@ -44,6 +48,8 @@ public final class SimplePluginManager implements PluginManager { private final SimpleCommandMap commandMap; private final Map permissions = new HashMap(); private final Map> defaultPerms = new LinkedHashMap>(); + private final Map> permSubs = new HashMap>(); + private final Map> defSubs = new HashMap>(); private final Comparator comparer = new Comparator() { public int compare(RegisteredListener i, RegisteredListener j) { int result = i.getPriority().compareTo(j.getPriority()); @@ -418,24 +424,117 @@ public final class SimplePluginManager implements PluginManager { } permissions.put(name, perm); + calculatePermissionDefault(perm); + } + public Set getDefaultPermissions(boolean op) { + return ImmutableSet.copyOf(defaultPerms.get(op)); + } + + public void removePermission(Permission perm) { + removePermission(perm.getName().toLowerCase()); + } + + public void removePermission(String name) { + permissions.remove(name); + } + + public void recalculatePermissionDefaults(Permission perm) { + if (permissions.containsValue(perm)) { + defaultPerms.get(true).remove(perm); + defaultPerms.get(false).remove(perm); + + calculatePermissionDefault(perm); + } + } + + private void calculatePermissionDefault(Permission perm) { if (!perm.getChildren().isEmpty()) { - switch (perm.getDefault()) { - case TRUE: - defaultPerms.get(true).add(perm); - defaultPerms.get(false).add(perm); - break; - case OP: - defaultPerms.get(true).add(perm); - break; - case NOT_OP: - defaultPerms.get(false).add(perm); - break; + if ((perm.getDefault() == PermissionDefault.OP) || (perm.getDefault() == PermissionDefault.TRUE)) { + defaultPerms.get(true).add(perm); + dirtyPermissibles(true); + } + if ((perm.getDefault() == PermissionDefault.NOT_OP) || (perm.getDefault() == PermissionDefault.TRUE)) { + defaultPerms.get(false).add(perm); + dirtyPermissibles(false); } } } - public Set getDefaultPermissions(boolean op) { - return defaultPerms.get(op); + private void dirtyPermissibles(boolean op) { + Set permissibles = getDefaultPermSubscriptions(op); + + for (Permissible p : permissibles) { + p.recalculatePermissions(); + } + } + + public void subscribeToPermission(String permission, Permissible permissible) { + String name = permission.toLowerCase(); + Map map = permSubs.get(name); + + if (map == null) { + map = new MapMaker().weakKeys().makeMap(); + permSubs.put(name, map); + } + + map.put(permissible, true); + } + + public void unsubscribeFromPermission(String permission, Permissible permissible) { + String name = permission.toLowerCase(); + Map map = permSubs.get(name); + + if (map != null) { + map.remove(permissible); + + if (map.isEmpty()) { + permSubs.remove(name); + } + } + } + + public Set getPermissionSubscriptions(String permission) { + String name = permission.toLowerCase(); + Map map = permSubs.get(name); + + if (map == null) { + return ImmutableSet.of(); + } else { + return ImmutableSet.copyOf(map.keySet()); + } + } + + public void subscribeToDefaultPerms(boolean op, Permissible permissible) { + Map map = defSubs.get(op); + + if (map == null) { + map = new MapMaker().weakKeys().makeMap(); + defSubs.put(op, map); + } + + map.put(permissible, true); + } + + public void unsubscribeFromDefaultPerms(boolean op, Permissible permissible) { + Map map = defSubs.get(op); + + if (map != null) { + map.remove(permissible); + + if (map.isEmpty()) { + defSubs.remove(op); + } + } + } + + public Set getDefaultPermSubscriptions(boolean op) { + Map map = defSubs.get(op); + + if (map == null) { + return ImmutableSet.of(); + } else { + return ImmutableSet.copyOf(map.keySet()); + } } }