diff options
-rw-r--r-- | pom.xml | 7 | ||||
-rw-r--r-- | src/main/java/org/bukkit/permissions/PermissibleBase.java | 17 | ||||
-rw-r--r-- | src/main/java/org/bukkit/permissions/Permission.java | 65 | ||||
-rw-r--r-- | src/main/java/org/bukkit/plugin/PluginManager.java | 84 | ||||
-rw-r--r-- | src/main/java/org/bukkit/plugin/SimplePluginManager.java | 125 |
5 files changed, 282 insertions, 16 deletions
@@ -100,5 +100,12 @@ <type>jar</type> <scope>compile</scope> </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava-collections</artifactId> + <version>r03</version> + <type>jar</type> + <scope>compile</scope> + </dependency> </dependencies> </project> 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<Permission> 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<String> 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<String, Boolean> children, boolean invert, PermissionAttachment attachment) { Set<String> 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<String, Boolean> getChildren() { - return new LinkedHashMap<String, Boolean>(children); + return children; } /** @@ -83,6 +86,23 @@ public class Permission { } /** + * 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 * * @return Brief description of this permission @@ -92,6 +112,47 @@ public class Permission { } /** + * 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<Permissible> 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<Permissible> 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. * * The data may contain the following keys: 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; /** @@ -153,9 +154,92 @@ 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 <b>not</b> 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 <b>not</b> 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<Permission> 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<Permissible> 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<Permissible> 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<String, Permission> permissions = new HashMap<String, Permission>(); private final Map<Boolean, Set<Permission>> defaultPerms = new LinkedHashMap<Boolean, Set<Permission>>(); + private final Map<String, Map<Permissible, Boolean>> permSubs = new HashMap<String, Map<Permissible, Boolean>>(); + private final Map<Boolean, Map<Permissible, Boolean>> defSubs = new HashMap<Boolean, Map<Permissible, Boolean>>(); private final Comparator<RegisteredListener> comparer = new Comparator<RegisteredListener>() { 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<Permission> 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<Permission> getDefaultPermissions(boolean op) { - return defaultPerms.get(op); + private void dirtyPermissibles(boolean op) { + Set<Permissible> permissibles = getDefaultPermSubscriptions(op); + + for (Permissible p : permissibles) { + p.recalculatePermissions(); + } + } + + public void subscribeToPermission(String permission, Permissible permissible) { + String name = permission.toLowerCase(); + Map<Permissible, Boolean> 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<Permissible, Boolean> map = permSubs.get(name); + + if (map != null) { + map.remove(permissible); + + if (map.isEmpty()) { + permSubs.remove(name); + } + } + } + + public Set<Permissible> getPermissionSubscriptions(String permission) { + String name = permission.toLowerCase(); + Map<Permissible, Boolean> map = permSubs.get(name); + + if (map == null) { + return ImmutableSet.of(); + } else { + return ImmutableSet.copyOf(map.keySet()); + } + } + + public void subscribeToDefaultPerms(boolean op, Permissible permissible) { + Map<Permissible, Boolean> 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<Permissible, Boolean> map = defSubs.get(op); + + if (map != null) { + map.remove(permissible); + + if (map.isEmpty()) { + defSubs.remove(op); + } + } + } + + public Set<Permissible> getDefaultPermSubscriptions(boolean op) { + Map<Permissible, Boolean> map = defSubs.get(op); + + if (map == null) { + return ImmutableSet.of(); + } else { + return ImmutableSet.copyOf(map.keySet()); + } } } |