Fixing an issue where it failed to start without xss compat, wasn't serving the js file and didn't create the app folder correctly
diff --git a/pom.xml b/pom.xml
index aa6e3d4..97e097e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,154 +1,162 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-    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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<!-- 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.sling</groupId>
-        <artifactId>sling</artifactId>
-        <version>30</version>
-        <relativePath />
-    </parent>
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.sling</groupId>
+		<artifactId>sling</artifactId>
+		<version>30</version>
+		<relativePath />
+	</parent>
 
-    <artifactId>org.apache.sling.serviceuser.webconsole</artifactId>
-    <packaging>bundle</packaging>
-    <version>1.0.1-SNAPSHOT</version>
+	<artifactId>org.apache.sling.serviceuser.webconsole</artifactId>
+	<packaging>bundle</packaging>
+	<version>1.0.0-SNAPSHOT</version>
 
-    <name>Apache Sling Service User Web Console</name>
-    <description>
+	<name>Apache Sling Service User Web Console</name>
+	<description>
         Provides an OSGi Web Console for creating, updating and viewing Service Users.
     </description>
 
-    <scm>
-        <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-serviceuser-webconsole.git</connection>
-        <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-serviceuser-webconsole.git</developerConnection>
-        <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-serviceuser-webconsole.git</url>
-      <tag>HEAD</tag>
-  </scm>
+	<scm>
+		<connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-serviceuser-webconsole.git</connection>
+		<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-serviceuser-webconsole.git</developerConnection>
+		<url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-serviceuser-webconsole.git</url>
+		<tag>HEAD</tag>
+	</scm>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <configuration>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-javadoc-plugin</artifactId>
-                <configuration>
-                    <excludePackageNames>
-                        org.apache.sling.serviceuser.console.impl
-                    </excludePackageNames>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.api</artifactId>
-            <version>2.5.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Import-Package>
+							<!-- Support XSS API 1.x and 2.x - we use only classes from the API 
+								with same signature in both versions -->
+							org.apache.sling.xss;version="[1.0.0,3)",
+							*
+						</Import-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<configuration>
+					<excludePackageNames>
+						org.apache.sling.serviceuser.console.impl
+					</excludePackageNames>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.api</artifactId>
+			<version>2.5.0</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
 			<artifactId>org.apache.sling.serviceusermapper</artifactId>
 			<version>1.4.0</version>
-            <scope>provided</scope>
-        </dependency>
-        
-        <!-- JCR Specific items -->
-        <dependency>
-            <groupId>org.apache.jackrabbit</groupId>
-            <artifactId>jackrabbit-api</artifactId>
-            <version>2.10.6</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>javax.jcr</groupId>
-            <artifactId>jcr</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.jcr.base</artifactId>
-            <version>2.1.0</version>
-            <scope>provided</scope>
-        </dependency>
-  
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
+			<scope>provided</scope>
+		</dependency>
 
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>osgi.core</artifactId>
-        </dependency>
-        <dependency>
-        	<groupId>org.osgi</groupId>
-        	<artifactId>org.osgi.compendium</artifactId>
-        	<version>4.2.0</version>
-        	<scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>javax.servlet-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-            <version>3.3.2</version>
-            <scope>provided</scope>
-        </dependency>
-        
-        <!-- Webconsole Dependencies -->
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.webconsole</artifactId>
-            <version>4.2.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.xss</artifactId>
-            <version>1.0.0</version>
-            <scope>provided</scope>
-        </dependency>
+		<!-- JCR Specific items -->
+		<dependency>
+			<groupId>org.apache.jackrabbit</groupId>
+			<artifactId>jackrabbit-api</artifactId>
+			<version>2.10.6</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>javax.jcr</groupId>
+			<artifactId>jcr</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.jcr.base</artifactId>
+			<version>2.1.0</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.jackrabbit</groupId>
+			<artifactId>jackrabbit-jcr-commons</artifactId>
+			<version>2.0.0</version>
+			<scope>provided</scope>
+		</dependency>
 
-        <!-- Testing -->
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-all</artifactId>
-            <version>1.9.5</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-api</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>osgi.core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>org.osgi.compendium</artifactId>
+			<version>4.2.0</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-lang3</artifactId>
+			<version>3.3.2</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- Webconsole Dependencies -->
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.apache.felix.webconsole</artifactId>
+			<version>4.2.0</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.xss</artifactId>
+			<version>1.0.0</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- Testing -->
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-simple</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-all</artifactId>
+			<version>1.9.5</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/serviceuser/webconsole/impl/ServiceUserWebConsolePlugin.java b/src/main/java/org/apache/sling/serviceuser/webconsole/impl/ServiceUserWebConsolePlugin.java
index fd9ab5f..5d952fa 100644
--- a/src/main/java/org/apache/sling/serviceuser/webconsole/impl/ServiceUserWebConsolePlugin.java
+++ b/src/main/java/org/apache/sling/serviceuser/webconsole/impl/ServiceUserWebConsolePlugin.java
@@ -21,6 +21,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.reflect.Array;
+import java.net.URL;
 import java.net.URLEncoder;
 import java.security.Principal;
 import java.util.ArrayList;
@@ -35,7 +36,6 @@
 import java.util.Map.Entry;
 
 import javax.jcr.AccessDeniedException;
-import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
@@ -56,17 +56,20 @@
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.felix.webconsole.SimpleWebConsolePlugin;
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
 import org.apache.felix.webconsole.WebConsoleConstants;
 import org.apache.felix.webconsole.WebConsoleUtil;
+import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
@@ -93,11 +96,7 @@
 		WebConsoleConstants.PLUGIN_TITLE + "=" + ServiceUserWebConsolePlugin.TITLE,
 		WebConsoleConstants.PLUGIN_CATEGORY + "=Sling" })
 @SuppressWarnings("serial")
-public class ServiceUserWebConsolePlugin extends SimpleWebConsolePlugin {
-
-	public ServiceUserWebConsolePlugin() {
-		super(LABEL, TITLE, "Sling", new String[0]);
-	}
+public class ServiceUserWebConsolePlugin extends AbstractWebConsolePlugin {
 
 	public static final String COMPONENT_NAME = "org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended";
 	public static final String LABEL = "serviceusers";
@@ -119,6 +118,9 @@
 	@Reference(policyOption = ReferencePolicyOption.GREEDY)
 	private XSSAPI xss;
 
+	@Reference(policyOption = ReferencePolicyOption.GREEDY)
+	private ResourceResolverFactory resolverFactory;
+
 	@Reference
 	private ServiceUserMapper mapper;
 
@@ -137,11 +139,11 @@
 				config = configs.next();
 				log.debug("Using existing configuration {}", config);
 			} else {
-				String path = appPath + "/config/" + COMPONENT_NAME + "-" + appPath.substring(appPath.lastIndexOf('/'));
+				String path = appPath + "/config/" + COMPONENT_NAME + "-" + appPath.substring(appPath.lastIndexOf('/') + 1);
 				log.debug("Creating new configuration {}", path);
 				config = ResourceUtil.getOrCreateResource(resolver, path, new HashMap<String, Object>() {
 					{
-						put(Property.JCR_PRIMARY_TYPE, "sling:OsgiConfig");
+						put(JcrConstants.JCR_PRIMARYTYPE, "sling:OsgiConfig");
 					}
 				}, NodeType.NT_FOLDER, false);
 				dirty = true;
@@ -223,102 +225,6 @@
 
 	}
 
-	private boolean updatePrivileges(HttpServletRequest request, ResourceResolver resolver) {
-
-		List<Pair<String, String>> privileges = this.getPrivileges(request);
-		String name = getParameter(request, PN_NAME, "");
-
-		List<String> currentPolicies = new ArrayList<String>();
-		findACLs(resolver, name, currentPolicies);
-		for (int i = 0; i < currentPolicies.size(); i++) {
-			String path = StringUtils.substringBefore(currentPolicies.get(i), "/rep:policy");
-			currentPolicies.set(i, StringUtils.isNotBlank(path) ? path : "/");
-		}
-		log.debug("Loaded current policy paths: {}", currentPolicies);
-
-		Map<String, List<String>> toSet = new HashMap<String, List<String>>();
-		for (Pair<String, String> privilege : privileges) {
-			if (!toSet.containsKey(privilege.getKey())) {
-				toSet.put(privilege.getKey(), new ArrayList<String>());
-			}
-			toSet.get(privilege.getKey()).add(privilege.getValue());
-		}
-		log.debug("Loaded updated policy paths: {}", currentPolicies);
-
-		String lastEntry = null;
-
-		try {
-
-			Session session = resolver.adaptTo(Session.class);
-			AccessControlManager accessManager = session.getAccessControlManager();
-			PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(session);
-
-			for (Entry<String, List<String>> pol : toSet.entrySet()) {
-				lastEntry = pol.getKey();
-				currentPolicies.remove(pol.getKey());
-				log.debug("Updating policies for {}", pol.getKey());
-
-				AccessControlPolicy[] policies = accessManager.getPolicies(pol.getKey());
-				List<String> toRemove = new ArrayList<String>();
-				for (AccessControlPolicy p : policies) {
-					if (p instanceof AccessControlList) {
-						AccessControlList policy = (AccessControlList) p;
-						for (AccessControlEntry entry : policy.getAccessControlEntries()) {
-							Principal prin = entry.getPrincipal();
-							if (prin.getName().equals(name)) {
-								for (Privilege privilege : entry.getPrivileges()) {
-									if (!pol.getValue().contains(privilege.getName())) {
-										log.debug("Removing privilege {}", privilege);
-										toRemove.add(privilege.getName());
-									}
-								}
-							}
-						}
-					}
-				}
-				Principal principal = principalManager.getPrincipal(name);
-				AccessControlUtil.replaceAccessControlEntry(session, pol.getKey(), principal,
-						pol.getValue().toArray(new String[pol.getValue().size()]), new String[0],
-						toRemove.toArray(new String[toRemove.size()]), null);
-			}
-			session.save();
-
-			for (String oldPolicy : currentPolicies) {
-				boolean removed = false;
-				log.debug("Removing policy for {}", oldPolicy);
-				AccessControlPolicy[] policies = accessManager.getPolicies(oldPolicy);
-				AccessControlEntry toRemove = null;
-				for (AccessControlPolicy p : policies) {
-					if (p instanceof AccessControlList) {
-						AccessControlList policy = (AccessControlList) p;
-						for (AccessControlEntry entry : policy.getAccessControlEntries()) {
-							Principal prin = entry.getPrincipal();
-							if (prin.getName().equals(name)) {
-								toRemove = entry;
-								break;
-							}
-						}
-						if (toRemove != null) {
-							removed = true;
-							policy.removeAccessControlEntry(toRemove);
-							accessManager.setPolicy(oldPolicy, policy);
-							session.save();
-							log.debug("Removed access control entry {}", toRemove);
-						}
-					}
-				}
-				if (!removed) {
-					log.warn("No policy found for {}", oldPolicy);
-				}
-			}
-		} catch (RepositoryException e) {
-			log.error("Exception updating principals with {}, failed on {}", toSet, lastEntry, e);
-			return false;
-		}
-
-		return true;
-	}
-
 	private List<String> extractPrincipals(Mapping mapping) {
 		List<String> principals = new ArrayList<String>();
 		String userName = mapping.map(mapping.getServiceName(), mapping.getSubServiceName());
@@ -404,6 +310,11 @@
 		return bundles;
 	}
 
+	@Override
+	public String getLabel() {
+		return LABEL;
+	}
+
 	private Resource getOrCreateServiceUser(HttpServletRequest request, ResourceResolver resolver) {
 
 		final String name = getParameter(request, PN_NAME, "");
@@ -450,12 +361,86 @@
 		return defaultValue;
 	}
 
+	private List<Pair<String, String>> getPrivileges(HttpServletRequest request) {
+		List<Pair<String, String>> privileges = new ArrayList<Pair<String, String>>();
+		List<String> params = Collections.list(request.getParameterNames());
+
+		for (String param : params) {
+			if (param.startsWith("acl-path-")) {
+				String path = request.getParameter(param);
+				String privilege = request.getParameter(param.replace("-path-", "-privilege-"));
+				if (StringUtils.isNotBlank(path) && StringUtils.isNotBlank(privilege)) {
+					privileges.add(new ImmutablePair<String, String>(path, privilege));
+				} else {
+					log.warn("Unable to load ACL due to missing value {}={}", path, privilege);
+				}
+			}
+		}
+
+		return privileges;
+	}
+
+	@SuppressWarnings("deprecation")
 	private ResourceResolver getResourceResolver(HttpServletRequest request) {
-		ResourceResolver resolver = (ResourceResolver) request
-				.getAttribute("org.apache.sling.auth.core.ResourceResolver");
+		ResourceResolver resolver = null;
+		try {
+			resolver = (ResourceResolver) request.getAttribute("org.apache.sling.auth.core.ResourceResolver");
+			if (resolver == null) {
+				log.warn("Resource resolver not available in request, falling back to adminstrative resource resolver");
+				resolver = resolverFactory.getAdministrativeResourceResolver(null);
+			}
+		} catch (LoginException le) {
+			throw new RuntimeException(
+					"Unable to get Administrative Resource Resolver, add the bundle org.apache.sling.serviceuser.webconsole in the Apache Sling Login Admin Whitelist",
+					le);
+		}
 		return resolver;
 	}
 
+	/**
+	 * Called internally by {@link AbstractWebConsolePlugin} to load resources.
+	 *
+	 * This particular implementation depends on the label. As example, if the
+	 * plugin is accessed as <code>/system/console/abc</code>, and the plugin
+	 * resources are accessed like
+	 * <code>/system/console/abc/res/logo.gif</code>, the code here will try
+	 * load resource <code>/res/logo.gif</code> from the bundle, providing the
+	 * plugin.
+	 *
+	 *
+	 * @param path
+	 *            the path to read.
+	 * @return the URL of the resource or <code>null</code> if not found.
+	 */
+	protected URL getResource(String path) {
+		String base = "/" + LABEL + "/";
+		return (path != null && path.startsWith(base)) ? getClass().getResource(path.substring(base.length() - 1))
+				: null;
+	}
+
+	private String[] getSupportedPrivileges(HttpServletRequest request) {
+		String[] names = null;
+		try {
+			ResourceResolver resolver = getResourceResolver(request);
+			Session session = resolver.adaptTo(Session.class);
+			AccessControlManager accessControl = session.getAccessControlManager();
+			Privilege[] privileges = accessControl.getSupportedPrivileges("/");
+			names = new String[privileges.length];
+			for (int i = 0; i < privileges.length; i++) {
+				names[i] = privileges[i].getName();
+			}
+			Arrays.sort(names);
+		} catch (RepositoryException re) {
+			log.error("Exception loading Supported Privileges", re);
+		}
+		return names;
+	}
+
+	@Override
+	public String getTitle() {
+		return TITLE;
+	}
+
 	private boolean hasPrincipal(Mapping map, String name) {
 		Iterable<String> principals = map.mapPrincipals(map.getServiceName(), map.getSubServiceName());
 		if (principals != null) {
@@ -533,6 +518,48 @@
 
 	}
 
+	private void printPrivilegeSelect(PrintWriter pw, String label, List<Pair<String, String>> privileges,
+			String[] supportedPrivileges, String alertMessage) {
+		pw.print("<td style='width:20%'>");
+		pw.print(xss.encodeForHTMLAttr(label));
+		pw.println("</td>");
+		pw.print("<td><table class=\"repeating-container\" style=\"width: 100%\" data-length=\"" + privileges.size()
+				+ "\"><tr><td>Path</td><td>Privilege</td><td></td>");
+
+		int idx = 0;
+		for (Pair<String, String> privilege : privileges) {
+			pw.print("</tr><tr class=\"repeating-item\"><td>");
+
+			pw.print("<input type=\"text\"  name=\"acl-path-" + idx + "\" value='");
+			pw.print(xss.encodeForHTMLAttr(StringUtils.defaultString(privilege.getKey())));
+			pw.print("' style='width:100%' />");
+
+			pw.print("</td><td>");
+
+			pw.print("<input type=\"text\" list=\"data-privileges\" name=\"acl-privilege-" + idx + "\" value='");
+			pw.print(xss.encodeForHTMLAttr(StringUtils.defaultString(privilege.getValue())));
+			pw.print("' style='width:100%' />");
+
+			pw.print("</td><td>");
+
+			pw.print("<input type=\"button\" value=\"&nbsp;-&nbsp;\" class=\"repeating-remove\" /></td>");
+		}
+		pw.print("</tr></table>");
+
+		pw.print("<input type=\"button\" value=\"&nbsp;+&nbsp;\" class=\"repeating-add\" />");
+
+		pw.print("<datalist id=\"data-privileges\">");
+		for (String option : supportedPrivileges) {
+			pw.print("<option");
+			pw.print(">");
+			pw.print(xss.encodeForHTMLAttr(option));
+			pw.print("</option>");
+		}
+		pw.print("</datalist><script src=\"/system/console/serviceusers/res/ui/serviceusermanager.js\"></script>");
+		infoDiv(pw, alertMessage);
+		pw.println("</td>");
+	}
+
 	private void printServiceUserDetails(HttpServletRequest request, PrintWriter pw)
 			throws AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
 		String name = getParameter(request, PN_USER, "");
@@ -676,44 +703,6 @@
 		}
 	}
 
-	private List<Pair<String, String>> getPrivileges(HttpServletRequest request) {
-		List<Pair<String, String>> privileges = new ArrayList<Pair<String, String>>();
-		List<String> params = Collections.list(request.getParameterNames());
-
-		for (String param : params) {
-			if (param.startsWith("acl-path-")) {
-				String path = request.getParameter(param);
-				String privilege = request.getParameter(param.replace("-path-", "-privilege-"));
-				if (StringUtils.isNotBlank(path) && StringUtils.isNotBlank(privilege)) {
-					privileges.add(new ImmutablePair<String, String>(path, privilege));
-				} else {
-					log.warn("Unable to load ACL due to missing value {}={}", path, privilege);
-				}
-			}
-		}
-
-		return privileges;
-	}
-
-	private String[] getSupportedPrivileges(HttpServletRequest request) {
-		String[] names = null;
-		try {
-			ResourceResolver resolver = getResourceResolver(request);
-			Session session = resolver.adaptTo(Session.class);
-			AccessControlManager accessControl = session.getAccessControlManager();
-			Privilege[] privileges = accessControl.getSupportedPrivileges("/");
-			names = new String[privileges.length];
-			for (int i = 0; i < privileges.length; i++) {
-				names[i] = privileges[i].getName();
-			}
-			Arrays.sort(names);
-		} catch (RepositoryException re) {
-			log.error("Exception loading Supported Privileges", re);
-		}
-		return names;
-
-	}
-
 	@Override
 	protected void renderContent(HttpServletRequest request, HttpServletResponse response)
 			throws ServletException, IOException {
@@ -745,48 +734,6 @@
 		}
 	}
 
-	private void printPrivilegeSelect(PrintWriter pw, String label, List<Pair<String, String>> privileges,
-			String[] supportedPrivileges, String alertMessage) {
-		pw.print("<td style='width:20%'>");
-		pw.print(xss.encodeForHTMLAttr(label));
-		pw.println("</td>");
-		pw.print("<td><table class=\"repeating-container\" style=\"width: 100%\" data-length=\"" + privileges.size()
-				+ "\"><tr><td>Path</td><td>Privilege</td><td></td>");
-
-		int idx = 0;
-		for (Pair<String, String> privilege : privileges) {
-			pw.print("</tr><tr class=\"repeating-item\"><td>");
-
-			pw.print("<input type=\"text\"  name=\"acl-path-" + idx + "\" value='");
-			pw.print(xss.encodeForHTMLAttr(StringUtils.defaultString(privilege.getKey())));
-			pw.print("' style='width:100%' />");
-
-			pw.print("</td><td>");
-
-			pw.print("<input type=\"text\" list=\"data-privileges\" name=\"acl-privilege-" + idx + "\" value='");
-			pw.print(xss.encodeForHTMLAttr(StringUtils.defaultString(privilege.getValue())));
-			pw.print("' style='width:100%' />");
-
-			pw.print("</td><td>");
-
-			pw.print("<input type=\"button\" value=\"&nbsp;-&nbsp;\" class=\"repeating-remove\" /></td>");
-		}
-		pw.print("</tr></table>");
-
-		pw.print("<input type=\"button\" value=\"&nbsp;+&nbsp;\" class=\"repeating-add\" />");
-
-		pw.print("<datalist id=\"data-privileges\">");
-		for (String option : supportedPrivileges) {
-			pw.print("<option");
-			pw.print(">");
-			pw.print(xss.encodeForHTMLAttr(option));
-			pw.print("</option>");
-		}
-		pw.print("</datalist><script src=\"/system/console/serviceusers/res/ui/serviceusermanager.js\"></script>");
-		infoDiv(pw, alertMessage);
-		pw.println("</td>");
-	}
-
 	private void selectField(PrintWriter pw, String label, String fieldName, String value, Collection<String> options,
 			String... alertMessages) {
 		pw.print("<td style='width:20%'>");
@@ -902,4 +849,100 @@
 		pw.println("</td>");
 	}
 
+	private boolean updatePrivileges(HttpServletRequest request, ResourceResolver resolver) {
+
+		List<Pair<String, String>> privileges = this.getPrivileges(request);
+		String name = getParameter(request, PN_NAME, "");
+
+		List<String> currentPolicies = new ArrayList<String>();
+		findACLs(resolver, name, currentPolicies);
+		for (int i = 0; i < currentPolicies.size(); i++) {
+			String path = StringUtils.substringBefore(currentPolicies.get(i), "/rep:policy");
+			currentPolicies.set(i, StringUtils.isNotBlank(path) ? path : "/");
+		}
+		log.debug("Loaded current policy paths: {}", currentPolicies);
+
+		Map<String, List<String>> toSet = new HashMap<String, List<String>>();
+		for (Pair<String, String> privilege : privileges) {
+			if (!toSet.containsKey(privilege.getKey())) {
+				toSet.put(privilege.getKey(), new ArrayList<String>());
+			}
+			toSet.get(privilege.getKey()).add(privilege.getValue());
+		}
+		log.debug("Loaded updated policy paths: {}", currentPolicies);
+
+		String lastEntry = null;
+
+		try {
+
+			Session session = resolver.adaptTo(Session.class);
+			AccessControlManager accessManager = session.getAccessControlManager();
+			PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(session);
+
+			for (Entry<String, List<String>> pol : toSet.entrySet()) {
+				lastEntry = pol.getKey();
+				currentPolicies.remove(pol.getKey());
+				log.debug("Updating policies for {}", pol.getKey());
+
+				AccessControlPolicy[] policies = accessManager.getPolicies(pol.getKey());
+				List<String> toRemove = new ArrayList<String>();
+				for (AccessControlPolicy p : policies) {
+					if (p instanceof AccessControlList) {
+						AccessControlList policy = (AccessControlList) p;
+						for (AccessControlEntry entry : policy.getAccessControlEntries()) {
+							Principal prin = entry.getPrincipal();
+							if (prin.getName().equals(name)) {
+								for (Privilege privilege : entry.getPrivileges()) {
+									if (!pol.getValue().contains(privilege.getName())) {
+										log.debug("Removing privilege {}", privilege);
+										toRemove.add(privilege.getName());
+									}
+								}
+							}
+						}
+					}
+				}
+				Principal principal = principalManager.getPrincipal(name);
+				AccessControlUtil.replaceAccessControlEntry(session, pol.getKey(), principal,
+						pol.getValue().toArray(new String[pol.getValue().size()]), new String[0],
+						toRemove.toArray(new String[toRemove.size()]), null);
+			}
+			session.save();
+
+			for (String oldPolicy : currentPolicies) {
+				boolean removed = false;
+				log.debug("Removing policy for {}", oldPolicy);
+				AccessControlPolicy[] policies = accessManager.getPolicies(oldPolicy);
+				AccessControlEntry toRemove = null;
+				for (AccessControlPolicy p : policies) {
+					if (p instanceof AccessControlList) {
+						AccessControlList policy = (AccessControlList) p;
+						for (AccessControlEntry entry : policy.getAccessControlEntries()) {
+							Principal prin = entry.getPrincipal();
+							if (prin.getName().equals(name)) {
+								toRemove = entry;
+								break;
+							}
+						}
+						if (toRemove != null) {
+							removed = true;
+							policy.removeAccessControlEntry(toRemove);
+							accessManager.setPolicy(oldPolicy, policy);
+							session.save();
+							log.debug("Removed access control entry {}", toRemove);
+						}
+					}
+				}
+				if (!removed) {
+					log.warn("No policy found for {}", oldPolicy);
+				}
+			}
+		} catch (RepositoryException e) {
+			log.error("Exception updating principals with {}, failed on {}", toSet, lastEntry, e);
+			return false;
+		}
+
+		return true;
+	}
+
 }