Coverage Report - org.acegisecurity.acl.basic.AbstractBasicAclEntry
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractBasicAclEntry
91% 
100% 
1.727
 
 1  
 /* Copyright 2004, 2005, 2006 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  
 
 21  
 import org.springframework.util.Assert;
 22  
 
 23  
 import java.util.Arrays;
 24  
 
 25  
 
 26  
 /**
 27  
  * Abstract implementation of {@link BasicAclEntry}.<P>Provides core bit mask handling methods.</p>
 28  
  *
 29  
  * @author Ben Alex
 30  
  * @version $Id: AbstractBasicAclEntry.java 1496 2006-05-23 13:38:33Z benalex $
 31  
  */
 32  
 public abstract class AbstractBasicAclEntry implements BasicAclEntry {
 33  
     //~ Static fields/initializers =====================================================================================
 34  
 
 35  2
     private static final Log logger = LogFactory.getLog(AbstractBasicAclEntry.class);
 36  
 
 37  
     //~ Instance fields ================================================================================================
 38  
 
 39  
     private AclObjectIdentity aclObjectIdentity;
 40  
     private AclObjectIdentity aclObjectParentIdentity;
 41  
     private Object recipient;
 42  
     private int[] validPermissions;
 43  196
     private int mask = 0; // default means no permissions
 44  
 
 45  
     //~ Constructors ===================================================================================================
 46  
 
 47  
     public AbstractBasicAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity,
 48  166
         AclObjectIdentity aclObjectParentIdentity, int mask) {
 49  166
         Assert.notNull(recipient, "recipient cannot be null");
 50  
 
 51  165
         Assert.notNull(aclObjectIdentity, "aclObjectIdentity cannot be null");
 52  
 
 53  164
         validPermissions = getValidPermissions();
 54  164
         Arrays.sort(validPermissions);
 55  
 
 56  1804
         for (int i = 0; i < validPermissions.length; i++) {
 57  1640
             if (logger.isDebugEnabled()) {
 58  0
                 logger.debug("Valid permission:   " + printPermissionsBlock(validPermissions[i]) + " "
 59  
                     + printBinary(validPermissions[i]) + " (" + validPermissions[i] + ")");
 60  
             }
 61  
         }
 62  
 
 63  164
         this.recipient = recipient;
 64  164
         this.aclObjectIdentity = aclObjectIdentity;
 65  164
         this.aclObjectParentIdentity = aclObjectParentIdentity;
 66  164
         this.mask = mask;
 67  164
     }
 68  
 
 69  
 /**
 70  
      * A protected constructor for use by Hibernate.
 71  
      */
 72  30
     protected AbstractBasicAclEntry() {
 73  30
         validPermissions = getValidPermissions();
 74  30
         Arrays.sort(validPermissions);
 75  30
     }
 76  
 
 77  
     //~ Methods ========================================================================================================
 78  
 
 79  
     public int addPermission(int permissionToAdd) {
 80  3
         return addPermissions(new int[] {permissionToAdd});
 81  
     }
 82  
 
 83  
     public int addPermissions(int[] permissionsToAdd) {
 84  7
         if (logger.isDebugEnabled()) {
 85  0
             logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask
 86  
                 + ")");
 87  
         }
 88  
 
 89  21
         for (int i = 0; i < permissionsToAdd.length; i++) {
 90  14
             if (logger.isDebugEnabled()) {
 91  0
                 logger.debug("Add     permission: " + printPermissionsBlock(permissionsToAdd[i]) + " "
 92  
                     + printBinary(permissionsToAdd[i]) + " (" + permissionsToAdd[i] + ")");
 93  
             }
 94  
 
 95  14
             this.mask |= permissionsToAdd[i];
 96  
         }
 97  
 
 98  7
         if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
 99  1
             throw new IllegalArgumentException("Resulting permission set will be invalid.");
 100  
         } else {
 101  6
             if (logger.isDebugEnabled()) {
 102  0
                 logger.debug("AFTER  Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " ("
 103  
                     + mask + ")");
 104  
             }
 105  
 
 106  6
             return this.mask;
 107  
         }
 108  
     }
 109  
 
 110  
     public int deletePermission(int permissionToDelete) {
 111  3
         return deletePermissions(new int[] {permissionToDelete});
 112  
     }
 113  
 
 114  
     public int deletePermissions(int[] permissionsToDelete) {
 115  4
         if (logger.isDebugEnabled()) {
 116  0
             logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask
 117  
                 + ")");
 118  
         }
 119  
 
 120  9
         for (int i = 0; i < permissionsToDelete.length; i++) {
 121  5
             if (logger.isDebugEnabled()) {
 122  0
                 logger.debug("Delete  permission: " + printPermissionsBlock(permissionsToDelete[i]) + " "
 123  
                     + printBinary(permissionsToDelete[i]) + " (" + permissionsToDelete[i] + ")");
 124  
             }
 125  
 
 126  5
             this.mask &= ~permissionsToDelete[i];
 127  
         }
 128  
 
 129  4
         if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
 130  1
             throw new IllegalArgumentException("Resulting permission set will be invalid.");
 131  
         } else {
 132  3
             if (logger.isDebugEnabled()) {
 133  0
                 logger.debug("AFTER  Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " ("
 134  
                     + mask + ")");
 135  
             }
 136  
 
 137  3
             return this.mask;
 138  
         }
 139  
     }
 140  
 
 141  
     public AclObjectIdentity getAclObjectIdentity() {
 142  39
         return this.aclObjectIdentity;
 143  
     }
 144  
 
 145  
     public AclObjectIdentity getAclObjectParentIdentity() {
 146  26
         return this.aclObjectParentIdentity;
 147  
     }
 148  
 
 149  
     public int getMask() {
 150  21
         return this.mask;
 151  
     }
 152  
 
 153  
     public Object getRecipient() {
 154  137
         return this.recipient;
 155  
     }
 156  
 
 157  
     /**
 158  
      * Subclasses must indicate the permissions they support. Each base permission should be an integer with a
 159  
      * base 2. ie: the first permission is 2^^0 (1), the second permission is 2^^1 (2), the third permission is 2^^2
 160  
      * (4) etc. Each base permission should be exposed by the subclass as a <code>public static final int</code>. It
 161  
      * is further recommended that valid combinations of permissions are also exposed as <code>public static final
 162  
      * int</code>s.<P>This method returns all permission integers that are allowed to be used together. <B>This
 163  
      * must include any combinations of valid permissions</b>. So if the permissions indicated by 2^^2 (4) and 2^^1
 164  
      * (2) can be used together, one of the integers returned by this method must be 6 (4 + 2). Otherwise attempts to
 165  
      * set the permission will be rejected, as the final resulting mask will be rejected.</p>
 166  
      *  <P>Whilst it may seem unduly time onerous to return every valid permission <B>combination</B>, doing so
 167  
      * delivers maximum flexibility in ensuring ACLs only reflect logical combinations. For example, it would be
 168  
      * inappropriate to grant a "read" and "write" permission along with an "unrestricted" permission, as the latter
 169  
      * implies the former permissions.</p>
 170  
      *
 171  
      * @return <b>every</b> valid combination of permissions
 172  
      */
 173  
     public abstract int[] getValidPermissions();
 174  
 
 175  
     public boolean isPermitted(int permissionToCheck) {
 176  40
         return isPermitted(this.mask, permissionToCheck);
 177  
     }
 178  
 
 179  
     protected boolean isPermitted(int maskToCheck, int permissionToCheck) {
 180  70
         return ((maskToCheck & permissionToCheck) == permissionToCheck);
 181  
     }
 182  
 
 183  
     private String printBinary(int i) {
 184  1
         String s = Integer.toString(i, 2);
 185  
 
 186  1
         String pattern = "................................";
 187  
 
 188  1
         String temp1 = pattern.substring(0, pattern.length() - s.length());
 189  
 
 190  1
         String temp2 = temp1 + s;
 191  
 
 192  1
         return temp2.replace('0', '.');
 193  
     }
 194  
 
 195  
     /**
 196  
      * Outputs the permissions in a human-friendly format. For example, this method may return "CR-D" to
 197  
      * indicate the passed integer permits create, permits read, does not permit update, and permits delete.
 198  
      *
 199  
      * @param i the integer containing the mask which should be printed
 200  
      *
 201  
      * @return the human-friend formatted block
 202  
      */
 203  
     public abstract String printPermissionsBlock(int i);
 204  
 
 205  
     /**
 206  
      * Outputs the permissions in human-friendly format for the current <code>AbstractBasicAclEntry</code>'s
 207  
      * mask.
 208  
      *
 209  
      * @return the human-friendly formatted block for this instance
 210  
      */
 211  
     public String printPermissionsBlock() {
 212  5
         return printPermissionsBlock(this.mask);
 213  
     }
 214  
 
 215  
     public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity) {
 216  27
         this.aclObjectIdentity = aclObjectIdentity;
 217  27
     }
 218  
 
 219  
     public void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity) {
 220  27
         this.aclObjectParentIdentity = aclObjectParentIdentity;
 221  27
     }
 222  
 
 223  
     public void setMask(int mask) {
 224  26
         this.mask = mask;
 225  26
     }
 226  
 
 227  
     public void setRecipient(Object recipient) {
 228  26
         this.recipient = recipient;
 229  26
     }
 230  
 
 231  
     public String toString() {
 232  1
         StringBuffer sb = new StringBuffer();
 233  1
         sb.append(getClass().getName());
 234  1
         sb.append("[").append(aclObjectIdentity).append(",").append(recipient);
 235  1
         sb.append("=").append(printPermissionsBlock(mask)).append(" ");
 236  1
         sb.append(printBinary(mask)).append(" (");
 237  1
         sb.append(mask).append(")").append("]");
 238  
 
 239  1
         return sb.toString();
 240  
     }
 241  
 
 242  
     public int togglePermission(int permissionToToggle) {
 243  4
         this.mask ^= permissionToToggle;
 244  
 
 245  4
         if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
 246  1
             throw new IllegalArgumentException("Resulting permission set will be invalid.");
 247  
         } else {
 248  3
             return this.mask;
 249  
         }
 250  
     }
 251  
 }