summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/bukkit/command/CommandSender.java10
-rw-r--r--src/main/java/org/bukkit/command/ConsoleCommandSender.java55
-rw-r--r--src/main/java/org/bukkit/entity/HumanEntity.java3
-rw-r--r--src/main/java/org/bukkit/permissions/Permissible.java106
-rw-r--r--src/main/java/org/bukkit/permissions/PermissibleBase.java242
-rw-r--r--src/main/java/org/bukkit/permissions/Permission.java146
-rw-r--r--src/main/java/org/bukkit/permissions/PermissionAttachment.java134
-rw-r--r--src/main/java/org/bukkit/permissions/PermissionAttachmentInfo.java62
-rw-r--r--src/main/java/org/bukkit/permissions/PermissionDefault.java65
-rw-r--r--src/main/java/org/bukkit/permissions/PermissionRemovedExecutor.java14
-rw-r--r--src/main/java/org/bukkit/permissions/ServerOperator.java22
-rw-r--r--src/main/java/org/bukkit/plugin/PluginDescriptionFile.java31
-rw-r--r--src/main/java/org/bukkit/plugin/PluginManager.java28
-rw-r--r--src/main/java/org/bukkit/plugin/SimplePluginManager.java44
-rw-r--r--src/main/java/org/bukkit/plugin/java/JavaPlugin.java5
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();
+ }
}