/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.sling.jcr.jackrabbit.accessmanager.post;

import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.security.AccessControlEntry;
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 javax.servlet.Servlet;

import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.jcr.base.util.AccessControlUtil;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
import org.apache.sling.jcr.jackrabbit.accessmanager.ModifyAce;
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.PrivilegesHelper;
import org.apache.sling.servlets.post.Modification;
import org.apache.sling.servlets.post.PostResponse;
import org.apache.sling.servlets.post.PostResponseCreator;
import org.apache.sling.servlets.post.SlingPostConstants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;

/**
 * <p>
 * Sling Post Servlet implementation for modifying the ACEs for a principal on a JCR
 * resource.
 * </p>
 * <h2>Rest Service Description</h2>
 * <p>
 * Modify a principal's ACEs for the node identified as a resource by the request
 * URL &gt;resource&lt;.modifyAce.html
 * </p>
 * <h3>Transport Details:</h3>
 * <h4>Methods</h4>
 * <ul>
 * <li>POST</li>
 * </ul>
 * <h4>Post Parameters</h4>
 * <dl>
 * <dt>principalId</dt>
 * <dd>The principal of the ACEs to modify in the ACL specified by the path.</dd>
 * <dt>privilege@[privilege_name]</dt>
 * <dd>One or more privileges which will be applied to the ACE. Any permissions that are present in an
 * existing ACE for the principal but not in the request are left untouched. The parameter value must be either 'allow', 'deny' or 'all'. 
 * For backward compatibility, 'granted' or 'denied' may also be used for the parameter value as an alias for 'allow' or 'deny'.</dd>
 * <dt>restriction@[restriction_name]</dt>
 * <dd>One or more restrictions which will be applied to the ACE. The value is the target value of the restriction to be set.</dd>
 * <dt>restriction@[restriction_name]@Delete</dt>
 * <dd>One or more restrictions which will be removed from the ACE</dd>
 * <dt>privilege@[privilege_name]@Delete</dt>
 * <dd>One param for each privilege to delete. The parameter value must be either 'allow', 'deny' or 'all' to specify which state to delete from</dd>
 * <dt>restriction@[privilege_name]@[restriction_name]@Allow</dt>
 * <dt>restriction@[privilege_name]@[restriction_name]@Deny</dt>
 * <dd>One param for each restriction value. The same parameter name may be used again for multi-value restrictions. The @Allow or @Deny suffix 
 *     specifies whether to apply the restriction to the 'allow' or 'deny' privilege.  The value is the target value of the restriction to be set.</dd>
 * <dt>restriction@[privilege_name]@[restriction_name]@Delete</dt>
 * <dd>One param for each restriction to delete. The parameter value must be either 'allow', 'deny' or 'all' to specify which state to delete from.</dd>
 * </dl>
 *
 * <h4>Response</h4>
 * <dl>
 * <dt>200</dt>
 * <dd>Success.</dd>
 * <dt>404</dt>
 * <dd>The resource was not found.</dd>
 * <dt>500</dt>
 * <dd>Failure. HTML explains the failure.</dd>
 * </dl>
 *
 * <h4>Notes</h4>
 * <p>
 * The principalId is assumed to refer directly to an Authorizable, that comes direct from
 * the UserManager. This can be a group or a user, but if its a group, denied permissions
 * will not be added to the group. The group will only contain granted privileges.
 * </p>
 */

@Component(service = {Servlet.class, ModifyAce.class},
property= {
        "sling.servlet.resourceTypes=sling/servlet/default",
        "sling.servlet.methods=POST",
        "sling.servlet.selectors=modifyAce",
        "sling.servlet.prefix:Integer=-1"
})
public class ModifyAceServlet extends AbstractAccessPostServlet implements ModifyAce {
    private static final long serialVersionUID = -9182485466670280437L;
    private static final String INVALID_OR_NOT_SUPPORTED_RESTRICTION_NAME_WAS_SUPPLIED = "Invalid restriction name was supplied";

    /**
     * Possible values for a privilege parameter
     */
    private enum PrivilegeValues {
            ALLOW("allow"),
            GRANTED("granted"),
            NONE("none"),
            DENIED("denied"),
            DENY("deny"),
            INVALID("*");

        private String paramValue;

        private PrivilegeValues(String paramValue) {
            this.paramValue = paramValue;
        }

        public static PrivilegeValues valueOfParam(String value) {
            return Stream.of(PrivilegeValues.values())
                .filter(item -> item.paramValue.equalsIgnoreCase(value))
                .findFirst()
                .orElse(INVALID);
        }
    }

    /**
     * Possible values for a delete privilege or restriction parameter
     */
    private enum DeleteValues {
        ALL("all"),
        ALLOW("allow"),
        DENY("deny"),
        INVALID("*");

        private String paramValue;

        private DeleteValues(String paramValue) {
            this.paramValue = paramValue;
        }

        public static DeleteValues valueOfParam(String value) {
            return Stream.of(DeleteValues.values())
                .filter(item -> item.paramValue.equalsIgnoreCase(value))
                .findFirst()
                .orElse(INVALID);
        }
    }

    private static final Pattern PRIVILEGE_PATTERN = Pattern.compile(String.format("^privilege@(.+)(?<!%s)$",
            SlingPostConstants.SUFFIX_DELETE));
    private static final Pattern PRIVILEGE_PATTERN_DELETE = Pattern.compile(String.format("^privilege@(.+)%s$",
            SlingPostConstants.SUFFIX_DELETE));
    private static final Pattern RESTRICTION_PATTERN = Pattern.compile("^restriction@([^@]+)(@([^@]+)@(Allow|Deny))?$");
    private static final Pattern RESTRICTION_PATTERN_DELETE = Pattern.compile(String.format("^restriction@([^@]+)(@([^@]+))?%s$",
                SlingPostConstants.SUFFIX_DELETE));

    private transient RestrictionProvider restrictionProvider = null;

    // NOTE: the @Reference annotation is not inherited, so subclasses will need to override the #bindRestrictionProvider 
    // and #unbindRestrictionProvider methods to provide the @Reference annotation.     
    //
    @Reference(cardinality=ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC, policyOption=ReferencePolicyOption.GREEDY)
    protected void bindRestrictionProvider(RestrictionProvider rp) {
        this.restrictionProvider = rp;
    }
    protected void unbindRestrictionProvider(RestrictionProvider rp) { //NOSONAR
        this.restrictionProvider = null;
    }

    /**
     * Overridden since the @Reference annotation is not inherited from the super method
     */
    @Override
    @Reference(service = PostResponseCreator.class,
        cardinality = ReferenceCardinality.MULTIPLE,
        policy = ReferencePolicy.DYNAMIC)
    protected void bindPostResponseCreator(PostResponseCreator creator, Map<String, Object> properties) {
        super.bindPostResponseCreator(creator, properties);
    }

    /* (non-Javadoc)
     * @see org.apache.sling.jackrabbit.usermanager.impl.post.AbstractPostServlet#unbindPostResponseCreator(org.apache.sling.servlets.post.PostResponseCreator, java.util.Map)
     */
    @Override
    protected void unbindPostResponseCreator(PostResponseCreator creator, Map<String, Object> properties) { //NOSONAR
        super.unbindPostResponseCreator(creator, properties);
    }

    /* (non-Javadoc)
     * @see org.apache.sling.jackrabbit.accessmanager.post.AbstractAccessPostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.servlets.post.PostResponse, java.util.List)
     */
    @Override
    protected void handleOperation(SlingHttpServletRequest request,
            PostResponse response, List<Modification> changes)
            throws RepositoryException {
        Session session = request.getResourceResolver().adaptTo(Session.class);
        String resourcePath = getItemPath(request);
        String principalId = request.getParameter("principalId");
        String order = request.getParameter("order");

        Principal principal = validateArgs(session, resourcePath, principalId);

        // Calculate a map of restriction names to the restriction definition.
        // Use for fast lookup during the calls below.
        Map<String, RestrictionDefinition> srMap = buildRestrictionNameToDefinitionMap(resourcePath);
        AccessControlManager acm = AccessControlUtil.getAccessControlManager(session);
        Map<Privilege, Integer> privilegeLongestDepthMap = PrivilegesHelper.buildPrivilegeLongestDepthMap(acm.privilegeFromName(PrivilegeConstants.JCR_ALL));

        // first calculate what is currently stored in the ace
        Map<Privilege, LocalPrivilege> privilegeToLocalPrivilegesMap = loadStoredAce(acm, resourcePath, principal, srMap);

        // and now merge the changes from the request parameters
        processPostedPrivilegeDeleteParams(acm, request, privilegeToLocalPrivilegesMap);
        processPostedRestrictionDeleteParams(acm, request, srMap, privilegeToLocalPrivilegesMap);
        processPostedPrivilegeParams(acm, request, privilegeToLocalPrivilegesMap, privilegeLongestDepthMap);
        processPostedRestrictionParams(acm, request, srMap, privilegeToLocalPrivilegesMap, privilegeLongestDepthMap);

        // consolidate any aggregates that are still valid
        PrivilegesHelper.consolidateAggregates(session, resourcePath, privilegeToLocalPrivilegesMap, privilegeLongestDepthMap);

        // and then store it
        modifyAce(session, resourcePath, principalId, privilegeToLocalPrivilegesMap.values(), order, false, changes);
    }

    /**
     * Verify that the user supplied arguments are valid
     * 
     * @param jcrSession the JCR session
     * @param resourcePath the resource path
     * @param principalId the principal id
     * @return the principal for the requested principalId
     */
    protected @NotNull Principal validateArgs(Session jcrSession, String resourcePath, String principalId) throws RepositoryException {
        if (jcrSession == null) {
            throw new RepositoryException("JCR Session not found");
        }

        if (restrictionProvider == null) {
            throw new IllegalStateException("No restriction provider is available so unable to process POSTed restriction values");
        }

        if (principalId == null) {
            throw new RepositoryException("principalId was not submitted.");
        }

        // validate that the submitted name is valid
        PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(jcrSession);
        Principal principal = principalManager.getPrincipal(principalId);
        if (principal == null) {
            throw new RepositoryException("Invalid principalId was submitted.");
        }

        validateResourcePath(jcrSession, resourcePath);

        AccessControlManager acm = AccessControlUtil.getAccessControlManager(jcrSession);
        JackrabbitAccessControlList acl = getAcl(acm, resourcePath, principal);
        if (acl == null) {
            throw new IllegalStateException("No access control list is available so unable to process");
        }

        return principal;
    }

    /**
     * Calculate a map of restriction names to the restriction definition
     * 
     * @param resourcePath the path of the resource
     * @return map of restriction names to definition
     */
    protected @NotNull Map<String, RestrictionDefinition> buildRestrictionNameToDefinitionMap(@NotNull String resourcePath) {
        Set<RestrictionDefinition> supportedRestrictions = restrictionProvider.getSupportedRestrictions(resourcePath);
        Map<String, RestrictionDefinition> srMap = new HashMap<>();
        for (RestrictionDefinition restrictionDefinition : supportedRestrictions) {
            srMap.put(restrictionDefinition.getName(), restrictionDefinition);
        }
        return srMap;
    }

    /**
     * Loads the state for the currently stored ACE for the specified principal.
     * The state for any aggregate privilege is expanded to make it easier to merge changes.
     * 
     * @param acm the access control manager
     * @param resourcePath the resource path
     * @param forPrincipal the principal to load the ace for
     * @param srMap map of restriction names to the restriction definition
     * @return the privileges from the ace as a map where the key is the privilege
     *          and the value is the LocalPrivilege that encapsulates the state
     */
    protected @NotNull Map<Privilege, LocalPrivilege> loadStoredAce(@NotNull AccessControlManager acm, @NotNull String resourcePath,
            @NotNull Principal forPrincipal, @NotNull Map<String, RestrictionDefinition> srMap) throws RepositoryException {
        Map<Privilege, LocalPrivilege> privilegeToLocalPrivilegesMap = new HashMap<>();
        JackrabbitAccessControlList acl = getAcl(acm, resourcePath, forPrincipal);
        AccessControlEntry[] accessControlEntries = acl.getAccessControlEntries();
        //evaluate these in reverse order so the entries with highest specificity are processed last
        for (int i = accessControlEntries.length - 1; i >= 0; i--) {
            AccessControlEntry accessControlEntry = accessControlEntries[i];
            JackrabbitAccessControlEntry jrAccessControlEntry = getJackrabbitAccessControlEntry(accessControlEntry, resourcePath, forPrincipal);
            if (jrAccessControlEntry != null) {
                Privilege[] privileges = jrAccessControlEntry.getPrivileges();
                if (privileges != null) {
                    boolean isAllow = jrAccessControlEntry.isAllow();
                    // populate the declared restrictions
                    @NotNull
                    String[] restrictionNames = jrAccessControlEntry.getRestrictionNames();
                    Set<LocalRestriction> restrictionItems = new HashSet<>();
                    for (String restrictionName : restrictionNames) {
                        RestrictionDefinition rd = srMap.get(restrictionName);
                        if (rd != null) { // should never get null value here
                            boolean isMulti = rd.getRequiredType().isArray();
                            if (isMulti) {
                                restrictionItems.add(new LocalRestriction(rd, jrAccessControlEntry.getRestrictions(restrictionName)));
                            } else {
                                restrictionItems.add(new LocalRestriction(rd, jrAccessControlEntry.getRestriction(restrictionName)));
                            }
                        }
                    }

                    if (isAllow) {
                        PrivilegesHelper.allow(privilegeToLocalPrivilegesMap, restrictionItems, Arrays.asList(privileges));
                    } else {
                        PrivilegesHelper.deny(privilegeToLocalPrivilegesMap, restrictionItems, Arrays.asList(privileges));
                    }
                }
            }
        }
        return privilegeToLocalPrivilegesMap;
    }

    protected @Nullable JackrabbitAccessControlEntry getJackrabbitAccessControlEntry(@NotNull AccessControlEntry entry, @NotNull String resourcePath,
            @NotNull Principal forPrincipal) {
        JackrabbitAccessControlEntry jrEntry = null;
        if (entry instanceof JackrabbitAccessControlEntry &&
                entry.getPrincipal().equals(forPrincipal)) {
            jrEntry = (JackrabbitAccessControlEntry)entry;
        }
        return jrEntry;
    }

    /**
     * Helper to return a filtered list of parameter names that match the pattern
     * @param request the current request
     * @param pattern the regex pattern to match
     * @return map of parameter names to Matcher that match the pattern
     */
    protected @NotNull Map<String, Matcher> getMatchedRequestParameterNames(@NotNull SlingHttpServletRequest request, @NotNull Pattern pattern) {
        Map<String, Matcher> keys = new HashMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String key = parameterNames.nextElement();
            Matcher matcher = pattern.matcher(key);
            if (matcher.matches()) {
                keys.put(key, matcher);
            }
        }
        return keys;
    }

    /**
     * Merge into the privilegeToLocalPrivilegesMap the changes requested in privilege
     * delete request parameters.
     * 
     * @param acm the access control manager
     * @param request the current request
     * @param privilegeToLocalPrivilegesMap the map containing the declared LocalPrivilege items
     */
    protected void processPostedPrivilegeDeleteParams(@NotNull AccessControlManager acm,
            @NotNull SlingHttpServletRequest request,
            @NotNull Map<Privilege, LocalPrivilege> privilegeToLocalPrivilegesMap) throws RepositoryException {
        @NotNull
        Map<String, Matcher> postedPrivilegeDeleteNames = getMatchedRequestParameterNames(request, PRIVILEGE_PATTERN_DELETE);
        for (Entry<String, Matcher> entry : postedPrivilegeDeleteNames.entrySet()) {
            String paramName = entry.getKey();
            Matcher matcher = entry.getValue();
            String privilegeName = matcher.group(1);
            Privilege privilege = acm.privilegeFromName(privilegeName);
            String paramValue = request.getParameter(paramName);
            DeleteValues value = DeleteValues.valueOfParam(paramValue);
            if (DeleteValues.ALL.equals(value) || DeleteValues.ALLOW.equals(value)) {
                PrivilegesHelper.unallow(privilegeToLocalPrivilegesMap,
                        Collections.singleton(privilege));
            }
            if (DeleteValues.ALL.equals(value) || DeleteValues.DENY.equals(value)) {
                PrivilegesHelper.undeny(privilegeToLocalPrivilegesMap,
                        Collections.singleton(privilege));
            }
        }
    }

    /**
     * Merge into the privilegeToLocalPrivilegesMap the changes requested in restriction
     * delete request parameters.
     * 
     * @param acm the access control manager
     * @param request the current request
     * @param srMap map of restriction names to the restriction definition
     * @param privilegeToLocalPrivilegesMap the map containing the declared LocalPrivilege items
     */
    protected void processPostedRestrictionDeleteParams(@NotNull AccessControlManager acm,
            @NotNull SlingHttpServletRequest request,
            @NotNull Map<String, RestrictionDefinition> srMap,
            @NotNull Map<Privilege, LocalPrivilege> privilegeToLocalPrivilegesMap) throws RepositoryException {
        @NotNull
        Map<String, Matcher> postedRestrictionDeleteNames = getMatchedRequestParameterNames(request, RESTRICTION_PATTERN_DELETE);
        for (Entry<String, Matcher> entry : postedRestrictionDeleteNames.entrySet()) {
            String paramName = entry.getKey();
            Matcher matcher = entry.getValue();
            String privilegeName;
            String restrictionName;
            if (matcher.group(2) != null) {
                privilegeName = matcher.group(1);
                restrictionName = matcher.group(3);
            } else {
                privilegeName = null;
                restrictionName = matcher.group(1);
            }
            RestrictionDefinition rd = srMap.get(restrictionName);
            if (rd == null) {
                //illegal restriction name?
                throw new AccessControlException(INVALID_OR_NOT_SUPPORTED_RESTRICTION_NAME_WAS_SUPPLIED);
            }
            Collection<Privilege> privileges;
            if (privilegeName == null) {
                // process for every privilege
                privileges = privilegeToLocalPrivilegesMap.keySet();
            } else {
                // process for the specific privilege only
                Privilege privilege = acm.privilegeFromName(privilegeName);
                privileges = Collections.singletonList(privilege);
            }
            String[] parameterValues;
            if (privilegeName == null) {
                // for backward compatibility, the restriction@[restriction_name]@Delete syntax
                //   deletes from both 'allow' and 'deny'
                parameterValues = new String[] { "all" };
            } else {
                parameterValues = request.getParameterValues(paramName);
            }
            for (String allowOrDeny : parameterValues) {
                DeleteValues value = DeleteValues.valueOfParam(allowOrDeny);
                switch (value) {
                case ALL:
                    // not specified try both the deny and allow sets
                    PrivilegesHelper.unallowOrUndenyRestriction(privilegeToLocalPrivilegesMap,
                            restrictionName, privileges);
                    break;
                case ALLOW:
                    PrivilegesHelper.unallowRestriction(privilegeToLocalPrivilegesMap,
                            restrictionName, privileges);
                    break;
                case DENY:
                    PrivilegesHelper.undenyRestriction(privilegeToLocalPrivilegesMap,
                            restrictionName, privileges);
                    break;
                default:
                    break;
                }
            }
        }
    }

    /**
     * Merge into the privilegeToLocalPrivilegesMap the changes requested in restriction
     * request parameters.
     * 
     * @param acm the access control manager
     * @param request the current request
     * @param srMap map of restriction names to the restriction definition
     * @param privilegeToLocalPrivilegesMap the map containing the declared LocalPrivilege items
     */
    protected void processPostedRestrictionParams(@NotNull AccessControlManager acm,
            @NotNull SlingHttpServletRequest request,
            @NotNull Map<String, RestrictionDefinition> srMap,
            @NotNull Map<Privilege, LocalPrivilege> privilegeToLocalPrivilegesMap,
            @NotNull Map<Privilege, Integer> privilegeLongestDepthMap) throws RepositoryException {
        Session session = request.getResourceResolver().adaptTo(Session.class);
        ValueFactory vf = session.getValueFactory();

        // first pass to collect all the restrictions so we can
        //    process them in the right order
        Map<Privilege, Map<LocalRestriction, Set<String>>> privilegeToLocalRestrictionMap = new HashMap<>();
        @NotNull
        Map<String, Matcher> postedRestrictionParams = getMatchedRequestParameterNames(request, RESTRICTION_PATTERN);
        for (Entry<String, Matcher> entry : postedRestrictionParams.entrySet()) {
            String paramName = entry.getKey();
            Matcher matcher = entry.getValue();
            String privilegeName;
            String restrictionName;
            String allowOrDeny;
            if (matcher.group(2) != null) {
                privilegeName = matcher.group(1);
                restrictionName = matcher.group(3);
                allowOrDeny = matcher.group(4);
            } else {
                privilegeName = null;
                restrictionName = matcher.group(1);
                allowOrDeny = null;
            }

            Privilege privilege = privilegeName == null ? null : acm.privilegeFromName(privilegeName);

            RestrictionDefinition rd = srMap.get(restrictionName);
            if (rd == null) {
                //illegal restriction name?
                throw new AccessControlException(INVALID_OR_NOT_SUPPORTED_RESTRICTION_NAME_WAS_SUPPLIED);
            }
            LocalRestriction localRestriction;
            int restrictionType = rd.getRequiredType().tag();
            if (rd.getRequiredType().isArray()) {
                // multi-value
                String[] parameterValues = request.getParameterValues(paramName);
                Value[] restrictionValue = new Value[parameterValues.length];
                for (int i = 0; i < parameterValues.length; i++) {
                    restrictionValue[i] = vf.createValue(parameterValues[i], restrictionType);
                }
                localRestriction = new LocalRestriction(rd, restrictionValue);
            } else {
                // single value
                Value restrictionValue = vf.createValue(request.getParameter(paramName), restrictionType);
                localRestriction = new LocalRestriction(rd, restrictionValue);
            }

            Map<LocalRestriction, Set<String>> lrMap = privilegeToLocalRestrictionMap.computeIfAbsent(privilege, k -> new HashMap<>());
            Set<String> valuesSet = lrMap.computeIfAbsent(localRestriction, k -> new HashSet<>());
            valuesSet.add(allowOrDeny);
        }

        List<Entry<Privilege, Map<LocalRestriction, Set<String>>>> sortedEntries = new ArrayList<>(privilegeToLocalRestrictionMap.entrySet());
        // sort the entries to process the most shallow last
        Collections.sort(sortedEntries, Comparator.nullsFirst(Comparator.comparing(entry -> privilegeLongestDepthMap.get(entry.getKey()))));
        for (Entry<Privilege, Map<LocalRestriction, Set<String>>> entry : sortedEntries) {
            Privilege privilege = entry.getKey();

            Collection<Privilege> privileges;
            if (privilege == null) {
                // process for every privilege
                privileges = privilegeToLocalPrivilegesMap.keySet();
            } else {
                // process for the specific privilege only
                privileges = Collections.singletonList(privilege);
            }

            Map<LocalRestriction, Set<String>> lrMap = entry.getValue();
            for (Entry<LocalRestriction, Set<String>> lrEntry : lrMap.entrySet()) {
                LocalRestriction localRestriction = lrEntry.getKey();
                // sort the values to ensure it processes the Allow entry last when
                //   there is a conflict
                List<PrivilegeValues> privilegeValues = lrEntry.getValue().stream()
                    .map(item -> item == null ? null : PrivilegeValues.valueOfParam(item))
                    .sorted(Comparator.nullsLast(Comparator.comparing(PrivilegeValues::ordinal).reversed()))
                    .collect(Collectors.toList());
                for (PrivilegeValues allowOrDeny : privilegeValues) {
                    if (allowOrDeny == null) {
                        // not specified try both the deny and allow sets
                        PrivilegesHelper.allowOrDenyRestriction(privilegeToLocalPrivilegesMap, localRestriction, privileges);
                    } else {
                        switch (allowOrDeny) {
                        case DENY:
                            PrivilegesHelper.denyRestriction(privilegeToLocalPrivilegesMap, localRestriction, privileges);
                            break;
                        case ALLOW:
                            PrivilegesHelper.allowRestriction(privilegeToLocalPrivilegesMap, localRestriction, privileges);
                            break;
                        default:
                            break;
                        }
                    }
                }
            }
        }
    }

    /**
     * Merge into the privilegeToLocalPrivilegesMap the changes requested in privilege
     * request parameters.
     * 
     * @param acm the access control manager
     * @param request the current request
     * @param privilegeToLocalPrivilegesMap the map containing the declared LocalPrivilege items
     */
    protected void processPostedPrivilegeParams(@NotNull AccessControlManager acm,
            @NotNull SlingHttpServletRequest request,
            @NotNull Map<Privilege, LocalPrivilege> privilegeToLocalPrivilegesMap,
            @NotNull Map<Privilege, Integer> privilegeLongestDepthMap) throws RepositoryException {
        @NotNull
        Map<String, Matcher> postedPrivilegeNameKeys = getMatchedRequestParameterNames(request, PRIVILEGE_PATTERN);

        // first pass to collect all the privileges so we can
        //    process them in the right order
        Map<Privilege, String> privilegeToParamNameMap = new HashMap<>();
        for (Entry<String, Matcher> entry : postedPrivilegeNameKeys.entrySet()) {
            String paramName = entry.getKey();
            Matcher matcher = entry.getValue();
            String privilegeName = matcher.group(1);
            Privilege privilege = acm.privilegeFromName(privilegeName);
            privilegeToParamNameMap.put(privilege, paramName);
        }
        List<Entry<Privilege, String>> sortedEntries = new ArrayList<>(privilegeToParamNameMap.entrySet());
        // sort the entries to process the most shallow last
        Collections.sort(sortedEntries, (e1, e2) -> privilegeLongestDepthMap.get(e1.getKey()).compareTo(privilegeLongestDepthMap.get(e2.getKey())));
        for (Entry<Privilege, String> entry : sortedEntries) {
            String paramName = entry.getValue();
            Privilege privilege = entry.getKey();

            String [] paramValues = request.getParameterValues(paramName);
            // convert and sort the values to ensure that allow goes after
            //  deny or none when there is a conflict
            List<PrivilegeValues> privilegeValues = Stream.of(paramValues)
                .map(PrivilegeValues::valueOfParam)
                .sorted((v1, v2) -> Integer.compare(v2.ordinal(), v1.ordinal()))
                .collect(Collectors.toList());
            for (PrivilegeValues value : privilegeValues) {
                switch (value) {
                case DENY:
                case DENIED:
                    PrivilegesHelper.deny(privilegeToLocalPrivilegesMap, Collections.emptySet(), Collections.singleton(privilege));
                    break;
                case ALLOW:
                case GRANTED:
                    PrivilegesHelper.allow(privilegeToLocalPrivilegesMap, Collections.emptySet(), Collections.singleton(privilege));
                    break;
                case NONE:
                    PrivilegesHelper.none(privilegeToLocalPrivilegesMap, Collections.singleton(privilege));
                    break;
                default:
                    break;
                }
            }
        }
    }

    /**
     * Lookup the ACL for the given resource
     * 
     * @param acm the access control manager
     * @param resourcePath the resource path
     * @param principal the principal for principalbased ACL
     * @return the found ACL object
     */
    protected JackrabbitAccessControlList getAcl(@NotNull AccessControlManager acm, String resourcePath, Principal principal)
            throws RepositoryException {
        AccessControlPolicy[] policies = acm.getPolicies(resourcePath);
        JackrabbitAccessControlList acl = null;
        for (AccessControlPolicy policy : policies) {
            if (policy instanceof JackrabbitAccessControlList) {
                acl = (JackrabbitAccessControlList) policy;
                break;
            }
        }
        if (acl == null) {
            AccessControlPolicyIterator applicablePolicies = acm.getApplicablePolicies(resourcePath);
            while (applicablePolicies.hasNext()) {
                AccessControlPolicy policy = applicablePolicies.nextAccessControlPolicy();
                if (policy instanceof JackrabbitAccessControlList) {
                    acl = (JackrabbitAccessControlList) policy;
                    break;
                }
            }
        }
        return acl;
    }

    /**
     * Remove all of the ACEs for the specified principal from the ACL
     * 
     * @param order the requested order (may be null)
     * @param principal the principal whose aces should be removed
     * @param acl the access control list to update
     * @return the original order if it was supplied, otherwise the order of the first ACE 
     */
    protected String removeAces(@NotNull String resourcePath, @Nullable String order, @NotNull Principal principal, @NotNull JackrabbitAccessControlList acl) // NOSONAR
            throws RepositoryException {
        AccessControlEntry[] existingAccessControlEntries = acl.getAccessControlEntries();
        for (int j = 0; j < existingAccessControlEntries.length; j++) {
            AccessControlEntry ace = existingAccessControlEntries[j];
            if (ace.getPrincipal().equals(principal)) {
                if (order == null || order.length() == 0) {
                    //order not specified, so keep track of the original ACE position.
                    order = String.valueOf(j);
                }

                acl.removeAccessControlEntry(ace);
            }
        }
        return order;
    }

    /**
     * Add ACEs for the specified principal to the ACL.  One ACE is added for each unique
     * restriction set.
     * 
     * @param resourcePath the path of the resource
     * @param principal the principal whose aces should be added
     * @param restrictionsToLocalPrivilegesMap the map containing the restrictions mapped to the LocalPrivlege items with those resrictions
     * @param isAllow true for 'allow' ACE, false for 'deny' ACE
     * @param acl the access control list to update
     */
    protected void addAces(@NotNull String resourcePath, @NotNull Principal principal,
            @NotNull Map<Set<LocalRestriction>, List<LocalPrivilege>> restrictionsToLocalPrivilegesMap,
            boolean isAllow,
            @NotNull JackrabbitAccessControlList acl) throws RepositoryException {

        List<Entry<Set<LocalRestriction>, List<LocalPrivilege>>> sortedEntries = new ArrayList<>(restrictionsToLocalPrivilegesMap.entrySet());
        // sort the entries to so the ACE without restrictions is last
        Collections.sort(sortedEntries, (e1, e2) -> Integer.compare(e2.getKey().size(), e1.getKey().size()));

        for (Entry<Set<LocalRestriction>, List<LocalPrivilege>> entry: sortedEntries) {
            Set<Privilege> privilegesSet = new HashSet<>();
            Map<String, Value> restrictions = new HashMap<>(); 
            Map<String, Value[]> mvRestrictions = new HashMap<>();

            Set<LocalRestriction> localRestrictions = entry.getKey();
            for (LocalRestriction localRestriction : localRestrictions) {
                if (localRestriction.isMultiValue()) {
                    mvRestrictions.put(localRestriction.getName(), localRestriction.getValues());
                } else {
                    restrictions.put(localRestriction.getName(), localRestriction.getValue());
                }
            }

            for (LocalPrivilege localPrivilege : entry.getValue()) {
                privilegesSet.add(localPrivilege.getPrivilege());
            }

            if (!privilegesSet.isEmpty()) {
                if (acl instanceof PrincipalAccessControlList) {
                    ((PrincipalAccessControlList)acl).addEntry(resourcePath, privilegesSet.toArray(new Privilege[privilegesSet.size()]), restrictions, mvRestrictions);
                } else {
                    acl.addEntry(principal, privilegesSet.toArray(new Privilege[privilegesSet.size()]), isAllow, restrictions, mvRestrictions);
                }
            }
        }
    }

    /**
     * Move the ACE(s) for the specified principal to the position specified by the 'order'
     * parameter. This is a copy of the private AccessControlUtil.reorderAccessControlEntries method.
     *
     * @param acl the acl of the node containing the ACE to position
     * @param principal the user or group of the ACE to position
     * @param order where the access control entry should go in the list.
     *         Value should be one of these:
     *         <table>
     *          <caption>Values</caption>
     *          <tr><td>first</td><td>Place the target ACE as the first amongst its siblings</td></tr>
     *          <tr><td>last</td><td>Place the target ACE as the last amongst its siblings</td></tr>
     *          <tr><td>before xyz</td><td>Place the target ACE immediately before the sibling whose name is xyz</td></tr>
     *          <tr><td>after xyz</td><td>Place the target ACE immediately after the sibling whose name is xyz</td></tr>
     *          <tr><td>numeric</td><td>Place the target ACE at the specified index</td></tr>
     *         </table>
     * @throws RepositoryException
     * @throws UnsupportedRepositoryOperationException
     * @throws AccessControlException
     */
    private static void reorderAccessControlEntries(AccessControlList acl,
            Principal principal, String order) throws RepositoryException {
        if (order == null || order.length() == 0) {
            return; //nothing to do
        }
        if (acl instanceof JackrabbitAccessControlList) {
            JackrabbitAccessControlList jacl = (JackrabbitAccessControlList)acl;

            AccessControlEntry[] accessControlEntries = jacl.getAccessControlEntries();
            if (accessControlEntries.length <= 1) {
                return; //only one ACE, so nothing to reorder.
            }

            AccessControlEntry beforeEntry = null;
            if ("first".equals(order)) {
                beforeEntry = accessControlEntries[0];
            } else if ("last".equals(order)) {
                // add to the end is the same as default
            } else if (order.startsWith("before ")) {
                String beforePrincipalName = order.substring(7);

                //find the index of the ACE of the 'before' principal
                for (int i=0; i < accessControlEntries.length; i++) {
                    if (beforePrincipalName.equals(accessControlEntries[i].getPrincipal().getName())) {
                        //found it!
                        beforeEntry = accessControlEntries[i];
                        break;
                    }
                }

                if (beforeEntry == null) {
                    //didn't find an ACE that matched the 'before' principal
                    throw new IllegalArgumentException("No ACE was found for the specified principal: " + beforePrincipalName);
                }
            } else if (order.startsWith("after ")) {
                String afterPrincipalName = order.substring(6);

                //find the index of the ACE of the 'after' principal
                for (int i = accessControlEntries.length - 1; i >= 0; i--) {
                    if (afterPrincipalName.equals(accessControlEntries[i].getPrincipal().getName())) {
                        //found it!

                        // the 'before' ACE is the next one after the 'after' ACE
                        if (i >= accessControlEntries.length - 1) {
                            //the after is the last one in the list
                            beforeEntry = null;
                        } else {
                            beforeEntry = accessControlEntries[i + 1];
                        }
                        break;
                    }
                }

                if (beforeEntry == null) {
                    //didn't find an ACE that matched the 'after' principal
                    throw new IllegalArgumentException("No ACE was found for the specified principal: " + afterPrincipalName);
                }
            } else {
                try {
                    int index = Integer.parseInt(order);
                    if (index > accessControlEntries.length) {
                        //invalid index
                        throw new IndexOutOfBoundsException("Index value is too large: " + index);
                    }

                    if (index == 0) {
                        beforeEntry = accessControlEntries[0];
                    } else {
                        //the index value is the index of the principal.  A principal may have more
                        // than one ACEs (deny + grant), so we need to compensate.
                        Set<Principal> processedPrincipals = new HashSet<>();
                        for (int i = 0; i < accessControlEntries.length; i++) {
                            Principal principal2 = accessControlEntries[i].getPrincipal();
                            if (processedPrincipals.size() == index &&
                                    !processedPrincipals.contains(principal2)) {
                                //we are now at the correct position in the list
                                beforeEntry = accessControlEntries[i];
                                break;
                            }

                            processedPrincipals.add(principal2);
                        }
                    }
                } catch (NumberFormatException nfe) {
                    //not a number.
                    throw new IllegalArgumentException("Illegal value for the order parameter: " + order);
                }
            }

            //now loop through the entries to move the affected ACEs to the specified
            // position.
            for (int i = accessControlEntries.length - 1; i >= 0; i--) {
                AccessControlEntry ace = accessControlEntries[i];
                if (principal.equals(ace.getPrincipal())) {
                    //this ACE is for the specified principal.
                    jacl.orderBefore(ace, beforeEntry);
                }
            }
        } else {
            throw new IllegalArgumentException("The acl must be an instance of JackrabbitAccessControlList");
        }
    }

    /* (non-Javadoc)
     * @see org.apache.sling.jcr.jackrabbit.accessmanager.ModifyAce#modifyAce(javax.jcr.Session, java.lang.String, java.lang.String, java.util.Map, java.lang.String, boolean)
     */
    @Override
    public void modifyAce(Session jcrSession, String resourcePath, String principalId, Map<String, String> privileges,
            String order, boolean autoSave) throws RepositoryException {
        modifyAce(jcrSession, resourcePath, principalId, privileges, order, 
                null, null, null, autoSave);
    }

    /* (non-Javadoc)
     * @see org.apache.sling.jcr.jackrabbit.accessmanager.ModifyAce#modifyAce(javax.jcr.Session, java.lang.String, java.lang.String, java.util.Map, java.lang.String)
     */
    public void modifyAce(Session jcrSession, String resourcePath,
            String principalId, Map<String, String> privileges, String order)
            throws RepositoryException {
        modifyAce(jcrSession, resourcePath, principalId, privileges, order, true);
    }
    
    /* (non-Javadoc)
     * @see org.apache.sling.jcr.jackrabbit.accessmanager.ModifyAce#modifyAce(javax.jcr.Session, java.lang.String, java.lang.String, java.util.Map, java.lang.String, java.util.Map, java.util.Map, java.util.Set)
     */
    @Override
    public void modifyAce(Session jcrSession, String resourcePath, String principalId, Map<String, String> privileges,
            String order, Map<String, Value> restrictions, Map<String, Value[]> mvRestrictions,
            Set<String> removeRestrictionNames) throws RepositoryException {
        modifyAce(jcrSession, resourcePath, principalId, privileges, order, 
                restrictions, mvRestrictions, removeRestrictionNames, true);
    }

    /* (non-Javadoc)
     * @see org.apache.sling.jcr.jackrabbit.accessmanager.ModifyAce#modifyAce(javax.jcr.Session, java.lang.String, java.lang.String, java.util.Map, java.lang.String, java.util.Map, java.util.Map, java.util.Set, boolean)
     */
    @Override
    public void modifyAce(Session jcrSession, String resourcePath, String principalId, Map<String, String> privileges,
            String order, Map<String, Value> restrictions, Map<String, Value[]> mvRestrictions,
            Set<String> removeRestrictionNames, boolean autoSave) throws RepositoryException {
        modifyAce(jcrSession, resourcePath, principalId, privileges, order, 
                restrictions, mvRestrictions, removeRestrictionNames, autoSave, null);
    }

    protected void modifyAce( // NOSONAR
            Session jcrSession, String resourcePath, String principalId, Map<String, String> privileges,
            String order, Map<String, Value> restrictions, Map<String, Value[]> mvRestrictions,
            Set<String> removeRestrictionNames, boolean autoSave, List<Modification> changes) throws RepositoryException {

        Principal principal = validateArgs(jcrSession, resourcePath, principalId);

        // Calculate a map of restriction names to the restriction definition.
        // Use for fast lookup during the calls below.
        AccessControlManager acm = AccessControlUtil.getAccessControlManager(jcrSession);
        Map<String, RestrictionDefinition> srMap = buildRestrictionNameToDefinitionMap(resourcePath);
        Map<Privilege, Integer> privilegeLongestDepthMap = PrivilegesHelper.buildPrivilegeLongestDepthMap(acm.privilegeFromName(PrivilegeConstants.JCR_ALL));

        // first calculate what is currently stored in the ace
        Map<Privilege, LocalPrivilege> privilegeToLocalPrivilegesMap = loadStoredAce(acm, resourcePath, principal, srMap);

        //process the restrictions to remove
        for (LocalPrivilege lp : privilegeToLocalPrivilegesMap.values()) {
            if (lp.isAllow()) {
                PrivilegesHelper.unallowRestrictions(privilegeToLocalPrivilegesMap, removeRestrictionNames, Collections.singleton(lp.getPrivilege()));
            }
            if (lp.isDeny()) {
                PrivilegesHelper.undenyRestrictions(privilegeToLocalPrivilegesMap, removeRestrictionNames, Collections.singleton(lp.getPrivilege()));
            }
        }

        // process the new restrictions
        Set<LocalRestriction> localRestrictions = new HashSet<>();
        if (restrictions != null) {
            for (Entry<String, Value> entry : restrictions.entrySet()) {
                RestrictionDefinition rd = srMap.get(entry.getKey());
                if (rd == null) {
                    //illegal restriction name?
                    throw new AccessControlException(INVALID_OR_NOT_SUPPORTED_RESTRICTION_NAME_WAS_SUPPLIED);
                }
                localRestrictions.add(new LocalRestriction(rd, entry.getValue()));
            }
        }
        if (mvRestrictions != null) {
            for (Entry<String, Value[]> entry : mvRestrictions.entrySet()) {
                RestrictionDefinition rd = srMap.get(entry.getKey());
                if (rd == null) {
                    //illegal restriction name?
                    throw new AccessControlException(INVALID_OR_NOT_SUPPORTED_RESTRICTION_NAME_WAS_SUPPLIED);
                }
                localRestrictions.add(new LocalRestriction(rd, entry.getValue()));
            }
        }

        // map the values to the privileges with that value
        Map<PrivilegeValues, Set<Privilege>> privilegeValueToPrivilegesMap = new EnumMap<>(PrivilegeValues.class);
        for (Entry<String, String> entry : privileges.entrySet()) {
            String privilegeName = entry.getKey();
            // for backward compatibility, deal with a prefixed value 
            if (privilegeName.startsWith("privilege@")) {
                privilegeName = privilegeName.substring(10);
            }
            Privilege privilege = acm.privilegeFromName(privilegeName);
            PrivilegeValues value = PrivilegeValues.valueOfParam(entry.getValue());
            Set<Privilege> privilegesSet = privilegeValueToPrivilegesMap.computeIfAbsent(value, k -> new HashSet<>());
            privilegesSet.add(privilege);
        }

        // process the new privileges
        for (Entry<PrivilegeValues, Set<Privilege>> entry : privilegeValueToPrivilegesMap.entrySet()) {
            switch (entry.getKey()) {
            case GRANTED:
            case ALLOW:
                PrivilegesHelper.allow(privilegeToLocalPrivilegesMap, localRestrictions, entry.getValue());
                break;
            case DENIED:
            case DENY:
                PrivilegesHelper.deny(privilegeToLocalPrivilegesMap, localRestrictions, entry.getValue());
                break;
            case NONE:
                PrivilegesHelper.none(privilegeToLocalPrivilegesMap, entry.getValue());
                break;
            default:
                break;
            }
        }

        // combine any aggregates that are still valid
        PrivilegesHelper.consolidateAggregates(jcrSession, resourcePath, privilegeToLocalPrivilegesMap, privilegeLongestDepthMap);

        modifyAce(jcrSession, resourcePath, principalId, 
                privilegeToLocalPrivilegesMap.values(), order, 
                autoSave, changes);
    }

    /* (non-Javadoc)
     * @see org.apache.sling.jcr.jackrabbit.accessmanager.ModifyAce#modifyAce(javax.jcr.Session, java.lang.String, java.lang.String, java.util.Collection, java.lang.String, boolean)
     */
    @Override
    public void modifyAce(
            Session jcrSession, String resourcePath, String principalId, 
            Collection<LocalPrivilege> localPrivileges, String order, 
            boolean autoSave) throws RepositoryException {
        modifyAce(jcrSession, resourcePath, principalId, 
                localPrivileges, order, 
                autoSave, null);
    }

    protected void modifyAce(
            Session jcrSession, String resourcePath, String principalId, 
            Collection<LocalPrivilege> localPrivileges, String order, 
            boolean autoSave, List<Modification> changes) throws RepositoryException {
        @NotNull
        Principal principal = validateArgs(jcrSession, resourcePath, principalId);

        // build a list of each of the LocalPrivileges that have the same restrictions
        Map<Set<LocalRestriction>, List<LocalPrivilege>> allowRestrictionsToLocalPrivilegesMap = new HashMap<>();
        Map<Set<LocalRestriction>, List<LocalPrivilege>> denyRestrictionsToLocalPrivilegesMap = new HashMap<>();
        for (LocalPrivilege localPrivilege: localPrivileges) {
            if (localPrivilege.isAllow()) {
                List<LocalPrivilege> list = allowRestrictionsToLocalPrivilegesMap.computeIfAbsent(localPrivilege.getAllowRestrictions(), key -> new ArrayList<>());
                list.add(localPrivilege);
            }
            if (localPrivilege.isDeny()) {
                List<LocalPrivilege> list = denyRestrictionsToLocalPrivilegesMap.computeIfAbsent(localPrivilege.getDenyRestrictions(), key -> new ArrayList<>());
                list.add(localPrivilege);
            }
        }

        try {
            // Get or create the ACL for the node.
            AccessControlManager acm = AccessControlUtil.getAccessControlManager(jcrSession);
            JackrabbitAccessControlList acl = getAcl(acm, resourcePath, principal);

            // remove all the old aces for the principal
            order = removeAces(resourcePath, order, principal, acl);

            // now add all the new aces that we have collected
            addAces(resourcePath, principal, denyRestrictionsToLocalPrivilegesMap, false, acl);
            addAces(resourcePath, principal, allowRestrictionsToLocalPrivilegesMap, true, acl);

            // reorder the aces
            reorderAccessControlEntries(acl, principal, order);

            // Store the actual changes.
            acm.setPolicy(acl.getPath(), acl);

            if (changes != null) {
                changes.add(Modification.onModified(principal.getName()));
            }

            if (autoSave && jcrSession.hasPendingChanges()) {
                jcrSession.save();
            }
        } catch (RepositoryException re) {
            throw new RepositoryException("Failed to create ace.", re);
        }
    }

}
