/*
 * 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.base.util;

import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
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;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
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;

/**
 * A simple utility class providing utilities with respect to
 * access control over repositories.
 */
public class AccessControlUtil {

	// the name of the accessor method for the AccessControlManager
    private static final String METHOD_GET_ACCESS_CONTROL_MANAGER = "getAccessControlManager";
    // the name of the accessor method for the UserManager
    private static final String METHOD_GET_USER_MANAGER = "getUserManager";
    // the name of the accessor method for the PrincipalManager
    private static final String METHOD_GET_PRINCIPAL_MANAGER = "getPrincipalManager";
    // the name of the JackrabbitAccessControlList method getPath
    private static final String METHOD_JACKRABBIT_ACL_GET_PATH = "getPath";
    // the name of the JackrabbitAccessControlList method
    private static final String METHOD_JACKRABBIT_ACL_IS_EMPTY = "isEmpty";
    // the name of the JackrabbitAccessControlList method
    private static final String METHOD_JACKRABBIT_ACL_SIZE = "size";
    // the name of the JackrabbitAccessControlList method
    private static final String METHOD_JACKRABBIT_ACL_ADD_ENTRY = "addEntry";
    // 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 -----------------------------------------------------

	/**
     * Returns the <code>AccessControlManager</code> for the given
     * <code>session</code>. If the session does not have a
     * <code>getAccessControlManager</code> method, a
     * <code>UnsupportedRepositoryOperationException</code> is thrown. Otherwise
     * the <code>AccessControlManager</code> is returned or if the call fails,
     * the respective exception is thrown.
     *
     * @param session The JCR Session whose <code>AccessControlManager</code> is
     *            to be returned. If the session is a pooled session, the
     *            session underlying the pooled session is actually used.
     * @return The <code>AccessControlManager</code> of the session
     * @throws UnsupportedRepositoryOperationException If the session has no
     *             <code>getAccessControlManager</code> method or the exception
     *             thrown by the method.
     * @throws RepositoryException Forwarded from the
     *             <code>getAccessControlManager</code> method call.
     */
	public static AccessControlManager getAccessControlManager(Session session)
											throws UnsupportedRepositoryOperationException, RepositoryException {
        return safeInvokeRepoMethod(session, METHOD_GET_ACCESS_CONTROL_MANAGER, AccessControlManager.class);
	}

	// ---------- JackrabbitSession methods -----------------------------------------------

	/**
	 * Returns the <code>UserManager</code> for the given
     * <code>session</code>. If the session does not have a
     * <code>getUserManager</code> method, a
     * <code>UnsupportedRepositoryOperationException</code> is thrown. Otherwise
     * the <code>UserManager</code> is returned or if the call fails,
     * the respective exception is thrown.
	 *
	 * @param session  The JCR Session whose <code>UserManager</code> is
     *            to be returned. If the session is not a <code>JackrabbitSession</code>
     *            uses reflection to retrive the manager from the repository.
	 * @return The <code>UserManager</code> of the session.
	 * @throws AccessDeniedException If this session is not allowed
	 * 			  to access user data.
	 * @throws UnsupportedRepositoryOperationException If the session has no
     *            <code>getUserManager</code> method or the exception
     *            thrown by the method.
	 * @throws RepositoryException Forwarded from the
     *             <code>getUserManager</code> method call.
	 */
	public static UserManager getUserManager(Session session)
										throws AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
		JackrabbitSession jackrabbitSession = getJackrabbitSession(session);
		if(jackrabbitSession != null) {
			return jackrabbitSession.getUserManager();
		} else {
			return safeInvokeRepoMethod(session, METHOD_GET_USER_MANAGER, UserManager.class);
		}
	}

	/**
	 * Returns the <code>PrincipalManager</code> for the given
     * <code>session</code>. If the session does not have a
     * <code>PrincipalManager</code> method, a
     * <code>UnsupportedRepositoryOperationException</code> is thrown. Otherwise
     * the <code>PrincipalManager</code> is returned or if the call fails,
     * the respective exception is thrown.
	 *
	 * @param session  The JCR Session whose <code>PrincipalManager</code> is
     *            to be returned. If the session is not a <code>JackrabbitSession</code>
     *            uses reflection to retrive the manager from the repository.
	 * @return The <code>PrincipalManager</code> of the session.
	 * @throws AccessDeniedException
	 * @throws UnsupportedRepositoryOperationException If the session has no
	 * 				<code>PrincipalManager</code> method or the exception
     *             	thrown by the method.
	 * @throws RepositoryException Forwarded from the
     *             <code>PrincipalManager</code> method call.
	 */
	public static PrincipalManager getPrincipalManager(Session session)
										throws AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
		JackrabbitSession jackrabbitSession = getJackrabbitSession(session);
		if(jackrabbitSession != null) {
			return jackrabbitSession.getPrincipalManager();
		} else {
			return safeInvokeRepoMethod(session, METHOD_GET_PRINCIPAL_MANAGER, PrincipalManager.class);
		}
	}

	// ---------- AccessControlList methods -----------------------------------------------

	/**
	 * Returns the path of the node <code>AccessControlList</code> acl
	 * has been created for.
	 */
	public static String getPath(AccessControlList acl) throws RepositoryException {
			return safeInvokeRepoMethod(acl, METHOD_JACKRABBIT_ACL_GET_PATH, String.class);
	}

	/**
	 * Returns <code>true</code> if <code>AccessControlList</code> acl
	 * does not yet define any entries.
	 */
    public static boolean isEmpty(AccessControlList acl) throws RepositoryException {
		return safeInvokeRepoMethod(acl, METHOD_JACKRABBIT_ACL_IS_EMPTY, Boolean.class);
    }

    /**
     * Returns the number of acl entries or 0 if the acl is empty.
     */
    public static int size(AccessControlList acl) throws RepositoryException {
		return safeInvokeRepoMethod(acl, METHOD_JACKRABBIT_ACL_SIZE, Integer.class);
    }

    /**
     * Same as {@link #addEntry(AccessControlList, Principal, Privilege[], boolean, Map)} using
     * some implementation specific restrictions.
     */
    @SuppressWarnings("unchecked")
	public static boolean addEntry(AccessControlList acl, Principal principal, Privilege privileges[], boolean isAllow)
        							throws AccessControlException, RepositoryException {
    	Object[] args = new Object[] {principal, privileges, isAllow};
    	Class[] types = new Class[] {Principal.class, Privilege[].class, boolean.class};
		return safeInvokeRepoMethod(acl, METHOD_JACKRABBIT_ACL_ADD_ENTRY, Boolean.class, args, types);
    }

    /**
     * Adds an access control entry to the acl consisting of the specified
     * <code>principal</code>, the specified <code>privileges</code>, the
     * <code>isAllow</code> flag and an optional map containing additional
     * restrictions.
     * <p/>
     * This method returns <code>true</code> if this policy was modified,
     * <code>false</code> otherwise.
     */
    @SuppressWarnings("unchecked")
	public static boolean addEntry(AccessControlList acl, Principal principal, Privilege privileges[], boolean isAllow, Map restrictions)
    															throws UnsupportedRepositoryOperationException, RepositoryException {
    	Object[] args = new Object[] {principal, privileges, isAllow, restrictions};
    	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
     * @deprecated use @link {@link #replaceAccessControlEntry(Session, String, Principal, String[], String[], String[], String)} instead.
     */
    public static void replaceAccessControlEntry(Session session, String resourcePath, Principal principal, 
			String[] grantedPrivilegeNames, String[] deniedPrivilegeNames, String[] removedPrivilegeNames)
    		throws RepositoryException {
    	replaceAccessControlEntry(session, 
    			resourcePath, 
    			principal, 
    			grantedPrivilegeNames, 
    			deniedPrivilegeNames, 
    			removedPrivilegeNames, 
    			null);
    }    
    
    /**
     * 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
     * @param order where the access control entry should go in the list.  
     *         Value should be one of these:
     *         <table>
     *          <tr><td>null</td><td>If the ACE for the principal doesn't exist add at the end, otherwise leave the ACE at it's current position.</td></tr>
     * 			<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 numeric index</td></tr>
	 *         </table>
     * @throws RepositoryException
     */
    public static void replaceAccessControlEntry(Session session, String resourcePath, Principal principal, 
    			String[] grantedPrivilegeNames, String[] deniedPrivilegeNames, String[] removedPrivilegeNames,
    			String order)
        		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 (int i=0; i < accessControlEntries.length; i++) {
    		AccessControlEntry ace = accessControlEntries[i];
    		if (principal.equals(ace.getPrincipal())) {
    			if (log.isDebugEnabled()) {
    				log.debug("Found Existing ACE for principal {} on resource {}", new Object[] {principal.getName(), resourcePath});
    			}
    			if (order == null || order.length() == 0) {
    				//order not specified, so keep track of the original ACE position.
    				order = String.valueOf(i);
    			}
    			
    			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()]));
    	}

    	//process any denied privileges
    	UserManager userManager = getUserManager(session);
    	Authorizable authorizable = userManager.getAuthorizable(principal);
   		//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);
   		}

   		
   		//order the ACL
   		reorderAccessControlEntries(acl, principal, order);
   		
    	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 -----------------------------------------------

    /**
     * Returns true if the AccessControlEntry represents 'allowed' rights or false
     * it it represents 'denied' rights.
     */
    public static boolean isAllow(AccessControlEntry ace) throws RepositoryException {
		return safeInvokeRepoMethod(ace, METHOD_JACKRABBIT_ACE_IS_ALLOW, Boolean.class);
    }

    // ---------- internal -----------------------------------------------------

    /**
     * Use reflection to invoke a repository method.
     */
    @SuppressWarnings("unchecked")
	private static <T> T safeInvokeRepoMethod(Object target, String methodName, Class<T> returnType, Object[] args, Class[] argsTypes)
    													throws UnsupportedRepositoryOperationException, RepositoryException {
    	try {
    		Method m = target.getClass().getMethod(methodName, argsTypes);
    		if (!m.isAccessible()) {
    			m.setAccessible(true);
    		}
			return (T) m.invoke(target, args);
    	} catch (InvocationTargetException ite) {
            // wraps the exception thrown by the method
            Throwable t = ite.getCause();
            if (t instanceof UnsupportedRepositoryOperationException) {
                throw (UnsupportedRepositoryOperationException) t;
            } else if (t instanceof AccessDeniedException) {
                throw (AccessDeniedException) t;
            } else if (t instanceof AccessControlException) {
                throw (AccessControlException) t;
            } else if (t instanceof RepositoryException) {
                throw (RepositoryException) t;
            } else if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else if (t instanceof Error) {
                throw (Error) t;
            } else {
                throw new RepositoryException(methodName, t);
            }
        } catch (Throwable t) {
            // any other problem is just encapsulated
            throw new RepositoryException(methodName, t);
        }
	}

    private static <T> T safeInvokeRepoMethod(Object target, String methodName, Class<T> returnType, Object... args)
																		throws UnsupportedRepositoryOperationException, RepositoryException {
    	return safeInvokeRepoMethod(target, methodName, returnType, args, new Class[0]);
    }

    /**
     * Unwrap the jackrabbit session.
     */
	private static JackrabbitSession getJackrabbitSession(Session session) {
		if (session instanceof JackrabbitSession)
			return (JackrabbitSession) session;
		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;
	}

	/**
	 * Move the ACE(s) for the specified principal to the position specified by the 'order'
	 * parameter. 
	 * 
	 * @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>
     * 			<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)) {
				beforeEntry = null;
			} 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<Principal>();
						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");
		}
	}
}
