001 package org.bukkit.permissions;
002
003 import java.util.HashMap;
004 import java.util.HashSet;
005 import java.util.LinkedList;
006 import java.util.List;
007 import java.util.Map;
008 import java.util.Set;
009 import java.util.logging.Level;
010 import org.bukkit.Bukkit;
011 import org.bukkit.plugin.Plugin;
012
013 /**
014 * Base Permissible for use in any Permissible object via proxy or extension
015 */
016 public class PermissibleBase implements Permissible {
017 private ServerOperator opable = null;
018 private Permissible parent = this;
019 private final List<PermissionAttachment> attachments = new LinkedList<PermissionAttachment>();
020 private final Map<String, PermissionAttachmentInfo> permissions = new HashMap<String, PermissionAttachmentInfo>();
021
022 public PermissibleBase(ServerOperator opable) {
023 this.opable = opable;
024
025 if (opable instanceof Permissible) {
026 this.parent = (Permissible) opable;
027 }
028
029 recalculatePermissions();
030 }
031
032 public boolean isOp() {
033 if (opable == null) {
034 return false;
035 } else {
036 return opable.isOp();
037 }
038 }
039
040 public void setOp(boolean value) {
041 if (opable == null) {
042 throw new UnsupportedOperationException("Cannot change op value as no ServerOperator is set");
043 } else {
044 opable.setOp(value);
045 }
046 }
047
048 public boolean isPermissionSet(String name) {
049 if (name == null) {
050 throw new IllegalArgumentException("Permission name cannot be null");
051 }
052
053 return permissions.containsKey(name.toLowerCase());
054 }
055
056 public boolean isPermissionSet(Permission perm) {
057 if (perm == null) {
058 throw new IllegalArgumentException("Permission cannot be null");
059 }
060
061 return isPermissionSet(perm.getName());
062 }
063
064 public boolean hasPermission(String inName) {
065 if (inName == null) {
066 throw new IllegalArgumentException("Permission name cannot be null");
067 }
068
069 String name = inName.toLowerCase();
070
071 if (isPermissionSet(name)) {
072 return permissions.get(name).getValue();
073 } else {
074 Permission perm = Bukkit.getServer().getPluginManager().getPermission(name);
075
076 if (perm != null) {
077 return perm.getDefault().getValue(isOp());
078 } else {
079 return Permission.DEFAULT_PERMISSION.getValue(isOp());
080 }
081 }
082 }
083
084 public boolean hasPermission(Permission perm) {
085 if (perm == null) {
086 throw new IllegalArgumentException("Permission cannot be null");
087 }
088
089 String name = perm.getName().toLowerCase();
090
091 if (isPermissionSet(name)) {
092 return permissions.get(name).getValue();
093 }
094 return perm.getDefault().getValue(isOp());
095 }
096
097 public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
098 if (name == null) {
099 throw new IllegalArgumentException("Permission name cannot be null");
100 } else if (plugin == null) {
101 throw new IllegalArgumentException("Plugin cannot be null");
102 } else if (!plugin.isEnabled()) {
103 throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled");
104 }
105
106 PermissionAttachment result = addAttachment(plugin);
107 result.setPermission(name, value);
108
109 recalculatePermissions();
110
111 return result;
112 }
113
114 public PermissionAttachment addAttachment(Plugin plugin) {
115 if (plugin == null) {
116 throw new IllegalArgumentException("Plugin cannot be null");
117 } else if (!plugin.isEnabled()) {
118 throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled");
119 }
120
121 PermissionAttachment result = new PermissionAttachment(plugin, parent);
122
123 attachments.add(result);
124 recalculatePermissions();
125
126 return result;
127 }
128
129 public void removeAttachment(PermissionAttachment attachment) {
130 if (attachment == null) {
131 throw new IllegalArgumentException("Attachment cannot be null");
132 }
133
134 if (attachments.contains(attachment)) {
135 attachments.remove(attachment);
136 PermissionRemovedExecutor ex = attachment.getRemovalCallback();
137
138 if (ex != null) {
139 ex.attachmentRemoved(attachment);
140 }
141
142 recalculatePermissions();
143 } else {
144 throw new IllegalArgumentException("Given attachment is not part of Permissible object " + parent);
145 }
146 }
147
148 public void recalculatePermissions() {
149 clearPermissions();
150 Set<Permission> defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp());
151 Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), parent);
152
153 for (Permission perm : defaults) {
154 String name = perm.getName().toLowerCase();
155 permissions.put(name, new PermissionAttachmentInfo(parent, name, null, true));
156 Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
157 calculateChildPermissions(perm.getChildren(), false, null);
158 }
159
160 for (PermissionAttachment attachment : attachments) {
161 calculateChildPermissions(attachment.getPermissions(), false, attachment);
162 }
163 }
164
165 public synchronized void clearPermissions() {
166 Set<String> perms = permissions.keySet();
167
168 for (String name : perms) {
169 Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, parent);
170 }
171
172 Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(false, parent);
173 Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(true, parent);
174
175 permissions.clear();
176 }
177
178 private void calculateChildPermissions(Map<String, Boolean> children, boolean invert, PermissionAttachment attachment) {
179 Set<String> keys = children.keySet();
180
181 for (String name : keys) {
182 Permission perm = Bukkit.getServer().getPluginManager().getPermission(name);
183 boolean value = children.get(name) ^ invert;
184 String lname = name.toLowerCase();
185
186 permissions.put(lname, new PermissionAttachmentInfo(parent, lname, attachment, value));
187 Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
188
189 if (perm != null) {
190 calculateChildPermissions(perm.getChildren(), !value, attachment);
191 }
192 }
193 }
194
195 public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
196 if (name == null) {
197 throw new IllegalArgumentException("Permission name cannot be null");
198 } else if (plugin == null) {
199 throw new IllegalArgumentException("Plugin cannot be null");
200 } else if (!plugin.isEnabled()) {
201 throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled");
202 }
203
204 PermissionAttachment result = addAttachment(plugin, ticks);
205
206 if (result != null) {
207 result.setPermission(name, value);
208 }
209
210 return result;
211 }
212
213 public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
214 if (plugin == null) {
215 throw new IllegalArgumentException("Plugin cannot be null");
216 } else if (!plugin.isEnabled()) {
217 throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is disabled");
218 }
219
220 PermissionAttachment result = addAttachment(plugin);
221
222 if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new RemoveAttachmentRunnable(result), ticks) == -1) {
223 Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add PermissionAttachment to " + parent + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1");
224 result.remove();
225 return null;
226 } else {
227 return result;
228 }
229 }
230
231 public Set<PermissionAttachmentInfo> getEffectivePermissions() {
232 return new HashSet<PermissionAttachmentInfo>(permissions.values());
233 }
234
235 private class RemoveAttachmentRunnable implements Runnable {
236 private PermissionAttachment attachment;
237
238 public RemoveAttachmentRunnable(PermissionAttachment attachment) {
239 this.attachment = attachment;
240 }
241
242 public void run() {
243 attachment.remove();
244 }
245 }
246 }