Clover coverage report - Acegi Security System for Spring - 1.0.0-RC1
Coverage timestamp: Mon Dec 5 2005 09:05:15 EST
file stats: LOC: 281   Methods: 20
NCLOC: 156   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AbstractBasicAclEntry.java 73.1% 89.1% 100% 87.3%
coverage coverage
 1    /* Copyright 2004, 2005 Acegi Technology Pty Limited
 2    *
 3    * Licensed under the Apache License, Version 2.0 (the "License");
 4    * you may not use this file except in compliance with the License.
 5    * You may obtain a copy of the License at
 6    *
 7    * http://www.apache.org/licenses/LICENSE-2.0
 8    *
 9    * Unless required by applicable law or agreed to in writing, software
 10    * distributed under the License is distributed on an "AS IS" BASIS,
 11    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    * See the License for the specific language governing permissions and
 13    * limitations under the License.
 14    */
 15   
 16    package org.acegisecurity.acl.basic;
 17   
 18    import org.apache.commons.logging.Log;
 19    import org.apache.commons.logging.LogFactory;
 20    import org.springframework.util.Assert;
 21   
 22    import java.util.Arrays;
 23   
 24   
 25    /**
 26    * Abstract implementation of {@link BasicAclEntry}.
 27    *
 28    * <P>
 29    * Provides core bit mask handling methods.
 30    * </p>
 31    *
 32    * @author Ben Alex
 33    * @version $Id: AbstractBasicAclEntry.java,v 1.5 2005/11/17 00:55:47 benalex Exp $
 34    */
 35    public abstract class AbstractBasicAclEntry implements BasicAclEntry {
 36    //~ Static fields/initializers =============================================
 37   
 38    private static final Log logger = LogFactory.getLog(AbstractBasicAclEntry.class);
 39   
 40    //~ Instance fields ========================================================
 41   
 42    private AclObjectIdentity aclObjectIdentity;
 43    private AclObjectIdentity aclObjectParentIdentity;
 44    private Object recipient;
 45    private int[] validPermissions;
 46    private int mask = 0; // default means no permissions
 47   
 48    //~ Constructors ===========================================================
 49   
 50  135 public AbstractBasicAclEntry(Object recipient,
 51    AclObjectIdentity aclObjectIdentity,
 52    AclObjectIdentity aclObjectParentIdentity, int mask) {
 53  135 Assert.notNull(recipient, "recipient cannot be null");
 54   
 55  134 Assert.notNull(aclObjectIdentity, "aclObjectIdentity cannot be null");
 56   
 57  133 validPermissions = getValidPermissions();
 58  133 Arrays.sort(validPermissions);
 59   
 60  133 for (int i = 0; i < validPermissions.length; i++) {
 61  1330 if (logger.isDebugEnabled()) {
 62  0 logger.debug("Valid permission: "
 63    + printPermissionsBlock(validPermissions[i]) + " "
 64    + printBinary(validPermissions[i]) + " ("
 65    + validPermissions[i] + ")");
 66    }
 67    }
 68   
 69  133 this.recipient = recipient;
 70  133 this.aclObjectIdentity = aclObjectIdentity;
 71  133 this.aclObjectParentIdentity = aclObjectParentIdentity;
 72  133 this.mask = mask;
 73    }
 74   
 75    /**
 76    * A protected constructor for use by Hibernate.
 77    */
 78  30 protected AbstractBasicAclEntry() {
 79  30 validPermissions = getValidPermissions();
 80  30 Arrays.sort(validPermissions);
 81    }
 82   
 83    //~ Methods ================================================================
 84   
 85  27 public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity) {
 86  27 this.aclObjectIdentity = aclObjectIdentity;
 87    }
 88   
 89  27 public AclObjectIdentity getAclObjectIdentity() {
 90  27 return this.aclObjectIdentity;
 91    }
 92   
 93  27 public void setAclObjectParentIdentity(
 94    AclObjectIdentity aclObjectParentIdentity) {
 95  27 this.aclObjectParentIdentity = aclObjectParentIdentity;
 96    }
 97   
 98  26 public AclObjectIdentity getAclObjectParentIdentity() {
 99  26 return this.aclObjectParentIdentity;
 100    }
 101   
 102    /**
 103    * Subclasses must indicate the permissions they support. Each base
 104    * permission should be an integer with a base 2. ie: the first permission
 105    * is 2^^0 (1), the second permission is 2^^1 (2), the third permission is
 106    * 2^^2 (4) etc. Each base permission should be exposed by the subclass as
 107    * a <code>public static final int</code>. It is further recommended that
 108    * valid combinations of permissions are also exposed as <code>public
 109    * static final int</code>s.
 110    *
 111    * <P>
 112    * This method returns all permission integers that are allowed to be used
 113    * together. <B>This must include any combinations of valid
 114    * permissions</b>. So if the permissions indicated by 2^^2 (4) and 2^^1
 115    * (2) can be used together, one of the integers returned by this method
 116    * must be 6 (4 + 2). Otherwise attempts to set the permission will be
 117    * rejected, as the final resulting mask will be rejected.
 118    * </p>
 119    *
 120    * <P>
 121    * Whilst it may seem unduly time onerous to return every valid permission
 122    * <B>combination</B>, doing so delivers maximum flexibility in ensuring
 123    * ACLs only reflect logical combinations. For example, it would be
 124    * inappropriate to grant a "read" and "write" permission along with an
 125    * "unrestricted" permission, as the latter implies the former
 126    * permissions.
 127    * </p>
 128    *
 129    * @return <b>every</b> valid combination of permissions
 130    */
 131    public abstract int[] getValidPermissions();
 132   
 133    /**
 134    * Outputs the permissions in a human-friendly format. For example, this
 135    * method may return "CR-D" to indicate the passed integer permits create,
 136    * permits read, does not permit update, and permits delete.
 137    *
 138    * @param i the integer containing the mask which should be printed
 139    *
 140    * @return the human-friend formatted block
 141    */
 142    public abstract String printPermissionsBlock(int i);
 143   
 144  26 public void setMask(int mask) {
 145  26 this.mask = mask;
 146    }
 147   
 148  21 public int getMask() {
 149  21 return this.mask;
 150    }
 151   
 152  40 public boolean isPermitted(int permissionToCheck) {
 153  40 return isPermitted(this.mask, permissionToCheck);
 154    }
 155   
 156  26 public void setRecipient(Object recipient) {
 157  26 this.recipient = recipient;
 158    }
 159   
 160  136 public Object getRecipient() {
 161  136 return this.recipient;
 162    }
 163   
 164  3 public int addPermission(int permissionToAdd) {
 165  3 return addPermissions(new int[] {permissionToAdd});
 166    }
 167   
 168  7 public int addPermissions(int[] permissionsToAdd) {
 169  7 if (logger.isDebugEnabled()) {
 170  0 logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask)
 171    + " " + printBinary(mask) + " (" + mask + ")");
 172    }
 173   
 174  7 for (int i = 0; i < permissionsToAdd.length; i++) {
 175  14 if (logger.isDebugEnabled()) {
 176  0 logger.debug("Add permission: "
 177    + printPermissionsBlock(permissionsToAdd[i]) + " "
 178    + printBinary(permissionsToAdd[i]) + " ("
 179    + permissionsToAdd[i] + ")");
 180    }
 181   
 182  14 this.mask |= permissionsToAdd[i];
 183    }
 184   
 185  7 if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
 186  1 throw new IllegalArgumentException(
 187    "Resulting permission set will be invalid.");
 188    } else {
 189  6 if (logger.isDebugEnabled()) {
 190  0 logger.debug("AFTER Permissions: "
 191    + printPermissionsBlock(mask) + " " + printBinary(mask)
 192    + " (" + mask + ")");
 193    }
 194   
 195  6 return this.mask;
 196    }
 197    }
 198   
 199  3 public int deletePermission(int permissionToDelete) {
 200  3 return deletePermissions(new int[] {permissionToDelete});
 201    }
 202   
 203  4 public int deletePermissions(int[] permissionsToDelete) {
 204  4 if (logger.isDebugEnabled()) {
 205  0 logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask)
 206    + " " + printBinary(mask) + " (" + mask + ")");
 207    }
 208   
 209  4 for (int i = 0; i < permissionsToDelete.length; i++) {
 210  5 if (logger.isDebugEnabled()) {
 211  0 logger.debug("Delete permission: "
 212    + printPermissionsBlock(permissionsToDelete[i]) + " "
 213    + printBinary(permissionsToDelete[i]) + " ("
 214    + permissionsToDelete[i] + ")");
 215    }
 216   
 217  5 this.mask &= ~permissionsToDelete[i];
 218    }
 219   
 220  4 if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
 221  1 throw new IllegalArgumentException(
 222    "Resulting permission set will be invalid.");
 223    } else {
 224  3 if (logger.isDebugEnabled()) {
 225  0 logger.debug("AFTER Permissions: "
 226    + printPermissionsBlock(mask) + " " + printBinary(mask)
 227    + " (" + mask + ")");
 228    }
 229   
 230  3 return this.mask;
 231    }
 232    }
 233   
 234    /**
 235    * Outputs the permissions in human-friendly format for the current
 236    * <code>AbstractBasicAclEntry</code>'s mask.
 237    *
 238    * @return the human-friendly formatted block for this instance
 239    */
 240  5 public String printPermissionsBlock() {
 241  5 return printPermissionsBlock(this.mask);
 242    }
 243   
 244  1 public String toString() {
 245  1 StringBuffer sb = new StringBuffer();
 246  1 sb.append(getClass().getName());
 247  1 sb.append("[").append(aclObjectIdentity).append(",").append(recipient);
 248  1 sb.append("=").append(printPermissionsBlock(mask)).append(" ");
 249  1 sb.append(printBinary(mask)).append(" (");
 250  1 sb.append(mask).append(")").append("]");
 251   
 252  1 return sb.toString();
 253    }
 254   
 255  4 public int togglePermission(int permissionToToggle) {
 256  4 this.mask ^= permissionToToggle;
 257   
 258  4 if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
 259  1 throw new IllegalArgumentException(
 260    "Resulting permission set will be invalid.");
 261    } else {
 262  3 return this.mask;
 263    }
 264    }
 265   
 266  70 protected boolean isPermitted(int maskToCheck, int permissionToCheck) {
 267  70 return ((maskToCheck & permissionToCheck) == permissionToCheck);
 268    }
 269   
 270  1 private String printBinary(int i) {
 271  1 String s = Integer.toString(i, 2);
 272   
 273  1 String pattern = "................................";
 274   
 275  1 String temp1 = pattern.substring(0, pattern.length() - s.length());
 276   
 277  1 String temp2 = temp1 + s;
 278   
 279  1 return temp2.replace('0', '.');
 280    }
 281    }