Author: enorman
Date: Sat Feb 27 02:02:09 2010
New Revision: 916893

URL: http://svn.apache.org/viewvc?rev=916893&view=rev
Log:
SLING-1411 Add replaceAccessControlEntry method to AccessControlUtil
Thanks to Ray Davis for the contribution.

Modified:
    
sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java
    
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
    
sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
    
sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java

Modified: 
sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java?rev=916893&r1=916892&r2=916893&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java
 (original)
+++ 
sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/util/AccessControlUtil.java
 Sat Feb 27 02:02:09 2010
@@ -18,10 +18,22 @@
  */
 package org.apache.sling.jcr.base.util;
 
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.RepositoryException;
@@ -31,12 +43,10 @@
 import javax.jcr.security.AccessControlException;
 import javax.jcr.security.AccessControlList;
 import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
 import javax.jcr.security.Privilege;
 
-import org.apache.jackrabbit.api.JackrabbitSession;
-import org.apache.jackrabbit.api.security.principal.PrincipalManager;
-import org.apache.jackrabbit.api.security.user.UserManager;
-
 /**
  * A simple utility class providing utilities with respect to
  * access control over repositories.
@@ -60,7 +70,7 @@
     // the name of the JackrabbitAccessControlEntry method
     private static final String METHOD_JACKRABBIT_ACE_IS_ALLOW = "isAllow";
 
-
+    private static final Logger log = 
LoggerFactory.getLogger(AccessControlUtil.class);
 
     // ---------- SessionImpl methods 
-----------------------------------------------------
 
@@ -201,6 +211,141 @@
        Class[] types = new Class[] {Principal.class, Privilege[].class, 
boolean.class, Map.class};
                return safeInvokeRepoMethod(acl, 
METHOD_JACKRABBIT_ACL_ADD_ENTRY, Boolean.class, args, types);
     }
+    
+    /**
+     * Replaces existing access control entries in the ACL for the specified
+     * <code>principal</code> and <code>resourcePath</code>. Any existing 
granted
+     * or denied privileges which do not conflict with the specified privileges
+     * are maintained. Where conflicts exist, existing privileges are dropped.
+     * The end result will be at most two ACEs for the principal: one for 
grants
+     * and one for denies. Aggregate privileges are disaggregated before 
checking
+     * for conflicts.
+     * @param session
+     * @param resourcePath
+     * @param principal
+     * @param grantedPrivilegeNames
+     * @param deniedPrivilegeNames
+     * @param removedPrivilegeNames privileges which, if they exist, should be
+     * removed for this principal and resource
+     * @throws RepositoryException
+     */
+    public static void replaceAccessControlEntry(Session session, String 
resourcePath, Principal principal, 
+                       String[] grantedPrivilegeNames, String[] 
deniedPrivilegeNames, String[] removedPrivilegeNames)
+                       throws RepositoryException {
+       AccessControlManager accessControlManager = 
getAccessControlManager(session);
+       Set<String> specifiedPrivilegeNames = new HashSet<String>();
+       Set<String> newGrantedPrivilegeNames = 
disaggregateToPrivilegeNames(accessControlManager, grantedPrivilegeNames, 
specifiedPrivilegeNames);
+       Set<String> newDeniedPrivilegeNames = 
disaggregateToPrivilegeNames(accessControlManager, deniedPrivilegeNames, 
specifiedPrivilegeNames);
+       disaggregateToPrivilegeNames(accessControlManager, 
removedPrivilegeNames, specifiedPrivilegeNames);
+
+       // Get or create the ACL for the node.
+       AccessControlList acl = null;
+       AccessControlPolicy[] policies = 
accessControlManager.getPolicies(resourcePath);
+       for (AccessControlPolicy policy : policies) {
+               if (policy instanceof AccessControlList) {
+                       acl = (AccessControlList) policy;
+                       break;
+               }
+       }
+       if (acl == null) {
+               AccessControlPolicyIterator applicablePolicies = 
accessControlManager.getApplicablePolicies(resourcePath);
+               while (applicablePolicies.hasNext()) {
+                       AccessControlPolicy policy = 
applicablePolicies.nextAccessControlPolicy();
+                       if (policy instanceof AccessControlList) {
+                               acl = (AccessControlList) policy;
+                               break;
+                       }
+               }
+       }
+       if (acl == null) {
+               throw new RepositoryException("Could not obtain ACL for 
resource " + resourcePath);
+       }
+       // Used only for logging.
+       Set<Privilege> oldGrants = null;
+       Set<Privilege> oldDenies = null;
+       if (log.isDebugEnabled()) {
+               oldGrants = new HashSet<Privilege>();
+               oldDenies = new HashSet<Privilege>();
+       }
+      
+       // Combine all existing ACEs for the target principal.
+       AccessControlEntry[] accessControlEntries = 
acl.getAccessControlEntries();
+       for (AccessControlEntry ace : accessControlEntries) {
+               if (principal.equals(ace.getPrincipal())) {
+                       if (log.isDebugEnabled()) {
+                               log.debug("Found Existing ACE for principal {} 
on resource {}", new Object[] {principal.getName(), resourcePath});
+                       }
+                       boolean isAllow = isAllow(ace);
+                       Privilege[] privileges = ace.getPrivileges();
+                       if (log.isDebugEnabled()) {
+                               if (isAllow) {
+                                       
oldGrants.addAll(Arrays.asList(privileges));
+                               } else {
+                                       
oldDenies.addAll(Arrays.asList(privileges));
+                               }
+                       }
+                       for (Privilege privilege : privileges) {
+                               Set<String> maintainedPrivileges = 
disaggregateToPrivilegeNames(privilege);
+                               // If there is any overlap with the newly 
specified privileges, then
+                               // break the existing privilege down; 
otherwise, maintain as is.
+                               if 
(!maintainedPrivileges.removeAll(specifiedPrivilegeNames)) {
+                                       // No conflicts, so preserve the 
original.
+                                       maintainedPrivileges.clear();
+                                       
maintainedPrivileges.add(privilege.getName());
+                               }
+                               if (!maintainedPrivileges.isEmpty()) {
+                                       if (isAllow) {
+                                               
newGrantedPrivilegeNames.addAll(maintainedPrivileges);
+                                       } else {
+                                               
newDeniedPrivilegeNames.addAll(maintainedPrivileges);
+                                       }
+                               }
+                       }
+                       // Remove the old ACE.
+                       acl.removeAccessControlEntry(ace);
+               }
+       }
+
+       //add a fresh ACE with the granted privileges
+       List<Privilege> grantedPrivilegeList = new ArrayList<Privilege>();
+       for (String name : newGrantedPrivilegeNames) {
+               Privilege privilege = 
accessControlManager.privilegeFromName(name);
+               grantedPrivilegeList.add(privilege);
+       }
+       if (grantedPrivilegeList.size() > 0) {
+               acl.addAccessControlEntry(principal, 
grantedPrivilegeList.toArray(new Privilege[grantedPrivilegeList.size()]));
+       }
+
+       //if the authorizable is a user (not a group) process any denied 
privileges
+       UserManager userManager = getUserManager(session);
+       Authorizable authorizable = userManager.getAuthorizable(principal);
+       if (!authorizable.isGroup()) {
+               //add a fresh ACE with the denied privileges
+               List<Privilege> deniedPrivilegeList = new 
ArrayList<Privilege>();
+               for (String name : newDeniedPrivilegeNames) {
+                       Privilege privilege = 
accessControlManager.privilegeFromName(name);
+                       deniedPrivilegeList.add(privilege);
+               }        
+               if (deniedPrivilegeList.size() > 0) {
+                       addEntry(acl, principal, 
deniedPrivilegeList.toArray(new Privilege[deniedPrivilegeList.size()]), false);
+               }
+       }
+
+       accessControlManager.setPolicy(resourcePath, acl);
+       if (log.isDebugEnabled()) {
+               List<String> oldGrantedNames = new 
ArrayList<String>(oldGrants.size());
+               for (Privilege privilege : oldGrants) {
+                       oldGrantedNames.add(privilege.getName());
+               }
+               List<String> oldDeniedNames = new 
ArrayList<String>(oldDenies.size());
+               for (Privilege privilege : oldDenies) {
+                       oldDeniedNames.add(privilege.getName());
+               }
+               log.debug("Updated ACE for principalId {} for resource {} from 
grants {}, denies {} to grants {}, denies {}", new Object [] {
+                               authorizable.getID(), resourcePath, 
oldGrantedNames, oldDeniedNames, newGrantedPrivilegeNames, 
newDeniedPrivilegeNames
+                       });
+       }
+       }
 
     // ---------- AccessControlEntry methods 
-----------------------------------------------
 
@@ -264,4 +409,40 @@
                else
                        return null;
        }
+  
+       /**
+        * Helper routine to transform an input array of privilege names into a 
set in
+        * a null-safe way while also adding its disaggregated privileges to an 
input set.
+        */
+       private static Set<String> 
disaggregateToPrivilegeNames(AccessControlManager accessControlManager, 
+                       String[] privilegeNames, Set<String> 
disaggregatedPrivilegeNames)
+      throws RepositoryException {
+               Set<String> originalPrivilegeNames = new HashSet<String>();
+               if (privilegeNames != null) {
+                       for (String privilegeName : privilegeNames) {
+                               originalPrivilegeNames.add(privilegeName);
+                               Privilege privilege = 
accessControlManager.privilegeFromName(privilegeName);
+                               
disaggregatedPrivilegeNames.addAll(disaggregateToPrivilegeNames(privilege));
+                       }
+               }
+               return originalPrivilegeNames;
+       }
+
+       /**
+        * Transform an aggregated privilege into a set of disaggregated 
privilege
+        * names. If the privilege is not an aggregate, the set will contain the
+        * original name.
+        */
+       private static Set<String> disaggregateToPrivilegeNames(Privilege 
privilege) {
+               Set<String> disaggregatedPrivilegeNames = new HashSet<String>();
+               if (privilege.isAggregate()) {
+                       Privilege[] privileges = 
privilege.getAggregatePrivileges();
+                       for (Privilege disaggregate : privileges) {
+                               
disaggregatedPrivilegeNames.add(disaggregate.getName());
+                       }
+               } else {
+                       disaggregatedPrivilegeNames.add(privilege.getName());
+               }
+               return disaggregatedPrivilegeNames;
+       }
 }

Modified: 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java?rev=916893&r1=916892&r2=916893&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
 (original)
+++ 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
 Sat Feb 27 02:02:09 2010
@@ -18,6 +18,13 @@
  */
 package org.apache.sling.jcr.contentloader.internal;
 
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.security.MessageDigest;
@@ -26,11 +33,9 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -47,18 +52,6 @@
 import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
-import javax.jcr.security.AccessControlEntry;
-import javax.jcr.security.AccessControlList;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.AccessControlPolicy;
-import javax.jcr.security.AccessControlPolicyIterator;
-import javax.jcr.security.Privilege;
-
-import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.Group;
-import org.apache.jackrabbit.api.security.user.User;
-import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.sling.jcr.base.util.AccessControlUtil;
 
 /**
  * The <code>ContentLoader</code> creates the nodes and properties.
@@ -810,120 +803,17 @@
                        throws RepositoryException {
                final Node parentNode = this.parentNodeStack.peek();
                Session session = parentNode.getSession();
-
-               UserManager userManager = 
AccessControlUtil.getUserManager(session);
-               Authorizable authorizable = 
userManager.getAuthorizable(principalId);
-               if (authorizable == null) {
+               PrincipalManager principalManager = 
AccessControlUtil.getPrincipalManager(session);
+               Principal principal = 
principalManager.getPrincipal(principalId);
+               if (principal == null) {
                        throw new RepositoryException("No principal found for 
id: " + principalId);
                }
-
                String resourcePath = parentNode.getPath();
 
-               AccessControlManager accessControlManager = 
AccessControlUtil.getAccessControlManager(session);
-               AccessControlList updatedAcl = null;
-               AccessControlPolicy[] policies = 
accessControlManager.getPolicies(resourcePath);
-               for (AccessControlPolicy policy : policies) {
-                 if (policy instanceof AccessControlList) {
-                   updatedAcl = (AccessControlList)policy;
-                   break;
-                 }
-               }
-               if (updatedAcl == null) {
-                 AccessControlPolicyIterator applicablePolicies = 
accessControlManager.getApplicablePolicies(resourcePath);
-                 while (applicablePolicies.hasNext()) {
-                   AccessControlPolicy policy = 
applicablePolicies.nextAccessControlPolicy();
-                   if (policy instanceof AccessControlList) {
-                     updatedAcl = (AccessControlList)policy;
-                   }
-                 }
-               }
-               if (updatedAcl == null) {
-                       throw new RepositoryException("Unable to find or create 
an access control policy to update for " + resourcePath);
-               }
-
-               Set<String> postedPrivilegeNames = new HashSet<String>();
-               if (grantedPrivilegeNames != null) {
-                       
postedPrivilegeNames.addAll(Arrays.asList(grantedPrivilegeNames));
+               if ((grantedPrivilegeNames != null) || (deniedPrivilegeNames != 
null)) {
+                       AccessControlUtil.replaceAccessControlEntry(session, 
resourcePath, principal,
+                                       grantedPrivilegeNames, 
deniedPrivilegeNames, null);
                }
-               if (deniedPrivilegeNames != null) {
-                       
postedPrivilegeNames.addAll(Arrays.asList(deniedPrivilegeNames));
-               }
-
-               List<Privilege> preserveGrantedPrivileges = new 
ArrayList<Privilege>();
-               List<Privilege> preserveDeniedPrivileges = new 
ArrayList<Privilege>();
-
-               //keep track of the existing Aces for the target principal
-               AccessControlEntry[] accessControlEntries = 
updatedAcl.getAccessControlEntries();
-               List<AccessControlEntry> oldAces = new 
ArrayList<AccessControlEntry>();
-               for (AccessControlEntry ace : accessControlEntries) {
-                       if (principalId.equals(ace.getPrincipal().getName())) {
-                               oldAces.add(ace);
-
-                               boolean isAllow = 
AccessControlUtil.isAllow(ace);
-                               Privilege[] privileges = ace.getPrivileges();
-                               for (Privilege privilege : privileges) {
-                                       String privilegeName = 
privilege.getName();
-                                       if 
(!postedPrivilegeNames.contains(privilegeName)) {
-                                               //this privilege was not 
posted, so record the existing state to be
-                                               // preserved when the ACE is 
re-created below
-                                               if (isAllow) {
-                                                       
preserveGrantedPrivileges.add(privilege);
-                                               } else {
-                                                       
preserveDeniedPrivileges.add(privilege);
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               //remove the old aces
-               if (!oldAces.isEmpty()) {
-                       for (AccessControlEntry ace : oldAces) {
-                               updatedAcl.removeAccessControlEntry(ace);
-                       }
-               }
-
-               //add a fresh ACE with the granted privileges
-               List<Privilege> grantedPrivilegeList = new 
ArrayList<Privilege>();
-               if (grantedPrivilegeNames != null) {
-                 for (String name : grantedPrivilegeNames) {
-                         if (name.length() == 0) {
-                                 continue; //empty, skip it.
-                         }
-                         Privilege privilege = 
accessControlManager.privilegeFromName(name);
-                         grantedPrivilegeList.add(privilege);
-           }
-               }
-               //add the privileges that should be preserved
-               grantedPrivilegeList.addAll(preserveGrantedPrivileges);
-
-               if (grantedPrivilegeList.size() > 0) {
-                       Principal principal = authorizable.getPrincipal();
-                       updatedAcl.addAccessControlEntry(principal, 
grantedPrivilegeList.toArray(new Privilege[grantedPrivilegeList.size()]));
-               }
-
-               //if the authorizable is a user (not a group) process any 
denied privileges
-               if (!authorizable.isGroup()) {
-                       //add a fresh ACE with the denied privileges
-                       List<Privilege> deniedPrivilegeList = new 
ArrayList<Privilege>();
-                       if (deniedPrivilegeNames != null) {
-                         for (String name : deniedPrivilegeNames) {
-                                 if (name.length() == 0) {
-                                         continue; //empty, skip it.
-                                 }
-                                 Privilege privilege = 
accessControlManager.privilegeFromName(name);
-                                 deniedPrivilegeList.add(privilege);
-                         }
-                       }
-                       //add the privileges that should be preserved
-                       deniedPrivilegeList.addAll(preserveDeniedPrivileges);
-                       if (deniedPrivilegeList.size() > 0) {
-                               Principal principal = 
authorizable.getPrincipal();
-                               AccessControlUtil.addEntry(updatedAcl, 
principal, deniedPrivilegeList.toArray(new 
Privilege[deniedPrivilegeList.size()]), false);
-                       }
-               }
-
-               accessControlManager.setPolicy(resourcePath, updatedAcl);
        }
 
        /**

Modified: 
sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java?rev=916893&r1=916892&r2=916893&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
 (original)
+++ 
sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
 Sat Feb 27 02:02:09 2010
@@ -16,8 +16,15 @@
  */
 package org.apache.sling.jcr.jackrabbit.accessmanager.post;
 
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.apache.sling.servlets.post.Modification;
+
 import java.security.Principal;
-import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
@@ -26,31 +33,16 @@
 import javax.jcr.Item;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.security.AccessControlEntry;
-import javax.jcr.security.AccessControlList;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.Privilege;
-
-import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceNotFoundException;
-import org.apache.sling.api.servlets.HtmlResponse;
-import org.apache.sling.jcr.base.util.AccessControlUtil;
-import org.apache.sling.servlets.post.Modification;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * <p>
- * Sling Post Servlet implementation for modifying the ACE for a principal on 
a JCR
+ * Sling Post Servlet implementation for modifying the ACEs for a principal on 
a JCR
  * resource.
  * </p>
  * <h2>Rest Service Description</h2>
  * <p>
- * Delete a set of Ace's from a node, the node is identified as a resource by 
the request
- * url &gt;resource&lt;.modifyAce.html
+ * Modify a principal's ACEs for the node identified as a resource by the 
request
+ * URL &gt;resource&lt;.modifyAce.html
  * </p>
  * <h4>Methods</h4>
  * <ul>
@@ -59,11 +51,11 @@
  * <h4>Post Parameters</h4>
  * <dl>
  * <dt>principalId</dt>
- * <dd>The principal of the Ace to modify in the ACL specified by the 
path.</dd>
+ * <dd>The principal of the ACEs to modify in the ACL specified by the 
path.</dd>
  * <dt>privil...@*</dt>
- * <dd>One of more privileges, either granted or denied, where set the 
permission in the
- * stored ACE is modified to match the request. Any permissions that are 
present in the
- * stored ACE, but are not in the request are left untouched.</dd>
+ * <dd>One or more privileges, either granted or denied or none, which will be 
applied
+ * to (or removed from) the node ACL. Any permissions that are present in an
+ * existing ACE for the principal but not in the request are left 
untouched.</dd>
  * </dl>
  *
  * <h4>Response</h4>
@@ -92,11 +84,6 @@
 public class ModifyAceServlet extends AbstractAccessPostServlet {
        private static final long serialVersionUID = -9182485466670280437L;
 
-       /**
-     * default log
-     */
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
        /* (non-Javadoc)
         * @see 
org.apache.sling.jackrabbit.accessmanager.post.AbstractAccessPostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest,
 org.apache.sling.api.servlets.HtmlResponse, java.util.List)
         */
@@ -113,88 +100,25 @@
                if (principalId == null) {
                        throw new RepositoryException("principalId was not 
submitted.");
                }
-               UserManager userManager = 
AccessControlUtil.getUserManager(session);
-               Authorizable authorizable = 
userManager.getAuthorizable(principalId);
-               if (authorizable == null) {
-                       throw new RepositoryException("No principal found for 
id: " + principalId);
-               }
-
-       String resourcePath = null;
-       Resource resource = request.getResource();
-       if (resource == null) {
+               PrincipalManager principalManager = 
AccessControlUtil.getPrincipalManager(session);
+               Principal principal = 
principalManager.getPrincipal(principalId);
+               String resourcePath = null;
+               Resource resource = request.getResource();
+               if (resource == null) {
                        throw new ResourceNotFoundException("Resource not 
found.");
-       } else {
-               Item item = resource.adaptTo(Item.class);
-               if (item != null) {
-                       resourcePath = item.getPath();
-               } else {
-                       throw new ResourceNotFoundException("Resource is not a 
JCR Node");
-               }
-       }
-
-               try {
-                       AccessControlManager accessControlManager = 
AccessControlUtil.getAccessControlManager(session);
-
-                       //SLING-997: keep track of the privilege names that 
were posted, so the others can be preserved
-                       PrivilegesState privilegesInfo = new 
PrivilegesState(log.isDebugEnabled());
-                       
-                       //calculate which privileges were POSTed.
-                       collectPostedPrivilegeNames(request, 
-                                       accessControlManager,
-                                       privilegesInfo);        
-
-                       //find the existing ACL
-                       AccessControlList updatedAcl = 
getAccessControlList(accessControlManager, resourcePath, true);
-
-                       //keep track of the existing ACEs for the target 
principal
-                       List<AccessControlEntry> oldAces = 
processExistingAccessControlEntries(resourcePath, 
-                                       authorizable, 
-                                       accessControlManager, 
-                                       updatedAcl, 
-                                       privilegesInfo); 
-                       
-                       //remove the old ACEs.  Re-created below.
-                       if (!oldAces.isEmpty()) {
-                               for (AccessControlEntry ace : oldAces) {
-                                       
updatedAcl.removeAccessControlEntry(ace);
-                               }
+               } else {
+                       Item item = resource.adaptTo(Item.class);
+                       if (item != null) {
+                               resourcePath = item.getPath();
+                       } else {
+                               throw new ResourceNotFoundException("Resource 
is not a JCR Node");
                        }
-                       
-                       //re-aggregate the granted/denied privileges into the 
best matched aggregate privilege
-                       reaggregatePrivileges(resourcePath,
-                                       accessControlManager,
-                                       privilegesInfo);
-                       
-                       //add fresh ACEs with the granted privileges
-                       buildFreshAccessControlEntries(authorizable, 
-                                       accessControlManager, 
-                                       updatedAcl, 
-                                       privilegesInfo);
-                       
-                       //store the updated ACL
-                       accessControlManager.setPolicy(resourcePath, 
updatedAcl);
-                       if (session.hasPendingChanges()) {
-                               session.save();
-                       }
-
-                       if (log.isDebugEnabled()) {
-                               log.debug("Updated ACE for principalId {0} for 
resource {1) from {2} to {3}", new Object [] {
-                                               authorizable.getID(), 
resourcePath, privilegesInfo.oldPrivileges.toString(), 
privilegesInfo.newPrivileges.toString()
-                               });
-                       }
-               } catch (RepositoryException re) {
-                       throw new RepositoryException("Failed to create ace.", 
re);
                }
-       }
-
-
-       /**
-        * Collect the privileges to assign from the http request.
-        */
-       private void collectPostedPrivilegeNames(SlingHttpServletRequest 
request,
-                       AccessControlManager accessControlManager,
-                       PrivilegesState privilegesInfo) throws 
RepositoryException {
-
+    
+               // Collect the modified privileges from the request.
+               Set<String> grantedPrivilegeNames = new HashSet<String>();
+               Set<String> deniedPrivilegeNames = new HashSet<String>();
+               Set<String> removedPrivilegeNames = new HashSet<String>();
                Enumeration<?> parameterNames = request.getParameterNames();
                while (parameterNames.hasMoreElements()) {
                        Object nextElement = parameterNames.nextElement();
@@ -202,237 +126,31 @@
                                String paramName = (String)nextElement;
                                if (paramName.startsWith("privilege@")) {
                                        String privilegeName = 
paramName.substring(10);
-                                       //keep track of which privileges should 
be changed
-                                       
privilegesInfo.postedPrivilegeNames.add(privilegeName); 
-                                       
                                        String parameterValue = 
request.getParameter(paramName);
                                        if (parameterValue != null && 
parameterValue.length() > 0) {
                                                if 
("granted".equals(parameterValue)) {
-                                                       Privilege privilege = 
accessControlManager.privilegeFromName(privilegeName);
-                                                       if 
(privilege.isAggregate()) {
-                                                               Privilege[] 
aggregatePrivileges = privilege.getAggregatePrivileges();
-                                                               for (Privilege 
privilege2 : aggregatePrivileges) {
-                                                                       
privilegesInfo.grantedPrivilegeNames.add(privilege2.getName());
-                                                               }
-                                                       } else {
-                                                               
privilegesInfo.grantedPrivilegeNames.add(privilegeName);
-                                                       }
+                                                       
grantedPrivilegeNames.add(privilegeName);
                                                } else if 
("denied".equals(parameterValue)) {
-                                                       Privilege privilege = 
accessControlManager.privilegeFromName(privilegeName);
-                                                       if 
(privilege.isAggregate()) {
-                                                               Privilege[] 
aggregatePrivileges = privilege.getAggregatePrivileges();
-                                                               for (Privilege 
privilege2 : aggregatePrivileges) {
-                                                                       
privilegesInfo.deniedPrivilegeNames.add(privilege2.getName());
-                                                               }
-                                                       } else {
-                                                               
privilegesInfo.deniedPrivilegeNames.add(privilegeName);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       
-       /**
-        * Process the existing ACL to determine which privileges to preserve.
-        */
-       private List<AccessControlEntry> processExistingAccessControlEntries(
-                       String resourcePath,
-                       Authorizable authorizable,
-                       AccessControlManager accessControlManager,
-                       AccessControlList updatedAcl,
-                       PrivilegesState privilegesInfo) throws 
RepositoryException {
-               
-               String principalId = authorizable.getPrincipal().getName();
-               AccessControlEntry[] accessControlEntries = 
updatedAcl.getAccessControlEntries();
-               List<AccessControlEntry> oldAces = new 
ArrayList<AccessControlEntry>();
-               for (AccessControlEntry ace : accessControlEntries) {
-                       if (principalId.equals(ace.getPrincipal().getName())) {
-                               if (log.isDebugEnabled()) {
-                                       log.debug("Found Existing ACE for 
principal {0} on resource: ", new Object[] {principalId, resourcePath});
-                               }
-                               oldAces.add(ace);
-
-                               boolean isAllow = 
AccessControlUtil.isAllow(ace);
-                               Privilege[] privileges = ace.getPrivileges();
-
-                               //build a list of (merged and expanded) 
privileges 
-                               Set<Privilege> mergedExistingPrivileges = new 
HashSet<Privilege>();
-                               for (Privilege privilege : privileges) {
-                                       if (privilege.isAggregate()) {
-                                               Privilege[] aggregatePrivileges 
= privilege.getAggregatePrivileges();
-                                               for (Privilege privilege2 : 
aggregatePrivileges) {
-                                                       
mergedExistingPrivileges.add(privilege2);
-                                               }
-                                       } else {
-                                               
mergedExistingPrivileges.add(privilege);
-                                       }
-                               }
-                               
-                               //now process the merged privileges set
-                               for (Privilege privilege : 
mergedExistingPrivileges) {
-                                       String privilegeName = 
privilege.getName();
-                                       if 
(!privilegesInfo.postedPrivilegeNames.contains(privilegeName)) {
-                                               //this privilege was not 
posted, so record the existing state to be 
-                                               // preserved when the ACE is 
re-created below
-                                               if (isAllow) {
-                                                       
privilegesInfo.grantedPrivilegeNames.add(privilegeName);
-                                               } else {
-                                                       
privilegesInfo.deniedPrivilegeNames.add(privilegeName);
-                                               }
-                                       }
-
-                                       if (log.isDebugEnabled()) {
-                                               //collect the information for 
debug logging
-                                               if 
(privilegesInfo.oldPrivileges.length() > 0) {
-                                                       
privilegesInfo.oldPrivileges.append(", "); //separate entries by commas
-                                               }
-                                               if (isAllow) {
-                                                       
privilegesInfo.oldPrivileges.append("granted=");
+                                                       
deniedPrivilegeNames.add(privilegeName);
                                                } else {
-                                                       
privilegesInfo.oldPrivileges.append("denied=");
+                                                       
removedPrivilegeNames.add(privilegeName);
                                                }
-                                               
privilegesInfo.oldPrivileges.append(privilege.getName());
-                                       }
-                               }
-                       }
-               }
-               
-               return oldAces;
-       }
-       
-       /**
-        * Given the set of granted/denied privileges, try to combine them
-        * into the best aggregate Privilege that contains them all.
-        */
-       private void reaggregatePrivileges(
-                       String resourcePath,
-                       AccessControlManager accessControlManager,
-                       PrivilegesState privilegesInfo) throws 
RepositoryException {
-               Privilege[] supportedPrivileges = 
accessControlManager.getSupportedPrivileges(resourcePath);
-               for (Privilege privilege : supportedPrivileges) {
-                       if (privilege.isAggregate()) {
-                               boolean grantedAggregatePrivilege = true;
-                               boolean deniedAggregatePrivilege = true;
-                               Privilege[] aggregatePrivileges = 
privilege.getAggregatePrivileges();
-                               for (Privilege privilege2 : 
aggregatePrivileges) {
-                                       String name = privilege2.getName();
-                                       if 
(!privilegesInfo.grantedPrivilegeNames.contains(name)) {
-                                               grantedAggregatePrivilege = 
false;
-                                       }
-                                       if 
(!privilegesInfo.deniedPrivilegeNames.contains(name)) {
-                                               deniedAggregatePrivilege = 
false;
-                                       }
-                               }
-                               
-                               if (grantedAggregatePrivilege) {
-                                       //add the aggregate privilege and 
remove the containing parts
-                                       
privilegesInfo.grantedPrivilegeNames.add(privilege.getName());
-                                       for (Privilege privilege2 : 
aggregatePrivileges) {
-                                               String name = 
privilege2.getName();
-                                               
privilegesInfo.grantedPrivilegeNames.remove(name);
-                                       }                                       
        
-                               }
-
-                               if (deniedAggregatePrivilege) {
-                                       //add the aggregate privilege and 
remove the containing parts
-                                       
privilegesInfo.deniedPrivilegeNames.add(privilege.getName());
-                                       for (Privilege privilege2 : 
aggregatePrivileges) {
-                                               String name = 
privilege2.getName();
-                                               
privilegesInfo.deniedPrivilegeNames.remove(name);
-                                       }                                       
        
-                               }
-                       }
-               }
-       }
-       
-       /**
-        * Create new ACE for the granted and denied privileges.
-        */
-       private void buildFreshAccessControlEntries(
-                       Authorizable authorizable,
-                       AccessControlManager accessControlManager,              
        
-                       AccessControlList updatedAcl,
-                       PrivilegesState privilegesInfo) throws 
RepositoryException {
-               List<Privilege> grantedPrivilegeList = new 
ArrayList<Privilege>();
-               for (String name : privilegesInfo.grantedPrivilegeNames) {
-                       if (name.length() == 0) {
-                               continue; //empty, skip it.
-                       }
-                       Privilege privilege = 
accessControlManager.privilegeFromName(name);
-                       grantedPrivilegeList.add(privilege);
-               }
-               
-               if (log.isDebugEnabled()) {
-                       for (Privilege privilege : grantedPrivilegeList) {
-                               if (privilegesInfo.newPrivileges.length() > 0) {
-                                       privilegesInfo.newPrivileges.append(", 
"); //separate entries by commas
-                               }
-                               privilegesInfo.newPrivileges.append("granted=");
-                               
privilegesInfo.newPrivileges.append(privilege.getName());
-                       }                               
-               }
-
-               if (grantedPrivilegeList.size() > 0) {
-                       Principal principal = authorizable.getPrincipal();
-                       updatedAcl.addAccessControlEntry(principal, 
grantedPrivilegeList.toArray(new Privilege[grantedPrivilegeList.size()]));
-               }
-
-               //if the authorizable is a user (not a group) process any 
denied privileges
-               if (!authorizable.isGroup()) {
-                       //add a fresh ACE with the denied privileges
-                       List<Privilege> deniedPrivilegeList = new 
ArrayList<Privilege>();
-                       for (String name : privilegesInfo.deniedPrivilegeNames) 
{
-                               if (name.length() == 0) {
-                                       continue; //empty, skip it.
-                               }
-                               Privilege privilege = 
accessControlManager.privilegeFromName(name);
-                               deniedPrivilegeList.add(privilege);
-                       }
-                       
-                       if (log.isDebugEnabled()) {
-                               for (Privilege privilege : deniedPrivilegeList) 
{
-                                       if 
(privilegesInfo.newPrivileges.length() > 0) {
-                                               
privilegesInfo.newPrivileges.append(", "); //separate entries by commas
                                        }
-                                       
privilegesInfo.newPrivileges.append("denied=");
-                                       
privilegesInfo.newPrivileges.append(privilege.getName());
                                }
                        }
-                       
-                       if (deniedPrivilegeList.size() > 0) {
-                               Principal principal = 
authorizable.getPrincipal();
-                               AccessControlUtil.addEntry(updatedAcl, 
principal, deniedPrivilegeList.toArray(new 
Privilege[deniedPrivilegeList.size()]), false);
-                       }
                }
-       }
-       
-       /**
-        * Contains the information about the privilege state as it 
-        * progresses through the update process. 
-        */
-       private static class PrivilegesState {
-               //stores the names of the privileges that were POSTed
-               Set<String> postedPrivilegeNames = new HashSet<String>();
-               
-               //stores the names of the privileges to be granted 
-               Set<String> grantedPrivilegeNames = new HashSet<String>();
-
-               //stores the names of the privileges to be denied 
-               Set<String> deniedPrivilegeNames = new HashSet<String>();
-
-               //collects debug information about the previous privileges
-               StringBuilder oldPrivileges = null;
-               
-               //collects debug information about the new privileges
-               StringBuilder newPrivileges = null;
 
-               public PrivilegesState(boolean isDebugEnabled) {
-                       if (isDebugEnabled) {
-                               oldPrivileges = new StringBuilder();
-                               newPrivileges = new StringBuilder();
+               // Make the actual changes.
+               try {
+                       AccessControlUtil.replaceAccessControlEntry(session, 
resourcePath, principal,
+                                       grantedPrivilegeNames.toArray(new 
String[grantedPrivilegeNames.size()]),
+                                       deniedPrivilegeNames.toArray(new 
String[deniedPrivilegeNames.size()]),
+                                       removedPrivilegeNames.toArray(new 
String[removedPrivilegeNames.size()]));
+                       if (session.hasPendingChanges()) {
+                               session.save();
                        }
+               } catch (RepositoryException re) {
+                       throw new RepositoryException("Failed to create ace.", 
re);
                }
        }
 }

Modified: 
sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java?rev=916893&r1=916892&r2=916893&view=diff
==============================================================================
--- 
sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java
 (original)
+++ 
sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java
 Sat Feb 27 02:02:09 2010
@@ -398,10 +398,9 @@
                postParams2.add(new NameValuePair("principalId", testUserId));
                //jcr:read is not posted, so it should remain in the granted ACE
                
-               //post the remaining privileges that when combined, correspond 
to the jcr:write aggregate privilege
-               postParams2.add(new 
NameValuePair("privil...@jcr:addChildNodes", "denied")); //add a new privilege
-               postParams2.add(new 
NameValuePair("privil...@jcr:removeChildNodes", "denied")); //add a new 
privilege
-               postParams2.add(new 
NameValuePair("privil...@jcr:modifyProperties", "denied")); //add a new 
privilege
+               //deny the full jcr:write aggregate privilege, which should 
merge with the
+               //existing part.
+               postParams2.add(new NameValuePair("privil...@jcr:write", 
"denied")); //add a new privilege
                
                assertAuthenticatedPostStatus(creds, postUrl, 
HttpServletResponse.SC_OK, postParams2, null);
                


Reply via email to