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 }