diff options
author | Dinnerbone <dinnerbone@dinnerbone.com> | 2011-07-17 17:17:47 +0100 |
---|---|---|
committer | Dinnerbone <dinnerbone@dinnerbone.com> | 2011-07-17 17:17:47 +0100 |
commit | fb594732b5ebbf04cfb617e779866a3b73f3bc66 (patch) | |
tree | 7cc81cdb6b90d6b52624f3ce04387578dce6f1e8 /src/main/java/org | |
parent | 6ff9f7cad6bbb38b796fed464153eb9634121a54 (diff) | |
download | bukkit-fb594732b5ebbf04cfb617e779866a3b73f3bc66.tar bukkit-fb594732b5ebbf04cfb617e779866a3b73f3bc66.tar.gz bukkit-fb594732b5ebbf04cfb617e779866a3b73f3bc66.tar.lz bukkit-fb594732b5ebbf04cfb617e779866a3b73f3bc66.tar.xz bukkit-fb594732b5ebbf04cfb617e779866a3b73f3bc66.zip |
Added new permission system
Diffstat (limited to 'src/main/java/org')
15 files changed, 958 insertions, 9 deletions
diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java index fb70241d..555ba1b3 100644 --- a/src/main/java/org/bukkit/command/CommandSender.java +++ b/src/main/java/org/bukkit/command/CommandSender.java @@ -1,8 +1,9 @@ package org.bukkit.command; import org.bukkit.Server; +import org.bukkit.permissions.Permissible; -public interface CommandSender { +public interface CommandSender extends Permissible { /** * Sends this sender a message @@ -12,13 +13,6 @@ public interface CommandSender { public void sendMessage(String message); /** - * Checks if this sender is currently op - * - * @return true if they are - */ - public boolean isOp(); - - /** * Returns the server instance that this command is running on * * @return Server instance diff --git a/src/main/java/org/bukkit/command/ConsoleCommandSender.java b/src/main/java/org/bukkit/command/ConsoleCommandSender.java index 5ee6a2dd..72ba11ce 100644 --- a/src/main/java/org/bukkit/command/ConsoleCommandSender.java +++ b/src/main/java/org/bukkit/command/ConsoleCommandSender.java @@ -1,13 +1,20 @@ package org.bukkit.command; +import java.util.Set; import org.bukkit.ChatColor; import org.bukkit.Server; +import org.bukkit.permissions.PermissibleBase; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionAttachment; +import org.bukkit.permissions.PermissionAttachmentInfo; +import org.bukkit.plugin.Plugin; /** * Represents CLI input from a console */ public class ConsoleCommandSender implements CommandSender { private final Server server; + private final PermissibleBase perm = new PermissibleBase(this); public ConsoleCommandSender(Server server) { this.server = server; @@ -21,6 +28,10 @@ public class ConsoleCommandSender implements CommandSender { return true; } + public void setOp(boolean value) { + throw new UnsupportedOperationException("Cannot change operator status of server console"); + } + public boolean isPlayer() { return false; } @@ -28,4 +39,48 @@ public class ConsoleCommandSender implements CommandSender { public Server getServer() { return server; } + + public boolean isPermissionSet(String name) { + return perm.isPermissionSet(name); + } + + public boolean isPermissionSet(Permission perm) { + return this.perm.isPermissionSet(perm); + } + + public boolean hasPermission(String name) { + return perm.hasPermission(name); + } + + public boolean hasPermission(Permission perm) { + return this.perm.hasPermission(perm); + } + + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { + return perm.addAttachment(plugin, name, value); + } + + public PermissionAttachment addAttachment(Plugin plugin) { + return perm.addAttachment(plugin); + } + + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { + return perm.addAttachment(plugin, name, value, ticks); + } + + public PermissionAttachment addAttachment(Plugin plugin, int ticks) { + return perm.addAttachment(plugin, ticks); + } + + public void removeAttachment(PermissionAttachment attachment) { + perm.removeAttachment(attachment); + } + + public void recalculatePermissions() { + perm.recalculatePermissions(); + } + + public Set<PermissionAttachmentInfo> getEffectivePermissions() { + return perm.getEffectivePermissions(); + } } diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java index cd788dbd..8c6efae8 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java @@ -2,11 +2,12 @@ package org.bukkit.entity; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; +import org.bukkit.permissions.Permissible; /** * Represents a human entity, such as an NPC or a player */ -public interface HumanEntity extends LivingEntity, AnimalTamer { +public interface HumanEntity extends LivingEntity, AnimalTamer, Permissible { /** * Returns the name of this player diff --git a/src/main/java/org/bukkit/permissions/Permissible.java b/src/main/java/org/bukkit/permissions/Permissible.java new file mode 100644 index 00000000..a7f61773 --- /dev/null +++ b/src/main/java/org/bukkit/permissions/Permissible.java @@ -0,0 +1,106 @@ + +package org.bukkit.permissions; + +import java.util.Set; +import org.bukkit.plugin.Plugin; + +/** + * Represents an object that may be assigned permissions + */ +public interface Permissible extends ServerOperator { + /** + * Checks if this object contains an override for the specified permission, by fully qualified name + * + * @param name Name of the permission + * @return true if the permission is set, otherwise false + */ + public boolean isPermissionSet(String name); + + /** + * Checks if this object contains an override for the specified {@link Permission} + * + * @param perm Permission to check + * @return true if the permission is set, otherwise false + */ + public boolean isPermissionSet(Permission perm); + + /** + * Gets the value of the specified permission, if set. + * + * If a permission override is not set on this object, the default value of the permission will be returned. + * + * @param name Name of the permission + * @return Value of the permission + */ + public boolean hasPermission(String name); + + /** + * Gets the value of the specified permission, if set. + * + * If a permission override is not set on this object, the default value of the permission will be returned + * + * @param perm Permission to get + * @return Value of the permission + */ + public boolean hasPermission(Permission perm); + + /** + * Adds a new {@link PermissionAttachment} with a single permission by name and value + * + * @param plugin Plugin responsible for this attachment, may not be null or disabled + * @param name Name of the permission to attach + * @param value Value of the permission + * @return The PermissionAttachment that was just created + */ + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value); + + /** + * Adds a new empty {@link PermissionAttachment} to this object + * + * @param plugin Plugin responsible for this attachment, may not be null or disabled + * @return The PermissionAttachment that was just created + */ + public PermissionAttachment addAttachment(Plugin plugin); + + /** + * Temporarily adds a new {@link PermissionAttachment} with a single permission by name and value + * + * @param plugin Plugin responsible for this attachment, may not be null or disabled + * @param name Name of the permission to attach + * @param value Value of the permission + * @param ticks Amount of ticks to automatically remove this attachment after + * @return The PermissionAttachment that was just created + */ + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks); + + /** + * Temporarily adds a new empty {@link PermissionAttachment} to this object + * + * @param plugin Plugin responsible for this attachment, may not be null or disabled + * @param ticks Amount of ticks to automatically remove this attachment after + * @return The PermissionAttachment that was just created + */ + public PermissionAttachment addAttachment(Plugin plugin, int ticks); + + /** + * Removes the given {@link PermissionAttachment} from this object + * + * @param attachment Attachment to remove + * @throws IllegalArgumentException Thrown when the specified attachment isn't part of this object + */ + public void removeAttachment(PermissionAttachment attachment); + + /** + * Recalculates the permissions for this object, if the attachments have changed values. + * + * This should very rarely need to be called from a plugin. + */ + public void recalculatePermissions(); + + /** + * Gets a set containing all of the permissions currently in effect by this object + * + * @return Set of currently effective permissions + */ + public Set<PermissionAttachmentInfo> getEffectivePermissions(); +} diff --git a/src/main/java/org/bukkit/permissions/PermissibleBase.java b/src/main/java/org/bukkit/permissions/PermissibleBase.java new file mode 100644 index 00000000..950cfc8b --- /dev/null +++ b/src/main/java/org/bukkit/permissions/PermissibleBase.java @@ -0,0 +1,242 @@ +package org.bukkit.permissions; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; + +/** + * Base Permissible for use in any Permissible object via proxy or extension + */ +public class PermissibleBase implements Permissible { + private ServerOperator opable = null; + private final List<PermissionAttachment> attachments = new LinkedList<PermissionAttachment>(); + private final Map<String, PermissionAttachmentInfo> permissions = new HashMap<String, PermissionAttachmentInfo>(); + private boolean dirtyPermissions = true; + + public PermissibleBase(ServerOperator opable) { + this.opable = opable; + } + + public boolean isOp() { + if (opable == null) { + return false; + } else { + return opable.isOp(); + } + } + + public void setOp(boolean value) { + if (opable == null) { + throw new UnsupportedOperationException("Cannot change op value as no ServerOperator is set"); + } else { + opable.setOp(value); + } + } + + public boolean isPermissionSet(String name) { + if (name == null) { + throw new IllegalArgumentException("Permission name cannot be null"); + } + + calculatePermissions(); + + return permissions.containsKey(name.toLowerCase()); + } + + public boolean isPermissionSet(Permission perm) { + if (perm == null) { + throw new IllegalArgumentException("Permission cannot be null"); + } + + return isPermissionSet(perm.getName()); + } + + public boolean hasPermission(String inName) { + if (inName == null) { + throw new IllegalArgumentException("Permission name cannot be null"); + } + + calculatePermissions(); + + String name = inName.toLowerCase(); + + if (isPermissionSet(name)) { + return permissions.get(name).getValue(); + } else { + Permission perm = Bukkit.getServer().getPluginManager().getPermission(name); + + if (perm != null) { + return perm.getDefault().getValue(isOp()); + } else { + return false; + } + } + } + + public boolean hasPermission(Permission perm) { + if (perm == null) { + throw new IllegalArgumentException("Permission cannot be null"); + } + + calculatePermissions(); + + String name = perm.getName().toLowerCase(); + + if (isPermissionSet(name)) { + return permissions.get(name).getValue(); + } else if (perm != null) { + return perm.getDefault().getValue(isOp()); + } else { + return false; + } + } + + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { + if (name == null) { + throw new IllegalArgumentException("Permission name cannot be null"); + } else if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { + throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled"); + } + + PermissionAttachment result = addAttachment(plugin); + result.setPermission(name, value); + + recalculatePermissions(); + + return result; + } + + public PermissionAttachment addAttachment(Plugin plugin) { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { + throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled"); + } + + PermissionAttachment result = new PermissionAttachment(plugin, this); + + attachments.add(result); + recalculatePermissions(); + + return result; + } + + public void removeAttachment(PermissionAttachment attachment) { + if (attachment == null) { + throw new IllegalArgumentException("Attachment cannot be null"); + } + + if (attachments.contains(attachment)) { + attachments.remove(attachment); + PermissionRemovedExecutor ex = attachment.getRemovalCallback(); + + if (ex != null) { + ex.attachmentRemoved(attachment); + } + + recalculatePermissions(); + } else { + throw new IllegalArgumentException("Given attachment is not part of Permissible object " + this); + } + } + + public void recalculatePermissions() { + dirtyPermissions = true; + } + + private synchronized void calculatePermissions() { + if (dirtyPermissions) { + permissions.clear(); + Set<Permission> defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp()); + + for (Permission perm : defaults) { + String name = perm.getName().toLowerCase(); + permissions.put(name, new PermissionAttachmentInfo(this, name, null, true)); + calculateChildPermissions(perm.getChildren(), false, null); + } + + for (PermissionAttachment attachment : attachments) { + calculateChildPermissions(attachment.getPermissions(), false, attachment); + } + + dirtyPermissions = false; + } + } + + private void calculateChildPermissions(Map<String, Boolean> children, boolean invert, PermissionAttachment attachment) { + Set<String> keys = children.keySet(); + + for (String name : keys) { + Permission perm = Bukkit.getServer().getPluginManager().getPermission(name); + boolean value = children.get(name) ^ invert; + String lname = name.toLowerCase(); + + permissions.put(lname, new PermissionAttachmentInfo(this, lname, attachment, value)); + + if (perm != null) { + calculateChildPermissions(perm.getChildren(), !value, attachment); + } + } + } + + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { + if (name == null) { + throw new IllegalArgumentException("Permission name cannot be null"); + } else if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { + throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled"); + } + + PermissionAttachment result = addAttachment(plugin, ticks); + + if (result != null) { + result.setPermission(name, value); + } + + return result; + } + + public PermissionAttachment addAttachment(Plugin plugin, int ticks) { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { + throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled"); + } + + PermissionAttachment result = addAttachment(plugin); + + if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new RemoveAttachmentRunnable(result), ticks) == -1) { + Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add PermissionAttachment to " + this + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1"); + result.remove(); + return null; + } else { + return result; + } + } + + public Set<PermissionAttachmentInfo> getEffectivePermissions() { + calculatePermissions(); + return new HashSet<PermissionAttachmentInfo>(permissions.values()); + } + + private class RemoveAttachmentRunnable implements Runnable { + private PermissionAttachment attachment; + + public RemoveAttachmentRunnable(PermissionAttachment attachment) { + this.attachment = attachment; + } + + public void run() { + attachment.remove(); + } + } +} diff --git a/src/main/java/org/bukkit/permissions/Permission.java b/src/main/java/org/bukkit/permissions/Permission.java new file mode 100644 index 00000000..d219832a --- /dev/null +++ b/src/main/java/org/bukkit/permissions/Permission.java @@ -0,0 +1,146 @@ + +package org.bukkit.permissions; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Represents a unique permission that may be attached to a {@link Permissible} + */ +public class Permission { + private final String name; + private final Map<String, Boolean> children = new LinkedHashMap<String, Boolean>(); + private PermissionDefault defaultValue = PermissionDefault.FALSE; + private String description; + + public Permission(String name) { + this(name, null, null, null); + } + + public Permission(String name, String description) { + this(name, description, null, null); + } + + public Permission(String name, PermissionDefault defaultValue) { + this(name, null, defaultValue, null); + } + + public Permission(String name, String description, PermissionDefault defaultValue) { + this(name, description, defaultValue, null); + } + + public Permission(String name, Map<String, Boolean> children) { + this(name, null, null, children); + } + + public Permission(String name, String description, Map<String, Boolean> children) { + this(name, description, null, children); + } + + public Permission(String name, PermissionDefault defaultValue, Map<String, Boolean> children) { + this(name, null, defaultValue, children); + } + + public Permission(String name, String description, PermissionDefault defaultValue, Map<String, Boolean> children) { + this.name = name; + this.description = (description == null) ? "" : description; + this.defaultValue = (defaultValue == null) ? defaultValue.FALSE : defaultValue; + + if (children != null) { + this.children.putAll(children); + } + } + + /** + * Returns the unique fully qualified name of this Permission + * + * @return Fully qualified name + */ + public String getName() { + return name; + } + + /** + * Gets the children of this permission. + * + * This is a copy and changes will not be saved. + * + * @return Permission children + */ + public Map<String, Boolean> getChildren() { + return new LinkedHashMap<String, Boolean>(children); + } + + /** + * Gets the default value of this permission. + * + * @return Default value of this permission. + */ + public PermissionDefault getDefault() { + return defaultValue; + } + + /** + * Gets a brief description of this permission, if set + * + * @return Brief description of this permission + */ + public String getDescription() { + return description; + } + + /** + * Loads a Permission from a map of data, usually used from retrieval from a yaml file. + * + * The data may contain the following keys: + * default: Boolean true or false. If not specified, false. + * children: Map<String, Boolean> of child permissions. If not specified, empty list. + * description: Short string containing a very small description of this description. If not specified, empty string. + * + * @param name Name of the permission + * @param data Map of keys + * @return Permission object + */ + public static Permission loadPermission(String name, Map<String, Object> data) { + if (name == null) { + throw new IllegalArgumentException("Name cannot be null"); + } + if (data == null) { + throw new IllegalArgumentException("Data cannot be null"); + } + String desc = null; + PermissionDefault def = null; + Map<String, Boolean> children = null; + + if (data.containsKey("default")) { + try { + PermissionDefault value = PermissionDefault.getByName(data.get("default").toString()); + if (value != null) { + def = value; + } else { + throw new IllegalArgumentException("'default' key contained unknown value"); + } + } catch (ClassCastException ex) { + throw new IllegalArgumentException("'default' key is of wrong type", ex); + } + } + + if (data.containsKey("children")) { + try { + children = (Map<String, Boolean>)data.get("children"); + } catch (ClassCastException ex) { + throw new IllegalArgumentException("'children' key is of wrong type", ex); + } + } + + if (data.containsKey("description")) { + try { + desc = (String)data.get("description"); + } catch (ClassCastException ex) { + throw new IllegalArgumentException("'description' key is of wrong type", ex); + } + } + + return new Permission(name, desc, def, children); + } +} diff --git a/src/main/java/org/bukkit/permissions/PermissionAttachment.java b/src/main/java/org/bukkit/permissions/PermissionAttachment.java new file mode 100644 index 00000000..92ba9904 --- /dev/null +++ b/src/main/java/org/bukkit/permissions/PermissionAttachment.java @@ -0,0 +1,134 @@ + +package org.bukkit.permissions; + +import java.util.Map; +import java.util.TreeMap; +import org.bukkit.plugin.Plugin; + +/** + * Holds information about a permission attachment on a {@link Permissible} object + */ +public class PermissionAttachment { + private PermissionRemovedExecutor removed; + private final TreeMap<String, Boolean> permissions = new TreeMap<String, Boolean>(); + private final Permissible permissible; + private final Plugin plugin; + + public PermissionAttachment(Plugin plugin, Permissible Permissible) { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { + throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled"); + } + + this.permissible = Permissible; + this.plugin = plugin; + } + + /** + * Gets the plugin responsible for this attachment + * + * @return Plugin responsible for this permission attachment + */ + public Plugin getPlugin() { + return plugin; + } + + /** + * Sets an object to be called for when this attachment is removed from a {@link Permissible}. May be null. + * + * @param ex Object to be called when this is removed + */ + public void setRemovalCallback(PermissionRemovedExecutor ex) { + removed = ex; + } + + /** + * Gets the class that was previously set to be called when this attachment was removed from a {@link Permissible}. May be null. + * + * @return Object to be called when this is removed + */ + public PermissionRemovedExecutor getRemovalCallback() { + return removed; + } + + /** + * Gets the Permissible that this is attached to + * + * @return Permissible containing this attachment + */ + public Permissible getPermissible() { + return permissible; + } + + /** + * Gets a copy of all set permissions and values contained within this attachment. + * + * This map may be modified but will not affect the attachment, as it is a copy. + * + * @return Copy of all permissions and values expressed by this attachment + */ + public Map<String, Boolean> getPermissions() { + return (Map<String, Boolean>)permissions.clone(); + } + + /** + * Sets a permission to the given value, by its fully qualified name + * + * @param name Name of the permission + * @param value New value of the permission + */ + public void setPermission(String name, boolean value) { + permissions.put(name.toLowerCase(), value); + permissible.recalculatePermissions(); + } + + /** + * Sets a permission to the given value + * + * @param perm Permission to set + * @param value New value of the permission + */ + public void setPermission(Permission perm, boolean value) { + setPermission(perm.getName(), value); + permissible.recalculatePermissions(); + } + + /** + * Removes the specified permission from this attachment. + * + * If the permission does not exist in this attachment, nothing will happen. + * + * @param name Name of the permission to remove + */ + public void unsetPermission(String name) { + permissions.remove(name.toLowerCase()); + permissible.recalculatePermissions(); + } + + /** + * Removes the specified permission from this attachment. + * + * If the permission does not exist in this attachment, nothing will happen. + * + * @param perm Permission to remove + */ + public void unsetPermission(Permission perm) { + unsetPermission(perm.getName()); + permissible.recalculatePermissions(); + } + + /** + * Removes this attachment from its registered {@link Permissible} + * + * @return true if the permissible was removed successfully, false if it did not exist + */ + public boolean remove() { + try { + permissible.removeAttachment(this); + return true; + } catch (IllegalArgumentException ex) { + return false; + } + } +} diff --git a/src/main/java/org/bukkit/permissions/PermissionAttachmentInfo.java b/src/main/java/org/bukkit/permissions/PermissionAttachmentInfo.java new file mode 100644 index 00000000..b43190d4 --- /dev/null +++ b/src/main/java/org/bukkit/permissions/PermissionAttachmentInfo.java @@ -0,0 +1,62 @@ + +package org.bukkit.permissions; + +/** + * Holds information on a permission and which {@link PermissionAttachment} provides it + */ +public class PermissionAttachmentInfo { + private final Permissible permissible; + private final String permission; + private final PermissionAttachment attachment; + private final boolean value; + + public PermissionAttachmentInfo(Permissible permissible, String permission, PermissionAttachment attachment, boolean value) { + if (permissible == null) { + throw new IllegalArgumentException("Permissible may not be null"); + } else if (permission == null) { + throw new IllegalArgumentException("Permissions may not be null"); + } + + this.permissible = permissible; + this.permission = permission; + this.attachment = attachment; + this.value = value; + } + + /** + * Gets the permissible this is attached to + * + * @return Permissible this permission is for + */ + public Permissible getPermissible() { + return permissible; + } + + /** + * Gets the permission being set + * + * @return Name of the permission + */ + public String getPermission() { + return permission; + } + + /** + * Gets the attachment providing this permission. This may be null for default + * permissions (usually parent permissions). + * + * @return Attachment + */ + public PermissionAttachment getAttachment() { + return attachment; + } + + /** + * Gets the value of this permission + * + * @return Value of the permission + */ + public boolean getValue() { + return value; + } +} diff --git a/src/main/java/org/bukkit/permissions/PermissionDefault.java b/src/main/java/org/bukkit/permissions/PermissionDefault.java new file mode 100644 index 00000000..78ff2f98 --- /dev/null +++ b/src/main/java/org/bukkit/permissions/PermissionDefault.java @@ -0,0 +1,65 @@ +package org.bukkit.permissions; + +import java.util.HashMap; +import java.util.Map; + +/** + * Represents the possible default values for permissions + */ +public enum PermissionDefault { + TRUE("true"), + FALSE("false"), + OP("op", "isop", "operator", "isoperator", "admin", "isadmin"), + NOT_OP("!op", "notop", "!operator", "notoperator", "!admin", "notadmin"); + + private final String[] names; + private final static Map<String, PermissionDefault> lookup = new HashMap<String, PermissionDefault>(); + + private PermissionDefault(String... names) { + this.names = names; + } + + /** + * Calculates the value of this PermissionDefault for the given operator value + * + * @param op If the target is op + * @return True if the default should be true, or false + */ + public boolean getValue(boolean op) { + switch (this) { + case TRUE: + return true; + case FALSE: + return false; + case OP: + return op; + case NOT_OP: + return !op; + default: + return false; + } + } + + /** + * Looks up a PermissionDefault by name + * + * @param name Name of the default + * @return Specified value, or null if not found + */ + public static PermissionDefault getByName(String name) { + return lookup.get(name.toLowerCase().replaceAll("[^a-z!]", "")); + } + + @Override + public String toString() { + return names[0]; + } + + static { + for (PermissionDefault value : values()) { + for (String name : value.names) { + lookup.put(name, value); + } + } + } +} diff --git a/src/main/java/org/bukkit/permissions/PermissionRemovedExecutor.java b/src/main/java/org/bukkit/permissions/PermissionRemovedExecutor.java new file mode 100644 index 00000000..7dc09125 --- /dev/null +++ b/src/main/java/org/bukkit/permissions/PermissionRemovedExecutor.java @@ -0,0 +1,14 @@ + +package org.bukkit.permissions; + +/** + * Represents a class which is to be notified when a {@link PermissionAttachment} is removed from a {@link Permissible} + */ +public interface PermissionRemovedExecutor { + /** + * Called when a {@link PermissionAttachment} is removed from a {@link Permissible} + * + * @param attachment Attachment which was removed + */ + public void attachmentRemoved(PermissionAttachment attachment); +} diff --git a/src/main/java/org/bukkit/permissions/ServerOperator.java b/src/main/java/org/bukkit/permissions/ServerOperator.java new file mode 100644 index 00000000..721c42a3 --- /dev/null +++ b/src/main/java/org/bukkit/permissions/ServerOperator.java @@ -0,0 +1,22 @@ +package org.bukkit.permissions; + +import org.bukkit.entity.Player; + +/** + * Represents an object that may become a server operator, such as a {@link Player} + */ +public interface ServerOperator { + /** + * Checks if this object is a server operator + * + * @return true if this is an operator, otherwise false + */ + public boolean isOp(); + + /** + * Sets the operator status of this object + * + * @param value New operator value + */ + public void setOp(boolean value); +} diff --git a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java index e505c26f..4d61c613 100644 --- a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java +++ b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java @@ -6,6 +6,10 @@ import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import org.bukkit.Bukkit; +import org.bukkit.permissions.Permission; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.SafeConstructor; @@ -25,6 +29,7 @@ public final class PluginDescriptionFile { private String website = null; private boolean database = false; private PluginLoadOrder order = PluginLoadOrder.POSTWORLD; + private ArrayList<Permission> permissions = new ArrayList<Permission>(); @SuppressWarnings("unchecked") public PluginDescriptionFile(final InputStream stream) throws InvalidDescriptionException { @@ -138,6 +143,10 @@ public final class PluginDescriptionFile { this.database = database; } + public ArrayList<Permission> getPermissions() { + return permissions; + } + private void loadMap(Map<String, Object> map) throws InvalidDescriptionException { try { name = map.get("name").toString(); @@ -247,6 +256,16 @@ public final class PluginDescriptionFile { throw new InvalidDescriptionException(ex, "authors are of wrong type"); } } + + if (map.containsKey("permissions")) { + try { + Map<String, Map<String, Object>> perms = (Map<String, Map<String, Object>>) map.get("permissions"); + + loadPermissions(perms); + } catch (ClassCastException ex) { + throw new InvalidDescriptionException(ex, "permissions are of wrong type"); + } + } } private Map<String, Object> saveMap() { @@ -282,4 +301,16 @@ public final class PluginDescriptionFile { return map; } + + private void loadPermissions(Map<String, Map<String, Object>> perms) { + Set<String> keys = perms.keySet(); + + for (String name : keys) { + try { + permissions.add(Permission.loadPermission(name, perms.get(name))); + } catch (Throwable ex) { + Bukkit.getServer().getLogger().log(Level.SEVERE, "Permission node '" + name + "' in plugin description file for " + getFullName() + " is invalid", ex); + } + } + } } diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java index 0d9781ab..b445f180 100644 --- a/src/main/java/org/bukkit/plugin/PluginManager.java +++ b/src/main/java/org/bukkit/plugin/PluginManager.java @@ -1,10 +1,12 @@ package org.bukkit.plugin; import java.io.File; +import java.util.Set; import org.bukkit.event.Event; import org.bukkit.event.Event.Priority; import org.bukkit.event.Listener; +import org.bukkit.permissions.Permission; /** * Handles all plugin management from the Server @@ -130,4 +132,30 @@ public interface PluginManager { * @param plugin Plugin to disable */ public void disablePlugin(Plugin plugin); + + /** + * Gets a {@link Permission} from its fully qualified name + * + * @param name Name of the permission + * @return Permission, or null if none + */ + public Permission getPermission(String name); + + /** + * Adds a {@link Permission} to this plugin manager. + * + * If a permission is already defined with the given name of the new permission, + * an exception will be thrown. + * + * @param perm Permission to add + * @throws IllegalArgumentException Thrown when a permission with the same name already exists + */ + public void addPermission(Permission perm); + + /** + * Gets the default permissions for the given op status + * + * @param op Which set of default permissions to get + */ + public Set<Permission> getDefaultPermissions(boolean op); } diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java index c285706b..eaf3b671 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -12,8 +12,10 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.Arrays; +import java.util.HashSet; import java.util.LinkedList; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.logging.Level; import java.util.regex.Matcher; import org.bukkit.Server; @@ -25,6 +27,7 @@ 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.Permission; import org.bukkit.util.FileUtil; @@ -39,6 +42,8 @@ public final class SimplePluginManager implements PluginManager { private final Map<Event.Type, SortedSet<RegisteredListener>> listeners = new EnumMap<Event.Type, SortedSet<RegisteredListener>>(Event.Type.class); private static File updateDirectory = null; 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 Comparator<RegisteredListener> comparer = new Comparator<RegisteredListener>() { public int compare(RegisteredListener i, RegisteredListener j) { int result = i.getPriority().compareTo(j.getPriority()); @@ -54,6 +59,9 @@ public final class SimplePluginManager implements PluginManager { public SimplePluginManager(Server instance, SimpleCommandMap commandMap) { server = instance; this.commandMap = commandMap; + + defaultPerms.put(true, new HashSet<Permission>()); + defaultPerms.put(false, new HashSet<Permission>()); } /** @@ -303,6 +311,9 @@ public final class SimplePluginManager implements PluginManager { lookupNames.clear(); listeners.clear(); fileAssociations.clear(); + permissions.clear(); + defaultPerms.get(true).clear(); + defaultPerms.get(false).clear(); } } @@ -394,4 +405,37 @@ public final class SimplePluginManager implements PluginManager { listeners.put(type, eventListeners); return eventListeners; } + + public Permission getPermission(String name) { + return permissions.get(name.toLowerCase()); + } + + public void addPermission(Permission perm) { + String name = perm.getName().toLowerCase(); + + if (permissions.containsKey(name)) { + throw new IllegalArgumentException("The permission " + name + " is already defined!"); + } + + permissions.put(name, 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; + } + } + } + + public Set<Permission> getDefaultPermissions(boolean op) { + return defaultPerms.get(op); + } } diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java index 81f0ed53..1fa153f1 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java @@ -263,4 +263,9 @@ public abstract class JavaPlugin implements Plugin { gen.runScript(true, gen.generateDropDdl()); } + + @Override + public String toString() { + return getDescription().getFullName(); + } } |