SEC-1012: Java-5-ifying the ACL package.

This commit is contained in:
Luke Taylor 2008-12-21 01:41:30 +00:00
parent 9cb361e88a
commit 14c50a9c96
31 changed files with 518 additions and 539 deletions

View File

@ -18,6 +18,7 @@ import org.springframework.security.acls.objectidentity.ObjectIdentity;
import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.Sid;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
/** /**
@ -55,7 +56,7 @@ public interface Acl extends Serializable {
* part of advanced permission checking.</p> * part of advanced permission checking.</p>
* *
* <p>Do <em>NOT</em> use this method for making authorization decisions. Instead use {@link * <p>Do <em>NOT</em> use this method for making authorization decisions. Instead use {@link
* #isGranted(Permission[], Sid[], boolean)}.</p> * #isGranted(List, List, boolean)}.</p>
* *
* <p>This method must operate correctly even if the <tt>Acl</tt> only represents a subset of * <p>This method must operate correctly even if the <tt>Acl</tt> only represents a subset of
* <tt>Sid</tt>s. The caller is responsible for correctly handling the result if only a subset of * <tt>Sid</tt>s. The caller is responsible for correctly handling the result if only a subset of
@ -64,7 +65,7 @@ public interface Acl extends Serializable {
* @return the list of entries represented by the <tt>Acl</tt>, or <tt>null</tt> if there are * @return the list of entries represented by the <tt>Acl</tt>, or <tt>null</tt> if there are
* no entries presently associated with this <tt>Acl</tt>. * no entries presently associated with this <tt>Acl</tt>.
*/ */
AccessControlEntry[] getEntries(); List<AccessControlEntry> getEntries();
/** /**
* Obtains the domain object this <tt>Acl</tt> provides entries for. This is immutable once an * Obtains the domain object this <tt>Acl</tt> provides entries for. This is immutable once an
@ -146,7 +147,7 @@ public interface Acl extends Serializable {
* @throws UnloadedSidException thrown if the <tt>Acl</tt> does not have details for one or more of the * @throws UnloadedSidException thrown if the <tt>Acl</tt> does not have details for one or more of the
* <tt>Sid</tt>s passed as arguments * <tt>Sid</tt>s passed as arguments
*/ */
boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
throws NotFoundException, UnloadedSidException; throws NotFoundException, UnloadedSidException;
/** /**
@ -166,5 +167,5 @@ public interface Acl extends Serializable {
* *
* @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this <tt>Acl</tt> instance * @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this <tt>Acl</tt> instance
*/ */
boolean isSidLoaded(Sid[] sids); boolean isSidLoaded(List<Sid> sids);
} }

View File

@ -1,6 +1,8 @@
package org.springframework.security.acls; package org.springframework.security.acls;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -60,8 +62,8 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
private boolean checkPermission(Authentication authentication, ObjectIdentity oid, Object permission) { private boolean checkPermission(Authentication authentication, ObjectIdentity oid, Object permission) {
// Obtain the SIDs applicable to the principal // Obtain the SIDs applicable to the principal
Sid[] sids = sidRetrievalStrategy.getSids(authentication); List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
Permission[] requiredPermission = resolvePermission(permission); List<Permission> requiredPermission = resolvePermission(permission);
try { try {
// Lookup only ACLs for SIDs we're interested in // Lookup only ACLs for SIDs we're interested in
@ -90,17 +92,17 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
} }
// TODO: Add permission resolver/PermissionFactory rewrite // TODO: Add permission resolver/PermissionFactory rewrite
Permission[] resolvePermission(Object permission) { List<Permission> resolvePermission(Object permission) {
if (permission instanceof Integer) { if (permission instanceof Integer) {
return new Permission[] {BasePermission.buildFromMask(((Integer)permission).intValue())}; return Arrays.asList(BasePermission.buildFromMask(((Integer)permission).intValue()));
} }
if (permission instanceof Permission) { if (permission instanceof Permission) {
return new Permission[] {(Permission)permission}; return Arrays.asList((Permission)permission);
} }
if (permission instanceof Permission[]) { if (permission instanceof Permission[]) {
return (Permission[]) permission; return Arrays.asList((Permission[])permission);
} }
if (permission instanceof String) { if (permission instanceof String) {
@ -114,7 +116,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
} }
if (p != null) { if (p != null) {
return new Permission[] {p}; return Arrays.asList(p);
} }
} }

View File

@ -17,6 +17,7 @@ package org.springframework.security.acls;
import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentity;
import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.Sid;
import java.util.List;
import java.util.Map; import java.util.Map;
@ -36,10 +37,10 @@ public interface AclService {
* *
* @return the children (or <tt>null</tt> if none were found) * @return the children (or <tt>null</tt> if none were found)
*/ */
ObjectIdentity[] findChildren(ObjectIdentity parentIdentity); List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
/** /**
* Same as {@link #readAclsById(ObjectIdentity[])} except it returns only a single Acl. * Same as {@link #readAclsById(Java.util.List<ObjectIdentity>)} except it returns only a single Acl.
* <p> * <p>
* This method should not be called as it does not leverage the underlying implementation's potential ability to * This method should not be called as it does not leverage the underlying implementation's potential ability to
* filter <tt>Acl</tt> entries based on a {@link Sid} parameter.</p> * filter <tt>Acl</tt> entries based on a {@link Sid} parameter.</p>
@ -53,7 +54,7 @@ public interface AclService {
Acl readAclById(ObjectIdentity object) throws NotFoundException; Acl readAclById(ObjectIdentity object) throws NotFoundException;
/** /**
* Same as {@link #readAclsById(ObjectIdentity[], Sid[])} except it returns only a single Acl. * Same as {@link #readAclsById(List, List)} except it returns only a single Acl.
* *
* @param object to locate an {@link Acl} for * @param object to locate an {@link Acl} for
* @param sids the security identities for which {@link Acl} information is required * @param sids the security identities for which {@link Acl} information is required
@ -63,8 +64,7 @@ public interface AclService {
* *
* @throws NotFoundException if an {@link Acl} was not found for the requested {@link ObjectIdentity} * @throws NotFoundException if an {@link Acl} was not found for the requested {@link ObjectIdentity}
*/ */
Acl readAclById(ObjectIdentity object, Sid[] sids) Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException;
throws NotFoundException;
/** /**
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s.<p>The returned map is * Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s.<p>The returned map is
@ -77,7 +77,7 @@ public interface AclService {
* *
* @throws NotFoundException if an {@link Acl} was not found for each requested {@link ObjectIdentity} * @throws NotFoundException if an {@link Acl} was not found for each requested {@link ObjectIdentity}
*/ */
Map readAclsById(ObjectIdentity[] objects) throws NotFoundException; Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException;
/** /**
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s, but only for the * Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s, but only for the
@ -97,6 +97,5 @@ public interface AclService {
* *
* @throws NotFoundException if an {@link Acl} was not found for each requested {@link ObjectIdentity} * @throws NotFoundException if an {@link Acl} was not found for each requested {@link ObjectIdentity}
*/ */
Map readAclsById(ObjectIdentity[] objects, Sid[] sids) Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) throws NotFoundException;
throws NotFoundException;
} }

View File

@ -26,7 +26,7 @@ import org.springframework.security.SpringSecurityException;
public class AlreadyExistsException extends SpringSecurityException { public class AlreadyExistsException extends SpringSecurityException {
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
/** /**
* Constructs an <code>AlreadyExistsException</code> with the specified message. * Constructs an <code>AlreadyExistsException</code> with the specified message.
* *
* @param msg the detail message * @param msg the detail message
@ -35,7 +35,7 @@ public class AlreadyExistsException extends SpringSecurityException {
super(msg); super(msg);
} }
/** /**
* Constructs an <code>AlreadyExistsException</code> with the specified message * Constructs an <code>AlreadyExistsException</code> with the specified message
* and root cause. * and root cause.
* *

View File

@ -14,8 +14,6 @@
*/ */
package org.springframework.security.acls; package org.springframework.security.acls;
/** /**
* A mutable ACL that provides audit capabilities. * A mutable ACL that provides audit capabilities.
* *

View File

@ -26,7 +26,7 @@ import org.springframework.security.SpringSecurityException;
public class ChildrenExistException extends SpringSecurityException { public class ChildrenExistException extends SpringSecurityException {
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
/** /**
* Constructs an <code>ChildrenExistException</code> with the specified * Constructs an <code>ChildrenExistException</code> with the specified
* message. * message.
* *
@ -36,7 +36,7 @@ public class ChildrenExistException extends SpringSecurityException {
super(msg); super(msg);
} }
/** /**
* Constructs an <code>ChildrenExistException</code> with the specified * Constructs an <code>ChildrenExistException</code> with the specified
* message and root cause. * message and root cause.
* *

View File

@ -26,7 +26,7 @@ import org.springframework.security.SpringSecurityException;
public class IdentityUnavailableException extends SpringSecurityException { public class IdentityUnavailableException extends SpringSecurityException {
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
/** /**
* Constructs an <code>IdentityUnavailableException</code> with the specified message. * Constructs an <code>IdentityUnavailableException</code> with the specified message.
* *
* @param msg the detail message * @param msg the detail message
@ -35,7 +35,7 @@ public class IdentityUnavailableException extends SpringSecurityException {
super(msg); super(msg);
} }
/** /**
* Constructs an <code>IdentityUnavailableException</code> with the specified message * Constructs an <code>IdentityUnavailableException</code> with the specified message
* and root cause. * and root cause.
* *

View File

@ -21,11 +21,9 @@ import org.springframework.security.acls.sid.Sid;
/** /**
* A mutable <tt>Acl</tt>. * A mutable <tt>Acl</tt>.
*
* <p> * <p>
* A mutable ACL must ensure that appropriate security checks are performed * A mutable ACL must ensure that appropriate security checks are performed
* before allowing access to its methods. * before allowing access to its methods.
* </p>
* *
* @author Ben Alex * @author Ben Alex
* @version $Id$ * @version $Id$

View File

@ -55,8 +55,6 @@ public interface MutableAclService extends AclService {
* *
* @param acl to modify * @param acl to modify
* *
* @return DOCUMENT ME!
*
* @throws NotFoundException if the relevant record could not be found (did you remember to use {@link * @throws NotFoundException if the relevant record could not be found (did you remember to use {@link
* #createAcl(ObjectIdentity)} to create the object, rather than creating it with the <code>new</code> * #createAcl(ObjectIdentity)} to create the object, rather than creating it with the <code>new</code>
* keyword?) * keyword?)

View File

@ -26,7 +26,7 @@ import org.springframework.security.SpringSecurityException;
public class NotFoundException extends SpringSecurityException { public class NotFoundException extends SpringSecurityException {
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
/** /**
* Constructs an <code>NotFoundException</code> with the specified message. * Constructs an <code>NotFoundException</code> with the specified message.
* *
* @param msg the detail message * @param msg the detail message
@ -35,7 +35,7 @@ public class NotFoundException extends SpringSecurityException {
super(msg); super(msg);
} }
/** /**
* Constructs an <code>NotFoundException</code> with the specified message * Constructs an <code>NotFoundException</code> with the specified message
* and root cause. * and root cause.
* *

View File

@ -23,7 +23,6 @@ import org.springframework.security.acls.sid.Sid;
* <p> * <p>
* Generally the owner of an ACL is able to call any ACL mutator method, as * Generally the owner of an ACL is able to call any ACL mutator method, as
* well as assign a new owner. * well as assign a new owner.
* </p>
* *
* @author Ben Alex * @author Ben Alex
* @version $Id$ * @version $Id$

View File

@ -27,7 +27,7 @@ import org.springframework.security.SpringSecurityException;
public class UnloadedSidException extends SpringSecurityException { public class UnloadedSidException extends SpringSecurityException {
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
/** /**
* Constructs an <code>NotFoundException</code> with the specified message. * Constructs an <code>NotFoundException</code> with the specified message.
* *
* @param msg the detail message * @param msg the detail message
@ -36,7 +36,7 @@ public class UnloadedSidException extends SpringSecurityException {
super(msg); super(msg);
} }
/** /**
* Constructs an <code>NotFoundException</code> with the specified message * Constructs an <code>NotFoundException</code> with the specified message
* and root cause. * and root cause.
* *

View File

@ -15,6 +15,9 @@
package org.springframework.security.acls.afterinvocation; package org.springframework.security.acls.afterinvocation;
import java.util.Arrays;
import java.util.List;
import org.springframework.security.Authentication; import org.springframework.security.Authentication;
import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttribute;
@ -48,15 +51,15 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
protected String processConfigAttribute; protected String processConfigAttribute;
protected Permission[] requirePermission = {BasePermission.READ}; protected List<Permission> requirePermission = Arrays.asList(BasePermission.READ);
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
public AbstractAclProvider(AclService aclService, String processConfigAttribute, Permission[] requirePermission) { public AbstractAclProvider(AclService aclService, String processConfigAttribute, List<Permission> requirePermission) {
Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory");
Assert.notNull(aclService, "An AclService is mandatory"); Assert.notNull(aclService, "An AclService is mandatory");
if ((requirePermission == null) || (requirePermission.length == 0)) { if (requirePermission == null || requirePermission.isEmpty()) {
throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
} }
@ -76,7 +79,7 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
// Obtain the SIDs applicable to the principal // Obtain the SIDs applicable to the principal
Sid[] sids = sidRetrievalStrategy.getSids(authentication); List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
Acl acl = null; Acl acl = null;

View File

@ -15,7 +15,6 @@
package org.springframework.security.acls.afterinvocation; package org.springframework.security.acls.afterinvocation;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -39,8 +38,8 @@ import org.springframework.security.acls.Permission;
* <p> * <p>
* This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
* #processConfigAttribute}. The provider will then lookup the ACLs from the <code>AclService</code> and ensure the * #processConfigAttribute}. The provider will then lookup the ACLs from the <code>AclService</code> and ensure the
* principal is {@link org.springframework.security.acls.Acl#isGranted(org.springframework.security.acls.Permission[], * principal is {@link org.springframework.security.acls.Acl#isGranted(List,
* org.springframework.security.acls.sid.Sid[], boolean) Acl.isGranted(Permission[], Sid[], boolean)} * List, boolean) Acl.isGranted(Permission[], Sid[], boolean)}
* when presenting the {@link #requirePermission} array to that method. * when presenting the {@link #requirePermission} array to that method.
* <p> * <p>
* If the principal does not have permission, that element will not be included in the returned * If the principal does not have permission, that element will not be included in the returned
@ -67,12 +66,13 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends Abstract
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService, Permission[] requirePermission) { public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService, List<Permission> requirePermission) {
super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission); super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission);
} }
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
@SuppressWarnings("unchecked")
public Object decide(Authentication authentication, Object object, List<ConfigAttribute> config, public Object decide(Authentication authentication, Object object, List<ConfigAttribute> config,
Object returnedObject) throws AccessDeniedException { Object returnedObject) throws AccessDeniedException {
@ -93,7 +93,7 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends Abstract
Filterer filterer; Filterer filterer;
if (returnedObject instanceof Collection) { if (returnedObject instanceof Collection) {
filterer = new CollectionFilterer((Collection<?>) returnedObject); filterer = new CollectionFilterer((Collection) returnedObject);
} else if (returnedObject.getClass().isArray()) { } else if (returnedObject.getClass().isArray()) {
filterer = new ArrayFilterer((Object[]) returnedObject); filterer = new ArrayFilterer((Object[]) returnedObject);
} else { } else {
@ -102,10 +102,7 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends Abstract
} }
// Locate unauthorised Collection elements // Locate unauthorised Collection elements
Iterator collectionIter = filterer.iterator();
for (Object domainObject : filterer) { for (Object domainObject : filterer) {
// Ignore nulls or entries which aren't instances of the configured domain object class // Ignore nulls or entries which aren't instances of the configured domain object class
if (domainObject == null || !getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) { if (domainObject == null || !getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) {
continue; continue;

View File

@ -14,7 +14,6 @@
*/ */
package org.springframework.security.acls.afterinvocation; package org.springframework.security.acls.afterinvocation;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -39,8 +38,8 @@ import org.springframework.security.acls.Permission;
* <p> * <p>
* This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
* #processConfigAttribute}. The provider will then lookup the ACLs from the <tt>AclService</tt> and ensure the * #processConfigAttribute}. The provider will then lookup the ACLs from the <tt>AclService</tt> and ensure the
* principal is {@link org.springframework.security.acls.Acl#isGranted(org.springframework.security.acls.Permission[], * principal is {@link org.springframework.security.acls.Acl#isGranted(List,
org.springframework.security.acls.sid.Sid[], boolean) Acl.isGranted(Permission[], Sid[], boolean)} List, boolean) Acl.isGranted(Permission[], Sid[], boolean)}
* when presenting the {@link #requirePermission} array to that method. * when presenting the {@link #requirePermission} array to that method.
* <p> * <p>
* Often users will setup an <code>AclEntryAfterInvocationProvider</code> with a {@link * Often users will setup an <code>AclEntryAfterInvocationProvider</code> with a {@link
@ -65,7 +64,7 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
public AclEntryAfterInvocationProvider(AclService aclService, Permission[] requirePermission) { public AclEntryAfterInvocationProvider(AclService aclService, List<Permission> requirePermission) {
super(aclService, "AFTER_ACL_READ", requirePermission); super(aclService, "AFTER_ACL_READ", requirePermission);
} }
@ -74,8 +73,6 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
public Object decide(Authentication authentication, Object object, List<ConfigAttribute> config, public Object decide(Authentication authentication, Object object, List<ConfigAttribute> config,
Object returnedObject) throws AccessDeniedException { Object returnedObject) throws AccessDeniedException {
Iterator iter = config.iterator();
if (returnedObject == null) { if (returnedObject == null) {
// AclManager interface contract prohibits nulls // AclManager interface contract prohibits nulls
// As they have permission to null/nothing, grant access // As they have permission to null/nothing, grant access
@ -94,9 +91,7 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
return returnedObject; return returnedObject;
} }
while (iter.hasNext()) { for (ConfigAttribute attr : config) {
ConfigAttribute attr = (ConfigAttribute) iter.next();
if (!this.supports(attr)) { if (!this.supports(attr)) {
continue; continue;
} }

View File

@ -60,6 +60,7 @@ class ArrayFilterer<T> implements Filterer<T> {
* *
* @see org.springframework.security.acls.afterinvocation.Filterer#getFilteredObject() * @see org.springframework.security.acls.afterinvocation.Filterer#getFilteredObject()
*/ */
@SuppressWarnings("unchecked")
public T[] getFilteredObject() { public T[] getFilteredObject() {
// Recreate an array of same type and filter the removed objects. // Recreate an array of same type and filter the removed objects.
int originalSize = list.length; int originalSize = list.length;
@ -87,6 +88,7 @@ class ArrayFilterer<T> implements Filterer<T> {
* *
* @see org.springframework.security.acls.afterinvocation.Filterer#iterator() * @see org.springframework.security.acls.afterinvocation.Filterer#iterator()
*/ */
@SuppressWarnings("unchecked")
public Iterator<T> iterator() { public Iterator<T> iterator() {
return new ArrayIterator(list); return new ArrayIterator(list);
} }

View File

@ -15,21 +15,18 @@
package org.springframework.security.acls.domain; package org.springframework.security.acls.domain;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.springframework.security.AccessDeniedException; import org.springframework.security.AccessDeniedException;
import org.springframework.security.Authentication; import org.springframework.security.Authentication;
import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthority;
import org.springframework.security.acls.Acl; import org.springframework.security.acls.Acl;
import org.springframework.security.acls.Permission;
import org.springframework.security.acls.sid.PrincipalSid; import org.springframework.security.acls.sid.PrincipalSid;
import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.Sid;
import org.springframework.security.acls.sid.SidRetrievalStrategy; import org.springframework.security.acls.sid.SidRetrievalStrategy;
import org.springframework.security.acls.sid.SidRetrievalStrategyImpl; import org.springframework.security.acls.sid.SidRetrievalStrategyImpl;
import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.context.SecurityContextHolder;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -112,14 +109,14 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
} }
// Try to get permission via ACEs within the ACL // Try to get permission via ACEs within the ACL
Sid[] sids = sidRetrievalStrategy.getSids(authentication); List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
if (acl.isGranted(new Permission[] {BasePermission.ADMINISTRATION}, sids, false)) { if (acl.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), sids, false)) {
return; return;
} }
throw new AccessDeniedException( throw new AccessDeniedException(
"Principal does not have required ACL permissions to perform requested operation"); "Principal does not have required ACL permissions to perform requested operation");
} }
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {

View File

@ -15,9 +15,10 @@
package org.springframework.security.acls.domain; package org.springframework.security.acls.domain;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Vector;
import org.springframework.security.acls.AccessControlEntry; import org.springframework.security.acls.AccessControlEntry;
import org.springframework.security.acls.Acl; import org.springframework.security.acls.Acl;
@ -44,11 +45,11 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
private Acl parentAcl; private Acl parentAcl;
private transient AclAuthorizationStrategy aclAuthorizationStrategy; private transient AclAuthorizationStrategy aclAuthorizationStrategy;
private transient AuditLogger auditLogger; private transient AuditLogger auditLogger;
private List aces = new Vector(); private List<AccessControlEntry> aces = new ArrayList<AccessControlEntry>();
private ObjectIdentity objectIdentity; private ObjectIdentity objectIdentity;
private Serializable id; private Serializable id;
private Sid owner; // OwnershipAcl private Sid owner; // OwnershipAcl
private Sid[] loadedSids = null; // includes all SIDs the WHERE clause covered, even if there was no ACE for a SID private List<Sid> loadedSids = null; // includes all SIDs the WHERE clause covered, even if there was no ACE for a SID
private boolean entriesInheriting = true; private boolean entriesInheriting = true;
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
@ -90,7 +91,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* @param owner the owner (required) * @param owner the owner (required)
*/ */
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
AuditLogger auditLogger, Acl parentAcl, Sid[] loadedSids, boolean entriesInheriting, Sid owner) { AuditLogger auditLogger, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(id, "Id required"); Assert.notNull(id, "Id required");
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
@ -110,19 +111,11 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* Private no-argument constructor for use by reflection-based persistence * Private no-argument constructor for use by reflection-based persistence
* tools along with field-level access. * tools along with field-level access.
*/ */
@SuppressWarnings("unused")
private AclImpl() {} private AclImpl() {}
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
private void verifyAceIndexExists(int aceIndex) {
if (aceIndex < 0) {
throw new NotFoundException("aceIndex must be greater than or equal to zero");
}
if (aceIndex > this.aces.size()) {
throw new NotFoundException("aceIndex must correctly refer to an index of the AccessControlEntry collection");
}
}
public void deleteAce(int aceIndex) throws NotFoundException { public void deleteAce(int aceIndex) throws NotFoundException {
aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
verifyAceIndexExists(aceIndex); verifyAceIndexExists(aceIndex);
@ -132,25 +125,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
} }
} }
public AccessControlEntry[] getEntries() { private void verifyAceIndexExists(int aceIndex) {
// Can safely return AccessControlEntry directly, as they're immutable outside the ACL package if (aceIndex < 0) {
return (AccessControlEntry[]) aces.toArray(new AccessControlEntry[] {}); throw new NotFoundException("aceIndex must be greater than or equal to zero");
} }
if (aceIndex > this.aces.size()) {
public Serializable getId() { throw new NotFoundException("aceIndex must correctly refer to an index of the AccessControlEntry collection");
return this.id; }
}
public ObjectIdentity getObjectIdentity() {
return objectIdentity;
}
public Sid getOwner() {
return this.owner;
}
public Acl getParentAcl() {
return parentAcl;
} }
public void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) throws NotFoundException { public void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) throws NotFoundException {
@ -171,6 +152,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
} }
} }
public List<AccessControlEntry> getEntries() {
// Can safely return AccessControlEntry directly, as they're immutable outside the ACL package
return new ArrayList<AccessControlEntry>(aces);
}
public Serializable getId() {
return this.id;
}
public ObjectIdentity getObjectIdentity() {
return objectIdentity;
}
public boolean isEntriesInheriting() { public boolean isEntriesInheriting() {
return entriesInheriting; return entriesInheriting;
} }
@ -206,7 +200,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the ACL was only loaded for a * @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the ACL was only loaded for a
* subset of SIDs * subset of SIDs
*/ */
public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
throws NotFoundException, UnloadedSidException { throws NotFoundException, UnloadedSidException {
Assert.notEmpty(permission, "Permissions required"); Assert.notEmpty(permission, "Permissions required");
Assert.notEmpty(sids, "SIDs required"); Assert.notEmpty(sids, "SIDs required");
@ -217,16 +211,14 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
AccessControlEntry firstRejection = null; AccessControlEntry firstRejection = null;
for (int i = 0; i < permission.length; i++) { for (Permission p : permission) {
for (int x = 0; x < sids.length; x++) { for (Sid sid: sids) {
// Attempt to find exact match for this permission mask and SID // Attempt to find exact match for this permission mask and SID
Iterator acesIterator = aces.iterator();
boolean scanNextSid = true; boolean scanNextSid = true;
while (acesIterator.hasNext()) { for (AccessControlEntry ace : aces ) {
AccessControlEntry ace = (AccessControlEntry) acesIterator.next();
if ((ace.getPermission().getMask() == permission[i].getMask()) && ace.getSid().equals(sids[x])) { if ((ace.getPermission().getMask() == p.getMask()) && ace.getSid().equals(sid)) {
// Found a matching ACE, so its authorization decision will prevail // Found a matching ACE, so its authorization decision will prevail
if (ace.isGranting()) { if (ace.isGranting()) {
// Success // Success
@ -246,7 +238,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
scanNextSid = false; // helps break the loop scanNextSid = false; // helps break the loop
break; // exit "aceIterator" while loop break; // exit aces loop
} }
} }
} }
@ -277,19 +269,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
} }
} }
public boolean isSidLoaded(Sid[] sids) { public boolean isSidLoaded(List<Sid> sids) {
// If loadedSides is null, this indicates all SIDs were loaded // If loadedSides is null, this indicates all SIDs were loaded
// Also return true if the caller didn't specify a SID to find // Also return true if the caller didn't specify a SID to find
if ((this.loadedSids == null) || (sids == null) || (sids.length == 0)) { if ((this.loadedSids == null) || (sids == null) || (sids.size() == 0)) {
return true; return true;
} }
// This ACL applies to a SID subset only. Iterate to check it applies. // This ACL applies to a SID subset only. Iterate to check it applies.
for (int i = 0; i < sids.length; i++) { for (Sid sid: sids) {
boolean found = false; boolean found = false;
for (int y = 0; y < this.loadedSids.length; y++) { for (Sid loadedSid : loadedSids) {
if (sids[i].equals(this.loadedSids[y])) { if (sid.equals(loadedSid)) {
// this SID is OK // this SID is OK
found = true; found = true;
@ -316,12 +308,20 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
this.owner = newOwner; this.owner = newOwner;
} }
public Sid getOwner() {
return this.owner;
}
public void setParent(Acl newParent) { public void setParent(Acl newParent) {
aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself"); Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself");
this.parentAcl = newParent; this.parentAcl = newParent;
} }
public Acl getParentAcl() {
return parentAcl;
}
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append("AclImpl["); sb.append("AclImpl[");
@ -389,9 +389,9 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
if ((this.loadedSids == null && rhs.loadedSids == null)) { if ((this.loadedSids == null && rhs.loadedSids == null)) {
return true; return true;
} }
if (this.loadedSids.length == rhs.loadedSids.length) { if (this.loadedSids.size() == rhs.loadedSids.size()) {
for (int i = 0; i < this.loadedSids.length; i++) { for (int i = 0; i < this.loadedSids.size(); i++) {
if (!this.loadedSids[i].equals(rhs.loadedSids[i])) { if (!this.loadedSids.get(i).equals(rhs.loadedSids.get(i))) {
return false; return false;
} }
} }

View File

@ -178,15 +178,14 @@ public final class BasicLookupStrategy implements LookupStrategy {
fieldAcl.setAccessible(true); fieldAcl.setAccessible(true);
// Obtain the "aces" from the input ACL // Obtain the "aces" from the input ACL
Iterator i = ((List) fieldAces.get(inputAcl)).iterator(); List<AccessControlEntryImpl> aces = (List<AccessControlEntryImpl>) fieldAces.get(inputAcl);
// Create a list in which to store the "aces" for the "result" AclImpl instance // Create a list in which to store the "aces" for the "result" AclImpl instance
List<AccessControlEntryImpl> acesNew = new ArrayList<AccessControlEntryImpl>(); List<AccessControlEntryImpl> acesNew = new ArrayList<AccessControlEntryImpl>();
// Iterate over the "aces" input and replace each nested AccessControlEntryImpl.getAcl() with the new "result" AclImpl instance // Iterate over the "aces" input and replace each nested AccessControlEntryImpl.getAcl() with the new "result" AclImpl instance
// This ensures StubAclParent instances are removed, as per SEC-951 // This ensures StubAclParent instances are removed, as per SEC-951
while(i.hasNext()) { for (AccessControlEntryImpl ace : aces) {
AccessControlEntryImpl ace = (AccessControlEntryImpl) i.next();
fieldAcl.set(ace, result); fieldAcl.set(ace, result);
acesNew.add(ace); acesNew.add(ace);
} }
@ -285,15 +284,132 @@ public final class BasicLookupStrategy implements LookupStrategy {
} }
/** /**
* Looks up a batch of <code>ObjectIdentity</code>s directly from the database.<p>The caller is responsible * Locates the primary key IDs specified in "findNow", adding AclImpl instances with StubAclParents to the
* for optimization issues, such as selecting the identities to lookup, ensuring the cache doesn't contain them * "acls" Map.
* already, and adding the returned elements to the cache etc.</p> *
* @param acls the AclImpls (with StubAclParents)
* @param findNow Long-based primary keys to retrieve
* @param sids
*/
private void lookupPrimaryKeys(final Map acls, final Set findNow, final List<Sid> sids) {
Assert.notNull(acls, "ACLs are required");
Assert.notEmpty(findNow, "Items to find now required");
String sql = computeRepeatingSql("(acl_object_identity.id = ?)", findNow.size());
Set parentsToLookup = (Set) jdbcTemplate.query(sql,
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps)
throws SQLException {
Iterator iter = findNow.iterator();
int i = 0;
while (iter.hasNext()) {
i++;
ps.setLong(i, ((Long) iter.next()).longValue());
}
}
}, new ProcessResultSet(acls, sids));
// Lookup the parents, now that our JdbcTemplate has released the database connection (SEC-547)
if (parentsToLookup.size() > 0) {
lookupPrimaryKeys(acls, parentsToLookup, sids);
}
}
/**
* The main method.
* <p>
* WARNING: This implementation completely disregards the "sids" argument! Every item in the cache is expected to
* contain all SIDs. If you have serious performance needs (e.g. a very large number of
* SIDs per object identity), you'll probably want to develop a custom {@link LookupStrategy} implementation
* instead.
* <p>
* The implementation works in batch sizes specified by {@link #batchSize}.
*
* @param objects the identities to lookup (required)
* @param sids the SIDs for which identities are required (ignored by this implementation)
*
* @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the located {@link Acl} and values
* are the located {@link Acl} (never <tt>null</tt> although some entries may be missing; this method
* should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used
* to automatically create entries if required)
*/
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) {
Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1");
Assert.notEmpty(objects, "Objects to lookup required");
// Map<ObjectIdentity,Acl>
Map<ObjectIdentity, Acl> result = new HashMap<ObjectIdentity, Acl>(); // contains FULLY loaded Acl objects
Set<ObjectIdentity> currentBatchToLoad = new HashSet<ObjectIdentity>(); // contains ObjectIdentitys
for (int i = 0; i < objects.size(); i++) {
boolean aclFound = false;
// Check we don't already have this ACL in the results
if (result.containsKey(objects.get(i))) {
aclFound = true;
}
// Check cache for the present ACL entry
if (!aclFound) {
Acl acl = aclCache.getFromCache(objects.get(i));
// Ensure any cached element supports all the requested SIDs
// (they should always, as our base impl doesn't filter on SID)
if (acl != null) {
if (acl.isSidLoaded(sids)) {
result.put(acl.getObjectIdentity(), acl);
aclFound = true;
} else {
throw new IllegalStateException(
"Error: SID-filtered element detected when implementation does not perform SID filtering "
+ "- have you added something to the cache manually?");
}
}
}
// Load the ACL from the database
if (!aclFound) {
currentBatchToLoad.add(objects.get(i));
}
// Is it time to load from JDBC the currentBatchToLoad?
if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.size())) {
if (currentBatchToLoad.size() > 0) {
Map<ObjectIdentity, Acl> loadedBatch = lookupObjectIdentities(currentBatchToLoad.toArray(new ObjectIdentity[] {}), sids);
// Add loaded batch (all elements 100% initialized) to results
result.putAll(loadedBatch);
// Add the loaded batch to the cache
Iterator<Acl> loadedAclIterator = loadedBatch.values().iterator();
while (loadedAclIterator.hasNext()) {
aclCache.putInCache((AclImpl) loadedAclIterator.next());
}
currentBatchToLoad.clear();
}
}
}
return result;
}
/**
* Looks up a batch of <code>ObjectIdentity</code>s directly from the database.
* <p>
* The caller is responsible for optimization issues, such as selecting the identities to lookup, ensuring the
* cache doesn't contain them already, and adding the returned elements to the cache etc.
* <p> * <p>
* This subclass is required to return fully valid <code>Acl</code>s, including properly-configured * This subclass is required to return fully valid <code>Acl</code>s, including properly-configured
* parent ACLs. * parent ACLs.
* *
*/ */
private Map<ObjectIdentity, Acl> lookupObjectIdentities(final ObjectIdentity[] objectIdentities, Sid[] sids) { @SuppressWarnings("unchecked")
private Map<ObjectIdentity, Acl> lookupObjectIdentities(final ObjectIdentity[] objectIdentities, List<Sid> sids) {
Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); Assert.notEmpty(objectIdentities, "Must provide identities to lookup");
final Map acls = new HashMap(); // contains Acls with StubAclParents final Map acls = new HashMap(); // contains Acls with StubAclParents
@ -343,120 +459,6 @@ public final class BasicLookupStrategy implements LookupStrategy {
return resultMap; return resultMap;
} }
/**
* Locates the primary key IDs specified in "findNow", adding AclImpl instances with StubAclParents to the
* "acls" Map.
*
* @param acls the AclImpls (with StubAclParents)
* @param findNow Long-based primary keys to retrieve
* @param sids
*/
private void lookupPrimaryKeys(final Map acls, final Set findNow, final Sid[] sids) {
Assert.notNull(acls, "ACLs are required");
Assert.notEmpty(findNow, "Items to find now required");
String sql = computeRepeatingSql("(acl_object_identity.id = ?)", findNow.size());
Set parentsToLookup = (Set) jdbcTemplate.query(sql,
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps)
throws SQLException {
Iterator iter = findNow.iterator();
int i = 0;
while (iter.hasNext()) {
i++;
ps.setLong(i, ((Long) iter.next()).longValue());
}
}
}, new ProcessResultSet(acls, sids));
// Lookup the parents, now that our JdbcTemplate has released the database connection (SEC-547)
if (parentsToLookup.size() > 0) {
lookupPrimaryKeys(acls, parentsToLookup, sids);
}
}
/**
* The main method.
* <p>
* WARNING: This implementation completely disregards the "sids" argument! Every item in the cache is expected to
* contain all SIDs. If you have serious performance needs (e.g. a very large number of
* SIDs per object identity), you'll probably want to develop a custom {@link LookupStrategy} implementation
* instead.
* <p>
* The implementation works in batch sizes specified by {@link #batchSize}.
*
* @param objects the identities to lookup (required)
* @param sids the SIDs for which identities are required (ignored by this implementation)
*
* @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the located {@link Acl} and values
* are the located {@link Acl} (never <tt>null</tt> although some entries may be missing; this method
* should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used
* to automatically create entries if required)
*/
public Map<ObjectIdentity, Acl> readAclsById(ObjectIdentity[] objects, Sid[] sids) {
Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1");
Assert.notEmpty(objects, "Objects to lookup required");
// Map<ObjectIdentity,Acl>
Map<ObjectIdentity, Acl> result = new HashMap<ObjectIdentity, Acl>(); // contains FULLY loaded Acl objects
Set<ObjectIdentity> currentBatchToLoad = new HashSet<ObjectIdentity>(); // contains ObjectIdentitys
for (int i = 0; i < objects.length; i++) {
boolean aclFound = false;
// Check we don't already have this ACL in the results
if (result.containsKey(objects[i])) {
aclFound = true;
}
// Check cache for the present ACL entry
if (!aclFound) {
Acl acl = aclCache.getFromCache(objects[i]);
// Ensure any cached element supports all the requested SIDs
// (they should always, as our base impl doesn't filter on SID)
if (acl != null) {
if (acl.isSidLoaded(sids)) {
result.put(acl.getObjectIdentity(), acl);
aclFound = true;
} else {
throw new IllegalStateException(
"Error: SID-filtered element detected when implementation does not perform SID filtering "
+ "- have you added something to the cache manually?");
}
}
}
// Load the ACL from the database
if (!aclFound) {
currentBatchToLoad.add(objects[i]);
}
// Is it time to load from JDBC the currentBatchToLoad?
if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.length)) {
if (currentBatchToLoad.size() > 0) {
Map<ObjectIdentity, Acl> loadedBatch = lookupObjectIdentities(currentBatchToLoad.toArray(new ObjectIdentity[] {}), sids);
// Add loaded batch (all elements 100% initialized) to results
result.putAll(loadedBatch);
// Add the loaded batch to the cache
Iterator<Acl> loadedAclIterator = loadedBatch.values().iterator();
while (loadedAclIterator.hasNext()) {
aclCache.putInCache((AclImpl) loadedAclIterator.next());
}
currentBatchToLoad.clear();
}
}
}
return result;
}
public void setBatchSize(int batchSize) { public void setBatchSize(int batchSize) {
this.batchSize = batchSize; this.batchSize = batchSize;
@ -466,9 +468,9 @@ public final class BasicLookupStrategy implements LookupStrategy {
private class ProcessResultSet implements ResultSetExtractor { private class ProcessResultSet implements ResultSetExtractor {
private Map acls; private Map acls;
private Sid[] sids; private List<Sid> sids;
public ProcessResultSet(Map acls, Sid[] sids) { public ProcessResultSet(Map acls, List<Sid> sids) {
Assert.notNull(acls, "ACLs cannot be null"); Assert.notNull(acls, "ACLs cannot be null");
this.acls = acls; this.acls = acls;
this.sids = sids; // can be null this.sids = sids; // can be null
@ -526,7 +528,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
this.id = id; this.id = id;
} }
public AccessControlEntry[] getEntries() { public List<AccessControlEntry> getEntries() {
throw new UnsupportedOperationException("Stub only"); throw new UnsupportedOperationException("Stub only");
} }
@ -550,12 +552,12 @@ public final class BasicLookupStrategy implements LookupStrategy {
throw new UnsupportedOperationException("Stub only"); throw new UnsupportedOperationException("Stub only");
} }
public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
throws NotFoundException, UnloadedSidException { throws NotFoundException, UnloadedSidException {
throw new UnsupportedOperationException("Stub only"); throw new UnsupportedOperationException("Stub only");
} }
public boolean isSidLoaded(Sid[] sids) { public boolean isSidLoaded(List<Sid> sids) {
throw new UnsupportedOperationException("Stub only"); throw new UnsupportedOperationException("Stub only");
} }
} }

View File

@ -33,6 +33,7 @@ import org.springframework.util.StringUtils;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -75,7 +76,7 @@ public class JdbcAclService implements AclService {
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity) { public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getJavaType().getName()}; Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getJavaType().getName()};
List objects = jdbcTemplate.query(selectAclObjectWithParent, args, List objects = jdbcTemplate.query(selectAclObjectWithParent, args,
new RowMapper() { new RowMapper() {
@ -92,11 +93,11 @@ public class JdbcAclService implements AclService {
return null; return null;
} }
return (ObjectIdentityImpl[]) objects.toArray(new ObjectIdentityImpl[objects.size()]); return objects;
} }
public Acl readAclById(ObjectIdentity object, Sid[] sids) throws NotFoundException { public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
Map map = readAclsById(new ObjectIdentity[] {object}, sids); Map<ObjectIdentity, Acl> map = readAclsById(Arrays.asList(object), sids);
Assert.isTrue(map.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object); Assert.isTrue(map.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object);
return (Acl) map.get(object); return (Acl) map.get(object);
@ -106,18 +107,18 @@ public class JdbcAclService implements AclService {
return readAclById(object, null); return readAclById(object, null);
} }
public Map readAclsById(ObjectIdentity[] objects) throws NotFoundException { public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException {
return readAclsById(objects, null); return readAclsById(objects, null);
} }
public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException { public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) throws NotFoundException {
Map result = lookupStrategy.readAclsById(objects, sids); Map<ObjectIdentity, Acl> result = lookupStrategy.readAclsById(objects, sids);
// Check every requested object identity was found (throw NotFoundException if needed) // Check every requested object identity was found (throw NotFoundException if needed)
for (int i = 0; i < objects.length; i++) { for (int i = 0; i < objects.size(); i++) {
if (!result.containsKey(objects[i])) { if (!result.containsKey(objects.get(i))) {
throw new NotFoundException("Unable to find ACL information for object identity '" throw new NotFoundException("Unable to find ACL information for object identity '"
+ objects[i].toString() + "'"); + objects.get(i).toString() + "'");
} }
} }

View File

@ -14,8 +14,15 @@
*/ */
package org.springframework.security.acls.jdbc; package org.springframework.security.acls.jdbc;
import org.springframework.security.Authentication; import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.security.Authentication;
import org.springframework.security.acls.AccessControlEntry; import org.springframework.security.acls.AccessControlEntry;
import org.springframework.security.acls.Acl; import org.springframework.security.acls.Acl;
import org.springframework.security.acls.AlreadyExistsException; import org.springframework.security.acls.AlreadyExistsException;
@ -29,26 +36,10 @@ import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
import org.springframework.security.acls.sid.GrantedAuthoritySid; import org.springframework.security.acls.sid.GrantedAuthoritySid;
import org.springframework.security.acls.sid.PrincipalSid; import org.springframework.security.acls.sid.PrincipalSid;
import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.Sid;
import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.context.SecurityContextHolder;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import java.lang.reflect.Array;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
/** /**
* Provides a base implementation of {@link MutableAclService}. * Provides a base implementation of {@link MutableAclService}.
@ -123,14 +114,13 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
jdbcTemplate.batchUpdate(insertEntry, jdbcTemplate.batchUpdate(insertEntry,
new BatchPreparedStatementSetter() { new BatchPreparedStatementSetter() {
public int getBatchSize() { public int getBatchSize() {
return acl.getEntries().length; return acl.getEntries().size();
} }
public void setValues(PreparedStatement stmt, int i) public void setValues(PreparedStatement stmt, int i)
throws SQLException { throws SQLException {
AccessControlEntry entry_ = (AccessControlEntry) Array.get(acl.getEntries(), i); AccessControlEntry entry_ = acl.getEntries().get(i);
Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class"); Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_; AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
stmt.setLong(1, ((Long) acl.getId()).longValue()); stmt.setLong(1, ((Long) acl.getId()).longValue());
@ -167,23 +157,21 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* *
* @return the primary key or null if not found * @return the primary key or null if not found
*/ */
protected Long createOrRetrieveClassPrimaryKey(Class clazz, boolean allowCreate) { protected Long createOrRetrieveClassPrimaryKey(Class<?> clazz, boolean allowCreate) {
List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, new Object[] {clazz.getName()}, Long.class); List<Long> classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, new Object[] {clazz.getName()}, Long.class);
Long classId = null;
if (classIds.isEmpty()) { if (!classIds.isEmpty()) {
if (allowCreate) { return classIds.get(0);
classId = null;
jdbcTemplate.update(insertClass, new Object[] {clazz.getName()});
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
"Transaction must be running");
classId = new Long(jdbcTemplate.queryForLong(classIdentityQuery));
}
} else {
classId = (Long) classIds.iterator().next();
} }
return classId; if (allowCreate) {
jdbcTemplate.update(insertClass, new Object[] {clazz.getName()});
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
"Transaction must be running");
return new Long(jdbcTemplate.queryForLong(classIdentityQuery));
}
return null;
} }
/** /**
@ -195,7 +183,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* *
* @return the primary key or null if not found * @return the primary key or null if not found
* *
* @throws IllegalArgumentException DOCUMENT ME! * @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized implementation.
*/ */
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) { protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
Assert.notNull(sid, "Sid required"); Assert.notNull(sid, "Sid required");
@ -212,23 +200,21 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
throw new IllegalArgumentException("Unsupported implementation of Sid"); throw new IllegalArgumentException("Unsupported implementation of Sid");
} }
List sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey, new Object[] {new Boolean(principal), sidName}, List<Long> sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey,
Long.class); new Object[] {new Boolean(principal), sidName}, Long.class);
Long sidId = null;
if (sidIds.isEmpty()) { if (!sidIds.isEmpty()) {
if (allowCreate) { return sidIds.get(0);
sidId = null;
jdbcTemplate.update(insertSid, new Object[] {new Boolean(principal), sidName});
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
"Transaction must be running");
sidId = new Long(jdbcTemplate.queryForLong(sidIdentityQuery));
}
} else {
sidId = (Long) sidIds.iterator().next();
} }
return sidId; if (allowCreate) {
jdbcTemplate.update(insertSid, new Object[] {new Boolean(principal), sidName});
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
"Transaction must be running");
return new Long(jdbcTemplate.queryForLong(sidIdentityQuery));
}
return null;
} }
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren)
@ -237,19 +223,19 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier"); Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier");
if (deleteChildren) { if (deleteChildren) {
ObjectIdentity[] children = findChildren(objectIdentity); List<ObjectIdentity> children = findChildren(objectIdentity);
if (children != null) { if (children != null) {
for (int i = 0; i < children.length; i++) { for (int i = 0; i < children.size(); i++) {
deleteAcl(children[i], true); deleteAcl(children.get(i), true);
} }
} }
} else { } else {
if (!foreignKeysInDatabase) { if (!foreignKeysInDatabase) {
// We need to perform a manual verification for what a FK would normally do // We need to perform a manual verification for what a FK would normally do
// We generally don't do this, in the interests of deadlock management // We generally don't do this, in the interests of deadlock management
ObjectIdentity[] children = findChildren(objectIdentity); List<ObjectIdentity> children = findChildren(objectIdentity);
if (children != null) { if (children != null) {
throw new ChildrenExistException("Cannot delete '" + objectIdentity + "' (has " + children.length throw new ChildrenExistException("Cannot delete '" + objectIdentity + "' (has " + children.size()
+ " children)"); + " children)");
} }
} }
@ -279,11 +265,9 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
/** /**
* Deletes a single row from acl_object_identity that is associated with the presented ObjectIdentity primary key. * Deletes a single row from acl_object_identity that is associated with the presented ObjectIdentity primary key.
*
* <p> * <p>
* We do not delete any entries from acl_class, even if no classes are using that class any longer. This is a * We do not delete any entries from acl_class, even if no classes are using that class any longer. This is a
* deadlock avoidance approach. * deadlock avoidance approach.
* </p>
* *
* @param oidPrimaryKey to delete the acl_object_identity * @param oidPrimaryKey to delete the acl_object_identity
*/ */
@ -314,12 +298,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* This implementation will simply delete all ACEs in the database and recreate them on each invocation of * This implementation will simply delete all ACEs in the database and recreate them on each invocation of
* this method. A more comprehensive implementation might use dirty state checking, or more likely use ORM * this method. A more comprehensive implementation might use dirty state checking, or more likely use ORM
* capabilities for create, update and delete operations of {@link MutableAcl}. * capabilities for create, update and delete operations of {@link MutableAcl}.
*
* @param acl DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws NotFoundException DOCUMENT ME!
*/ */
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier"); Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
@ -342,10 +320,10 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
private void clearCacheIncludingChildren(ObjectIdentity objectIdentity) { private void clearCacheIncludingChildren(ObjectIdentity objectIdentity) {
Assert.notNull(objectIdentity, "ObjectIdentity required"); Assert.notNull(objectIdentity, "ObjectIdentity required");
ObjectIdentity[] children = findChildren(objectIdentity); List<ObjectIdentity> children = findChildren(objectIdentity);
if (children != null) { if (children != null) {
for (int i = 0; i < children.length; i++) { for (int i = 0; i < children.size(); i++) {
clearCacheIncludingChildren(children[i]); clearCacheIncludingChildren(children.get(i));
} }
} }
aclCache.evictFromCache(objectIdentity); aclCache.evictFromCache(objectIdentity);
@ -357,7 +335,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* *
* @param acl to modify (a row must already exist in acl_object_identity) * @param acl to modify (a row must already exist in acl_object_identity)
* *
* @throws NotFoundException DOCUMENT ME! * @throws NotFoundException if the ACL could not be found to update.
*/ */
protected void updateObjectIdentity(MutableAcl acl) { protected void updateObjectIdentity(MutableAcl acl) {
Long parentId = null; Long parentId = null;

View File

@ -19,6 +19,7 @@ import org.springframework.security.acls.NotFoundException;
import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentity;
import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.Sid;
import java.util.List;
import java.util.Map; import java.util.Map;
@ -43,5 +44,5 @@ public interface LookupStrategy {
* should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used * should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used
* to automatically create entries if required) * to automatically create entries if required)
*/ */
Map<ObjectIdentity, Acl> readAclsById(ObjectIdentity[] objects, Sid[] sids); Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids);
} }

View File

@ -15,6 +15,8 @@
package org.springframework.security.acls.sid; package org.springframework.security.acls.sid;
import java.util.List;
import org.springframework.security.Authentication; import org.springframework.security.Authentication;
@ -28,5 +30,5 @@ import org.springframework.security.Authentication;
public interface SidRetrievalStrategy { public interface SidRetrievalStrategy {
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
Sid[] getSids(Authentication authentication); List<Sid> getSids(Authentication authentication);
} }

View File

@ -15,6 +15,7 @@
package org.springframework.security.acls.sid; package org.springframework.security.acls.sid;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.security.Authentication; import org.springframework.security.Authentication;
@ -32,14 +33,14 @@ import org.springframework.security.GrantedAuthority;
public class SidRetrievalStrategyImpl implements SidRetrievalStrategy { public class SidRetrievalStrategyImpl implements SidRetrievalStrategy {
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
public Sid[] getSids(Authentication authentication) { public List<Sid> getSids(Authentication authentication) {
List<GrantedAuthority> authorities = authentication.getAuthorities(); List<GrantedAuthority> authorities = authentication.getAuthorities();
Sid[] sids = new Sid[authorities.size() + 1]; List<Sid> sids = new ArrayList<Sid>(authorities.size() + 1);
sids[0] = new PrincipalSid(authentication); sids.add(new PrincipalSid(authentication));
for (int i = 1; i <= authorities.size(); i++) { for (GrantedAuthority authority : authorities) {
sids[i] = new GrantedAuthoritySid(authorities.get(i - 1)); sids.add(new GrantedAuthoritySid(authority));
} }
return sids; return sids;

View File

@ -16,6 +16,7 @@ package org.springframework.security.acls.vote;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -49,8 +50,8 @@ import org.springframework.util.StringUtils;
* The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the {@link #processConfigAttribute}. * The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the {@link #processConfigAttribute}.
* The provider will then locate the first method argument of type {@link #processDomainObjectClass}. Assuming that * The provider will then locate the first method argument of type {@link #processDomainObjectClass}. Assuming that
* method argument is non-null, the provider will then lookup the ACLs from the <code>AclManager</code> and ensure the * method argument is non-null, the provider will then lookup the ACLs from the <code>AclManager</code> and ensure the
* principal is {@link Acl#isGranted(org.springframework.security.acls.Permission[], * principal is {@link Acl#isGranted(List,
* org.springframework.security.acls.sid.Sid[], boolean)} when presenting the {@link #requirePermission} array to that * List, boolean)} when presenting the {@link #requirePermission} array to that
* method. * method.
* <p> * <p>
* If the method argument is <tt>null</tt>, the voter will abstain from voting. If the method argument * If the method argument is <tt>null</tt>, the voter will abstain from voting. If the method argument
@ -91,7 +92,7 @@ public class AclEntryVoter extends AbstractAclVoter {
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
private String internalMethod; private String internalMethod;
private String processConfigAttribute; private String processConfigAttribute;
private Permission[] requirePermission; private List<Permission> requirePermission;
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
@ -105,7 +106,7 @@ public class AclEntryVoter extends AbstractAclVoter {
this.aclService = aclService; this.aclService = aclService;
this.processConfigAttribute = processConfigAttribute; this.processConfigAttribute = processConfigAttribute;
this.requirePermission = requirePermission; this.requirePermission = Arrays.asList(requirePermission);
} }
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
@ -196,7 +197,7 @@ public class AclEntryVoter extends AbstractAclVoter {
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
// Obtain the SIDs applicable to the principal // Obtain the SIDs applicable to the principal
Sid[] sids = sidRetrievalStrategy.getSids(authentication); List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
Acl acl; Acl acl;

View File

@ -1,6 +1,8 @@
package org.springframework.security.acls; package org.springframework.security.acls;
import static org.junit.Assert.*; import static org.junit.Assert.assertTrue;
import java.util.List;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery; import org.jmock.Mockery;
@ -10,7 +12,6 @@ import org.junit.Test;
import org.springframework.security.Authentication; import org.springframework.security.Authentication;
import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentity;
import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy; import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy;
import org.springframework.security.acls.sid.Sid;
import org.springframework.security.acls.sid.SidRetrievalStrategy; import org.springframework.security.acls.sid.SidRetrievalStrategy;
/** /**
@ -45,9 +46,9 @@ public class AclPermissionEvaluatorTests {
ignoring(user); ignoring(user);
ignoring(oidStrategy); ignoring(oidStrategy);
ignoring(sidStrategy); ignoring(sidStrategy);
oneOf(service).readAclById(with(any(ObjectIdentity.class)), with(any(Sid[].class))); oneOf(service).readAclById(with(any(ObjectIdentity.class)), with(any(List.class)));
will(returnValue(acl)); will(returnValue(acl));
oneOf(acl).isGranted(with(any(Permission[].class)), with(any(Sid[].class)), with(equal(false))); oneOf(acl).isGranted(with(any(List.class)), with(any(List.class)), with(equal(false)));
will(returnValue(true)); will(returnValue(true));
}}); }});

View File

@ -3,6 +3,8 @@ package org.springframework.security.acls.domain;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -41,6 +43,13 @@ import org.springframework.security.util.FieldUtils;
* @author Andrei Stefan * @author Andrei Stefan
*/ */
public class AclImplTests { public class AclImplTests {
private static final List<Permission> READ = Arrays.asList(BasePermission.READ );
private static final List<Permission> WRITE = Arrays.asList(BasePermission.WRITE);
private static final List<Permission> CREATE = Arrays.asList(BasePermission.CREATE );
private static final List<Permission> DELETE = Arrays.asList(BasePermission.DELETE );
private static final List<Sid> SCOTT = Arrays.asList((Sid)new PrincipalSid("scott"));
private static final List<Sid> BEN = Arrays.asList((Sid)new PrincipalSid("ben"));
Authentication auth = new TestingAuthenticationToken("johndoe", "ignored", "ROLE_ADMINISTRATOR"); Authentication auth = new TestingAuthenticationToken("johndoe", "ignored", "ROLE_ADMINISTRATOR");
Mockery jmockCtx = new Mockery(); Mockery jmockCtx = new Mockery();
AclAuthorizationStrategy mockAuthzStrategy; AclAuthorizationStrategy mockAuthzStrategy;
@ -137,31 +146,31 @@ public class AclImplTests {
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true);
service.updateAcl(acl); service.updateAcl(acl);
// Check it was successfully added // Check it was successfully added
assertEquals(1, acl.getEntries().length); assertEquals(1, acl.getEntries().size());
assertEquals(acl.getEntries()[0].getAcl(), acl); assertEquals(acl.getEntries().get(0).getAcl(), acl);
assertEquals(acl.getEntries()[0].getPermission(), BasePermission.READ); assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ);
assertEquals(acl.getEntries()[0].getSid(), new GrantedAuthoritySid("ROLE_TEST1")); assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid("ROLE_TEST1"));
// Add a second permission // Add a second permission
acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true);
service.updateAcl(acl); service.updateAcl(acl);
// Check it was added on the last position // Check it was added on the last position
assertEquals(2, acl.getEntries().length); assertEquals(2, acl.getEntries().size());
assertEquals(acl.getEntries()[1].getAcl(), acl); assertEquals(acl.getEntries().get(1).getAcl(), acl);
assertEquals(acl.getEntries()[1].getPermission(), BasePermission.READ); assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.READ);
assertEquals(acl.getEntries()[1].getSid(), new GrantedAuthoritySid("ROLE_TEST2")); assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid("ROLE_TEST2"));
// Add a third permission, after the first one // Add a third permission, after the first one
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), false); acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), false);
service.updateAcl(acl); service.updateAcl(acl);
assertEquals(3, acl.getEntries().length); assertEquals(3, acl.getEntries().size());
// Check the third entry was added between the two existent ones // Check the third entry was added between the two existent ones
assertEquals(acl.getEntries()[0].getPermission(), BasePermission.READ); assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ);
assertEquals(acl.getEntries()[0].getSid(), new GrantedAuthoritySid("ROLE_TEST1")); assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid("ROLE_TEST1"));
assertEquals(acl.getEntries()[1].getPermission(), BasePermission.WRITE); assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.WRITE);
assertEquals(acl.getEntries()[1].getSid(), new GrantedAuthoritySid("ROLE_TEST3")); assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid("ROLE_TEST3"));
assertEquals(acl.getEntries()[2].getPermission(), BasePermission.READ); assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.READ);
assertEquals(acl.getEntries()[2].getSid(), new GrantedAuthoritySid("ROLE_TEST2")); assertEquals(acl.getEntries().get(2).getSid(), new GrantedAuthoritySid("ROLE_TEST2"));
} }
@Test(expected=NotFoundException.class) @Test(expected=NotFoundException.class)
@ -191,22 +200,22 @@ public class AclImplTests {
// Delete first permission and check the order of the remaining permissions is kept // Delete first permission and check the order of the remaining permissions is kept
acl.deleteAce(0); acl.deleteAce(0);
assertEquals(2, acl.getEntries().length); assertEquals(2, acl.getEntries().size());
assertEquals(acl.getEntries()[0].getSid(), new GrantedAuthoritySid("ROLE_TEST2")); assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid("ROLE_TEST2"));
assertEquals(acl.getEntries()[1].getSid(), new GrantedAuthoritySid("ROLE_TEST3")); assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid("ROLE_TEST3"));
// Add one more permission and remove the permission in the middle // Add one more permission and remove the permission in the middle
acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true); acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true);
service.updateAcl(acl); service.updateAcl(acl);
acl.deleteAce(1); acl.deleteAce(1);
assertEquals(2, acl.getEntries().length); assertEquals(2, acl.getEntries().size());
assertEquals(acl.getEntries()[0].getSid(), new GrantedAuthoritySid("ROLE_TEST2")); assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid("ROLE_TEST2"));
assertEquals(acl.getEntries()[1].getSid(), new GrantedAuthoritySid("ROLE_TEST4")); assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid("ROLE_TEST4"));
// Remove remaining permissions // Remove remaining permissions
acl.deleteAce(1); acl.deleteAce(1);
acl.deleteAce(0); acl.deleteAce(0);
assertEquals(0, acl.getEntries().length); assertEquals(0, acl.getEntries().size());
} }
@Test @Test
@ -229,14 +238,15 @@ public class AclImplTests {
public void testIsGrantingRejectsEmptyParameters() throws Exception { public void testIsGrantingRejectsEmptyParameters() throws Exception {
MutableAcl acl = new AclImpl(objectIdentity, new Long(1), mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid( MutableAcl acl = new AclImpl(objectIdentity, new Long(1), mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid(
"johndoe")); "johndoe"));
Sid ben = new PrincipalSid("ben");
try { try {
acl.isGranted(new Permission[] {}, new Sid[] { new PrincipalSid("ben") }, false); acl.isGranted(new ArrayList<Permission>(0), Arrays.asList(ben) , false);
fail("It should have thrown IllegalArgumentException"); fail("It should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
} }
try { try {
acl.isGranted(new Permission[] { BasePermission.READ }, new Sid[] {}, false); acl.isGranted(READ, new ArrayList<Sid>(0), false);
fail("It should have thrown IllegalArgumentException"); fail("It should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
@ -261,25 +271,22 @@ public class AclImplTests {
rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), true); rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), true);
// Check permissions granting // Check permissions granting
Permission[] permissions = new Permission[] { BasePermission.READ, BasePermission.CREATE }; List<Permission> permissions = Arrays.asList(BasePermission.READ, BasePermission.CREATE);
Sid[] sids = new Sid[] { new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_GUEST") }; List<Sid> sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_GUEST"));
assertFalse(rootAcl.isGranted(permissions, sids, false)); assertFalse(rootAcl.isGranted(permissions, sids, false));
try { try {
rootAcl.isGranted(permissions, new Sid[] { new PrincipalSid("scott") }, false); rootAcl.isGranted(permissions, SCOTT, false);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
} }
assertTrue(rootAcl.isGranted(new Permission[] { BasePermission.WRITE }, new Sid[] { new PrincipalSid("scott") }, assertTrue(rootAcl.isGranted(WRITE, SCOTT, false));
false)); assertFalse(rootAcl.isGranted(WRITE,
assertFalse(rootAcl.isGranted(new Permission[] { BasePermission.WRITE }, new Sid[] { new PrincipalSid("rod"), Arrays.asList(new PrincipalSid("rod"), new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false));
new GrantedAuthoritySid("WRITE_ACCESS_ROLE") }, false)); assertTrue(rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false));
assertTrue(rootAcl.isGranted(new Permission[] { BasePermission.WRITE }, new Sid[] {
new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), new PrincipalSid("rod") }, false));
try { try {
// Change the type of the Sid and check the granting process // Change the type of the Sid and check the granting process
rootAcl.isGranted(new Permission[] { BasePermission.WRITE }, new Sid[] { new GrantedAuthoritySid("rod"), rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid("rod"), new PrincipalSid("WRITE_ACCESS_ROLE")), false);
new PrincipalSid("WRITE_ACCESS_ROLE") }, false);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -326,45 +333,33 @@ public class AclImplTests {
childAcl1.insertAce(0, BasePermission.CREATE, new PrincipalSid("scott"), true); childAcl1.insertAce(0, BasePermission.CREATE, new PrincipalSid("scott"), true);
// Check granting process for parent1 // Check granting process for parent1
assertTrue(parentAcl1.isGranted(new Permission[] { BasePermission.READ }, new Sid[] { new PrincipalSid("scott") }, assertTrue(parentAcl1.isGranted(READ, SCOTT, false));
false)); assertTrue(parentAcl1.isGranted(READ, Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_USER_READ")), false));
assertTrue(parentAcl1.isGranted(new Permission[] { BasePermission.READ }, new Sid[] { new GrantedAuthoritySid( assertTrue(parentAcl1.isGranted(WRITE, BEN, false));
"ROLE_USER_READ") }, false)); assertFalse(parentAcl1.isGranted(DELETE, BEN, false));
assertTrue(parentAcl1.isGranted(new Permission[] { BasePermission.WRITE }, new Sid[] { new PrincipalSid("ben") }, assertFalse(parentAcl1.isGranted(DELETE, SCOTT, false));
false));
assertFalse(parentAcl1.isGranted(new Permission[] { BasePermission.DELETE }, new Sid[] { new PrincipalSid("ben") },
false));
assertFalse(parentAcl1.isGranted(new Permission[] { BasePermission.DELETE },
new Sid[] { new PrincipalSid("scott") }, false));
// Check granting process for parent2 // Check granting process for parent2
assertTrue(parentAcl2.isGranted(new Permission[] { BasePermission.CREATE }, new Sid[] { new PrincipalSid("ben") }, assertTrue(parentAcl2.isGranted(CREATE, BEN, false));
false)); assertTrue(parentAcl2.isGranted(WRITE, BEN, false));
assertTrue(parentAcl2.isGranted(new Permission[] { BasePermission.WRITE }, new Sid[] { new PrincipalSid("ben") }, assertFalse(parentAcl2.isGranted(DELETE, BEN, false));
false));
assertFalse(parentAcl2.isGranted(new Permission[] { BasePermission.DELETE }, new Sid[] { new PrincipalSid("ben") },
false));
// Check granting process for child1 // Check granting process for child1
assertTrue(childAcl1.isGranted(new Permission[] { BasePermission.CREATE }, new Sid[] { new PrincipalSid("scott") }, assertTrue(childAcl1.isGranted(CREATE, SCOTT,
false));
assertTrue(childAcl1.isGranted(new Permission[] { BasePermission.READ }, new Sid[] { new GrantedAuthoritySid(
"ROLE_USER_READ") }, false));
assertFalse(childAcl1.isGranted(new Permission[] { BasePermission.DELETE }, new Sid[] { new PrincipalSid("ben") },
false)); false));
assertTrue(childAcl1.isGranted(READ, Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_USER_READ")), false));
assertFalse(childAcl1.isGranted(DELETE, BEN, false));
// Check granting process for child2 (doesn't inherit the permissions from its parent) // Check granting process for child2 (doesn't inherit the permissions from its parent)
try { try {
assertTrue(childAcl2.isGranted(new Permission[] { BasePermission.CREATE }, assertTrue(childAcl2.isGranted(CREATE, SCOTT, false));
new Sid[] { new PrincipalSid("scott") }, false));
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
assertTrue(true); assertTrue(true);
} }
try { try {
assertTrue(childAcl2.isGranted(new Permission[] { BasePermission.CREATE }, new Sid[] { new PrincipalSid( assertTrue(childAcl2.isGranted(CREATE, Arrays.asList((Sid)new PrincipalSid("johndoe")), false));
"johndoe") }, false));
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -386,9 +381,9 @@ public class AclImplTests {
acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true); acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true);
service.updateAcl(acl); service.updateAcl(acl);
assertEquals(acl.getEntries()[0].getPermission(), BasePermission.READ); assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ);
assertEquals(acl.getEntries()[1].getPermission(), BasePermission.WRITE); assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.WRITE);
assertEquals(acl.getEntries()[2].getPermission(), BasePermission.CREATE); assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.CREATE);
// Change each permission // Change each permission
acl.updateAce(0, BasePermission.CREATE); acl.updateAce(0, BasePermission.CREATE);
@ -396,9 +391,9 @@ public class AclImplTests {
acl.updateAce(2, BasePermission.READ); acl.updateAce(2, BasePermission.READ);
// Check the change was successfuly made // Check the change was successfuly made
assertEquals(acl.getEntries()[0].getPermission(), BasePermission.CREATE); assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.CREATE);
assertEquals(acl.getEntries()[1].getPermission(), BasePermission.DELETE); assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.DELETE);
assertEquals(acl.getEntries()[2].getPermission(), BasePermission.READ); assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.READ);
} }
@Test @Test
@ -414,20 +409,20 @@ public class AclImplTests {
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true); acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true);
service.updateAcl(acl); service.updateAcl(acl);
assertFalse(((AuditableAccessControlEntry) acl.getEntries()[0]).isAuditFailure()); assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditFailure());
assertFalse(((AuditableAccessControlEntry) acl.getEntries()[1]).isAuditFailure()); assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditFailure());
assertFalse(((AuditableAccessControlEntry) acl.getEntries()[0]).isAuditSuccess()); assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditSuccess());
assertFalse(((AuditableAccessControlEntry) acl.getEntries()[1]).isAuditSuccess()); assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditSuccess());
// Change each permission // Change each permission
((AuditableAcl) acl).updateAuditing(0, true, true); ((AuditableAcl) acl).updateAuditing(0, true, true);
((AuditableAcl) acl).updateAuditing(1, true, true); ((AuditableAcl) acl).updateAuditing(1, true, true);
// Check the change was successfuly made // Check the change was successfuly made
assertTrue(((AuditableAccessControlEntry) acl.getEntries()[0]).isAuditFailure()); assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditFailure());
assertTrue(((AuditableAccessControlEntry) acl.getEntries()[1]).isAuditFailure()); assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditFailure());
assertTrue(((AuditableAccessControlEntry) acl.getEntries()[0]).isAuditSuccess()); assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditSuccess());
assertTrue(((AuditableAccessControlEntry) acl.getEntries()[1]).isAuditSuccess()); assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditSuccess());
} }
@Test @Test
@ -452,7 +447,7 @@ public class AclImplTests {
assertEquals(acl.getOwner(), new PrincipalSid("johndoe")); assertEquals(acl.getOwner(), new PrincipalSid("johndoe"));
assertNull(acl.getParentAcl()); assertNull(acl.getParentAcl());
assertTrue(acl.isEntriesInheriting()); assertTrue(acl.isEntriesInheriting());
assertEquals(2, acl.getEntries().length); assertEquals(2, acl.getEntries().size());
acl.setParent(parentAcl); acl.setParent(parentAcl);
assertEquals(acl.getParentAcl(), parentAcl); assertEquals(acl.getParentAcl(), parentAcl);
@ -466,19 +461,19 @@ public class AclImplTests {
@Test @Test
public void testIsSidLoaded() throws Exception { public void testIsSidLoaded() throws Exception {
Sid[] loadedSids = new Sid[] { new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_IGNORED") }; List<Sid> loadedSids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_IGNORED"));
MutableAcl acl = new AclImpl(objectIdentity, new Long(1), mockAuthzStrategy, mockAuditLogger, null, loadedSids, true, new PrincipalSid( MutableAcl acl = new AclImpl(objectIdentity, new Long(1), mockAuthzStrategy, mockAuditLogger, null, loadedSids, true, new PrincipalSid(
"johndoe")); "johndoe"));
assertTrue(acl.isSidLoaded(loadedSids)); assertTrue(acl.isSidLoaded(loadedSids));
assertTrue(acl.isSidLoaded(new Sid[] { new GrantedAuthoritySid("ROLE_IGNORED"), new PrincipalSid("ben") })); assertTrue(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new PrincipalSid("ben"))));
assertTrue(acl.isSidLoaded(new Sid[] { new GrantedAuthoritySid("ROLE_IGNORED")})); assertTrue(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_IGNORED"))));
assertTrue(acl.isSidLoaded(new Sid[] { new PrincipalSid("ben") })); assertTrue(acl.isSidLoaded(BEN));
assertTrue(acl.isSidLoaded(null)); assertTrue(acl.isSidLoaded(null));
assertTrue(acl.isSidLoaded(new Sid[] { })); assertTrue(acl.isSidLoaded(new ArrayList<Sid>(0)));
assertTrue(acl.isSidLoaded(new Sid[] { new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED") })); assertTrue(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED"))));
assertFalse(acl.isSidLoaded(new Sid[] { new GrantedAuthoritySid("ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED") })); assertFalse(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED"))));
assertFalse(acl.isSidLoaded(new Sid[] { new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL") })); assertFalse(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL"))));
} }
//~ Inner Classes ================================================================================================== //~ Inner Classes ==================================================================================================
@ -495,8 +490,9 @@ public class AclImplTests {
* Mock implementation that populates the aces list with fully initialized AccessControlEntries * Mock implementation that populates the aces list with fully initialized AccessControlEntries
* @see org.springframework.security.acls.MutableAclService#updateAcl(org.springframework.security.acls.MutableAcl) * @see org.springframework.security.acls.MutableAclService#updateAcl(org.springframework.security.acls.MutableAcl)
*/ */
@SuppressWarnings("unchecked")
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
AccessControlEntry[] oldAces = acl.getEntries(); List<AccessControlEntry> oldAces = acl.getEntries();
Field acesField = FieldUtils.getField(AclImpl.class, "aces"); Field acesField = FieldUtils.getField(AclImpl.class, "aces");
acesField.setAccessible(true); acesField.setAccessible(true);
List newAces; List newAces;
@ -504,8 +500,8 @@ public class AclImplTests {
newAces = (List) acesField.get(acl); newAces = (List) acesField.get(acl);
newAces.clear(); newAces.clear();
for (int i = 0; i < oldAces.length; i++) { for (int i = 0; i < oldAces.size(); i++) {
AccessControlEntry ac = oldAces[i]; AccessControlEntry ac = oldAces.get(i);
// Just give an ID to all this acl's aces, rest of the fields are just copied // Just give an ID to all this acl's aces, rest of the fields are just copied
newAces.add(new AccessControlEntryImpl(new Long(i + 1), ac.getAcl(), ac.getSid(), ac.getPermission(), ac newAces.add(new AccessControlEntryImpl(new Long(i + 1), ac.getAcl(), ac.getSid(), ac.getPermission(), ac
.isGranting(), ((AuditableAccessControlEntry) ac).isAuditSuccess(), .isGranting(), ((AuditableAccessControlEntry) ac).isAuditSuccess(),
@ -519,7 +515,7 @@ public class AclImplTests {
return acl; return acl;
} }
public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity) { public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
return null; return null;
} }
@ -527,15 +523,15 @@ public class AclImplTests {
return null; return null;
} }
public Acl readAclById(ObjectIdentity object, Sid[] sids) throws NotFoundException { public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
return null; return null;
} }
public Map readAclsById(ObjectIdentity[] objects) throws NotFoundException { public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException {
return null; return null;
} }
public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException { public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) throws NotFoundException {
return null; return null;
} }
} }

View File

@ -89,12 +89,11 @@ public class AclPermissionInheritanceTests extends TestCase {
parent = (MutableAcl) child.getParentAcl(); parent = (MutableAcl) child.getParentAcl();
assertEquals("Fails because child has a stale reference to its parent", assertEquals("Fails because child has a stale reference to its parent", 2, parent.getEntries().size());
2, parent.getEntries().length); assertEquals(1, parent.getEntries().get(0).getPermission().getMask());
assertEquals(1, parent.getEntries()[0].getPermission().getMask()); assertEquals(new PrincipalSid("john"), parent.getEntries().get(0).getSid());
assertEquals(new PrincipalSid("john"), parent.getEntries()[0].getSid()); assertEquals(1, parent.getEntries().get(1).getPermission().getMask());
assertEquals(1, parent.getEntries()[1].getPermission().getMask()); assertEquals(new PrincipalSid("joe"), parent.getEntries().get(1).getSid());
assertEquals(new PrincipalSid("joe"), parent.getEntries()[1].getSid());
} }
public void test2() throws Exception { public void test2() throws Exception {
@ -121,11 +120,11 @@ public class AclPermissionInheritanceTests extends TestCase {
parent = (MutableAcl) child.getParentAcl(); parent = (MutableAcl) child.getParentAcl();
assertEquals(2, parent.getEntries().length); assertEquals(2, parent.getEntries().size());
assertEquals(16, parent.getEntries()[0].getPermission().getMask()); assertEquals(16, parent.getEntries().get(0).getPermission().getMask());
assertEquals(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), parent.getEntries()[0].getSid()); assertEquals(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), parent.getEntries().get(0).getSid());
assertEquals(8, parent.getEntries()[1].getPermission().getMask()); assertEquals(8, parent.getEntries().get(1).getPermission().getMask());
assertEquals(new PrincipalSid("terry"), parent.getEntries()[1].getSid()); assertEquals(new PrincipalSid("terry"), parent.getEntries().get(1).getSid());
} }

View File

@ -1,5 +1,7 @@
package org.springframework.security.acls.jdbc; package org.springframework.security.acls.jdbc;
import java.util.Arrays;
import java.util.List;
import java.util.Map; import java.util.Map;
import junit.framework.Assert; import junit.framework.Assert;
@ -42,11 +44,8 @@ public class BasicLookupStrategyTests {
//~ Instance fields ================================================================================================ //~ Instance fields ================================================================================================
private static JdbcTemplate jdbcTemplate; private static JdbcTemplate jdbcTemplate;
private LookupStrategy strategy; private LookupStrategy strategy;
private static TestDataSource dataSource; private static TestDataSource dataSource;
private static CacheManager cacheManager; private static CacheManager cacheManager;
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
@ -123,7 +122,7 @@ public class BasicLookupStrategyTests {
// Deliberately use an integer for the child, to reproduce bug report in SEC-819 // Deliberately use an integer for the child, to reproduce bug report in SEC-819
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(102)); ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(102));
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(new ObjectIdentity[] { topParentOid, middleParentOid, childOid }, null); Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
checkEntries(topParentOid, middleParentOid, childOid, map); checkEntries(topParentOid, middleParentOid, childOid, map);
} }
@ -134,11 +133,11 @@ public class BasicLookupStrategyTests {
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(102)); ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(102));
// Objects were put in cache // Objects were put in cache
strategy.readAclsById(new ObjectIdentity[] { topParentOid, middleParentOid, childOid }, null); strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
// Let's empty the database to force acls retrieval from cache // Let's empty the database to force acls retrieval from cache
emptyDatabase(); emptyDatabase();
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(new ObjectIdentity[] { topParentOid, middleParentOid, childOid }, null); Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
checkEntries(topParentOid, middleParentOid, childOid, map); checkEntries(topParentOid, middleParentOid, childOid, map);
} }
@ -151,7 +150,7 @@ public class BasicLookupStrategyTests {
// Set a batch size to allow multiple database queries in order to retrieve all acls // Set a batch size to allow multiple database queries in order to retrieve all acls
((BasicLookupStrategy) this.strategy).setBatchSize(1); ((BasicLookupStrategy) this.strategy).setBatchSize(1);
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(new ObjectIdentity[] { topParentOid, middleParentOid, childOid }, null); Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
checkEntries(topParentOid, middleParentOid, childOid, map); checkEntries(topParentOid, middleParentOid, childOid, map);
} }
@ -174,9 +173,9 @@ public class BasicLookupStrategyTests {
Assert.assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity()); Assert.assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity());
// Check their ACEs were correctly retrieved // Check their ACEs were correctly retrieved
Assert.assertEquals(2, topParent.getEntries().length); Assert.assertEquals(2, topParent.getEntries().size());
Assert.assertEquals(1, middleParent.getEntries().length); Assert.assertEquals(1, middleParent.getEntries().size());
Assert.assertEquals(1, child.getEntries().length); Assert.assertEquals(1, child.getEntries().size());
// Check object identities were correctly retrieved // Check object identities were correctly retrieved
Assert.assertEquals(topParentOid, topParent.getObjectIdentity()); Assert.assertEquals(topParentOid, topParent.getObjectIdentity());
@ -187,39 +186,39 @@ public class BasicLookupStrategyTests {
Assert.assertTrue(topParent.isEntriesInheriting()); Assert.assertTrue(topParent.isEntriesInheriting());
Assert.assertEquals(topParent.getId(), new Long(1)); Assert.assertEquals(topParent.getId(), new Long(1));
Assert.assertEquals(topParent.getOwner(), new PrincipalSid("ben")); Assert.assertEquals(topParent.getOwner(), new PrincipalSid("ben"));
Assert.assertEquals(topParent.getEntries()[0].getId(), new Long(1)); Assert.assertEquals(topParent.getEntries().get(0).getId(), new Long(1));
Assert.assertEquals(topParent.getEntries()[0].getPermission(), BasePermission.READ); Assert.assertEquals(topParent.getEntries().get(0).getPermission(), BasePermission.READ);
Assert.assertEquals(topParent.getEntries()[0].getSid(), new PrincipalSid("ben")); Assert.assertEquals(topParent.getEntries().get(0).getSid(), new PrincipalSid("ben"));
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries()[0]).isAuditFailure()); Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditFailure());
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries()[0]).isAuditSuccess()); Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditSuccess());
Assert.assertTrue(((AuditableAccessControlEntry) topParent.getEntries()[0]).isGranting()); Assert.assertTrue(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isGranting());
Assert.assertEquals(topParent.getEntries()[1].getId(), new Long(2)); Assert.assertEquals(topParent.getEntries().get(1).getId(), new Long(2));
Assert.assertEquals(topParent.getEntries()[1].getPermission(), BasePermission.WRITE); Assert.assertEquals(topParent.getEntries().get(1).getPermission(), BasePermission.WRITE);
Assert.assertEquals(topParent.getEntries()[1].getSid(), new PrincipalSid("ben")); Assert.assertEquals(topParent.getEntries().get(1).getSid(), new PrincipalSid("ben"));
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries()[1]).isAuditFailure()); Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditFailure());
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries()[1]).isAuditSuccess()); Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditSuccess());
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries()[1]).isGranting()); Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isGranting());
Assert.assertTrue(middleParent.isEntriesInheriting()); Assert.assertTrue(middleParent.isEntriesInheriting());
Assert.assertEquals(middleParent.getId(), new Long(2)); Assert.assertEquals(middleParent.getId(), new Long(2));
Assert.assertEquals(middleParent.getOwner(), new PrincipalSid("ben")); Assert.assertEquals(middleParent.getOwner(), new PrincipalSid("ben"));
Assert.assertEquals(middleParent.getEntries()[0].getId(), new Long(3)); Assert.assertEquals(middleParent.getEntries().get(0).getId(), new Long(3));
Assert.assertEquals(middleParent.getEntries()[0].getPermission(), BasePermission.DELETE); Assert.assertEquals(middleParent.getEntries().get(0).getPermission(), BasePermission.DELETE);
Assert.assertEquals(middleParent.getEntries()[0].getSid(), new PrincipalSid("ben")); Assert.assertEquals(middleParent.getEntries().get(0).getSid(), new PrincipalSid("ben"));
Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries()[0]).isAuditFailure()); Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditFailure());
Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries()[0]).isAuditSuccess()); Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditSuccess());
Assert.assertTrue(((AuditableAccessControlEntry) middleParent.getEntries()[0]).isGranting()); Assert.assertTrue(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isGranting());
Assert.assertTrue(child.isEntriesInheriting()); Assert.assertTrue(child.isEntriesInheriting());
Assert.assertEquals(child.getId(), new Long(3)); Assert.assertEquals(child.getId(), new Long(3));
Assert.assertEquals(child.getOwner(), new PrincipalSid("ben")); Assert.assertEquals(child.getOwner(), new PrincipalSid("ben"));
Assert.assertEquals(child.getEntries()[0].getId(), new Long(4)); Assert.assertEquals(child.getEntries().get(0).getId(), new Long(4));
Assert.assertEquals(child.getEntries()[0].getPermission(), BasePermission.DELETE); Assert.assertEquals(child.getEntries().get(0).getPermission(), BasePermission.DELETE);
Assert.assertEquals(child.getEntries()[0].getSid(), new PrincipalSid("ben")); Assert.assertEquals(child.getEntries().get(0).getSid(), new PrincipalSid("ben"));
Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries()[0]).isAuditFailure()); Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditFailure());
Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries()[0]).isAuditSuccess()); Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditSuccess());
Assert.assertFalse((child.getEntries()[0]).isGranting()); Assert.assertFalse((child.getEntries().get(0)).isGranting());
} }
@Test @Test
@ -233,7 +232,7 @@ public class BasicLookupStrategyTests {
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(103)); ObjectIdentity middleParent2Oid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(103));
// Retrieve the child // Retrieve the child
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(new ObjectIdentity[] { childOid }, null); Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(childOid), null);
// Check that the child and all its parents were retrieved // Check that the child and all its parents were retrieved
Assert.assertNotNull(map.get(childOid)); Assert.assertNotNull(map.get(childOid));
@ -265,9 +264,9 @@ public class BasicLookupStrategyTests {
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(107)); ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(107));
// First lookup only child, thus populating the cache with grandParent, parent1 and child // First lookup only child, thus populating the cache with grandParent, parent1 and child
Permission[] checkPermission = new Permission[] { BasePermission.READ }; List<Permission> checkPermission = Arrays.asList(BasePermission.READ);
Sid[] sids = new Sid[] { new PrincipalSid("ben") }; List<Sid> sids = Arrays.asList((Sid)new PrincipalSid("ben"));
ObjectIdentity[] childOids = new ObjectIdentity[] { childOid }; List<ObjectIdentity> childOids = Arrays.asList(childOid);
((BasicLookupStrategy) this.strategy).setBatchSize(6); ((BasicLookupStrategy) this.strategy).setBatchSize(6);
Map<ObjectIdentity, Acl> foundAcls = strategy.readAclsById(childOids, sids); Map<ObjectIdentity, Acl> foundAcls = strategy.readAclsById(childOids, sids);
@ -278,7 +277,7 @@ public class BasicLookupStrategyTests {
// Search for object identities has to be done in the following order: last element have to be one which // Search for object identities has to be done in the following order: last element have to be one which
// is already in cache and the element before it must not be stored in cache // is already in cache and the element before it must not be stored in cache
ObjectIdentity[] allOids = new ObjectIdentity[] { grandParentOid, parent1Oid, parent2Oid, childOid }; List<ObjectIdentity> allOids = Arrays.asList(grandParentOid, parent1Oid, parent2Oid, childOid);
try { try {
foundAcls = strategy.readAclsById(allOids, sids); foundAcls = strategy.readAclsById(allOids, sids);
Assert.assertTrue(true); Assert.assertTrue(true);

View File

@ -14,6 +14,8 @@
*/ */
package org.springframework.security.acls.jdbc; package org.springframework.security.acls.jdbc;
import java.util.Arrays;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.security.Authentication; import org.springframework.security.Authentication;
@ -35,7 +37,6 @@ import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken; import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
/** /**
* Integration tests the ACL system using an in-memory database. * Integration tests the ACL system using an in-memory database.
* *
@ -119,7 +120,7 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
jdbcMutableAclService.updateAcl(child); jdbcMutableAclService.updateAcl(child);
// Let's check if we can read them back correctly // Let's check if we can read them back correctly
Map map = jdbcMutableAclService.readAclsById(new ObjectIdentity[] {topParentOid, middleParentOid, childOid}); Map map = jdbcMutableAclService.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid));
assertEquals(3, map.size()); assertEquals(3, map.size());
// Replace our current objects with their retrieved versions // Replace our current objects with their retrieved versions
@ -138,27 +139,33 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity()); assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity());
// Check their ACEs were correctly persisted // Check their ACEs were correctly persisted
assertEquals(2, topParent.getEntries().length); assertEquals(2, topParent.getEntries().size());
assertEquals(1, middleParent.getEntries().length); assertEquals(1, middleParent.getEntries().size());
assertEquals(1, child.getEntries().length); assertEquals(1, child.getEntries().size());
// Check the retrieved rights are correct // Check the retrieved rights are correct
assertTrue(topParent.isGranted(new Permission[] {BasePermission.READ}, new Sid[] {new PrincipalSid(auth)}, false)); List<Permission> read = Arrays.asList(BasePermission.READ);
assertFalse(topParent.isGranted(new Permission[] {BasePermission.WRITE}, new Sid[] {new PrincipalSid(auth)}, false)); List<Permission> write = Arrays.asList(BasePermission.WRITE);
assertTrue(middleParent.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, false)); List<Permission> delete = Arrays.asList(BasePermission.DELETE);
assertFalse(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, false)); List<Sid> pSid = Arrays.asList((Sid)new PrincipalSid(auth));
assertTrue(topParent.isGranted(read, pSid, false));
assertFalse(topParent.isGranted(write, pSid, false));
assertTrue(middleParent.isGranted(delete, pSid, false));
assertFalse(child.isGranted(delete, pSid, false));
try { try {
child.isGranted(new Permission[] {BasePermission.ADMINISTRATION}, new Sid[] {new PrincipalSid(auth)}, false); child.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), pSid, false);
fail("Should have thrown NotFoundException"); fail("Should have thrown NotFoundException");
} catch (NotFoundException expected) { } catch (NotFoundException expected) {
assertTrue(true); assertTrue(true);
} }
// Now check the inherited rights (when not explicitly overridden) also look OK // Now check the inherited rights (when not explicitly overridden) also look OK
assertTrue(child.isGranted(new Permission[] {BasePermission.READ}, new Sid[] {new PrincipalSid(auth)}, false)); assertTrue(child.isGranted(read, pSid, false));
assertFalse(child.isGranted(new Permission[] {BasePermission.WRITE}, new Sid[] {new PrincipalSid(auth)}, false)); assertFalse(child.isGranted(write, pSid, false));
assertFalse(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, false)); assertFalse(child.isGranted(delete, pSid, false));
// Next change the child so it doesn't inherit permissions from above // Next change the child so it doesn't inherit permissions from above
child.setEntriesInheriting(false); child.setEntriesInheriting(false);
@ -167,17 +174,17 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
assertFalse(child.isEntriesInheriting()); assertFalse(child.isEntriesInheriting());
// Check the child permissions no longer inherit // Check the child permissions no longer inherit
assertFalse(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, true)); assertFalse(child.isGranted(delete, pSid, true));
try { try {
child.isGranted(new Permission[] {BasePermission.READ}, new Sid[] {new PrincipalSid(auth)}, true); child.isGranted(read, pSid, true);
fail("Should have thrown NotFoundException"); fail("Should have thrown NotFoundException");
} catch (NotFoundException expected) { } catch (NotFoundException expected) {
assertTrue(true); assertTrue(true);
} }
try { try {
child.isGranted(new Permission[] {BasePermission.WRITE}, new Sid[] {new PrincipalSid(auth)}, true); child.isGranted(write, pSid, true);
fail("Should have thrown NotFoundException"); fail("Should have thrown NotFoundException");
} catch (NotFoundException expected) { } catch (NotFoundException expected) {
assertTrue(true); assertTrue(true);
@ -192,19 +199,19 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
// Save the changed child // Save the changed child
jdbcMutableAclService.updateAcl(child); jdbcMutableAclService.updateAcl(child);
child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
assertEquals(3, child.getEntries().length); assertEquals(3, child.getEntries().size());
// Output permissions // Output permissions
for (int i = 0; i < child.getEntries().length; i++) { for (int i = 0; i < child.getEntries().size(); i++) {
System.out.println(child.getEntries()[i]); System.out.println(child.getEntries().get(i));
} }
// Check the permissions are as they should be // Check the permissions are as they should be
assertFalse(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, true)); // as earlier permission overrode assertFalse(child.isGranted(delete, pSid, true)); // as earlier permission overrode
assertTrue(child.isGranted(new Permission[] {BasePermission.CREATE}, new Sid[] {new PrincipalSid(auth)}, true)); assertTrue(child.isGranted(Arrays.asList(BasePermission.CREATE), pSid, true));
// Now check the first ACE (index 0) really is DELETE for our Sid and is non-granting // Now check the first ACE (index 0) really is DELETE for our Sid and is non-granting
AccessControlEntry entry = child.getEntries()[0]; AccessControlEntry entry = child.getEntries().get(0);
assertEquals(BasePermission.DELETE.getMask(), entry.getPermission().getMask()); assertEquals(BasePermission.DELETE.getMask(), entry.getPermission().getMask());
assertEquals(new PrincipalSid(auth), entry.getSid()); assertEquals(new PrincipalSid(auth), entry.getSid());
assertFalse(entry.isGranting()); assertFalse(entry.isGranting());
@ -215,8 +222,8 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
// Save and check it worked // Save and check it worked
child = jdbcMutableAclService.updateAcl(child); child = jdbcMutableAclService.updateAcl(child);
assertEquals(2, child.getEntries().length); assertEquals(2, child.getEntries().size());
assertTrue(child.isGranted(new Permission[] {BasePermission.DELETE}, new Sid[] {new PrincipalSid(auth)}, false)); assertTrue(child.isGranted(delete, pSid, false));
SecurityContextHolder.clearContext(); SecurityContextHolder.clearContext();
} }
@ -380,7 +387,7 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
parent = (MutableAcl) child.getParentAcl(); parent = (MutableAcl) child.getParentAcl();
assertEquals("Fails because child has a stale reference to its parent", 2, parent.getEntries().length); assertEquals("Fails because child has a stale reference to its parent", 2, parent.getEntries().size());
assertEquals(1, parent.getEntries()[0].getPermission().getMask()); assertEquals(1, parent.getEntries()[0].getPermission().getMask());
assertEquals(new PrincipalSid("ben"), parent.getEntries()[0].getSid()); assertEquals(new PrincipalSid("ben"), parent.getEntries()[0].getSid());
assertEquals(1, parent.getEntries()[1].getPermission().getMask()); assertEquals(1, parent.getEntries()[1].getPermission().getMask());
@ -400,14 +407,14 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
CumulativePermission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION); CumulativePermission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION);
assertEquals(17, cm.getMask()); assertEquals(17, cm.getMask());
topParent.insertAce(null, cm, new PrincipalSid(auth), true); topParent.insertAce(null, cm, new PrincipalSid(auth), true);
assertEquals(1, topParent.getEntries().length); assertEquals(1, topParent.getEntries().size());
// Explictly save the changed ACL // Explictly save the changed ACL
topParent = jdbcMutableAclService.updateAcl(topParent); topParent = jdbcMutableAclService.updateAcl(topParent);
// Check the mask was retrieved correctly // Check the mask was retrieved correctly
assertEquals(17, topParent.getEntries()[0].getPermission().getMask()); assertEquals(17, topParent.getEntries()[0].getPermission().getMask());
assertTrue(topParent.isGranted(new Permission[] {cm}, new Sid[] {new PrincipalSid(auth)}, true)); assertTrue(topParent.isGranted(new Permission[] {cm}, pSid, true));
SecurityContextHolder.clearContext(); SecurityContextHolder.clearContext();
} }

View File

@ -1,5 +1,7 @@
package org.springframework.security.acls.sid; package org.springframework.security.acls.sid;
import java.util.List;
import junit.framework.Assert; import junit.framework.Assert;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -18,20 +20,20 @@ public class SidRetrievalStrategyTests extends TestCase {
public void testSidsRetrieval() throws Exception { public void testSidsRetrieval() throws Exception {
Authentication authentication = new TestingAuthenticationToken("scott", "password", "ROLE_1", "ROLE_2", "ROLE_3"); Authentication authentication = new TestingAuthenticationToken("scott", "password", "ROLE_1", "ROLE_2", "ROLE_3");
SidRetrievalStrategy retrStrategy = new SidRetrievalStrategyImpl(); SidRetrievalStrategy retrStrategy = new SidRetrievalStrategyImpl();
Sid[] sids = retrStrategy.getSids(authentication); List<Sid> sids = retrStrategy.getSids(authentication);
assertNotNull(sids); assertNotNull(sids);
assertEquals(4, sids.length); assertEquals(4, sids.size());
assertNotNull(sids[0]); assertNotNull(sids.get(0));
assertTrue(sids[0] instanceof PrincipalSid); assertTrue(sids.get(0) instanceof PrincipalSid);
for (int i = 1; i < sids.length; i++) { for (int i = 1; i < sids.size(); i++) {
assertTrue(sids[i] instanceof GrantedAuthoritySid); assertTrue(sids.get(i) instanceof GrantedAuthoritySid);
} }
Assert.assertEquals("scott", ((PrincipalSid) sids[0]).getPrincipal()); Assert.assertEquals("scott", ((PrincipalSid) sids.get(0)).getPrincipal());
Assert.assertEquals("ROLE_1", ((GrantedAuthoritySid) sids[1]).getGrantedAuthority()); Assert.assertEquals("ROLE_1", ((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority());
Assert.assertEquals("ROLE_2", ((GrantedAuthoritySid) sids[2]).getGrantedAuthority()); Assert.assertEquals("ROLE_2", ((GrantedAuthoritySid) sids.get(2)).getGrantedAuthority());
Assert.assertEquals("ROLE_3", ((GrantedAuthoritySid) sids[3]).getGrantedAuthority()); Assert.assertEquals("ROLE_3", ((GrantedAuthoritySid) sids.get(3)).getGrantedAuthority());
} }
} }