From 9f512c384e736cb1aa6d777284af902ad5b3131d Mon Sep 17 00:00:00 2001
From: Ben Alex This method is
- * typically used for administrative purposes. The order that entries appear in the array is unspecified. However, if implementations use
- * particular ordering logic in authorization decisions, the entries returned by this method MUST be
- * ordered in that manner. Do NOT use this method for making authorization decisions. Instead use {@link
- * #isGranted(Permission[], Sid[])}. This method must operate correctly even if the This
- * method solely represents the presence of a navigation hierarchy between the parent This method must operate correctly even if the The mere link between an An array of The actual approach used to make authorization decisions is left to the implementation and is not
- * specified by this interface. For example, an implementation MAY search the current ACL in the order
- * the ACL entries have been stored. If a single entry is found that has the same active bits as are shown in a
- * passed This method must operate correctly even if the It is normal to load an This method is
+ * typically used for administrative purposes. The order that entries appear in the array is unspecified. However, if implementations use
+ * particular ordering logic in authorization decisions, the entries returned by this method MUST be
+ * ordered in that manner. Do NOT use this method for making authorization decisions. Instead use {@link
+ * #isGranted(Permission[], Sid[])}. This method must operate correctly even if the This
+ * method solely represents the presence of a navigation hierarchy between the parent This method must operate correctly even if the The mere link between an An array of The actual approach used to make authorization decisions is left to the implementation and is not
+ * specified by this interface. For example, an implementation MAY search the current ACL in the order
+ * the ACL entries have been stored. If a single entry is found that has the same active bits as are shown in a
+ * passed This method must operate correctly even if the It is normal to load an Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. The returned map is
- * keyed on the passed objects, with the values being the Implementations MAY provide a subset of the ACLs via this method
- * although this is NOT a requirement. This is intended to allow performance optimisations within implementations.
- * Callers should therefore use this method in preference to the alternative overloaded version which does not
- * have performance optimisation opportunities. The returned map is keyed on the passed objects, with the values being the This method
+ * should not be called as it does not leverage the underlaying implementation's potential ability to filter
+ * The returned map is
+ * keyed on the passed objects, with the values being the Implementations MAY provide a subset of the ACLs via this method
+ * although this is NOT a requirement. This is intended to allow performance optimisations within implementations.
+ * Callers should therefore use this method in preference to the alternative overloaded version which does not
+ * have performance optimisation opportunities. The returned map is keyed on the passed objects, with the values being the Implementations
- * are free to format the pattern as they see fit, although under no circumstances may {@link #RESERVED_OFF} or
- * {@link #RESERVED_ON} be used within the pattern. An exemption is in the case of {@link #RESERVED_OFF} which is
- * used to denote a bit that is off (clear). Implementations may also elect to use {@link #RESERVED_ON} internally
- * for computation purposes, although this method may not return any The returned String must be 32 characters in length. This method is only used for user interface and logging purposes. It is not used in any permission
- * calculations. Therefore, duplication of characters within the output is permitted. Implementations
+ * are free to format the pattern as they see fit, although under no circumstances may {@link #RESERVED_OFF} or
+ * {@link #RESERVED_ON} be used within the pattern. An exemption is in the case of {@link #RESERVED_OFF} which is
+ * used to denote a bit that is off (clear). Implementations may also elect to use {@link #RESERVED_ON} internally
+ * for computation purposes, although this method may not return any The returned String must be 32 characters in length. This method is only used for user interface and logging purposes. It is not used in any permission
+ * calculations. Therefore, duplication of characters within the output is permitted. Permission will be granted provided the current
+ * principal is either the owner (as defined by the ACL), has {@link BasePermission#ADMINISTRATION} (as defined by the
+ * ACL and via a {@link Sid} retrieved for the current principal via {@link #sidRetrievalStrategy}), or if the current
+ * principal holds the relevant system-wide {@link GrantedAuthority} and injected into the constructor. Normally a principal must be the
- * owner of the ACL in order to make most changes. The authorities passed to this method provide a way for
- * non-owners to modify the ACL (and indeed modify audit parameters, which are not available to ACL owners). Methods return
- * Methods return
+ * NB: This implementation does attempt to provide
- * reasonably optimised lookups - within the constraints of a normalised database and standard ANSI SQL features. If
- * you are willing to sacrifice either of these constraints (eg use a particular database feature such as hierarchical
- * queries or materalized views, or reduce normalisation) you are likely to achieve better performance. In such
- * situations you will need to provide your own custom NB: This implementation does attempt to provide
+ * reasonably optimised lookups - within the constraints of a normalised database and standard ANSI SQL features. If
+ * you are willing to sacrifice either of these constraints (eg use a particular database feature such as hierarchical
+ * queries or materalized views, or reduce normalisation) you are likely to achieve better performance. In such
+ * situations you will need to provide your own custom 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. This subclass is required to return fully valid WARNING: This implementation completely disregards the "sids" argument! Every item in
- * the cache is expected to contain all SIDs. The implementation works in batch sizes specfied by {@link #batchSize}. 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. This subclass is required to return fully valid WARNING: This implementation completely disregards the "sids" parameter! Every item
+ * in the cache is expected to contain all SIDs. If you have serious performance needs (eg a very large number of
+ * SIDs per object identity), you'll probably want to develop a custom {@link LookupStrategy} implementation
+ * instead. The implementation works in batch sizes specfied by {@link #batchSize}. Requires the "dirty" flags in {@link
+ * org.acegisecurity.acls.domain.AclImpl} and {@link org.acegisecurity.acls.domain.AccessControlEntryImpl} to be set,
+ * so that the implementation can detect changed parameters easily. Because ACLs are largely immutable, it is strongly recommended to use
- * a synthetic identifier (such as a database sequence number for the primary key). Do not use an identifier with
- * business meaning, as that business meaning may change. Because ACLs are largely immutable, it is strongly recommended to use
+ * a synthetic identifier (such as a database sequence number for the primary key). Do not use an identifier with
+ * business meaning, as that business meaning may change. Uses Uses Considers an object of the same class equal if it has the same
- * Considers an object of the same class equal if it has the same
+ * This is a basic implementation that simply
- * uses the This is a basic implementation that simply
+ * uses the This is a basic implementation
- * that simply uses the This is a basic implementation
+ * that simply uses the The returned array will always contain the {@link PrincipalSid}
+ * before any {@link GrantedAuthoritySid} elements. Given a The This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
+ * #processConfigAttribute}. The provider will then lookup the ACLs from the If the principal does not have permission, that element will not be included in the returned
+ * Often users will setup a If the provided All comparisons and prefixes are case sensitive. Given a domain object instance returned from a secure object invocation, ensures the principal has
+ * appropriate permission as defined by the {@link AclService}. The This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
+ * #processConfigAttribute}. The provider will then lookup the ACLs from the Often users will setup an If the principal does not have sufficient permissions, an If the provided All comparisons and prefixes are case sensitive. One or more comma separate numeric are specified via the
+ * For this class to operate it must be able to access the application context via the
+ * Given a domain object instance passed as a method argument, ensures the principal has appropriate permission
- * as defined by the {@link AclManager}. Provides helper methods for writing domain object ACL voters. Is not bound to any particular ACL system. Given a domain object instance passed as a method argument, ensures the principal has appropriate permission
+ * as indicated by the {@link AclService}. The 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 method argument is non-null, the provider will then lookup the ACLs from
+ * the If the method argument is In practical terms users will typically setup a number of null if unsaved
- */
- public Serializable getId();
-
- public Permission getPermission();
-
- public Sid getSid();
-
- /**
- * Indicates the a Permission is being granted to the relevant Sid. If false,
- * indicates the permission is being revoked/blocked.
- *
- * @return true if being granted, false otherwise
- */
- public boolean isGranting();
-}
+ */
+public interface AccessControlEntry {
+ //~ Methods ========================================================================================================
+
+ public Acl getAcl();
+
+ /**
+ * Obtains an identifier that represents this ACE.
+ *
+ * @return the identifier, or null if unsaved
+ */
+ public Serializable getId();
+
+ public Permission getPermission();
+
+ public Sid getSid();
+
+ /**
+ * Indicates the a Permission is being granted to the relevant Sid. If false, indicates the permission is
+ * being revoked/blocked.
+ *
+ * @return true if being granted, false otherwise
+ */
+ public boolean isGranting();
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/Acl.java b/core/src/main/java/org/acegisecurity/acls/Acl.java
similarity index 90%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/Acl.java
rename to core/src/main/java/org/acegisecurity/acls/Acl.java
index 63783de867..546f9f898e 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/Acl.java
+++ b/core/src/main/java/org/acegisecurity/acls/Acl.java
@@ -1,26 +1,25 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.acls.objectidentity.ObjectIdentity;
-import org.acegisecurity.acls.sid.Sid;
-
-import java.io.Serializable;
-
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.acls.objectidentity.ObjectIdentity;
+import org.acegisecurity.acls.sid.Sid;
+
+import java.io.Serializable;
+
+
/**
* Represents an access control list (ACL) for a domain object.
*
@@ -40,105 +39,114 @@ import java.io.Serializable;
*
* @author Ben Alex
* @version $Id$
- */
-public interface Acl extends Serializable {
- //~ Methods ========================================================================================================
-
- /**
- * Returns all of the entries represented by the present Acl (not parents).Acl only represents a subset of
- * Sids. The caller is responsible for correctly handling the result if only a subset of
- * Sids is represented.Acl
- */
- public AccessControlEntry[] getEntries();
-
- /**
- * Obtains the domain object this Acl provides entries for. This is immutable once an
- * Acl is created.
- *
- * @return the object identity
- */
- public ObjectIdentity getObjectIdentity();
-
- /**
- * A domain object may have a parent for the purpose of ACL inheritance. If there is a parent, its ACL can
- * be accessed via this method. In turn, the parent's parent (grandparent) can be accessed and so on.Acl and this
- * Acl. For actual inheritance to take place, the {@link #isEntriesInheriting()} must also be
- * true.Acl only represents a subset of
- * Sids. The caller is responsible for correctly handling the result if only a subset of
- * Sids is represented.Acl
- */
- public Acl getParentAcl();
-
- /**
- * Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down into the current
- * Acl.Acl and a parent Acl on its own
- * is insufficient to cause ACL entries to inherit down. This is because a domain object may wish to have entirely
- * independent entries, but maintain the link with the parent for navigation purposes. Thus, this method denotes
- * whether or not the navigation relationship also extends to the actual inheritence of entries.true if parent ACL entries inherit into the current Acl
- */
- public boolean isEntriesInheriting();
-
- /**
- * This is the actual authorization logic method, and must be used whenever ACL authorization decisions are
- * required.Sids are presented, representing security identifies of the current
- * principal. In addition, an array of Permissions is presented which will have one or more bits set
- * in order to indicate the permissions needed for an affirmative authorization decision. An array is presented
- * because holding any of the Permissions inside the array will be sufficient for an
- * affirmative authorization.Permission, that entry's grant or deny state may determine the authorization decision. If
- * the case of a deny state, the deny decision will only be relevant if all other Permissions passed
- * in the array have also been unsuccessfully searched. If no entry is found that match the bits in the current
- * ACL, provided that {@link #isEntriesInheriting()} is true, the authorization decision may be
- * passed to the parent ACL. If there is no matching entry, the implementation MAY throw an exception, or make a
- * predefined authorization decision.Acl only represents a subset of
- * Sids. The caller is responsible for correctly handling the result if only a subset of
- * Sids is represented.true denotes the query is for administrative purposes and no logger or
- * auditing (if supported by the implementation) should be undertaken
- *
- * @return true is authorization is granted
- *
- * @throws NotFoundException MAY be thrown if an implementation cannot make an authoritative authorization decision
- * @throws UnloadedSidException thrown if the Acl does not have details for one or more of the
- * Sids passed as arguments
- */
- public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode)
- throws NotFoundException, UnloadedSidException;
-
- /**
- * For efficiency reasons an Acl may be loaded and not contain entries for every
- * Sid in the system. If an Acl has been loaded and does not represent every
- * Sid, all methods of the Sid can only be used within the limited scope of the
- * Sid instances it actually represents.Acl for only
- * particular Sids if read-only authorization decisions are being made. However, if user interface
- * reporting or modification of Acls are desired, an Acl should be loaded with all
- * Sids. This method denotes whether or not the specified Sids have been loaded or not.true if every passed Sid is represented by this Acl instance
- */
- public boolean isSidLoaded(Sid[] sids);
-}
+ */
+public interface Acl extends Serializable {
+ //~ Methods ========================================================================================================
+
+ /**
+ * Returns all of the entries represented by the present Acl (not parents).Acl only represents a subset of
+ * Sids. The caller is responsible for correctly handling the result if only a subset of
+ * Sids is represented.Acl
+ */
+ public AccessControlEntry[] getEntries();
+
+ /**
+ * Obtains the domain object this Acl provides entries for. This is immutable once an
+ * Acl is created.
+ *
+ * @return the object identity
+ */
+ public ObjectIdentity getObjectIdentity();
+
+ /**
+ * Determines the owner of the Acl. The meaning of ownership varies by implementation and is
+ * unspecified.
+ *
+ * @return the owner (may be null if the implementation does not use ownership concepts)
+ */
+ public Sid getOwner();
+
+ /**
+ * A domain object may have a parent for the purpose of ACL inheritance. If there is a parent, its ACL can
+ * be accessed via this method. In turn, the parent's parent (grandparent) can be accessed and so on.Acl and this
+ * Acl. For actual inheritance to take place, the {@link #isEntriesInheriting()} must also be
+ * true.Acl only represents a subset of
+ * Sids. The caller is responsible for correctly handling the result if only a subset of
+ * Sids is represented.Acl
+ */
+ public Acl getParentAcl();
+
+ /**
+ * Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down into the current
+ * Acl.Acl and a parent Acl on its own
+ * is insufficient to cause ACL entries to inherit down. This is because a domain object may wish to have entirely
+ * independent entries, but maintain the link with the parent for navigation purposes. Thus, this method denotes
+ * whether or not the navigation relationship also extends to the actual inheritence of entries.true if parent ACL entries inherit into the current Acl
+ */
+ public boolean isEntriesInheriting();
+
+ /**
+ * This is the actual authorization logic method, and must be used whenever ACL authorization decisions are
+ * required.Sids are presented, representing security identifies of the current
+ * principal. In addition, an array of Permissions is presented which will have one or more bits set
+ * in order to indicate the permissions needed for an affirmative authorization decision. An array is presented
+ * because holding any of the Permissions inside the array will be sufficient for an
+ * affirmative authorization.Permission, that entry's grant or deny state may determine the authorization decision. If
+ * the case of a deny state, the deny decision will only be relevant if all other Permissions passed
+ * in the array have also been unsuccessfully searched. If no entry is found that match the bits in the current
+ * ACL, provided that {@link #isEntriesInheriting()} is true, the authorization decision may be
+ * passed to the parent ACL. If there is no matching entry, the implementation MAY throw an exception, or make a
+ * predefined authorization decision.Acl only represents a subset of
+ * Sids.true denotes the query is for administrative purposes and no logging
+ * or auditing (if supported by the implementation) should be undertaken
+ *
+ * @return true is authorization is granted
+ *
+ * @throws NotFoundException MUST be thrown if an implementation cannot make an authoritative authorization
+ * decision, usually because there is no ACL information for this particular permission and/or SID
+ * @throws UnloadedSidException thrown if the Acl does not have details for one or more of the
+ * Sids passed as arguments
+ */
+ public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode)
+ throws NotFoundException, UnloadedSidException;
+
+ /**
+ * For efficiency reasons an Acl may be loaded and not contain entries for every
+ * Sid in the system. If an Acl has been loaded and does not represent every
+ * Sid, all methods of the Sid can only be used within the limited scope of the
+ * Sid instances it actually represents.Acl for only
+ * particular Sids if read-only authorization decisions are being made. However, if user interface
+ * reporting or modification of Acls are desired, an Acl should be loaded with all
+ * Sids. This method denotes whether or not the specified Sids have been loaded or not.Sid
+ * supports
+ *
+ * @return true if every passed Sid is represented by this Acl instance
+ */
+ public boolean isSidLoaded(Sid[] sids);
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/AclFormattingUtils.java b/core/src/main/java/org/acegisecurity/acls/AclFormattingUtils.java
similarity index 97%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/AclFormattingUtils.java
rename to core/src/main/java/org/acegisecurity/acls/AclFormattingUtils.java
index af9969878d..f846c6619b 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/AclFormattingUtils.java
+++ b/core/src/main/java/org/acegisecurity/acls/AclFormattingUtils.java
@@ -1,106 +1,105 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.springframework.util.Assert;
-
-
-/**
- * Utility methods for displaying ACL information.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class AclFormattingUtils {
- //~ Methods ========================================================================================================
-
- public static String demergePatterns(String original, String removeBits) {
- Assert.notNull(original, "Original string required");
- Assert.notNull(removeBits, "Bits To Remove string required");
- Assert.isTrue(original.length() == removeBits.length(),
- "Original and Bits To Remove strings must be identical length");
-
- char[] replacement = new char[original.length()];
-
- for (int i = 0; i < original.length(); i++) {
- if (removeBits.charAt(i) == Permission.RESERVED_OFF) {
- replacement[i] = original.charAt(i);
- } else {
- replacement[i] = Permission.RESERVED_OFF;
- }
- }
-
- return new String(replacement);
- }
-
- public static String mergePatterns(String original, String extraBits) {
- Assert.notNull(original, "Original string required");
- Assert.notNull(extraBits, "Extra Bits string required");
- Assert.isTrue(original.length() == extraBits.length(),
- "Original and Extra Bits strings must be identical length");
-
- char[] replacement = new char[extraBits.length()];
-
- for (int i = 0; i < extraBits.length(); i++) {
- if (extraBits.charAt(i) == Permission.RESERVED_OFF) {
- replacement[i] = original.charAt(i);
- } else {
- replacement[i] = extraBits.charAt(i);
- }
- }
-
- return new String(replacement);
- }
-
- private static String printBinary(int i, char on, char off) {
- String s = Integer.toString(i, 2);
- String pattern = Permission.THIRTY_TWO_RESERVED_OFF;
- String temp2 = pattern.substring(0, pattern.length() - s.length()) + s;
-
- return temp2.replace('0', off).replace('1', on);
- }
-
- /**
- * Returns a representation of the active bits in the presented mask, with each active bit being denoted by
- * character "".Acls that apply for the passed Objects.Acl instances. Any unknown objects will not
- * have a map key.null)
- *
- * @throws NotFoundException DOCUMENT ME!
- */
- public Map readAclsById(ObjectIdentity[] objects) throws NotFoundException;
-
- /**
- * Obtains all the Acls that apply for the passed Objects, but only for the
- * security identifies passed.Acl
- * instances. Any unknown objects (or objects for which the interested Sids do not have entries) will
- * not have a map key.null to denote
- * all entries)
- *
- * @return a map with zero or more elements (never null)
- *
- * @throws NotFoundException DOCUMENT ME!
- */
- public Map readAclsById(ObjectIdentity[] objects, Sid[] sids)
- throws NotFoundException;
-}
+ */
+public interface AclService {
+ //~ Methods ========================================================================================================
+
+ /**
+ * Locates all object identities that use the specified parent. This is useful for administration tools.
+ *
+ * @param parentIdentity to locate children of
+ *
+ * @return the children (or null if none were found)
+ */
+ public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity);
+
+ /**
+ * Same as {@link #readAclsById(ObjectIdentity[])} except it returns only a single Acl.Acl entries based on a {@link Sid} parameter.Acls that apply for the passed Objects.Acl instances. Any unknown objects will not
+ * have a map key.null)
+ *
+ * @throws NotFoundException DOCUMENT ME!
+ */
+ public Map readAclsById(ObjectIdentity[] objects) throws NotFoundException;
+
+ /**
+ * Obtains all the Acls that apply for the passed Objects, but only for the
+ * security identifies passed.Acl
+ * instances. Any unknown objects (or objects for which the interested Sids do not have entries) will
+ * not have a map key.null to denote
+ * all entries)
+ *
+ * @return a map with zero or more elements (never null)
+ *
+ * @throws NotFoundException DOCUMENT ME!
+ */
+ public Map readAclsById(ObjectIdentity[] objects, Sid[] sids)
+ throws NotFoundException;
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/AlreadyExistsException.java b/core/src/main/java/org/acegisecurity/acls/AlreadyExistsException.java
similarity index 96%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/AlreadyExistsException.java
rename to core/src/main/java/org/acegisecurity/acls/AlreadyExistsException.java
index 9ae2d3820e..babb4416e4 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/AlreadyExistsException.java
+++ b/core/src/main/java/org/acegisecurity/acls/AlreadyExistsException.java
@@ -1,49 +1,48 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.AcegiSecurityException;
-
-
-/**
- * Thrown if an Acl entry already exists for the object.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class AlreadyExistsException extends AcegiSecurityException {
- //~ Constructors ===================================================================================================
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.AcegiSecurityException;
+
+
+/**
+ * Thrown if an Acl entry already exists for the object.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class AlreadyExistsException extends AcegiSecurityException {
+ //~ Constructors ===================================================================================================
+
/**
* Constructs an AlreadyExistsException with the specified message.
*
* @param msg the detail message
- */
- public AlreadyExistsException(String msg) {
- super(msg);
- }
-
+ */
+ public AlreadyExistsException(String msg) {
+ super(msg);
+ }
+
/**
* Constructs an AlreadyExistsException with the specified message
* and root cause.
*
* @param msg the detail message
* @param t root cause
- */
- public AlreadyExistsException(String msg, Throwable t) {
- super(msg, t);
- }
-}
+ */
+ public AlreadyExistsException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/AuditableAccessControlEntry.java b/core/src/main/java/org/acegisecurity/acls/AuditableAccessControlEntry.java
similarity index 97%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/AuditableAccessControlEntry.java
rename to core/src/main/java/org/acegisecurity/acls/AuditableAccessControlEntry.java
index 22f7a8fb3a..3fcda04325 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/AuditableAccessControlEntry.java
+++ b/core/src/main/java/org/acegisecurity/acls/AuditableAccessControlEntry.java
@@ -1,31 +1,30 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
/**
* Represents an ACE that provides auditing information.
*
* @author Ben Alex
* @version $Id$
*
- */
-public interface AuditableAccessControlEntry extends AccessControlEntry {
- //~ Methods ========================================================================================================
-
- public boolean isAuditFailure();
-
- public boolean isAuditSuccess();
-}
+ */
+public interface AuditableAccessControlEntry extends AccessControlEntry {
+ //~ Methods ========================================================================================================
+
+ public boolean isAuditFailure();
+
+ public boolean isAuditSuccess();
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/AuditableAcl.java b/core/src/main/java/org/acegisecurity/acls/AuditableAcl.java
similarity index 87%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/AuditableAcl.java
rename to core/src/main/java/org/acegisecurity/acls/AuditableAcl.java
index 51bc15e1a9..cb5c4ecfa9 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/AuditableAcl.java
+++ b/core/src/main/java/org/acegisecurity/acls/AuditableAcl.java
@@ -1,29 +1,31 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import java.io.Serializable;
+
+
/**
* A mutable ACL that provides audit capabilities.
*
* @author Ben Alex
* @version $Id$
*
- */
-public interface AuditableAcl extends MutableAcl {
- //~ Methods ========================================================================================================
-
- public void updateAuditing(Long aceId, boolean auditSuccess, boolean auditFailure);
-}
+ */
+public interface AuditableAcl extends MutableAcl {
+ //~ Methods ========================================================================================================
+
+ public void updateAuditing(Serializable aceId, boolean auditSuccess, boolean auditFailure);
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/ChildrenExistException.java b/core/src/main/java/org/acegisecurity/acls/ChildrenExistException.java
similarity index 96%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/ChildrenExistException.java
rename to core/src/main/java/org/acegisecurity/acls/ChildrenExistException.java
index 0c87da7968..c7c8b07e48 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/ChildrenExistException.java
+++ b/core/src/main/java/org/acegisecurity/acls/ChildrenExistException.java
@@ -1,50 +1,49 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.AcegiSecurityException;
-
-
-/**
- * Thrown if an {@link Acl} cannot be deleted because children Acls exist.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class ChildrenExistException extends AcegiSecurityException {
- //~ Constructors ===================================================================================================
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.AcegiSecurityException;
+
+
+/**
+ * Thrown if an {@link Acl} cannot be deleted because children Acls exist.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class ChildrenExistException extends AcegiSecurityException {
+ //~ Constructors ===================================================================================================
+
/**
* Constructs an ChildrenExistException with the specified
* message.
*
* @param msg the detail message
- */
- public ChildrenExistException(String msg) {
- super(msg);
- }
-
+ */
+ public ChildrenExistException(String msg) {
+ super(msg);
+ }
+
/**
* Constructs an ChildrenExistException with the specified
* message and root cause.
*
* @param msg the detail message
* @param t root cause
- */
- public ChildrenExistException(String msg, Throwable t) {
- super(msg, t);
- }
-}
+ */
+ public ChildrenExistException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/IdentityUnavailableException.java b/core/src/main/java/org/acegisecurity/acls/IdentityUnavailableException.java
similarity index 96%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/IdentityUnavailableException.java
rename to core/src/main/java/org/acegisecurity/acls/IdentityUnavailableException.java
index df97a57aa9..7e346beebb 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/IdentityUnavailableException.java
+++ b/core/src/main/java/org/acegisecurity/acls/IdentityUnavailableException.java
@@ -1,49 +1,48 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.AcegiSecurityException;
-
-
-/**
- * Thrown if an ACL identity could not be extracted from an object.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class IdentityUnavailableException extends AcegiSecurityException {
- //~ Constructors ===================================================================================================
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.AcegiSecurityException;
+
+
+/**
+ * Thrown if an ACL identity could not be extracted from an object.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class IdentityUnavailableException extends AcegiSecurityException {
+ //~ Constructors ===================================================================================================
+
/**
* Constructs an IdentityUnavailableException with the specified message.
*
* @param msg the detail message
- */
- public IdentityUnavailableException(String msg) {
- super(msg);
- }
-
+ */
+ public IdentityUnavailableException(String msg) {
+ super(msg);
+ }
+
/**
* Constructs an IdentityUnavailableException with the specified message
* and root cause.
*
* @param msg the detail message
* @param t root cause
- */
- public IdentityUnavailableException(String msg, Throwable t) {
- super(msg, t);
- }
-}
+ */
+ public IdentityUnavailableException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/MutableAcl.java b/core/src/main/java/org/acegisecurity/acls/MutableAcl.java
similarity index 61%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/MutableAcl.java
rename to core/src/main/java/org/acegisecurity/acls/MutableAcl.java
index 3cc7774df0..8bcd8ab45a 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/MutableAcl.java
+++ b/core/src/main/java/org/acegisecurity/acls/MutableAcl.java
@@ -1,25 +1,24 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.acls.sid.Sid;
-
-import java.io.Serializable;
-
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.acls.sid.Sid;
+
+import java.io.Serializable;
+
+
/**
* A mutable Acl.
*
@@ -30,31 +29,47 @@ import java.io.Serializable;
*
* @author Ben Alex
* @version $Id$
- */
-public interface MutableAcl extends Acl {
- //~ Methods ========================================================================================================
-
- public void deleteAce(Long aceId) throws NotFoundException;
-
- /**
- * Obtains an identifier that represents this MutableAcl.
- *
- * @return the identifier, or null if unsaved
- */
- public Serializable getId();
-
- public void insertAce(Long afterAceId, Permission permission, Sid sid, boolean granting)
- throws NotFoundException;
-
- public void setEntriesInheriting(boolean entriesInheriting);
-
- /**
- * Changes the parent of this ACL.
- *
- * @param newParent the new parent
- */
- public void setParent(MutableAcl newParent);
-
- public void updateAce(Long aceId, Permission permission)
- throws NotFoundException;
-}
+ */
+public interface MutableAcl extends Acl {
+ //~ Methods ========================================================================================================
+
+ public void deleteAce(Serializable aceId) throws NotFoundException;
+
+ /**
+ * Retrieves all of the non-deleted {@link AccessControlEntry} instances currently stored by the
+ * MutableAcl. The returned objects should be immutable outside the package, and therefore it is safe
+ * to return them to the caller for informational purposes. The AccessControlEntry information is
+ * needed so that invocations of update and delete methods on the MutableAcl can refer to a valid
+ * {@link AccessControlEntry#getId()}.
+ *
+ * @return DOCUMENT ME!
+ */
+ public AccessControlEntry[] getEntries();
+
+ /**
+ * Obtains an identifier that represents this MutableAcl.
+ *
+ * @return the identifier, or null if unsaved
+ */
+ public Serializable getId();
+
+ public void insertAce(Serializable afterAceId, Permission permission, Sid sid, boolean granting)
+ throws NotFoundException;
+
+ /**
+ * Change the value returned by {@link Acl#isEntriesInheriting()}.
+ *
+ * @param entriesInheriting the new value
+ */
+ public void setEntriesInheriting(boolean entriesInheriting);
+
+ /**
+ * Changes the parent of this ACL.
+ *
+ * @param newParent the new parent
+ */
+ public void setParent(MutableAcl newParent);
+
+ public void updateAce(Serializable aceId, Permission permission)
+ throws NotFoundException;
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/MutableAclService.java b/core/src/main/java/org/acegisecurity/acls/MutableAclService.java
similarity index 72%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/MutableAclService.java
rename to core/src/main/java/org/acegisecurity/acls/MutableAclService.java
index 66b73f9fe5..9b866e052b 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/MutableAclService.java
+++ b/core/src/main/java/org/acegisecurity/acls/MutableAclService.java
@@ -1,74 +1,65 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.acls.objectidentity.ObjectIdentity;
-
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.acls.objectidentity.ObjectIdentity;
+
+
/**
* Provides support for creating and storing Acl instances.
*
* @author Ben Alex
* @version $Id$
- */
-public interface MutableAclService extends AclService {
- //~ Methods ========================================================================================================
-
- /**
- * Creates an empty Acl object in the database. It will have no entries. The returned object
- * will then be used to add entries.
- *
- * @param object the object identity to create
- *
- * @return an ACL object with its ID set
- *
- * @throws AlreadyExistsException if the passed object identity already has a record
- */
- public MutableAcl createAcl(ObjectIdentity object)
- throws AlreadyExistsException;
-
- /**
- * Removes the specified entry from the database.
- *
- * @param object the object identity to remove
- * @param deleteChildren whether to cascade the delete to children
- *
- * @throws ChildrenExistException if the deleteChildren argument was false but children exist
- */
- public void deleteAcl(ObjectIdentity object, boolean deleteChildren)
- throws ChildrenExistException;
-
- /**
- * Locates all object identities that use the specified parent. This is useful for administration tools,
- * and before issuing a {@link #deleteAcl(ObjectIdentity, boolean)}.
- *
- * @param parentIdentity to locate children of
- *
- * @return the children (or null if none were found)
- */
- public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity);
-
- /**
- * Changes an existing Acl in the database.
- *
- * @param acl to modify
- *
- * @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 new
- * keyword?)
- */
- public void updateAcl(MutableAcl acl) throws NotFoundException;
-}
+ */
+public interface MutableAclService extends AclService {
+ //~ Methods ========================================================================================================
+
+ /**
+ * Creates an empty Acl object in the database. It will have no entries. The returned object
+ * will then be used to add entries.
+ *
+ * @param objectIdentity the object identity to create
+ *
+ * @return an ACL object with its ID set
+ *
+ * @throws AlreadyExistsException if the passed object identity already has a record
+ */
+ public MutableAcl createAcl(ObjectIdentity objectIdentity)
+ throws AlreadyExistsException;
+
+ /**
+ * Removes the specified entry from the database.
+ *
+ * @param objectIdentity the object identity to remove
+ * @param deleteChildren whether to cascade the delete to children
+ *
+ * @throws ChildrenExistException if the deleteChildren argument was false but children exist
+ */
+ public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren)
+ throws ChildrenExistException;
+
+ /**
+ * Changes an existing Acl in the database.
+ *
+ * @param acl to modify
+ *
+ * @return DOCUMENT ME!
+ *
+ * @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 new
+ * keyword?)
+ */
+ public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException;
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/NotFoundException.java b/core/src/main/java/org/acegisecurity/acls/NotFoundException.java
similarity index 96%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/NotFoundException.java
rename to core/src/main/java/org/acegisecurity/acls/NotFoundException.java
index 4129bb18a6..74d0f1004b 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/NotFoundException.java
+++ b/core/src/main/java/org/acegisecurity/acls/NotFoundException.java
@@ -1,49 +1,48 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.AcegiSecurityException;
-
-
-/**
- * Thrown if an ACL-related object cannot be found.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class NotFoundException extends AcegiSecurityException {
- //~ Constructors ===================================================================================================
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.AcegiSecurityException;
+
+
+/**
+ * Thrown if an ACL-related object cannot be found.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class NotFoundException extends AcegiSecurityException {
+ //~ Constructors ===================================================================================================
+
/**
* Constructs an NotFoundException with the specified message.
*
* @param msg the detail message
- */
- public NotFoundException(String msg) {
- super(msg);
- }
-
+ */
+ public NotFoundException(String msg) {
+ super(msg);
+ }
+
/**
* Constructs an NotFoundException with the specified message
* and root cause.
*
* @param msg the detail message
* @param t root cause
- */
- public NotFoundException(String msg, Throwable t) {
- super(msg, t);
- }
-}
+ */
+ public NotFoundException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/OwnershipAcl.java b/core/src/main/java/org/acegisecurity/acls/OwnershipAcl.java
similarity index 94%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/OwnershipAcl.java
rename to core/src/main/java/org/acegisecurity/acls/OwnershipAcl.java
index f4af13deb8..d8c44456a0 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/OwnershipAcl.java
+++ b/core/src/main/java/org/acegisecurity/acls/OwnershipAcl.java
@@ -1,23 +1,22 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.acls.sid.Sid;
-
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.acls.sid.Sid;
+
+
/**
* A mutable ACL that provides ownership capabilities.
*
@@ -28,11 +27,9 @@ import org.acegisecurity.acls.sid.Sid;
*
* @author Ben Alex
* @version $Id$
- */
-public interface OwnershipAcl extends MutableAcl {
- //~ Methods ========================================================================================================
-
- public Sid getOwner();
-
- public void setOwner(Sid newOwner);
-}
+ */
+public interface OwnershipAcl extends MutableAcl {
+ //~ Methods ========================================================================================================
+
+ public void setOwner(Sid newOwner);
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/Permission.java b/core/src/main/java/org/acegisecurity/acls/Permission.java
similarity index 97%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/Permission.java
rename to core/src/main/java/org/acegisecurity/acls/Permission.java
index 667b226419..2104090c13 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/Permission.java
+++ b/core/src/main/java/org/acegisecurity/acls/Permission.java
@@ -1,57 +1,56 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls;
-
-import org.acegisecurity.acls.sid.Sid;
-
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.acls.sid.Sid;
+
+
/**
* Represents a permission granted to a {@link Sid} for a given domain object.
*
* @author Ben Alex
* @version $Id$
- */
-public interface Permission {
- //~ Static fields/initializers =====================================================================================
-
- public static final char RESERVED_ON = '~';
- public static final char RESERVED_OFF = '.';
- public static final String THIRTY_TWO_RESERVED_OFF = "................................";
-
- //~ Methods ========================================================================================================
-
- /**
- * Returns the bits that represents the permission.
- *
- * @return the bits that represent the permission
- */
- public int getMask();
-
- /**
- * Returns a 32-character long bit pattern String representing this permission.String containing {@link
- * #RESERVED_ON}.String representing this permission.String containing {@link
+ * #RESERVED_ON}.Sids and
- * the caller has requested details for an unloaded Sid.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class UnloadedSidException extends AcegiSecurityException {
- //~ Constructors ===================================================================================================
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls;
+
+import org.acegisecurity.AcegiSecurityException;
+
+
+/**
+ * Thrown if an {@link Acl} cannot perform an operation because it only loaded a subset of Sids and
+ * the caller has requested details for an unloaded Sid.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class UnloadedSidException extends AcegiSecurityException {
+ //~ Constructors ===================================================================================================
+
/**
* Constructs an NotFoundException with the specified message.
*
* @param msg the detail message
- */
- public UnloadedSidException(String msg) {
- super(msg);
- }
-
+ */
+ public UnloadedSidException(String msg) {
+ super(msg);
+ }
+
/**
* Constructs an NotFoundException with the specified message
* and root cause.
*
* @param msg the detail message
* @param t root cause
- */
- public UnloadedSidException(String msg, Throwable t) {
- super(msg, t);
- }
-}
+ */
+ public UnloadedSidException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/AccessControlEntryImpl.java b/core/src/main/java/org/acegisecurity/acls/domain/AccessControlEntryImpl.java
similarity index 82%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/domain/AccessControlEntryImpl.java
rename to core/src/main/java/org/acegisecurity/acls/domain/AccessControlEntryImpl.java
index b1c25929b4..c810d376f5 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/AccessControlEntryImpl.java
+++ b/core/src/main/java/org/acegisecurity/acls/domain/AccessControlEntryImpl.java
@@ -1,149 +1,133 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.domain;
-
-import org.acegisecurity.acls.AccessControlEntry;
-import org.acegisecurity.acls.Acl;
-import org.acegisecurity.acls.AuditableAccessControlEntry;
-import org.acegisecurity.acls.Permission;
-import org.acegisecurity.acls.sid.Sid;
-
-import org.springframework.util.Assert;
-
-import java.io.Serializable;
-
-
-/**
- * An immutable default implementation of AccessControlEntry.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry {
- //~ Instance fields ================================================================================================
-
- private Acl acl;
- private Permission permission;
- private Serializable id;
- private Sid sid;
- private boolean aceDirty = false;
- private boolean auditFailure = false;
- private boolean auditSuccess = false;
- private boolean granting;
-
- //~ Constructors ===================================================================================================
-
- public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
- boolean auditSuccess, boolean auditFailure) {
- Assert.notNull(acl, "Acl required");
- Assert.notNull(sid, "Sid required");
- Assert.notNull(permission, "Permission required");
- this.id = id;
- this.acl = acl; // can be null
- this.sid = sid;
- this.permission = permission;
- this.granting = granting;
- this.auditSuccess = auditSuccess;
- this.auditFailure = auditFailure;
- }
-
- //~ Methods ========================================================================================================
-
- public void clearDirtyFlags() {
- this.aceDirty = false;
- }
-
- public boolean equals(Object arg0) {
- if (!(arg0 instanceof AccessControlEntryImpl)) {
- return false;
- }
-
- AccessControlEntryImpl rhs = (AccessControlEntryImpl) arg0;
-
- if ((this.aceDirty != rhs.isAceDirty()) || (this.auditFailure != rhs.isAuditFailure())
- || (this.auditSuccess != rhs.isAuditSuccess()) || (this.granting != rhs.isGranting())
- || !this.acl.equals(rhs.getAcl()) || !this.id.equals(rhs.getId())
- || !this.permission.equals(rhs.getPermission()) || !this.sid.equals(rhs.getSid())) {
- return false;
- }
-
- return true;
- }
-
- public Acl getAcl() {
- return acl;
- }
-
- public Serializable getId() {
- return id;
- }
-
- public Permission getPermission() {
- return permission;
- }
-
- public Sid getSid() {
- return sid;
- }
-
- public boolean isAceDirty() {
- return aceDirty;
- }
-
- public boolean isAuditFailure() {
- return auditFailure;
- }
-
- public boolean isAuditSuccess() {
- return auditSuccess;
- }
-
- public boolean isGranting() {
- return granting;
- }
-
- void setAuditFailure(boolean auditFailure) {
- this.auditFailure = auditFailure;
- this.aceDirty = true;
- }
-
- void setAuditSuccess(boolean auditSuccess) {
- this.auditSuccess = auditSuccess;
- this.aceDirty = true;
- }
-
- void setId(Serializable id) {
- this.id = id;
- }
-
- void setPermission(Permission permission) {
- Assert.notNull(permission, "Permission required");
- this.permission = permission;
- this.aceDirty = true;
- }
-
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append("AccessControlEntryImpl[");
- sb.append("id: ").append(this.id).append("; ");
- sb.append("granting: ").append(this.granting).append("; ");
- sb.append("sid: ").append(this.sid).append("; ");
- sb.append("permission: ").append(this.permission);
- sb.append("]");
-
- return sb.toString();
- }
-}
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls.domain;
+
+import org.acegisecurity.acls.AccessControlEntry;
+import org.acegisecurity.acls.Acl;
+import org.acegisecurity.acls.AuditableAccessControlEntry;
+import org.acegisecurity.acls.Permission;
+import org.acegisecurity.acls.sid.Sid;
+
+import org.springframework.util.Assert;
+
+import java.io.Serializable;
+
+
+/**
+ * An immutable default implementation of AccessControlEntry.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry {
+ //~ Instance fields ================================================================================================
+
+ private Acl acl;
+ private Permission permission;
+ private Serializable id;
+ private Sid sid;
+ private boolean auditFailure = false;
+ private boolean auditSuccess = false;
+ private boolean granting;
+
+ //~ Constructors ===================================================================================================
+
+ public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
+ boolean auditSuccess, boolean auditFailure) {
+ Assert.notNull(acl, "Acl required");
+ Assert.notNull(sid, "Sid required");
+ Assert.notNull(permission, "Permission required");
+ this.id = id;
+ this.acl = acl; // can be null
+ this.sid = sid;
+ this.permission = permission;
+ this.granting = granting;
+ this.auditSuccess = auditSuccess;
+ this.auditFailure = auditFailure;
+ }
+
+ //~ Methods ========================================================================================================
+
+ public boolean equals(Object arg0) {
+ if (!(arg0 instanceof AccessControlEntryImpl)) {
+ return false;
+ }
+
+ AccessControlEntryImpl rhs = (AccessControlEntryImpl) arg0;
+
+ if ((this.auditFailure != rhs.isAuditFailure()) || (this.auditSuccess != rhs.isAuditSuccess())
+ || (this.granting != rhs.isGranting()) || !this.acl.equals(rhs.getAcl()) || !this.id.equals(rhs.getId())
+ || !this.permission.equals(rhs.getPermission()) || !this.sid.equals(rhs.getSid())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public Acl getAcl() {
+ return acl;
+ }
+
+ public Serializable getId() {
+ return id;
+ }
+
+ public Permission getPermission() {
+ return permission;
+ }
+
+ public Sid getSid() {
+ return sid;
+ }
+
+ public boolean isAuditFailure() {
+ return auditFailure;
+ }
+
+ public boolean isAuditSuccess() {
+ return auditSuccess;
+ }
+
+ public boolean isGranting() {
+ return granting;
+ }
+
+ void setAuditFailure(boolean auditFailure) {
+ this.auditFailure = auditFailure;
+ }
+
+ void setAuditSuccess(boolean auditSuccess) {
+ this.auditSuccess = auditSuccess;
+ }
+
+ void setPermission(Permission permission) {
+ Assert.notNull(permission, "Permission required");
+ this.permission = permission;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("AccessControlEntryImpl[");
+ sb.append("id: ").append(this.id).append("; ");
+ sb.append("granting: ").append(this.granting).append("; ");
+ sb.append("sid: ").append(this.sid).append("; ");
+ sb.append("permission: ").append(this.permission).append("; ");
+ sb.append("auditSuccess: ").append(this.auditSuccess).append("; ");
+ sb.append("auditFailure: ").append(this.auditFailure);
+ sb.append("]");
+
+ return sb.toString();
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategy.java b/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategy.java
new file mode 100644
index 0000000000..7530340600
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategy.java
@@ -0,0 +1,38 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acegisecurity.acls.domain;
+
+import org.acegisecurity.acls.Acl;
+
+
+/**
+ * Strategy used by {@link AclImpl} to determine whether a principal is permitted to call
+ * adminstrative methods on the AclImpl.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public interface AclAuthorizationStrategy {
+ //~ Static fields/initializers =====================================================================================
+
+ public static final int CHANGE_OWNERSHIP = 0;
+ public static final int CHANGE_AUDITING = 1;
+ public static final int CHANGE_GENERAL = 2;
+
+ //~ Methods ========================================================================================================
+
+ public void securityCheck(Acl acl, int changeType);
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategyImpl.java b/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategyImpl.java
new file mode 100644
index 0000000000..da35c839a0
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/domain/AclAuthorizationStrategyImpl.java
@@ -0,0 +1,125 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acegisecurity.acls.domain;
+
+import org.acegisecurity.AccessDeniedException;
+import org.acegisecurity.Authentication;
+import org.acegisecurity.GrantedAuthority;
+
+import org.acegisecurity.acls.Acl;
+import org.acegisecurity.acls.Permission;
+import org.acegisecurity.acls.sid.PrincipalSid;
+import org.acegisecurity.acls.sid.Sid;
+import org.acegisecurity.acls.sid.SidRetrievalStrategy;
+import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl;
+
+import org.acegisecurity.context.SecurityContextHolder;
+
+import org.springframework.util.Assert;
+
+
+/**
+ * Default implementation of {@link AclAuthorizationStrategy}.GrantedAuthoritys that have
+ * special permissions (index 0 is the authority needed to change
+ * ownership, index 1 is the authority needed to modify auditing details,
+ * index 2 is the authority needed to change other ACL and ACE details) (required)
+ */
+ public AclAuthorizationStrategyImpl(GrantedAuthority[] auths) {
+ Assert.notEmpty(auths, "GrantedAuthority[] with three elements required");
+ Assert.isTrue(auths.length == 3, "GrantedAuthority[] with three elements required");
+ this.gaTakeOwnership = auths[0];
+ this.gaModifyAuditing = auths[1];
+ this.gaGeneralChanges = auths[2];
+ }
+
+ //~ Methods ========================================================================================================
+
+ public void securityCheck(Acl acl, int changeType) {
+ if ((SecurityContextHolder.getContext() == null)
+ || (SecurityContextHolder.getContext().getAuthentication() == null)
+ || !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
+ throw new AccessDeniedException("Authenticated principal required to operate with ACLs");
+ }
+
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+ // Check if authorized by virtue of ACL ownership
+ Sid currentUser = new PrincipalSid(authentication);
+
+ if (currentUser.equals(acl.getOwner()) && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
+ return;
+ }
+
+ // Not authorized by ACL ownership; try via adminstrative permissions
+ GrantedAuthority requiredAuthority = null;
+
+ if (changeType == CHANGE_AUDITING) {
+ requiredAuthority = this.gaModifyAuditing;
+ } else if (changeType == CHANGE_GENERAL) {
+ requiredAuthority = this.gaGeneralChanges;
+ } else if (changeType == CHANGE_OWNERSHIP) {
+ requiredAuthority = this.gaTakeOwnership;
+ } else {
+ throw new IllegalArgumentException("Unknown change type");
+ }
+
+ // Iterate this principal's authorities to determine right
+ GrantedAuthority[] auths = authentication.getAuthorities();
+
+ for (int i = 0; i < auths.length; i++) {
+ if (requiredAuthority.equals(auths[i])) {
+ return;
+ }
+ }
+
+ // Try to get permission via ACEs within the ACL
+ Sid[] sids = sidRetrievalStrategy.getSids(authentication);
+
+ if (acl.isGranted(new Permission[] {BasePermission.ADMINISTRATION}, sids, false)) {
+ return;
+ }
+
+ throw new AccessDeniedException(
+ "Principal does not have required ACL permissions to perform requested operation");
+ }
+
+ public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
+ Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
+ this.sidRetrievalStrategy = sidRetrievalStrategy;
+ }
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/AclImpl.java b/core/src/main/java/org/acegisecurity/acls/domain/AclImpl.java
similarity index 62%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/domain/AclImpl.java
rename to core/src/main/java/org/acegisecurity/acls/domain/AclImpl.java
index ac1996e792..ac290fd194 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/AclImpl.java
+++ b/core/src/main/java/org/acegisecurity/acls/domain/AclImpl.java
@@ -12,13 +12,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.acegisecurity.acls.domain;
-import org.acegisecurity.AccessDeniedException;
-import org.acegisecurity.Authentication;
-import org.acegisecurity.GrantedAuthority;
-
import org.acegisecurity.acls.AccessControlEntry;
import org.acegisecurity.acls.Acl;
import org.acegisecurity.acls.AuditableAcl;
@@ -28,11 +23,8 @@ import org.acegisecurity.acls.OwnershipAcl;
import org.acegisecurity.acls.Permission;
import org.acegisecurity.acls.UnloadedSidException;
import org.acegisecurity.acls.objectidentity.ObjectIdentity;
-import org.acegisecurity.acls.sid.PrincipalSid;
import org.acegisecurity.acls.sid.Sid;
-import org.acegisecurity.context.SecurityContextHolder;
-
import org.springframework.util.Assert;
import java.io.Serializable;
@@ -49,29 +41,17 @@ import java.util.Vector;
* @version $Id
*/
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
- //~ Static fields/initializers =====================================================================================
-
- private static final int CHANGE_OWNERSHIP = 0;
- private static final int CHANGE_AUDITING = 1;
- private static final int CHANGE_GENERAL = 2;
-
//~ Instance fields ================================================================================================
private Acl parentAcl;
- private AuditLogger auditLogger = new ConsoleAuditLogger(); // AuditableAcl
- private GrantedAuthority gaGeneralChanges;
- private GrantedAuthority gaModifyAuditing;
- private GrantedAuthority gaTakeOwnership;
+ private AclAuthorizationStrategy aclAuthorizationStrategy;
+ private AuditLogger auditLogger;
private List aces = new Vector();
- private List deletedAces = new Vector();
- private Long id;
private ObjectIdentity objectIdentity;
+ private Serializable id;
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 boolean aclDirty = false; // for snapshot detection
- private boolean addedAces = false; // for snapshot detection
- private boolean entriesInheriting = false;
- private boolean updatedAces = false; // for snapshot detection
+ private boolean entriesInheriting = true;
//~ Constructors ===================================================================================================
@@ -81,17 +61,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
*
* @param objectIdentity the object identity this ACL relates to (required)
* @param id the primary key assigned to this ACL (required)
- * @param auths an array of GrantedAuthoritys that have
- * special permissions (index 0 is the authority needed to change
- * ownership, index 1 is the authority needed to modify auditing details,
- * index 2 is the authority needed to change other ACL and ACE details) (required)
+ * @param aclAuthorizationStrategy authorization strategy (required)
+ * @param auditLogger audit logger (required)
*/
- public AclImpl(ObjectIdentity objectIdentity, Long id, GrantedAuthority[] auths) {
+ public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
+ AuditLogger auditLogger) {
Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(id, "Id required");
+ Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
+ Assert.notNull(auditLogger, "AuditLogger required");
this.objectIdentity = objectIdentity;
this.id = id;
- this.setAuthorities(auths);
+ this.aclAuthorizationStrategy = aclAuthorizationStrategy;
+ this.auditLogger = auditLogger;
}
/**
@@ -100,10 +82,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
*
* @param objectIdentity the object identity this ACL relates to (required)
* @param id the primary key assigned to this ACL (required)
- * @param auths an array of GrantedAuthoritys that have
- * special permissions (index 0 is the authority needed to change
- * ownership, index 1 is the authority needed to modify auditing details,
- * index 2 is the authority needed to change other ACL and ACE details) (required)
+ * @param aclAuthorizationStrategy authorization strategy (required)
+ * @param auditLogger audit logger (required)
* @param parentAcl the parent (may be null)
* @param loadedSids the loaded SIDs if only a subset were loaded (may be
* null)
@@ -111,14 +91,17 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* this ACL
* @param owner the owner (required)
*/
- public AclImpl(ObjectIdentity objectIdentity, Long id, Acl parentAcl, GrantedAuthority[] auths, Sid[] loadedSids,
- boolean entriesInheriting, Sid owner) {
+ public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
+ AuditLogger auditLogger, Acl parentAcl, Sid[] loadedSids, boolean entriesInheriting, Sid owner) {
Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(id, "Id required");
+ Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
Assert.notNull(owner, "Owner required");
+ Assert.notNull(auditLogger, "AuditLogger required");
this.objectIdentity = objectIdentity;
this.id = id;
- setAuthorities(auths);
+ this.aclAuthorizationStrategy = aclAuthorizationStrategy;
+ this.auditLogger = auditLogger;
this.parentAcl = parentAcl; // may be null
this.loadedSids = loadedSids; // may be null
this.entriesInheriting = entriesInheriting;
@@ -133,17 +116,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
//~ Methods ========================================================================================================
- /**
- * Clears the dirty flags on the Acl, but not any associated ACEs.
- */
- public void clearDirtyFlags() {
- this.aclDirty = false;
- this.addedAces = false;
- this.updatedAces = false;
- }
-
- public void deleteAce(Long aceId) throws NotFoundException {
- securityCheck(CHANGE_GENERAL);
+ public void deleteAce(Serializable aceId) throws NotFoundException {
+ aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
synchronized (aces) {
int offset = findAceOffset(aceId);
@@ -152,12 +126,11 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
throw new NotFoundException("Requested ACE ID not found");
}
- aces.remove(offset);
- deletedAces.add(aceId);
+ this.aces.remove(offset);
}
}
- private int findAceOffset(Long aceId) {
+ private int findAceOffset(Serializable aceId) {
Assert.notNull(aceId, "ACE ID is required");
synchronized (aces) {
@@ -174,7 +147,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
}
public AccessControlEntry[] getEntries() {
- // Can safely return AccessControlEntry directly, as they're immutable
+ // Can safely return AccessControlEntry directly, as they're immutable outside the ACL package
return (AccessControlEntry[]) aces.toArray(new AccessControlEntry[] {});
}
@@ -194,9 +167,9 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
return parentAcl;
}
- public void insertAce(Long afterAceId, Permission permission, Sid sid, boolean granting)
+ public void insertAce(Serializable afterAceId, Permission permission, Sid sid, boolean granting)
throws NotFoundException {
- securityCheck(CHANGE_GENERAL);
+ aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
Assert.notNull(permission, "Permission required");
Assert.notNull(sid, "Sid required");
@@ -210,17 +183,11 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
throw new NotFoundException("Requested ACE ID not found");
}
- aces.add(offset + 1, ace);
+ this.aces.add(offset + 1, ace);
} else {
- aces.add(ace);
+ this.aces.add(ace);
}
}
-
- this.addedAces = true;
- }
-
- public boolean isAclDirty() {
- return aclDirty;
}
public boolean isEntriesInheriting() {
@@ -231,18 +198,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* Determines authorization. The order of the permission and sid arguments is
* extremely important! The method will iterate through each of the permissions in the order
* specified. For each iteration, all of the sids will be considered, again in the order they are
- * presented. The iteration of each permission:sid combination will then inspect the ACEs in the
- * order they appear in the ACL. When the first full match is found (ie an ACE that has the SID currently
- * being searched for and the exact permission bit mask being search for), the grant or deny flag for that ACE
- * will prevail. If the ACE specifies to grant access, the method will return true. If the ACE
- * specifies to deny access, the loop will stop and the next permission iteration will be performed.
- * If each permission indicates to deny access, the first deny ACE found will be considered the reason for the
- * failure (as it was the first match found, and is therefore the one most logically requiring changes - although
- * not always). If absolutely no matching ACE was found at all for any permission, the parent ACL will be tried
- * (provided that there is a parent and {@link #isEntriesInheriting()} is true. The parent ACL will
- * also scan its parent and so on. If ultimately no matching ACE is found, a NotFoundException will
- * be thrown and the caller will need to decide how to handle the permission check. Similarly, if any of the
- * passed SIDs were not loaded by the ACL, the UnloadedSidException will be thrown.
+ * presented. A search will then be performed for the first {@link AccessControlEntry} object that directly
+ * matches that permission:sid combination. When the first full match is found (ie an ACE
+ * that has the SID currently being searched for and the exact permission bit mask being search for), the grant or
+ * deny flag for that ACE will prevail. If the ACE specifies to grant access, the method will return
+ * true. If the ACE specifies to deny access, the loop will stop and the next permission
+ * iteration will be performed. If each permission indicates to deny access, the first deny ACE found will be
+ * considered the reason for the failure (as it was the first match found, and is therefore the one most logically
+ * requiring changes - although not always). If absolutely no matching ACE was found at all for any permission,
+ * the parent ACL will be tried (provided that there is a parent and {@link #isEntriesInheriting()} is
+ * true. The parent ACL will also scan its parent and so on. If ultimately no matching ACE is found,
+ * a NotFoundException will be thrown and the caller will need to decide how to handle the permission
+ * check. Similarly, if any of the SID arguments presented to the method were not loaded by the ACL,
+ * UnloadedSidException will be thrown.
*
* @param permission the exact permissions to scan for (order is important)
* @param sids the exact SIDs to scan for (order is important)
@@ -335,7 +303,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
return true;
}
- // This ACL applies to a SID subset. 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++) {
boolean found = false;
@@ -356,83 +324,22 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
return true;
}
- protected void securityCheck(int changeType) {
- if ((SecurityContextHolder.getContext() == null)
- || (SecurityContextHolder.getContext().getAuthentication() == null)
- || !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
- throw new AccessDeniedException("Authenticated principal required to operate with ACLs");
- }
-
- Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-
- // Check if authorized by virtue of ACL ownership
- Sid currentUser = new PrincipalSid(authentication);
-
- if (currentUser.equals(this.owner) && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
- return;
- }
-
- // Not authorized by ACL ownership; try via adminstrative permissions
- GrantedAuthority requiredAuthority = null;
-
- if (changeType == CHANGE_AUDITING) {
- requiredAuthority = this.gaModifyAuditing;
- } else if (changeType == CHANGE_GENERAL) {
- requiredAuthority = this.gaGeneralChanges;
- } else if (changeType == CHANGE_OWNERSHIP) {
- requiredAuthority = this.gaTakeOwnership;
- } else {
- throw new IllegalArgumentException("Unknown change type");
- }
-
- // Iterate this principal's authorities to determine right
- GrantedAuthority[] auths = authentication.getAuthorities();
-
- for (int i = 0; i < auths.length; i++) {
- if (requiredAuthority.equals(auths[i])) {
- return;
- }
- }
-
- throw new AccessDeniedException(
- "Principal does not have required ACL permissions to perform requested operation");
- }
-
- /**
- * Change the special adminstrative permissions honoured by this object.GrantedAuthoritys that have administrative permissions (index 0 is the
- * authority needed to change ownership, index 1 is the authority needed to modify auditing details, index
- * 2 is the authority needed to change other ACL and ACE details)
- */
- private void setAuthorities(GrantedAuthority[] auths) {
- Assert.notEmpty(auths, "GrantedAuthority[] with three elements required");
- Assert.isTrue(auths.length == 3, "GrantedAuthority[] with three elements required");
- this.gaTakeOwnership = auths[0];
- this.gaModifyAuditing = auths[1];
- this.gaGeneralChanges = auths[2];
- }
-
public void setEntriesInheriting(boolean entriesInheriting) {
- securityCheck(CHANGE_GENERAL);
+ aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
this.entriesInheriting = entriesInheriting;
- this.aclDirty = true;
}
public void setOwner(Sid newOwner) {
- securityCheck(CHANGE_OWNERSHIP);
+ aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
Assert.notNull(newOwner, "Owner required");
this.owner = newOwner;
- this.aclDirty = true;
}
public void setParent(MutableAcl newParent) {
- securityCheck(CHANGE_GENERAL);
+ aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
Assert.notNull(newParent, "New Parent required");
+ Assert.isTrue(!newParent.equals(this), "Cannot be the parent of yourself");
this.parentAcl = newParent;
- this.aclDirty = true;
}
public String toString() {
@@ -455,6 +362,10 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
sb.append(iterator.next().toString()).append("\r\n");
}
+ if (count == 0) {
+ sb.append("no ACEs; ");
+ }
+
sb.append("inheriting: ").append(this.entriesInheriting).append("; ");
sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString());
sb.append("]");
@@ -462,9 +373,9 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
return sb.toString();
}
- public void updateAce(Long aceId, Permission permission)
+ public void updateAce(Serializable aceId, Permission permission)
throws NotFoundException {
- securityCheck(CHANGE_GENERAL);
+ aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
synchronized (aces) {
int offset = findAceOffset(aceId);
@@ -476,12 +387,10 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(offset);
ace.setPermission(permission);
}
-
- this.updatedAces = true;
}
- public void updateAuditing(Long aceId, boolean auditSuccess, boolean auditFailure) {
- securityCheck(CHANGE_AUDITING);
+ public void updateAuditing(Serializable aceId, boolean auditSuccess, boolean auditFailure) {
+ aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_AUDITING);
synchronized (aces) {
int offset = findAceOffset(aceId);
@@ -494,7 +403,5 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
ace.setAuditSuccess(auditSuccess);
ace.setAuditFailure(auditFailure);
}
-
- this.updatedAces = true;
}
}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/AuditLogger.java b/core/src/main/java/org/acegisecurity/acls/domain/AuditLogger.java
similarity index 96%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/domain/AuditLogger.java
rename to core/src/main/java/org/acegisecurity/acls/domain/AuditLogger.java
index d618761c7e..9bf11e9276 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/AuditLogger.java
+++ b/core/src/main/java/org/acegisecurity/acls/domain/AuditLogger.java
@@ -1,32 +1,31 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.domain;
-
-import org.acegisecurity.acls.AccessControlEntry;
-
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls.domain;
+
+import org.acegisecurity.acls.AccessControlEntry;
+
+
/**
* Used by AclImpl to log audit events.
*
* @author Ben Alex
* @version $Id$
*
- */
-public interface AuditLogger {
- //~ Methods ========================================================================================================
-
- public void logIfNeeded(boolean granted, AccessControlEntry ace);
-}
+ */
+public interface AuditLogger {
+ //~ Methods ========================================================================================================
+
+ public void logIfNeeded(boolean granted, AccessControlEntry ace);
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/domain/BasePermission.java b/core/src/main/java/org/acegisecurity/acls/domain/BasePermission.java
new file mode 100644
index 0000000000..58e4d3ba9a
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/domain/BasePermission.java
@@ -0,0 +1,164 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls.domain;
+
+import org.acegisecurity.acls.AclFormattingUtils;
+import org.acegisecurity.acls.Permission;
+
+import org.springframework.util.Assert;
+
+import java.lang.reflect.Field;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+
+/**
+ * A set of standard permissions.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class BasePermission implements Permission {
+ //~ Static fields/initializers =====================================================================================
+
+ public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
+ public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
+ public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
+ public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
+ public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
+ private static Map locallyDeclaredPermissionsByInteger = new HashMap();
+ private static Map locallyDeclaredPermissionsByName = new HashMap();
+
+ static {
+ Field[] fields = BasePermission.class.getDeclaredFields();
+
+ for (int i = 0; i < fields.length; i++) {
+ try {
+ Object fieldValue = fields[i].get(null);
+
+ if (BasePermission.class.isAssignableFrom(fieldValue.getClass())) {
+ // Found a BasePermission static field
+ BasePermission perm = (BasePermission) fieldValue;
+ locallyDeclaredPermissionsByInteger.put(new Integer(perm.getMask()), perm);
+ locallyDeclaredPermissionsByName.put(fields[i].getName(), perm);
+ }
+ } catch (Exception ignore) {}
+ }
+ }
+
+ //~ Instance fields ================================================================================================
+
+ private char code;
+ private int mask;
+
+ //~ Constructors ===================================================================================================
+
+ private BasePermission(int mask, char code) {
+ this.mask = mask;
+ this.code = code;
+ }
+
+ //~ Methods ========================================================================================================
+
+ /**
+ * Dynamically creates a CumulativePermission or BasePermission representing the
+ * active bits in the passed mask.
+ *
+ * @param mask to build
+ *
+ * @return a Permission representing the requested object
+ */
+ public static Permission buildFromMask(int mask) {
+ if (locallyDeclaredPermissionsByInteger.containsKey(new Integer(mask))) {
+ // The requested mask has an exactly match against a statically-defined BasePermission, so return it
+ return (Permission) locallyDeclaredPermissionsByInteger.get(new Integer(mask));
+ }
+
+ // To get this far, we have to use a CumulativePermission
+ CumulativePermission permission = new CumulativePermission();
+
+ for (int i = 0; i < 32; i++) {
+ int permissionToCheck = 1 << i;
+
+ if ((mask & permissionToCheck) == permissionToCheck) {
+ Permission p = (Permission) locallyDeclaredPermissionsByInteger.get(new Integer(permissionToCheck));
+ Assert.state(p != null,
+ "Mask " + permissionToCheck + " does not have a corresponding static BasePermission");
+ permission.set(p);
+ }
+ }
+
+ return permission;
+ }
+
+ public static Permission[] buildFromMask(int[] masks) {
+ if ((masks == null) || (masks.length == 0)) {
+ return new Permission[] {};
+ }
+
+ List list = new Vector();
+
+ for (int i = 0; i < masks.length; i++) {
+ list.add(BasePermission.buildFromMask(masks[i]));
+ }
+
+ return (Permission[]) list.toArray(new Permission[] {});
+ }
+
+ public static Permission buildFromName(String name) {
+ Assert.isTrue(locallyDeclaredPermissionsByName.containsKey(name), "Unknown permission '" + name + "'");
+
+ return (Permission) locallyDeclaredPermissionsByName.get(name);
+ }
+
+ public static Permission[] buildFromName(String[] names) {
+ if ((names == null) || (names.length == 0)) {
+ return new Permission[] {};
+ }
+
+ List list = new Vector();
+
+ for (int i = 0; i < names.length; i++) {
+ list.add(BasePermission.buildFromName(names[i]));
+ }
+
+ return (Permission[]) list.toArray(new Permission[] {});
+ }
+
+ public boolean equals(Object arg0) {
+ if (!(arg0 instanceof BasePermission)) {
+ return false;
+ }
+
+ BasePermission rhs = (BasePermission) arg0;
+
+ return (this.mask == rhs.getMask());
+ }
+
+ public int getMask() {
+ return mask;
+ }
+
+ public String getPattern() {
+ return AclFormattingUtils.printBinary(mask, code);
+ }
+
+ public String toString() {
+ return "BasePermission[" + getPattern() + "=" + mask + "]";
+ }
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/ConsoleAuditLogger.java b/core/src/main/java/org/acegisecurity/acls/domain/ConsoleAuditLogger.java
similarity index 87%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/domain/ConsoleAuditLogger.java
rename to core/src/main/java/org/acegisecurity/acls/domain/ConsoleAuditLogger.java
index a0f2ff230f..da867b0bdf 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/ConsoleAuditLogger.java
+++ b/core/src/main/java/org/acegisecurity/acls/domain/ConsoleAuditLogger.java
@@ -1,46 +1,45 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.domain;
-
-import org.acegisecurity.acls.AccessControlEntry;
-import org.acegisecurity.acls.AuditableAccessControlEntry;
-
-import org.springframework.util.Assert;
-
-
-/**
- * DOCUMENT ME!
- *
- * @author $author$
- * @version $Revision$
- */
-public class ConsoleAuditLogger implements AuditLogger {
- //~ Methods ========================================================================================================
-
- public void logIfNeeded(boolean granted, AccessControlEntry ace) {
- Assert.notNull(ace, "AccessControlEntry required");
-
- if (ace instanceof AuditableAccessControlEntry) {
- AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace;
-
- if (granted && auditableAce.isAuditSuccess()) {
- System.out.println("GRANTED due to ACE: " + ace);
- } else if (!granted && auditableAce.isAuditFailure()) {
- System.out.println("DENIED due to ACE: " + ace);
- }
- }
- }
-}
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls.domain;
+
+import org.acegisecurity.acls.AccessControlEntry;
+import org.acegisecurity.acls.AuditableAccessControlEntry;
+
+import org.springframework.util.Assert;
+
+
+/**
+ * A bsaic implementation of {@link AuditLogger}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class ConsoleAuditLogger implements AuditLogger {
+ //~ Methods ========================================================================================================
+
+ public void logIfNeeded(boolean granted, AccessControlEntry ace) {
+ Assert.notNull(ace, "AccessControlEntry required");
+
+ if (ace instanceof AuditableAccessControlEntry) {
+ AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace;
+
+ if (granted && auditableAce.isAuditSuccess()) {
+ System.out.println("GRANTED due to ACE: " + ace);
+ } else if (!granted && auditableAce.isAuditFailure()) {
+ System.out.println("DENIED due to ACE: " + ace);
+ }
+ }
+ }
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/CumulativePermission.java b/core/src/main/java/org/acegisecurity/acls/domain/CumulativePermission.java
similarity index 96%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/domain/CumulativePermission.java
rename to core/src/main/java/org/acegisecurity/acls/domain/CumulativePermission.java
index 6bf953f855..33b2e5e70e 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/CumulativePermission.java
+++ b/core/src/main/java/org/acegisecurity/acls/domain/CumulativePermission.java
@@ -1,79 +1,78 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.domain;
-
-import org.acegisecurity.acls.AclFormattingUtils;
-import org.acegisecurity.acls.Permission;
-
-
-/**
- * Represents a Permission that is constructed at runtime from other permissions.this, in order to facilitate method chaining.Permission that is constructed at runtime from other permissions.this, in order to facilitate method chaining.LookupStrategy. This class does not support
- * subclassing, as it is likely to change in future releases and therefore subclassing is unsupported.LookupStrategy. This class does not support
+ * subclassing, as it is likely to change in future releases and therefore subclassing is unsupported.Map of AclImpl instances which contain
- * StubAclParents into proper, valid AclImpls with correct ACL parents.
- *
- * @param inputMap the unconverted AclImpls
- * @param currentIdentity the currentAcl that we wish to convert (this may be
- *
- * @return
- *
- * @throws IllegalStateException DOCUMENT ME!
- */
- private AclImpl convert(Map inputMap, Long currentIdentity) {
- Assert.notEmpty(inputMap, "InputMap required");
- Assert.notNull(currentIdentity, "CurrentIdentity required");
-
- // Retrieve this Acl from the InputMap
- Acl uncastAcl = (Acl) inputMap.get(currentIdentity);
- Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl");
-
- AclImpl inputAcl = (AclImpl) uncastAcl;
-
- Acl parent = inputAcl.getParentAcl();
-
- if ((parent != null) && parent instanceof StubAclParent) {
- // Lookup the parent
- StubAclParent stubAclParent = (StubAclParent) parent;
- parent = convert(inputMap, stubAclParent.getId());
- }
-
- // Now we have the parent (if there is one), create the true AclImpl
- AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), (Long) inputAcl.getId(), parent, auths, null,
- inputAcl.isEntriesInheriting(), inputAcl.getOwner());
-
- // Copy the "aces" from the input to the destination
- Field field = getAccessibleField(AclImpl.class, "aces");
-
- try {
- field.set(result, field.get(inputAcl));
- } catch (IllegalAccessException ex) {
- throw new IllegalStateException("Could not obtain or set AclImpl.ace field");
- }
-
- return result;
- }
-
- /**
- * Accepts the current ResultSet row, and converts it into an AclImpl that
- * contains a StubAclParent
- *
- * @param acls the Map we should add the converted Acl to
- * @param rs the ResultSet focused on a current row
- *
- * @throws SQLException if something goes wrong converting values
- * @throws IllegalStateException DOCUMENT ME!
- */
- private void convertCurrentResultIntoObject(Map acls, ResultSet rs)
- throws SQLException {
- Long id = new Long(rs.getLong("ACL_ID"));
-
- // If we already have an ACL for this ID, just create the ACE
- AclImpl acl = (AclImpl) acls.get(id);
-
- if (acl == null) {
- // Make an AclImpl and pop it into the Map
- ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("CLASS"),
- new Long(rs.getLong("OBJECT_ID_IDENTITY")));
-
- Acl parentAcl = null;
- long parentAclId = rs.getLong("PARENT_OBJECT");
-
- if (parentAclId != 0) {
- parentAcl = new StubAclParent(new Long(parentAclId));
- }
-
- boolean entriesInheriting = rs.getBoolean("ENTRIES_INHERITING");
- Sid owner;
-
- if (rs.getBoolean("ACL_PRINCIPAL")) {
- owner = new PrincipalSid(rs.getString("ACL_SID"));
- } else {
- owner = new GrantedAuthoritySid(rs.getString("ACL_SID"));
- }
-
- acl = new AclImpl(objectIdentity, id, parentAcl, auths, null, entriesInheriting, owner);
- acls.put(id, acl);
- }
-
- // Add an extra ACE to the ACL (ORDER BY maintains the ACE list order)
- Long aceId = new Long(rs.getLong("ACE_ID"));
- Sid recipient;
-
- if (rs.getBoolean("ACE_PRINCIPAL")) {
- recipient = new PrincipalSid(rs.getString("ACE_SID"));
- } else {
- recipient = new GrantedAuthoritySid(rs.getString("ACE_SID"));
- }
-
- Permission permission = BasePermission.buildFromMask(rs.getInt("MASK"));
- boolean granting = rs.getBoolean("GRANTING");
- boolean auditSuccess = rs.getBoolean("AUDIT_SUCCESS");
- boolean auditFailure = rs.getBoolean("AUDIT_FAILURE");
-
- AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting,
- auditSuccess, auditFailure);
-
- Field acesField = getAccessibleField(AclImpl.class, "aces");
- List aces;
-
- try {
- aces = (List) acesField.get(acl);
- } catch (IllegalAccessException ex) {
- throw new IllegalStateException("Could not obtain AclImpl.ace field: cause[" + ex.getMessage() + "]");
-
- }
-
- // Add the ACE if it doesn't already exist in the ACL.aces field
- if (!aces.contains(ace)) {
- aces.add(ace);
- }
- }
-
- private static Field getAccessibleField(Class clazz, String protectedField) {
- Field field = null;
-
- try {
- field = clazz.getDeclaredField(protectedField);
- } catch (NoSuchFieldException nsf) {}
-
- if (field == null) {
- // Unable to locate, so try the superclass (if there is one)
- if (clazz.getSuperclass() != null) {
- field = getAccessibleField(clazz.getSuperclass(), protectedField);
- } else {
- throw new IllegalArgumentException("Couldn't find '" + protectedField + "' field");
- }
- }
-
- // We have a field, so process
- field.setAccessible(true);
-
- return field;
- }
-
- /**
- * Looks up a batch of ObjectIdentitys directly from the database.Acls, including properly-configured
- * parent ACLs.Map of AclImpl instances which contain
+ * StubAclParents into proper, valid AclImpls with correct ACL parents.
+ *
+ * @param inputMap the unconverted AclImpls
+ * @param currentIdentity the currentAcl that we wish to convert (this may be
+ *
+ * @return
+ *
+ * @throws IllegalStateException DOCUMENT ME!
+ */
+ private AclImpl convert(Map inputMap, Long currentIdentity) {
+ Assert.notEmpty(inputMap, "InputMap required");
+ Assert.notNull(currentIdentity, "CurrentIdentity required");
+
+ // Retrieve this Acl from the InputMap
+ Acl uncastAcl = (Acl) inputMap.get(currentIdentity);
+ Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl");
+
+ AclImpl inputAcl = (AclImpl) uncastAcl;
+
+ Acl parent = inputAcl.getParentAcl();
+
+ if ((parent != null) && parent instanceof StubAclParent) {
+ // Lookup the parent
+ StubAclParent stubAclParent = (StubAclParent) parent;
+ parent = convert(inputMap, stubAclParent.getId());
+ }
+
+ // Now we have the parent (if there is one), create the true AclImpl
+ AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), (Long) inputAcl.getId(), aclAuthorizationStrategy,
+ auditLogger, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
+
+ // Copy the "aces" from the input to the destination
+ Field field = FieldUtils.getField(AclImpl.class, "aces");
+
+ try {
+ field.setAccessible(true);
+ field.set(result, field.get(inputAcl));
+ } catch (IllegalAccessException ex) {
+ throw new IllegalStateException("Could not obtain or set AclImpl.ace field");
+ }
+
+ return result;
+ }
+
+ /**
+ * Accepts the current ResultSet row, and converts it into an AclImpl that
+ * contains a StubAclParent
+ *
+ * @param acls the Map we should add the converted Acl to
+ * @param rs the ResultSet focused on a current row
+ *
+ * @throws SQLException if something goes wrong converting values
+ * @throws IllegalStateException DOCUMENT ME!
+ */
+ private void convertCurrentResultIntoObject(Map acls, ResultSet rs)
+ throws SQLException {
+ Long id = new Long(rs.getLong("ACL_ID"));
+
+ // If we already have an ACL for this ID, just create the ACE
+ AclImpl acl = (AclImpl) acls.get(id);
+
+ if (acl == null) {
+ // Make an AclImpl and pop it into the Map
+ ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("CLASS"),
+ new Long(rs.getLong("OBJECT_ID_IDENTITY")));
+
+ Acl parentAcl = null;
+ long parentAclId = rs.getLong("PARENT_OBJECT");
+
+ if (parentAclId != 0) {
+ parentAcl = new StubAclParent(new Long(parentAclId));
+ }
+
+ boolean entriesInheriting = rs.getBoolean("ENTRIES_INHERITING");
+ Sid owner;
+
+ if (rs.getBoolean("ACL_PRINCIPAL")) {
+ owner = new PrincipalSid(rs.getString("ACL_SID"));
+ } else {
+ owner = new GrantedAuthoritySid(rs.getString("ACL_SID"));
+ }
+
+ acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, auditLogger, parentAcl, null,
+ entriesInheriting, owner);
+ acls.put(id, acl);
+ }
+
+ // Add an extra ACE to the ACL (ORDER BY maintains the ACE list order)
+ // It is permissable to have no ACEs in an ACL (which is detected by a null ACE_SID)
+ if (rs.getString("ACE_SID") != null) {
+ Long aceId = new Long(rs.getLong("ACE_ID"));
+ Sid recipient;
+
+ if (rs.getBoolean("ACE_PRINCIPAL")) {
+ recipient = new PrincipalSid(rs.getString("ACE_SID"));
+ } else {
+ recipient = new GrantedAuthoritySid(rs.getString("ACE_SID"));
+ }
+
+ Permission permission = BasePermission.buildFromMask(rs.getInt("MASK"));
+ boolean granting = rs.getBoolean("GRANTING");
+ boolean auditSuccess = rs.getBoolean("AUDIT_SUCCESS");
+ boolean auditFailure = rs.getBoolean("AUDIT_FAILURE");
+
+ AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting,
+ auditSuccess, auditFailure);
+
+ Field acesField = FieldUtils.getField(AclImpl.class, "aces");
+ List aces;
+
+ try {
+ acesField.setAccessible(true);
+ aces = (List) acesField.get(acl);
+ } catch (IllegalAccessException ex) {
+ throw new IllegalStateException("Could not obtain AclImpl.ace field: cause[" + ex.getMessage() + "]");
+ }
+
+ // Add the ACE if it doesn't already exist in the ACL.aces field
+ if (!aces.contains(ace)) {
+ aces.add(ace);
+ }
+ }
+ }
+
+ /**
+ * Looks up a batch of ObjectIdentitys directly from the database.Acls, including properly-configured
+ * parent ACLs.AclService.null - implementations may elect not
- * to provide SID optimisations)
- *
- * @return the Map pursuant to the interface contract for {@link
- * org.acegisecurity.acls.AclService#readAclsById(ObjectIdentity[], Sid[])}
- */
- public Map readAclsById(ObjectIdentity[] objects, Sid[] sids);
-}
+ */
+public interface LookupStrategy {
+ //~ Methods ========================================================================================================
+
+ /**
+ * Perform database-specific optimized lookup.
+ *
+ * @param objects the identities to lookup (required)
+ * @param sids the SIDs for which identities are required (may be null - implementations may elect not
+ * to provide SID optimisations)
+ *
+ * @return the Map pursuant to the interface contract for {@link
+ * org.acegisecurity.acls.AclService#readAclsById(ObjectIdentity[], Sid[])}
+ */
+ public Map readAclsById(ObjectIdentity[] objects, Sid[] sids);
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/jdbc/package.html b/core/src/main/java/org/acegisecurity/acls/jdbc/package.html
new file mode 100644
index 0000000000..adbee4c539
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/jdbc/package.html
@@ -0,0 +1,5 @@
+
+
+JDBC-based persistence of ACL information.
+
+
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentity.java b/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentity.java
similarity index 97%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentity.java
rename to core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentity.java
index b92cd44565..c8b347693f 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentity.java
+++ b/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentity.java
@@ -1,23 +1,22 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.objectidentity;
-
-import java.io.Serializable;
-
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls.objectidentity;
+
+import java.io.Serializable;
+
+
/**
* Interface representing the identity of an individual domain object instance.
*
@@ -32,40 +31,40 @@ import java.io.Serializable;
*
* @author Ben Alex
* @version $Id$
- */
-public interface ObjectIdentity extends Serializable {
- //~ Methods ========================================================================================================
-
- /**
- * Refer to the java.lang.Object documentation for the interface contract.
- *
- * @param obj to be compared
- *
- * @return true if the objects are equal, false otherwise
- */
- public boolean equals(Object obj);
-
- /**
- * Obtains the actual identifier. This identifier must not be reused to represent other domain objects with
- * the same javaType.javaType
- */
- public Serializable getIdentifier();
-
- /**
- * Obtains the Java type represented by the domain object.
- *
- * @return the Java type of the domain object
- */
- public Class getJavaType();
-
- /**
- * Refer to the java.lang.Object documentation for the interface contract.
- *
- * @return a hash code representation of this object
- */
- public int hashCode();
-}
+ */
+public interface ObjectIdentity extends Serializable {
+ //~ Methods ========================================================================================================
+
+ /**
+ * Refer to the java.lang.Object documentation for the interface contract.
+ *
+ * @param obj to be compared
+ *
+ * @return true if the objects are equal, false otherwise
+ */
+ public boolean equals(Object obj);
+
+ /**
+ * Obtains the actual identifier. This identifier must not be reused to represent other domain objects with
+ * the same javaType.javaType
+ */
+ public Serializable getIdentifier();
+
+ /**
+ * Obtains the Java type represented by the domain object.
+ *
+ * @return the Java type of the domain object
+ */
+ public Class getJavaType();
+
+ /**
+ * Refer to the java.lang.Object documentation for the interface contract.
+ *
+ * @return a hash code representation of this object
+ */
+ public int hashCode();
+}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityImpl.java b/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityImpl.java
similarity index 94%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityImpl.java
rename to core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityImpl.java
index 816cbbf473..fe3a309a24 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityImpl.java
+++ b/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityImpl.java
@@ -1,146 +1,147 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.objectidentity;
-
-import org.acegisecurity.acl.basic.AclObjectIdentity;
-
-import org.acegisecurity.acls.IdentityUnavailableException;
-
-import org.springframework.util.Assert;
-import org.springframework.util.ReflectionUtils;
-
-import java.io.Serializable;
-
-import java.lang.reflect.Method;
-
-
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.acls.objectidentity;
+
+import org.acegisecurity.acl.basic.AclObjectIdentity;
+
+import org.acegisecurity.acls.IdentityUnavailableException;
+
+import org.springframework.util.Assert;
+import org.springframework.util.ReflectionUtils;
+
+import java.io.Serializable;
+
+import java.lang.reflect.Method;
+
+
+/**
+ * Simple implementation of {@link AclObjectIdentity}.Strings to store the identity of the
+ * domain object instance. Also offers a constructor that uses reflection to build the identity information.Strings to store the identity of the
- * domain object instance. Also offers a constructor that uses reflection to build the identity information.NamedEntityObjectIdentity based on the passed
+ * Creates the ObjectIdentityImpl based on the passed
* object instance. The passed object must provide a getId()
- * method, otherwise an exception will be thrown.
+ * method, otherwise an exception will be thrown. The object passed will
+ * be considered the {@link #javaType}, so if more control is required,
+ * an alternate constructor should be used instead.
*
* @param object the domain object instance to create an identity for
*
* @throws IdentityUnavailableException if identity could not be extracted
- */
- public ObjectIdentityImpl(Object object) throws IdentityUnavailableException {
- Assert.notNull(object, "object cannot be null");
-
- this.javaType = object.getClass();
-
- Object result;
-
- try {
- Method method = this.javaType.getMethod("getId", new Class[] {});
- result = method.invoke(object, new Object[] {});
- } catch (Exception e) {
- throw new IdentityUnavailableException("Could not extract identity from object " + object, e);
- }
-
- Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable");
- this.identifier = (Serializable) result;
- }
-
- //~ Methods ========================================================================================================
-
- /**
- * Important so caching operates properly.classname and id properties.true if the presented object matches this object
- */
- public boolean equals(Object arg0) {
- if (arg0 == null) {
- return false;
- }
-
- if (!(arg0 instanceof ObjectIdentityImpl)) {
- return false;
- }
-
- ObjectIdentityImpl other = (ObjectIdentityImpl) arg0;
-
- if (this.getIdentifier().equals(other.getIdentifier()) && this.getJavaType().equals(other.getJavaType())) {
- return true;
- }
-
- return false;
- }
-
- public Serializable getIdentifier() {
- return identifier;
- }
-
- public Class getJavaType() {
- return javaType;
- }
-
- /**
- * Important so caching operates properly.
- *
- * @return the hash
- */
- public int hashCode() {
- int code = 31;
- code ^= this.javaType.hashCode();
- code ^= this.identifier.hashCode();
-
- return code;
- }
-
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append(this.getClass().getName()).append("[");
- sb.append("Java Type: ").append(this.javaType);
- sb.append("; Identifier: ").append(this.identifier).append("]");
-
- return sb.toString();
- }
-}
+ */
+ public ObjectIdentityImpl(Object object) throws IdentityUnavailableException {
+ Assert.notNull(object, "object cannot be null");
+
+ this.javaType = object.getClass();
+
+ Object result;
+
+ try {
+ Method method = this.javaType.getMethod("getId", new Class[] {});
+ result = method.invoke(object, new Object[] {});
+ } catch (Exception e) {
+ throw new IdentityUnavailableException("Could not extract identity from object " + object, e);
+ }
+
+ Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable");
+ this.identifier = (Serializable) result;
+ }
+
+ //~ Methods ========================================================================================================
+
+ /**
+ * Important so caching operates properly.classname and id properties.true if the presented object matches this object
+ */
+ public boolean equals(Object arg0) {
+ if (arg0 == null) {
+ return false;
+ }
+
+ if (!(arg0 instanceof ObjectIdentityImpl)) {
+ return false;
+ }
+
+ ObjectIdentityImpl other = (ObjectIdentityImpl) arg0;
+
+ if (this.getIdentifier().equals(other.getIdentifier()) && this.getJavaType().equals(other.getJavaType())) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public Serializable getIdentifier() {
+ return identifier;
+ }
+
+ public Class getJavaType() {
+ return javaType;
+ }
+
+ /**
+ * Important so caching operates properly.
+ *
+ * @return the hash
+ */
+ public int hashCode() {
+ int code = 31;
+ code ^= this.javaType.hashCode();
+ code ^= this.identifier.hashCode();
+
+ return code;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.getClass().getName()).append("[");
+ sb.append("Java Type: ").append(this.javaType);
+ sb.append("; Identifier: ").append(this.identifier).append("]");
+
+ return sb.toString();
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrievalStrategy.java b/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrievalStrategy.java
new file mode 100644
index 0000000000..7687ab21b1
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrievalStrategy.java
@@ -0,0 +1,30 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acegisecurity.acls.objectidentity;
+
+/**
+ * Strategy interface that provides the ability to determine which {@link ObjectIdentity}
+ * will be returned for a particular domain object
+ *
+ * @author Ben Alex
+ * @version $Id$
+ *
+ */
+public interface ObjectIdentityRetrievalStrategy {
+ //~ Methods ========================================================================================================
+
+ public ObjectIdentity getObjectIdentity(Object domainObject);
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrievalStrategyImpl.java b/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrievalStrategyImpl.java
new file mode 100644
index 0000000000..436e535192
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/objectidentity/ObjectIdentityRetrievalStrategyImpl.java
@@ -0,0 +1,31 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acegisecurity.acls.objectidentity;
+
+/**
+ * Basic implementation of {@link ObjectIdentityRetrievalStrategy} that uses the constructor of {@link
+ * ObjectIdentityImpl} to create the {@link ObjectIdentity}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class ObjectIdentityRetrievalStrategyImpl implements ObjectIdentityRetrievalStrategy {
+ //~ Methods ========================================================================================================
+
+ public ObjectIdentity getObjectIdentity(Object domainObject) {
+ return new ObjectIdentityImpl(domainObject);
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/objectidentity/package.html b/core/src/main/java/org/acegisecurity/acls/objectidentity/package.html
new file mode 100644
index 0000000000..8e08176b32
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/objectidentity/package.html
@@ -0,0 +1,5 @@
+
+
+Provides indirection between ACL packages and domain objects.
+
+
diff --git a/core/src/main/java/org/acegisecurity/acls/package.html b/core/src/main/java/org/acegisecurity/acls/package.html
new file mode 100644
index 0000000000..e738e3cb94
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/package.html
@@ -0,0 +1,5 @@
+
+
+Interfaces and shared classes to manage access control lists (ACLs) for domain object instances.
+
+
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/sid/GrantedAuthoritySid.java b/core/src/main/java/org/acegisecurity/acls/sid/GrantedAuthoritySid.java
similarity index 97%
rename from sandbox/other/src/main/java/org/acegisecurity/acls/sid/GrantedAuthoritySid.java
rename to core/src/main/java/org/acegisecurity/acls/sid/GrantedAuthoritySid.java
index b298f93f2a..4572805d58 100644
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/sid/GrantedAuthoritySid.java
+++ b/core/src/main/java/org/acegisecurity/acls/sid/GrantedAuthoritySid.java
@@ -1,68 +1,67 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.sid;
-
-import org.acegisecurity.GrantedAuthority;
-
-import org.springframework.util.Assert;
-
-
-/**
- * Represents a GrantedAuthority as a Sid.String-based principal for Sid comparison. More complex principal objects may
- * wish to provide an alternative Sid implementation that uses some other identifier.GrantedAuthority as a Sid.String-based principal for Sid comparison. More complex principal objects may
+ * wish to provide an alternative Sid implementation that uses some other identifier.Authentication.getPrincipal() as a Sid.String-based principal for Sid comparison. More complex principal
- * objects may wish to provide an alternative Sid implementation that uses some other identifier.Authentication.getPrincipal() as a Sid.String-based principal for Sid comparison. More complex principal
+ * objects may wish to provide an alternative Sid implementation that uses some other identifier.java.lang.Object documentation for the interface contract.
- *
- * @param obj to be compared
- *
- * @return true if the objects are equal, false otherwise
- */
- public boolean equals(Object obj);
-
- /**
- * Refer to the java.lang.Object documentation for the interface contract.
- *
- * @return a hash code representation of this object
- */
- public int hashCode();
-}
+ */
+public interface Sid {
+ //~ Methods ========================================================================================================
+
+ /**
+ * Refer to the java.lang.Object documentation for the interface contract.
+ *
+ * @param obj to be compared
+ *
+ * @return true if the objects are equal, false otherwise
+ */
+ public boolean equals(Object obj);
+
+ /**
+ * Refer to the java.lang.Object documentation for the interface contract.
+ *
+ * @return a hash code representation of this object
+ */
+ public int hashCode();
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/sid/SidRetrievalStrategy.java b/core/src/main/java/org/acegisecurity/acls/sid/SidRetrievalStrategy.java
new file mode 100644
index 0000000000..209bae7209
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/sid/SidRetrievalStrategy.java
@@ -0,0 +1,32 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acegisecurity.acls.sid;
+
+import org.acegisecurity.Authentication;
+
+
+/**
+ * Strategy interface that provides an ability to determine the {@link Sid} instances applicable
+ * for an {@link Authentication}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public interface SidRetrievalStrategy {
+ //~ Methods ========================================================================================================
+
+ public Sid[] getSids(Authentication authentication);
+}
diff --git a/core/src/main/java/org/acegisecurity/acls/sid/SidRetrievalStrategyImpl.java b/core/src/main/java/org/acegisecurity/acls/sid/SidRetrievalStrategyImpl.java
new file mode 100644
index 0000000000..7fe5a8b9c6
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/acls/sid/SidRetrievalStrategyImpl.java
@@ -0,0 +1,48 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acegisecurity.acls.sid;
+
+import org.acegisecurity.Authentication;
+import org.acegisecurity.GrantedAuthority;
+
+import java.util.List;
+import java.util.Vector;
+
+
+/**
+ * Basic implementation of {@link SidRetrievalStrategy} that creates a {@link Sid} for the principal, as well as
+ * every granted authority the principal holds.true
+ */
+ public boolean supports(Class clazz) {
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java b/core/src/main/java/org/acegisecurity/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java
new file mode 100644
index 0000000000..22312fe534
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java
@@ -0,0 +1,133 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acegisecurity.afterinvocation;
+
+import org.acegisecurity.AccessDeniedException;
+import org.acegisecurity.Authentication;
+import org.acegisecurity.AuthorizationServiceException;
+import org.acegisecurity.ConfigAttribute;
+import org.acegisecurity.ConfigAttributeDefinition;
+
+import org.acegisecurity.acls.Acl;
+import org.acegisecurity.acls.AclService;
+import org.acegisecurity.acls.Permission;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+
+/**
+ * Collection of domain object instances returned from a secure object invocation, remove
+ * any Collection elements the principal does not have appropriate permission to access as defined by the
+ * {@link AclService}.AclService is used to retrieve the access control list (ACL) permissions associated with
+ * each Collection domain object instance element for the current Authentication object.AclService and ensure the
+ * principal is {@link Acl#isGranted(org.acegisecurity.acls.Permission[], org.acegisecurity.acls.sid.Sid[], boolean)}
+ * when presenting the {@link #requirePermission} array to that method.Collection.BasicAclEntryAfterInvocationProvider with a {@link
+ * #processConfigAttribute} of AFTER_ACL_COLLECTION_READ and a {@link #requirePermission} of
+ * BasePermission.READ. These are also the defaults.returnObject is null, a nullCollection
+ * will be returned. If the provided returnObject is not a Collection, an {@link
+ * AuthorizationServiceException} will be thrown.AclService is used to retrieve the access control list (ACL) permissions associated with a
+ * domain object instance for the current Authentication object.AclService and ensure the
+ * principal is {@link Acl#isGranted(org.acegisecurity.acls.Permission[], org.acegisecurity.acls.sid.Sid[], boolean)}
+ * when presenting the {@link #requirePermission} array to that method.AclEntryAfterInvocationProvider with a {@link
+ * #processConfigAttribute} of AFTER_ACL_READ and a {@link #requirePermission} of
+ * BasePermission.READ. These are also the defaults.AccessDeniedException will be thrown.returnObject is null, permission will always be granted and
+ * null will be returned.hasPermission attribute. Those permissions are then converted into {@link Permission} instances. These
+ * instances are then presented as an array to the {@link Acl#isGranted(Permission[],
+ * org.acegisecurity.acls.sid.Sid[], boolean)} method. The {@link Sid} presented is determined by the {@link
+ * SidRetrievalStrategy}.WebApplicationContextUtils and locate an {@link AclService} and {@link SidRetrievalStrategy}.
+ * Application contexts must provide one and only one of these Java types.ServletContext can be accessed as required by Spring's
+ * WebApplicationContextUtils
+ *
+ * @return the Spring application context (never null)
+ */
+ protected ApplicationContext getContext(PageContext pageContext) {
+ ServletContext servletContext = pageContext.getServletContext();
+
+ return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
+ }
+
+ public Object getDomainObject() {
+ return domainObject;
+ }
+
+ public String getHasPermission() {
+ return hasPermission;
+ }
+
+ private void initializeIfRequired() throws JspException {
+ if (applicationContext == null) {
+ this.applicationContext = getContext(pageContext);
+
+ Map map = applicationContext.getBeansOfType(AclService.class);
+
+ if (map.size() != 1) {
+ throw new JspException(
+ "Found incorrect number of AclService instances in application context - you must have only have one!");
+ }
+
+ aclService = (AclService) map.values().iterator().next();
+
+ map = applicationContext.getBeansOfType(SidRetrievalStrategy.class);
+
+ if (map.size() == 0) {
+ sidRetrievalStrategy = new SidRetrievalStrategyImpl();
+ } else if (map.size() == 1) {
+ sidRetrievalStrategy = (SidRetrievalStrategy) map.values().iterator().next();
+ } else {
+ throw new JspException(
+ "Found incorrect number of SidRetrievalStrategy instances in application context - you must have only have one!");
+ }
+
+ map = applicationContext.getBeansOfType(ObjectIdentityRetrievalStrategy.class);
+
+ if (map.size() == 0) {
+ objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
+ } else if (map.size() == 1) {
+ objectIdentityRetrievalStrategy = (ObjectIdentityRetrievalStrategy) map.values().iterator().next();
+ } else {
+ throw new JspException(
+ "Found incorrect number of ObjectIdentityRetrievalStrategy instances in application context - you must have only have one!");
+ }
+ }
+ }
+
+ private Permission[] parsePermissionsString(String integersString)
+ throws NumberFormatException {
+ final Set permissions = new HashSet();
+ final StringTokenizer tokenizer;
+ tokenizer = new StringTokenizer(integersString, ",", false);
+
+ while (tokenizer.hasMoreTokens()) {
+ String integer = tokenizer.nextToken();
+ permissions.add(BasePermission.buildFromMask(new Integer(integer).intValue()));
+ }
+
+ return (Permission[]) permissions.toArray(new Permission[] {});
+ }
+
+ public void setDomainObject(Object domainObject) {
+ this.domainObject = domainObject;
+ }
+
+ public void setHasPermission(String hasPermission) {
+ this.hasPermission = hasPermission;
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/vote/AbstractAclVoter.java b/core/src/main/java/org/acegisecurity/vote/AbstractAclVoter.java
index ba0fd58451..3819df738e 100644
--- a/core/src/main/java/org/acegisecurity/vote/AbstractAclVoter.java
+++ b/core/src/main/java/org/acegisecurity/vote/AbstractAclVoter.java
@@ -12,13 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.acegisecurity.vote;
import org.acegisecurity.AuthorizationServiceException;
-import org.acegisecurity.acl.AclManager;
-
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.JoinPoint;
@@ -28,8 +25,7 @@ import org.springframework.util.Assert;
/**
- * AclService is used to retrieve the access control list (ACL) permissions associated with a
+ * domain object instance for the current Authentication object.AclManager and ensure the principal is {@link Acl#isGranted(org.acegisecurity.acls.Permission[],
+ * org.acegisecurity.acls.sid.Sid[], boolean)} when presenting the {@link #requirePermission} array to that method.null, the voter will abstain from voting. If the method argument
+ * could not be found, an {@link org.acegisecurity.AuthorizationServiceException} will be thrown.AclEntryVoters. Each will have a
+ * different {@link #processDomainObjectClass}, {@link #processConfigAttribute} and {@link #requirePermission}
+ * combination. For example, a small application might employ the following instances of AclEntryVoter:
+ *
+ *
+ * Alternatively, you could have used a common superclass or interface for the {@link #processDomainObjectClass}
+ * if both BankAccount, configuration attribute
+ * VOTE_ACL_BANK_ACCONT_READ, require permission BasePermission.READBankAccount, configuration attribute
+ * VOTE_ACL_BANK_ACCOUNT_WRITE, require permission list BasePermission.WRITE and
+ * BasePermission.CREATE (allowing the principal to have either of these two permissionsCustomer, configuration attribute
+ * VOTE_ACL_CUSTOMER_READ, require permission BasePermission.READCustomer, configuration attribute
+ * VOTE_ACL_CUSTOMER_WRITE, require permission list BasePermission.WRITE and
+ * BasePermission.CREATEBankAccount and Customer had common parents.
If the principal does not have sufficient permissions, the voter will vote to deny access.
+ *All comparisons and prefixes are case sensitive.
+ * + * @author Ben Alex + * @version $Id$ + */ +public class AclEntryVoter extends AbstractAclVoter { + //~ Static fields/initializers ===================================================================================== + + private static final Log logger = LogFactory.getLog(AclEntryVoter.class); + + //~ Instance fields ================================================================================================ + + private AclService aclService; + private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + private String internalMethod; + private String processConfigAttribute; + private Permission[] requirePermission; + + //~ Constructors =================================================================================================== + + public AclEntryVoter(AclService aclService, String processConfigAttribute, Permission[] requirePermission) { + Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); + Assert.notNull(aclService, "An AclService is mandatory"); + + if ((requirePermission == null) || (requirePermission.length == 0)) { + throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); + } + + this.aclService = aclService; + this.processConfigAttribute = processConfigAttribute; + this.requirePermission = requirePermission; + } + + //~ Methods ======================================================================================================== + + /** + * Optionally specifies a method of the domain object that will be used to obtain a contained domain + * object. That contained domain object will be used for the ACL evaluation. This is useful if a domain object + * contains a parent that an ACL evaluation should be targeted for, instead of the child domain object (which + * perhaps is being created and as such does not yet have any ACL permissions) + * + * @returnnull to use the domain object, or the name of a method (that requires no arguments) that
+ * should be invoked to obtain an Object which will be the domain object used for ACL
+ * evaluation
+ */
+ public String getInternalMethod() {
+ return internalMethod;
+ }
+
+ public String getProcessConfigAttribute() {
+ return processConfigAttribute;
+ }
+
+ public void setInternalMethod(String internalMethod) {
+ this.internalMethod = internalMethod;
+ }
+
+ public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
+ Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required");
+ this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
+ }
+
+ public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
+ Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
+ this.sidRetrievalStrategy = sidRetrievalStrategy;
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getProcessConfigAttribute())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
+ Iterator iter = config.getConfigAttributes();
+
+ while (iter.hasNext()) {
+ ConfigAttribute attr = (ConfigAttribute) iter.next();
+
+ if (this.supports(attr)) {
+ // Need to make an access decision on this invocation
+ // Attempt to locate the domain object instance to process
+ Object domainObject = getDomainObjectInstance(object);
+
+ // If domain object is null, vote to abstain
+ if (domainObject == null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Voting to abstain - domainObject is null");
+ }
+
+ return AccessDecisionVoter.ACCESS_ABSTAIN;
+ }
+
+ // Evaluate if we are required to use an inner domain object
+ if ((internalMethod != null) && !"".equals(internalMethod)) {
+ try {
+ Class clazz = domainObject.getClass();
+ Method method = clazz.getMethod(internalMethod, new Class[] {});
+ domainObject = method.invoke(domainObject, new Object[] {});
+ } catch (NoSuchMethodException nsme) {
+ throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
+ + "' does not provide the requested internalMethod: " + internalMethod);
+ } catch (IllegalAccessException iae) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("IllegalAccessException", iae);
+
+ if (iae.getCause() != null) {
+ logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause());
+ }
+ }
+
+ throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ + " for object: " + domainObject);
+ } catch (InvocationTargetException ite) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("InvocationTargetException", ite);
+
+ if (ite.getCause() != null) {
+ logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause());
+ }
+ }
+
+ throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
+ + " for object: " + domainObject);
+ }
+ }
+
+ // Obtain the OID applicable to the domain object
+ ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
+
+ // Obtain the SIDs applicable to the principal
+ Sid[] sids = sidRetrievalStrategy.getSids(authentication);
+
+ Acl acl;
+
+ try {
+ // Lookup only ACLs for SIDs we're interested in
+ acl = aclService.readAclById(objectIdentity, sids);
+ } catch (NotFoundException nfe) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Voting to deny access - no ACLs apply for this principal");
+ }
+
+ return AccessDecisionVoter.ACCESS_DENIED;
+ }
+
+ try {
+ if (acl.isGranted(requirePermission, sids, false)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Voting to grant access");
+ }
+
+ return AccessDecisionVoter.ACCESS_GRANTED;
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "Voting to deny access - ACLs returned, but insufficient permissions for this principal");
+ }
+
+ return AccessDecisionVoter.ACCESS_DENIED;
+ }
+ } catch (NotFoundException nfe) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Voting to deny access - no ACLs apply for this principal");
+ }
+
+ return AccessDecisionVoter.ACCESS_DENIED;
+ }
+ }
+ }
+
+ // No configuration attribute matched, so abstain
+ return AccessDecisionVoter.ACCESS_ABSTAIN;
+ }
+}
diff --git a/core/src/main/resources/org/acegisecurity/taglibs/authz.tld b/core/src/main/resources/org/acegisecurity/taglibs/authz.tld
index b87b169650..ca44f27dac 100644
--- a/core/src/main/resources/org/acegisecurity/taglibs/authz.tld
+++ b/core/src/main/resources/org/acegisecurity/taglibs/authz.tld
@@ -113,4 +113,34 @@
+
- <%
- SimpleAclEntry simpleAcl = ((SimpleAclEntry) pageContext.getAttribute("acl"));
- String permissionBlock = simpleAcl.printPermissionsBlock();
- %>
- <%= permissionBlock %>
- [
|
-
- |
-
+
+
">Manage diff --git a/samples/contacts/src/main/webapp/common/WEB-INF/jsp/index.jsp b/samples/contacts/src/main/webapp/common/WEB-INF/jsp/index.jsp index 024bef7e72..98756513e5 100644 --- a/samples/contacts/src/main/webapp/common/WEB-INF/jsp/index.jsp +++ b/samples/contacts/src/main/webapp/common/WEB-INF/jsp/index.jsp @@ -18,12 +18,12 @@
ContactManager bean and
- * convenience test support methods.
- *
- * @author David Leal
- * @author Ben Alex
- */
-public abstract class AbstractContactsSampleTest extends AbstractTransactionalSpringContextTests {
-
- protected ContactManager contactManager;
-
- protected String[] getConfigLocations() {
- setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
- return new String[] { "applicationContext-common-authorization.xml",
- "applicationContext-common-business.xml",
- "applicationContext-contacts-test.xml" };
- }
-
- /**
- * Locates the first Contact of the exact name specified.
- *
- * - * Uses the {@link ContactManager#getAll()} method. - *
- * - * @param id - * Identify of the contact to locate (must be an exact match) - * - * @return the domain ornull if not found
- */
- protected Contact getContact(String id) {
- List contacts = contactManager.getAll();
- Iterator iter = contacts.iterator();
-
- while (iter.hasNext()) {
- Contact contact = (Contact) iter.next();
-
- if (contact.getId().equals(id)) {
- return contact;
- }
- }
-
- return null;
- }
-
- protected void assertContainsContact(String id, List contacts) {
- Iterator iter = contacts.iterator();
- System.out.println(contacts);
- while (iter.hasNext()) {
- Contact contact = (Contact) iter.next();
-
- if (contact.getId().toString().equals(id)) {
- return;
- }
- }
-
- fail("List of contacts should have contained: " + id);
- }
-
- protected void assertNotContainsContact(String id, List contacts) {
- Iterator iter = contacts.iterator();
-
- while (iter.hasNext()) {
- Contact domain = (Contact) iter.next();
-
- if (domain.getId().toString().equals(id)) {
- fail("List of contact should NOT (but did) contain: " + id);
- }
- }
- }
-
- protected void makeActiveUser(String username) {
- String password = "";
-
- if ("marissa".equals(username)) {
- password = "koala";
- } else if ("dianne".equals(username)) {
- password = "emu";
- } else if ("scott".equals(username)) {
- password = "wombat";
- } else if ("peter".equals(username)) {
- password = "opal";
- }
-
- Authentication authRequest = new UsernamePasswordAuthenticationToken(
- username, password);
- SecurityContextImpl secureContext = new SecurityContextImpl();
- secureContext.setAuthentication(authRequest);
- SecurityContextHolder.setContext(secureContext);
- }
-
- protected void onTearDownInTransaction() {
- destroySecureContext();
- }
-
- private static void destroySecureContext() {
- SecurityContextHolder.setContext(new SecurityContextImpl());
- }
-
- public void setContactManager(ContactManager contactManager) {
- this.contactManager = contactManager;
- }
-}
diff --git a/samples/contacts/src/test/java/sample/contact/GetAllContactsTests.java b/samples/contacts/src/test/java/sample/contact/GetAllContactsTests.java
index f4f5062b94..462a4c536d 100644
--- a/samples/contacts/src/test/java/sample/contact/GetAllContactsTests.java
+++ b/samples/contacts/src/test/java/sample/contact/GetAllContactsTests.java
@@ -12,68 +12,174 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package sample.contact;
+import org.acegisecurity.Authentication;
+
+import org.acegisecurity.acls.domain.BasePermission;
+import org.acegisecurity.acls.sid.PrincipalSid;
+
+import org.acegisecurity.context.SecurityContextHolder;
+
+import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+
+import org.springframework.test.AbstractTransactionalSpringContextTests;
+
+import java.util.Iterator;
import java.util.List;
/**
- * Tests {@link
- * com.acegitech.dns.domain.DomainManager#findAllDomainsLike(String)}.
+ * Tests {@link ContactManager}.
*
* @author David Leal
+ * @author Ben Alex
*/
-public class GetAllContactsTests extends AbstractContactsSampleTest {
- //~ Methods ================================================================
+public class GetAllContactsTests extends AbstractTransactionalSpringContextTests {
+ //~ Instance fields ================================================================================================
- public void testFindAllDomainsLikeAsDianne() {
+ protected ContactManager contactManager;
+
+ //~ Methods ========================================================================================================
+
+ protected void assertContainsContact(String id, List contacts) {
+ Iterator iter = contacts.iterator();
+ System.out.println(contacts);
+
+ while (iter.hasNext()) {
+ Contact contact = (Contact) iter.next();
+
+ if (contact.getId().toString().equals(id)) {
+ return;
+ }
+ }
+
+ fail("List of contacts should have contained: " + id);
+ }
+
+ protected void assertNotContainsContact(String id, List contacts) {
+ Iterator iter = contacts.iterator();
+
+ while (iter.hasNext()) {
+ Contact domain = (Contact) iter.next();
+
+ if (domain.getId().toString().equals(id)) {
+ fail("List of contact should NOT (but did) contain: " + id);
+ }
+ }
+ }
+
+ private static void destroySecureContext() {
+ SecurityContextHolder.clearContext();
+ }
+
+ protected String[] getConfigLocations() {
+ setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
+
+ return new String[] {
+ "applicationContext-common-authorization.xml", "applicationContext-common-business.xml",
+ "applicationContext-contacts-test.xml"
+ };
+ }
+
+ /**
+ * Locates the first Contact of the exact name specified.Uses the {@link + * ContactManager#getAll()} method.
+ * + * @param id Identify of the contact to locate (must be an exact match) + * + * @return the domain ornull if not found
+ */
+ protected Contact getContact(String id) {
+ List contacts = contactManager.getAll();
+ Iterator iter = contacts.iterator();
+
+ while (iter.hasNext()) {
+ Contact contact = (Contact) iter.next();
+
+ if (contact.getId().equals(id)) {
+ return contact;
+ }
+ }
+
+ return null;
+ }
+
+ protected void makeActiveUser(String username) {
+ String password = "";
+
+ if ("marissa".equals(username)) {
+ password = "koala";
+ } else if ("dianne".equals(username)) {
+ password = "emu";
+ } else if ("scott".equals(username)) {
+ password = "wombat";
+ } else if ("peter".equals(username)) {
+ password = "opal";
+ }
+
+ Authentication authRequest = new UsernamePasswordAuthenticationToken(username, password);
+ SecurityContextHolder.getContext().setAuthentication(authRequest);
+ }
+
+ protected void onTearDownInTransaction() {
+ destroySecureContext();
+ }
+
+ public void setContactManager(ContactManager contactManager) {
+ this.contactManager = contactManager;
+ }
+
+ public void testDianne() {
makeActiveUser("dianne"); // has ROLE_USER
-
+
List contacts = contactManager.getAll();
assertEquals(4, contacts.size());
-
+
assertContainsContact(Long.toString(4), contacts);
assertContainsContact(Long.toString(5), contacts);
assertContainsContact(Long.toString(6), contacts);
assertContainsContact(Long.toString(8), contacts);
-
+
assertNotContainsContact(Long.toString(1), contacts);
assertNotContainsContact(Long.toString(2), contacts);
assertNotContainsContact(Long.toString(3), contacts);
-
}
- public void testFindAllDomainsLikeAsMarissa() {
+ public void testMarissa() {
makeActiveUser("marissa"); // has ROLE_SUPERVISOR
-
- List contacts = contactManager.getAll();
-
+
+ List contacts = contactManager.getAll();
+
assertEquals(4, contacts.size());
-
+
assertContainsContact(Long.toString(1), contacts);
assertContainsContact(Long.toString(2), contacts);
assertContainsContact(Long.toString(3), contacts);
assertContainsContact(Long.toString(4), contacts);
-
- assertNotContainsContact(Long.toString(5), contacts);
-
+
+ assertNotContainsContact(Long.toString(5), contacts);
+
+ Contact c1 = contactManager.getById(new Long(4));
+
+ contactManager.deletePermission(c1, new PrincipalSid("bob"), BasePermission.ADMINISTRATION);
}
- public void testFindAllDomainsLikeAsScott() {
+ public void testScott() {
makeActiveUser("scott"); // has ROLE_USER
-
+
List contacts = contactManager.getAll();
-
- assertEquals(5, contacts.size());
-
+
+ assertEquals(5, contacts.size());
+
assertContainsContact(Long.toString(4), contacts);
assertContainsContact(Long.toString(6), contacts);
assertContainsContact(Long.toString(7), contacts);
assertContainsContact(Long.toString(8), contacts);
assertContainsContact(Long.toString(9), contacts);
-
- assertNotContainsContact(Long.toString(1), contacts);
-
+
+ assertNotContainsContact(Long.toString(1), contacts);
}
}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/BasePermission.java b/sandbox/other/src/main/java/org/acegisecurity/acls/domain/BasePermission.java
deleted file mode 100644
index b8398aec23..0000000000
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/domain/BasePermission.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.domain;
-
-import org.acegisecurity.acls.AclFormattingUtils;
-import org.acegisecurity.acls.Permission;
-
-/**
- * DOCUMENT ME!
- *
- * @author $author$
- * @version $Revision$
- */
-public class BasePermission implements Permission {
- //~ Static fields/initializers =====================================================================================
-
- public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
- public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
- public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
- public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
- public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
-
- //~ Instance fields ================================================================================================
-
- private char code;
- private int mask;
-
- //~ Constructors ===================================================================================================
-
- private BasePermission(int mask, char code) {
- this.mask = mask;
- this.code = code;
- }
-
- //~ Methods ========================================================================================================
-
- /**
- * Dynamically creates a CumulativePermission representing the active bits in the passed mask.
- * NB: Only uses BasePermission!
- *
- * @param mask to review
- *
- * @return DOCUMENT ME!
- */
- public static Permission buildFromMask(int mask) {
- CumulativePermission permission = new CumulativePermission();
-
- // TODO: Write the rest of it to iterate through the 32 bits and instantiate BasePermissions
- if (mask == 1) {
- permission.set(READ);
- }
-
- if (mask == 2) {
- permission.set(WRITE);
- }
-
- if (mask == 4) {
- permission.set(CREATE);
- }
-
- if (mask == 8) {
- permission.set(DELETE);
- }
-
- if (mask == 16) {
- permission.set(ADMINISTRATION);
- }
-
- return permission;
- }
-
- public boolean equals(Object arg0) {
- if (!(arg0 instanceof BasePermission)) {
- return false;
- }
-
- BasePermission rhs = (BasePermission) arg0;
-
- return (this.mask == rhs.getMask());
- }
-
- public int getMask() {
- return mask;
- }
-
- public String getPattern() {
- return AclFormattingUtils.printBinary(mask, code);
- }
-
- public String toString() {
- return "BasePermission[" + getPattern() + "=" + mask + "]";
- }
-}
diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/jdbc/JdbcAclService.java b/sandbox/other/src/main/java/org/acegisecurity/acls/jdbc/JdbcAclService.java
deleted file mode 100644
index c27d26dcba..0000000000
--- a/sandbox/other/src/main/java/org/acegisecurity/acls/jdbc/JdbcAclService.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.acegisecurity.acls.jdbc;
-
-import org.acegisecurity.acls.AclService;
-import org.acegisecurity.acls.NotFoundException;
-import org.acegisecurity.acls.objectidentity.ObjectIdentity;
-import org.acegisecurity.acls.sid.Sid;
-
-import org.springframework.jdbc.core.JdbcTemplate;
-
-import org.springframework.util.Assert;
-
-import java.util.Map;
-
-import javax.sql.DataSource;
-
-
-/**
- * Simple JDBC-based implementation of AclService.Requires the "dirty" flags in {@link - * org.acegisecurity.acls.domain.AclImpl} and {@link org.acegisecurity.acls.domain.AccessControlEntryImpl} to be set, - * so that the implementation can detect changed parameters easily.
- * - * @author Ben Alex - * @version $Id$ - */ -public class JdbcAclService implements AclService /*, MutableAclService */ { - //~ Instance fields ================================================================================================ - - private AclCache aclCache; - private JdbcTemplate template; - private LookupStrategy lookupStrategy; - - //~ Constructors =================================================================================================== - - public JdbcAclService(DataSource dataSource, AclCache aclCache, LookupStrategy lookupStrategy) { - Assert.notNull(dataSource, "DataSource required"); - Assert.notNull(aclCache, "AclCache required"); - Assert.notNull(lookupStrategy, "LookupStrategy required"); - this.template = new JdbcTemplate(dataSource); - this.aclCache = aclCache; - this.lookupStrategy = lookupStrategy; - } - - //~ Methods ======================================================================================================== - - public Map readAclsById(ObjectIdentity[] objects) { - return readAclsById(objects, null); - } - - /** - * Method required by interface. - * - * @param objects DOCUMENT ME! - * @param sids DOCUMENT ME! - * - * @return DOCUMENT ME! - * - * @throws NotFoundException DOCUMENT ME! - */ - public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) - throws NotFoundException { - return lookupStrategy.readAclsById(objects, sids); - } -} diff --git a/sandbox/other/src/main/java/org/acegisecurity/acls/package.html b/sandbox/other/src/main/java/org/acegisecurity/acls/package.html deleted file mode 100644 index 692d065470..0000000000 --- a/sandbox/other/src/main/java/org/acegisecurity/acls/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Enables retrieval of access control lists (ACLs) for domain object instances. - - diff --git a/sandbox/other/src/test/java/org/acegisecurity/acls/jdbc/JdbcAclServiceTests.java b/sandbox/other/src/test/java/org/acegisecurity/acls/jdbc/JdbcAclServiceTests.java deleted file mode 100644 index 88e4266a46..0000000000 --- a/sandbox/other/src/test/java/org/acegisecurity/acls/jdbc/JdbcAclServiceTests.java +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.acegisecurity.acls.jdbc; - -import org.acegisecurity.acls.Acl; -import org.acegisecurity.acls.objectidentity.ObjectIdentity; -import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl; - -import org.springframework.test.AbstractDependencyInjectionSpringContextTests; - -import java.util.Iterator; -import java.util.Map; - - -/** - * DOCUMENT ME! - * - * @author $author$ - * @version $Revision$ - */ -public class JdbcAclServiceTests extends AbstractDependencyInjectionSpringContextTests { - //~ Instance fields ================================================================================================ - - private JdbcAclService jdbcAclService; - - //~ Methods ======================================================================================================== - - protected String[] getConfigLocations() { - return new String[] {"classpath:org/acegisecurity/acls/jdbc/applicationContext-test.xml"}; - } - - public void setJdbcAclService(JdbcAclService jdbcAclService) { - this.jdbcAclService = jdbcAclService; - } - - public void testStub() { - ObjectIdentity id1 = new ObjectIdentityImpl("java.lang.Object", new Long(1)); - ObjectIdentity id2 = new ObjectIdentityImpl("java.lang.Object", new Long(2)); - ObjectIdentity id3 = new ObjectIdentityImpl("java.lang.Object", new Long(3)); - ObjectIdentity id4 = new ObjectIdentityImpl("java.lang.Object", new Long(4)); - ObjectIdentity id5 = new ObjectIdentityImpl("java.lang.Object", new Long(5)); - ObjectIdentity id6 = new ObjectIdentityImpl("java.lang.Object", new Long(6)); - Map map = jdbcAclService.readAclsById(new ObjectIdentity[] {id1, id2, id3, id4, id5, id6}); - Iterator iterator = map.keySet().iterator(); - - while (iterator.hasNext()) { - ObjectIdentity identity = (ObjectIdentity) iterator.next(); - assertEquals(identity, ((Acl) map.get(identity)).getObjectIdentity()); - System.out.println(map.get(identity)); - } - } -} diff --git a/sandbox/other/src/test/java/org/acegisecurity/acls/jdbc/testData.sql b/sandbox/other/src/test/java/org/acegisecurity/acls/jdbc/testData.sql deleted file mode 100644 index fe9d2d2ecc..0000000000 --- a/sandbox/other/src/test/java/org/acegisecurity/acls/jdbc/testData.sql +++ /dev/null @@ -1,70 +0,0 @@ -CREATE TABLE ACL_SID( -ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, -PRINCIPAL BOOLEAN NOT NULL, -SID VARCHAR_IGNORECASE(100) NOT NULL, -CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL)); - -INSERT INTO ACL_SID VALUES (1, TRUE, 'MARISSA'); -INSERT INTO ACL_SID VALUES (2, TRUE, 'DIANNE'); -INSERT INTO ACL_SID VALUES (3, TRUE, 'SCOTT'); -INSERT INTO ACL_SID VALUES (4, TRUE, 'PETER'); - -CREATE TABLE ACL_CLASS( -ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, -CLASS VARCHAR_IGNORECASE(100) NOT NULL, -CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS)); - -INSERT INTO ACL_CLASS VALUES (1, 'sample.contact.Contact'); - -CREATE TABLE ACL_OBJECT_IDENTITY( -ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, -OBJECT_ID_CLASS BIGINT NOT NULL, -OBJECT_ID_IDENTITY BIGINT NOT NULL, -PARENT_OBJECT BIGINT, -OWNER_SID BIGINT, -ENTRIES_INHERITING BOOLEAN NOT NULL, -CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY), -CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID), -CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID), -CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID)); - -INSERT INTO ACL_OBJECT_IDENTITY VALUES (1, 1, 1, NULL, 1, TRUE); -INSERT INTO ACL_OBJECT_IDENTITY VALUES (2, 1, 2, 1, 2, TRUE); -INSERT INTO ACL_OBJECT_IDENTITY VALUES (3, 1, 3, 1, 1, FALSE); -INSERT INTO ACL_OBJECT_IDENTITY VALUES (4, 1, 4, 1, 2, TRUE); -INSERT INTO ACL_OBJECT_IDENTITY VALUES (5, 1, 5, 1, 2, FALSE); -INSERT INTO ACL_OBJECT_IDENTITY VALUES (6, 1, 6, NULL, 1, TRUE); - -CREATE TABLE ACL_ENTRY( -ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, -ACL_OBJECT_IDENTITY BIGINT NOT NULL, -ACE_ORDER INT NOT NULL, -SID BIGINT NOT NULL, -MASK INTEGER NOT NULL, -GRANTING BOOLEAN NOT NULL, -AUDIT_SUCCESS BOOLEAN NOT NULL, -AUDIT_FAILURE BOOLEAN NOT NULL, -CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER), -CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID), -CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID)); - -INSERT INTO ACL_ENTRY VALUES (1, 1, 1, 2, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (2, 1, 2, 1, 2, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (3, 1, 3, 3, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (4, 2, 1, 3, 4, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (5, 2, 2, 4, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (6, 3, 1, 3, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (7, 3, 2, 4, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (8, 3, 3, 1, 8, FALSE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (9, 4, 1, 4, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (10, 5, 1, 2, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (11, 5, 2, 3, 8, FALSE, TRUE, TRUE); -INSERT INTO ACL_ENTRY VALUES (12, 5, 3, 1, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (13, 5, 4, 4, 8, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (14, 6, 1, 2, 1, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (15, 6, 2, 1, 2, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (16, 6, 3, 2, 4, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (17, 6, 4, 3, 2, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (18, 6, 5, 3, 1, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (19, 6, 6, 4, 4, TRUE, FALSE, FALSE); -INSERT INTO ACL_ENTRY VALUES (20, 6, 7, 4, 2, TRUE, FALSE, FALSE);