You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:47:46 UTC

[sling-org-apache-sling-jcr-jackrabbit-usermanager] annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator created (now 4e684df)

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a change to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git.


      at 4e684df  (tag)
 tagging ef415cb91ca16077d38a50580103aa1f892ae395 (commit)
      by Felix Meschberger
      on Thu Jun 18 09:21:02 2009 +0000

- Log -----------------------------------------------------------------
org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
-----------------------------------------------------------------------

This annotated tag includes the following new commits:

     new 8b60a66  SLING-875 add new jackrabbit-usermanager module (thanks Eric for providing)
     new 854533d  SLING-875: New Bundle for a ResourceProvider and Sling Post Operations for interacting with the jackrabbit UserManager https://issues.apache.org/jira/browse/SLING-875
     new 9b865b8  SLING-941: Lots of svn:eol-style settings missing
     new 2745b63  Use released version of jackrabbit api
     new 72ad816  Use jackrabbit api bundle instead of Sling's obsolete version.
     new 3164640  Use release parent pom
     new 87d5271  Use released version as dependencies.
     new e512ac0  [maven-release-plugin] prepare release org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator
     new 70ae9d9  [maven-release-plugin] prepare for next development iteration
     new 38e866b  Use next dev version of parent pom
     new 8fd85d1  [maven-release-plugin]  copy for tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
     new c84c5b4  Move Sling to new TLP location
     new ef415cb  Move Sling to new TLP location

The 13 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@sling.apache.org" <co...@sling.apache.org>'].

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 08/13: [maven-release-plugin] prepare release org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit e512ac01295753eea967ee7434e025e695208f5e
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue May 5 16:20:28 2009 +0000

    [maven-release-plugin] prepare release org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@771890 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/pom.xml b/pom.xml
index 3d4dff1..78ef32e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
 
 	<artifactId>org.apache.sling.jcr.jackrabbit.usermanager</artifactId>
 	<packaging>bundle</packaging>
-	<version>2.0.0-incubator-SNAPSHOT</version>
+	<version>2.0.0-incubator</version>
 	<name>Apache Sling Jackrabbit UserManager Support</name>
 	<description>
 		Provides ResourceProvider and SlingPostOperations for the Jackrabbit
@@ -38,13 +38,13 @@
 
 	<scm>
 		<connection>
-			scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+			scm:svn:http://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator
 		</connection>
 		<developerConnection>
-			scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+			scm:svn:https://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator
 		</developerConnection>
 		<url>
-			http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+			http://svn.apache.org/viewvc/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator
 		</url>
 	</scm>
 
@@ -63,8 +63,8 @@
 						<Private-Package>
                             org.apache.sling.jackrabbit.usermanager.*
 						</Private-Package>
-						<Sling-Initial-Content></Sling-Initial-Content>
-						<Sling-Nodetypes></Sling-Nodetypes>
+						<Sling-Initial-Content />
+						<Sling-Nodetypes />
 					</instructions>
 				</configuration>
 			</plugin>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 10/13: Use next dev version of parent pom

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 38e866b8c45da3c2a192f7eda894b4b8532004f3
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue May 5 17:11:34 2009 +0000

    Use next dev version of parent pom
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@771937 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 02e8827..c22d4da 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
 	<parent>
 		<groupId>org.apache.sling</groupId>
 		<artifactId>sling</artifactId>
-		<version>5-incubator</version>
+		<version>6-incubator-SNAPSHOT</version>
 		<relativePath>../../../parent/pom.xml</relativePath>
 	</parent>
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 03/13: SLING-941: Lots of svn:eol-style settings missing

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 9b865b88f900ebd5963e801f0d94c1ea7cfc368f
Author: Jukka Zitting <ju...@apache.org>
AuthorDate: Fri Apr 24 12:14:03 2009 +0000

    SLING-941: Lots of svn:eol-style settings missing
    
    Set svn:eol-style to native on all Java files that lack the setting.
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@768268 13f79535-47bb-0310-9956-ffa450edef68

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 02/13: SLING-875: New Bundle for a ResourceProvider and Sling Post Operations for interacting with the jackrabbit UserManager https://issues.apache.org/jira/browse/SLING-875

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 854533dccdb1e5a87f014716f594dbb8d9ec68fb
Author: Juan Vazquez <jv...@apache.org>
AuthorDate: Thu Mar 19 20:53:24 2009 +0000

    SLING-875: New Bundle for a ResourceProvider and Sling Post Operations for interacting with the jackrabbit UserManager
    https://issues.apache.org/jira/browse/SLING-875
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@756191 13f79535-47bb-0310-9956-ffa450edef68
---
 ...n.java => AbstractAuthorizablePostServlet.java} | 411 +++++++++++++--------
 .../usermanager/post/AbstractGroupPostServlet.java |  95 +++++
 .../usermanager/post/AbstractUserPostServlet.java  |  81 ++++
 ...eration.java => ChangeUserPasswordServlet.java} |  22 +-
 ...GroupOperation.java => CreateGroupServlet.java} |  33 +-
 ...teUserOperation.java => CreateUserServlet.java} |  30 +-
 .../post/DeleteAuthorizableOperation.java          |  73 ----
 .../post/DeleteAuthorizableServlet.java            | 159 ++++++++
 ...zableOperation.java => UpdateGroupServlet.java} |  24 +-
 ...izableOperation.java => UpdateUserServlet.java} |  30 +-
 10 files changed, 662 insertions(+), 296 deletions(-)

diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizableOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizablePostServlet.java
similarity index 65%
rename from src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizableOperation.java
rename to src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizablePostServlet.java
index 06f6577..ab1d5cf 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizableOperation.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizablePostServlet.java
@@ -16,15 +16,14 @@
  */
 package org.apache.sling.jackrabbit.usermanager.post;
 
-import java.io.UnsupportedEncodingException;
-import java.security.NoSuchAlgorithmException;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Dictionary;
+import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.NoSuchElementException;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
@@ -32,30 +31,39 @@ import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.Group;
-import org.apache.jackrabbit.util.Text;
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.request.RequestParameter;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.api.wrappers.SlingRequestPaths;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.jackrabbit.usermanager.post.impl.DateParser;
 import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
 import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
-import org.apache.sling.servlets.post.AbstractSlingPostOperation;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.SlingPostConstants;
 import org.osgi.service.component.ComponentContext;
-
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * Base class for operations that do work on authorizable resources
+ * Base class for all the POST servlets for the UserManager operations 
  */
-public abstract class AbstractAuthorizableOperation extends AbstractSlingPostOperation {
-	
+public abstract class AbstractAuthorizablePostServlet extends SlingAllMethodsServlet {
+	private static final long serialVersionUID = -5918670409789895333L;
+
+	/**
+     * default log
+     */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
     /**
      * @scr.property values.0="EEE MMM dd yyyy HH:mm:ss 'GMT'Z"
      *               values.1="yyyy-MM-dd'T'HH:mm:ss.SSSZ"
@@ -65,17 +73,7 @@ public abstract class AbstractAuthorizableOperation extends AbstractSlingPostOpe
     private static final String PROP_DATE_FORMAT = "servlet.post.dateFormats";
 	
 	private DateParser dateParser;
-
-
-	/**
-     * To be used for the encryption. E.g. for passwords in
-     * {@link javax.jcr.SimpleCredentials#getPassword()}  SimpleCredentials} 
-     * @scr.property valueRef="DEFAULT_PASSWORD_DIGEST_ALGORITHM"
-     */
-    private static final String PROP_PASSWORD_DIGEST_ALGORITHM = "password.digest.algorithm";
-    private static final String DEFAULT_PASSWORD_DIGEST_ALGORITHM = "sha1";
-    private String passwordDigestAlgoritm = null;
-
+	
     // ---------- SCR Integration ----------------------------------------------
 
     protected void activate(ComponentContext context) {
@@ -86,90 +84,178 @@ public abstract class AbstractAuthorizableOperation extends AbstractSlingPostOpe
         for (String dateFormat : dateFormats) {
             dateParser.register(dateFormat);
         }
-        Object propValue = props.get(PROP_PASSWORD_DIGEST_ALGORITHM);
-        if (propValue instanceof String) {
-        	passwordDigestAlgoritm = (String)propValue;
-        } else {
-        	passwordDigestAlgoritm = DEFAULT_PASSWORD_DIGEST_ALGORITHM;
-        }
     }
 
     protected void deactivate(ComponentContext context) {
         dateParser = null;
-        passwordDigestAlgoritm = null;
     }
 	
-    protected String digestPassword(String pwd) throws IllegalArgumentException {
+    
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.servlets.SlingAllMethodsServlet#doPost(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.SlingHttpServletResponse)
+	 */
+	@Override
+	protected void doPost(SlingHttpServletRequest request,
+			SlingHttpServletResponse httpResponse) throws ServletException,
+			IOException {
+        // prepare the response
+        HtmlResponse htmlResponse = new HtmlResponse();
+        htmlResponse.setReferer(request.getHeader("referer"));
+
+        // calculate the paths
+        String path = getItemPath(request);
+        htmlResponse.setPath(path);
+
+        // location
+        htmlResponse.setLocation(externalizePath(request, path));
+
+        // parent location
+        path = ResourceUtil.getParent(path);
+        if (path != null) {
+        	htmlResponse.setParentLocation(externalizePath(request, path));
+        }
+
+        Session session = request.getResourceResolver().adaptTo(Session.class);
+
+        final List<Modification> changes = new ArrayList<Modification>();
+        
         try {
-            StringBuffer password = new StringBuffer();
-            password.append("{").append(passwordDigestAlgoritm).append("}");
-            password.append(Text.digest(passwordDigestAlgoritm, pwd.getBytes("UTF-8")));
-            return password.toString();
-        } catch (NoSuchAlgorithmException e) {
-            throw new IllegalArgumentException(e.toString());
-        } catch (UnsupportedEncodingException e) {
-            throw new IllegalArgumentException(e.toString());
+            handleOperation(request, htmlResponse, changes);
+            
+            //TODO: maybe handle SlingAuthorizablePostProcessor handlers here
+            
+            // set changes on html response
+            for(Modification change : changes) {
+                switch ( change.getType() ) {
+                    case MODIFY : htmlResponse.onModified(change.getSource()); break;
+                    case DELETE : htmlResponse.onDeleted(change.getSource()); break;
+                    case MOVE :   htmlResponse.onMoved(change.getSource(), change.getDestination()); break;
+                    case COPY :   htmlResponse.onCopied(change.getSource(), change.getDestination()); break;
+                    case CREATE : htmlResponse.onCreated(change.getSource()); break;
+                    case ORDER : htmlResponse.onChange("ordered", change.getSource(), change.getDestination()); break;
+                }
+            }
+            
+            if (session.hasPendingChanges()) {
+                session.save();
+            }
+        } catch (ResourceNotFoundException rnfe) {
+            htmlResponse.setStatus(HttpServletResponse.SC_NOT_FOUND,
+                rnfe.getMessage());
+        } catch (Throwable throwable) {
+            log.debug("Exception while handling POST "
+                + request.getResource().getPath() + " with "
+                + getClass().getName(), throwable);
+            htmlResponse.setError(throwable);
+        } finally {
+            try {
+                if (session.hasPendingChanges()) {
+                    session.refresh(false);
+                }
+            } catch (RepositoryException e) {
+                log.warn("RepositoryException in finally block: {}",
+                    e.getMessage(), e);
+            }
         }
-    }
-	
+        
+        // check for redirect URL if processing succeeded
+        if (htmlResponse.isSuccessful()) {
+            String redirect = getRedirectUrl(request, htmlResponse);
+            if (redirect != null) {
+                httpResponse.sendRedirect(redirect);
+                return;
+            }
+        }
+
+        // create a html response and send if unsuccessful or no redirect
+        htmlResponse.send(httpResponse, isSetStatus(request));
+	}
 
+	/**
+	 * Extending Servlet should implement this operation to do the work
+	 * 
+	 * @param request the sling http request to process
+	 * @param htmlResponse the response 
+	 * @param changes 
+	 */
+	abstract protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes) throws RepositoryException;
+	
+	
     /**
-     * Update the group membership based on the ":member" request
-     * parameters.  If the ":member" value ends with @Delete it is removed
-     * from the group membership, otherwise it is added to the group membership.
-     * 
-     * @param request
-     * @param authorizable
-     * @throws RepositoryException
+     * compute redirect URL (SLING-126)
+     *
+     * @param ctx the post processor
+     * @return the redirect location or <code>null</code>
      */
-	protected void updateGroupMembership(SlingHttpServletRequest request,
-			Authorizable authorizable, List<Modification> changes) throws RepositoryException {
-		if (authorizable.isGroup()) {
-			Group group = ((Group)authorizable);
-    		String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + group.getID(); 
-
-	    	ResourceResolver resolver = request.getResourceResolver();
-	    	Resource baseResource = request.getResource();
-	    	boolean changed = false;
-
-	    	//first remove any members posted as ":member@Delete"
-	    	String[] membersToDelete = request.getParameterValues(SlingPostConstants.RP_PREFIX + "member" + SlingPostConstants.SUFFIX_DELETE);
-	    	if (membersToDelete != null) {
-				for (String member : membersToDelete) {
-	                Resource res = resolver.getResource(baseResource, member);
-	                if (res != null) {
-	                	Authorizable memberAuthorizable = res.adaptTo(Authorizable.class);
-	                	if (memberAuthorizable != null) {
-	                		group.removeMember(memberAuthorizable);
-	                		changed = true;
-	                	}
-	                }
-					
-				}
-	    	}
-	    	
-	    	//second add any members posted as ":member"
-	    	String[] membersToAdd = request.getParameterValues(SlingPostConstants.RP_PREFIX + "member");
-	    	if (membersToAdd != null) {
-				for (String member : membersToAdd) {
-	                Resource res = resolver.getResource(baseResource, member);
-	                if (res != null) {
-	                	Authorizable memberAuthorizable = res.adaptTo(Authorizable.class);
-	                	if (memberAuthorizable != null) {
-	                		group.addMember(memberAuthorizable);
-	                		changed = true;
-	                	}
-	                }
-				}
-	    	}
-
-	    	if (changed) {
-        		//add an entry to the changes list to record the membership change
-        		changes.add(Modification.onModified(groupPath + "/members"));
-	    	}
-		}
-	}
-    
+    protected String getRedirectUrl(HttpServletRequest request, HtmlResponse ctx) {
+        // redirect param has priority (but see below, magic star)
+        String result = request.getParameter(SlingPostConstants.RP_REDIRECT_TO);
+        if (result != null && ctx.getPath() != null) {
+
+            // redirect to created/modified Resource
+            int star = result.indexOf('*');
+            if (star >= 0) {
+                StringBuffer buf = new StringBuffer();
+
+                // anything before the star
+                if (star > 0) {
+                    buf.append(result.substring(0, star));
+                }
+
+                // append the name of the manipulated node
+                buf.append(ResourceUtil.getName(ctx.getPath()));
+
+                // anything after the star
+                if (star < result.length() - 1) {
+                    buf.append(result.substring(star + 1));
+                }
+
+                // use the created path as the redirect result
+                result = buf.toString();
+
+            } else if (result.endsWith(SlingPostConstants.DEFAULT_CREATE_SUFFIX)) {
+                // if the redirect has a trailing slash, append modified node
+                // name
+                result = result.concat(ResourceUtil.getName(ctx.getPath()));
+            }
+
+            if (log.isDebugEnabled()) {
+                log.debug("Will redirect to " + result);
+            }
+        }
+        return result;
+    }
+
+    protected boolean isSetStatus(SlingHttpServletRequest request) {
+        String statusParam = request.getParameter(SlingPostConstants.RP_STATUS);
+        if (statusParam == null) {
+            log.debug(
+                "getStatusMode: Parameter {} not set, assuming standard status code",
+                SlingPostConstants.RP_STATUS);
+            return true;
+        }
+
+        if (SlingPostConstants.STATUS_VALUE_BROWSER.equals(statusParam)) {
+            log.debug(
+                "getStatusMode: Parameter {} asks for user-friendly status code",
+                SlingPostConstants.RP_STATUS);
+            return false;
+        }
+
+        if (SlingPostConstants.STATUS_VALUE_STANDARD.equals(statusParam)) {
+            log.debug(
+                "getStatusMode: Parameter {} asks for standard status code",
+                SlingPostConstants.RP_STATUS);
+            return true;
+        }
+
+        log.debug(
+            "getStatusMode: Parameter {} set to unknown value {}, assuming standard status code",
+            SlingPostConstants.RP_STATUS);
+        return true;
+    }
+	
     
     
     // ------ The methods below are based on the private methods from the ModifyOperation class -----
@@ -553,82 +639,79 @@ public abstract class AbstractAuthorizableOperation extends AbstractSlingPostOpe
 	}
 
 	
+	// ------ These methods were copied from AbstractSlingPostOperation ------
+
     /**
-     * Returns an iterator on <code>Resource</code> instances addressed in the
-     * {@link SlingPostConstants#RP_APPLY_TO} request parameter. If the request
-     * parameter is not set, <code>null</code> is returned. If the parameter
-     * is set with valid resources an empty iterator is returned. Any resources
-     * addressed in the {@link SlingPostConstants#RP_APPLY_TO} parameter is
-     * ignored.
-     *
-     * @param request The <code>SlingHttpServletRequest</code> object used to
-     *            get the {@link SlingPostConstants#RP_APPLY_TO} parameter.
-     * @return The iterator of resources listed in the parameter or
-     *         <code>null</code> if the parameter is not set in the request.
+     * Returns the path of the resource of the request as the item path.
+     * <p>
+     * This method may be overwritten by extension if the operation has
+     * different requirements on path processing.
      */
-    protected Iterator<Resource> getApplyToResources(
-            SlingHttpServletRequest request) {
-
-        String[] applyTo = request.getParameterValues(SlingPostConstants.RP_APPLY_TO);
-        if (applyTo == null) {
-            return null;
-        }
-
-        return new ApplyToIterator(request, applyTo);
+    protected String getItemPath(SlingHttpServletRequest request) {
+        return request.getResource().getPath();
     }
 
-    private static class ApplyToIterator implements Iterator<Resource> {
-
-        private final ResourceResolver resolver;
-        private final Resource baseResource;
-        private final String[] paths;
-
-        private int pathIndex;
-
-        private Resource nextResource;
-
-        ApplyToIterator(SlingHttpServletRequest request, String[] paths) {
-            this.resolver = request.getResourceResolver();
-            this.baseResource = request.getResource();
-            this.paths = paths;
-            this.pathIndex = 0;
-
-            nextResource = seek();
-        }
-
-        public boolean hasNext() {
-            return nextResource != null;
-        }
-
-        public Resource next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
+    /**
+     * Returns an external form of the given path prepending the context path
+     * and appending a display extension.
+     *
+     * @param path the path to externalize
+     * @return the url
+     */
+    protected final String externalizePath(SlingHttpServletRequest request,
+            String path) {
+        StringBuffer ret = new StringBuffer();
+        ret.append(SlingRequestPaths.getContextPath(request));
+        ret.append(request.getResourceResolver().map(path));
+
+        // append optional extension
+        String ext = request.getParameter(SlingPostConstants.RP_DISPLAY_EXTENSION);
+        if (ext != null && ext.length() > 0) {
+            if (ext.charAt(0) != '.') {
+                ret.append('.');
             }
-
-            Resource result = nextResource;
-            nextResource = seek();
-
-            return result;
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
+            ret.append(ext);
         }
 
-        private Resource seek() {
-            while (pathIndex < paths.length) {
-                String path = paths[pathIndex];
-                pathIndex++;
+        return ret.toString();
+    }
+	
+    /**
+     * Returns <code>true</code> if the <code>name</code> starts with either
+     * of the prefixes
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>},
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_PARENT <code>../</code>}
+     * and {@link SlingPostConstants#ITEM_PREFIX_ABSOLUTE <code>/</code>}.
+     */
+    protected boolean hasItemPathPrefix(String name) {
+        return name.startsWith(SlingPostConstants.ITEM_PREFIX_ABSOLUTE)
+            || name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_CURRENT)
+            || name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_PARENT);
+    }
+    
+    /**
+     * Returns true if any of the request parameters starts with
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>}.
+     * In this case only parameters starting with either of the prefixes
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>},
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_PARENT <code>../</code>}
+     * and {@link SlingPostConstants#ITEM_PREFIX_ABSOLUTE <code>/</code>} are
+     * considered as providing content to be stored. Otherwise all parameters
+     * not starting with the command prefix <code>:</code> are considered as
+     * parameters to be stored.
+     */
+    protected final boolean requireItemPathPrefix(
+            SlingHttpServletRequest request) {
 
-                Resource res = resolver.getResource(baseResource, path);
-                if (res != null) {
-                    return res;
-                }
-            }
+        boolean requirePrefix = false;
 
-            // no more elements in the array
-            return null;
+        Enumeration<?> names = request.getParameterNames();
+        while (names.hasMoreElements() && !requirePrefix) {
+            String name = (String) names.nextElement();
+            requirePrefix = name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_CURRENT);
         }
+
+        return requirePrefix;
     }
-	
+    
 }
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractGroupPostServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractGroupPostServlet.java
new file mode 100644
index 0000000..675aeb8
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractGroupPostServlet.java
@@ -0,0 +1,95 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Base class for servlets manipulating groups
+ */
+public abstract class AbstractGroupPostServlet extends AbstractAuthorizablePostServlet {
+	private static final long serialVersionUID = 1159063041816944076L;
+
+	/**
+     * Update the group membership based on the ":member" request
+     * parameters.  If the ":member" value ends with @Delete it is removed
+     * from the group membership, otherwise it is added to the group membership.
+     * 
+     * @param request
+     * @param authorizable
+     * @throws RepositoryException
+     */
+	protected void updateGroupMembership(SlingHttpServletRequest request,
+			Authorizable authorizable, List<Modification> changes) throws RepositoryException {
+		if (authorizable.isGroup()) {
+			Group group = ((Group)authorizable);
+    		String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + group.getID(); 
+
+	    	ResourceResolver resolver = request.getResourceResolver();
+	    	Resource baseResource = request.getResource();
+	    	boolean changed = false;
+
+	    	//first remove any members posted as ":member@Delete"
+	    	String[] membersToDelete = request.getParameterValues(SlingPostConstants.RP_PREFIX + "member" + SlingPostConstants.SUFFIX_DELETE);
+	    	if (membersToDelete != null) {
+				for (String member : membersToDelete) {
+	                Resource res = resolver.getResource(baseResource, member);
+	                if (res != null) {
+	                	Authorizable memberAuthorizable = res.adaptTo(Authorizable.class);
+	                	if (memberAuthorizable != null) {
+	                		group.removeMember(memberAuthorizable);
+	                		changed = true;
+	                	}
+	                }
+					
+				}
+	    	}
+	    	
+	    	//second add any members posted as ":member"
+	    	String[] membersToAdd = request.getParameterValues(SlingPostConstants.RP_PREFIX + "member");
+	    	if (membersToAdd != null) {
+				for (String member : membersToAdd) {
+	                Resource res = resolver.getResource(baseResource, member);
+	                if (res != null) {
+	                	Authorizable memberAuthorizable = res.adaptTo(Authorizable.class);
+	                	if (memberAuthorizable != null) {
+	                		group.addMember(memberAuthorizable);
+	                		changed = true;
+	                	}
+	                }
+				}
+	    	}
+
+	    	if (changed) {
+        		//add an entry to the changes list to record the membership change
+        		changes.add(Modification.onModified(groupPath + "/members"));
+	    	}
+		}
+	}
+	
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractUserPostServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractUserPostServlet.java
new file mode 100644
index 0000000..8e32ae9
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractUserPostServlet.java
@@ -0,0 +1,81 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Dictionary;
+
+import org.apache.jackrabbit.util.Text;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Base class for servlets manipulating users
+ */
+public abstract class AbstractUserPostServlet extends AbstractAuthorizablePostServlet {
+	private static final long serialVersionUID = -8401210711297654453L;
+
+	/**
+     * To be used for the encryption. E.g. for passwords in
+     * {@link javax.jcr.SimpleCredentials#getPassword()}  SimpleCredentials} 
+     * @scr.property valueRef="DEFAULT_PASSWORD_DIGEST_ALGORITHM"
+     */
+    private static final String PROP_PASSWORD_DIGEST_ALGORITHM = "password.digest.algorithm";
+    private static final String DEFAULT_PASSWORD_DIGEST_ALGORITHM = "sha1";
+    private String passwordDigestAlgoritm = null;
+
+    // ---------- SCR Integration ----------------------------------------------
+
+    protected void activate(ComponentContext context) {
+        super.activate(context);
+        
+        Dictionary<?, ?> props = context.getProperties();
+
+        Object propValue = props.get(PROP_PASSWORD_DIGEST_ALGORITHM);
+        if (propValue instanceof String) {
+        	passwordDigestAlgoritm = (String)propValue;
+        } else {
+        	passwordDigestAlgoritm = DEFAULT_PASSWORD_DIGEST_ALGORITHM;
+        }
+    }
+
+    protected void deactivate(ComponentContext context) {
+        super.deactivate(context);
+        passwordDigestAlgoritm = null;
+    }
+    
+    /**
+     * Digest the given password using the configured digest algorithm
+     * 
+     * @param pwd the value to digest
+     * @return the digested value
+     * @throws IllegalArgumentException
+     */
+    protected String digestPassword(String pwd) throws IllegalArgumentException {
+        try {
+            StringBuffer password = new StringBuffer();
+            password.append("{").append(passwordDigestAlgoritm).append("}");
+            password.append(Text.digest(passwordDigestAlgoritm, pwd.getBytes("UTF-8")));
+            return password.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalArgumentException(e.toString());
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+    
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangePasswordOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangeUserPasswordServlet.java
similarity index 78%
rename from src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangePasswordOperation.java
rename to src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangeUserPasswordServlet.java
index 9972ede..9feddec 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangePasswordOperation.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangeUserPasswordServlet.java
@@ -26,25 +26,29 @@ import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.api.servlets.HtmlResponse;
 import org.apache.sling.servlets.post.Modification;
 
 /**
- * Sling Post Operation implementation for updating the password of
- * a user in the jackrabbit UserManager.
+ * Sling Post Operation implementation for updating the password of a user in the 
+ * jackrabbit UserManager.
  * 
  * @scr.component metatype="no" immediate="true"
- * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
- * @scr.property name="sling.post.operation" value="changePassword"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" value="sling/user"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="changePassword" 
  */
-public class ChangePasswordOperation extends AbstractAuthorizableOperation {
+public class ChangeUserPasswordServlet extends AbstractUserPostServlet {
+	private static final long serialVersionUID = 1923614318474654502L;
 
 	/* (non-Javadoc)
-	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
 	 */
 	@Override
-	protected void doRun(SlingHttpServletRequest request,
-			HtmlResponse response, List<Modification> changes)
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes)
 			throws RepositoryException {
 		Authorizable authorizable = null;
 		Resource resource = request.getResource();
@@ -54,7 +58,7 @@ public class ChangePasswordOperation extends AbstractAuthorizableOperation {
 		
 		//check that the user was located.
 		if (authorizable == null || authorizable.isGroup()) {
-			throw new RepositoryException("User to update could not be determined.");
+			throw new ResourceNotFoundException("User to update could not be determined.");
 		}
 
 		if ("anonymous".equals(authorizable.getID())) {
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupServlet.java
similarity index 79%
rename from src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupOperation.java
rename to src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupServlet.java
index 08e2456..a7e162b 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupOperation.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupServlet.java
@@ -35,33 +35,36 @@ import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.SlingPostConstants;
 
 /**
- * Sling Post Operation implementation for creating a group in the jackrabbit
+ * Sling Post Servlet implementation for creating a group in the jackrabbit
  * UserManager.
- *
- * @scr.component metatype="no" immediate="true"
- * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
- * @scr.property name="sling.post.operation" value="createGroup"
+ * 
+ * @scr.component immediate="true" 
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" value="sling/groups"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="create" 
  */
-public class CreateGroupOperation extends AbstractAuthorizableOperation {
+public class CreateGroupServlet extends AbstractGroupPostServlet {
+	private static final long serialVersionUID = -1084915263933901466L;
 
 	/* (non-Javadoc)
-	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
 	 */
 	@Override
-	protected void doRun(SlingHttpServletRequest request,
-			HtmlResponse response, List<Modification> changes)
-			throws RepositoryException {
-		Session session = request.getResourceResolver().adaptTo(Session.class);
-		if (session == null) {
-			throw new RepositoryException("JCR Session not found");
-		}
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes) throws RepositoryException {
 		
 		//check that the submitted parameter values have valid values.
 		final String principalName = request.getParameter(SlingPostConstants.RP_NODE_NAME);
 		if (principalName == null) {
 			throw new RepositoryException("Group name was not submitted");
 		}
-		
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+
 		try {
 			UserManager userManager = AccessControlUtil.getUserManager(session);
 			Authorizable authorizable = userManager.getAuthorizable(principalName);
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserServlet.java
similarity index 86%
rename from src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserOperation.java
rename to src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserServlet.java
index c0e385f..c8259dc 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserOperation.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserServlet.java
@@ -35,17 +35,27 @@ import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.SlingPostConstants;
 import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * Sling Post Operation implementation for creating a user in the jackrabbit
+ * Sling Post Servlet implementation for creating a user in the jackrabbit
  * UserManager.
  * 
  * @scr.component immediate="true" label="%createUser.post.operation.name"
  *                description="%createUser.post.operation.description"
- * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
- * @scr.property name="sling.post.operation" value="createUser"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" value="sling/users"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="create" 
  */
-public class CreateUserOperation extends AbstractAuthorizableOperation {
+public class CreateUserServlet extends AbstractUserPostServlet {
+	private static final long serialVersionUID = 6871481922737658675L;
+
+	/**
+     * default log
+     */
+    private final Logger log = LoggerFactory.getLogger(getClass());
 
     /** @scr.property label="%self.registration.enabled.name" 
      * 					description="%self.registration.enabled.description" 
@@ -87,7 +97,6 @@ public class CreateUserOperation extends AbstractAuthorizableOperation {
             }
         }
     }
-    
 
     // ---------- SCR integration ---------------------------------------------
 
@@ -107,15 +116,15 @@ public class CreateUserOperation extends AbstractAuthorizableOperation {
         	selfRegistrationEnabled = DEFAULT_SELF_REGISTRATION_ENABLED;
         }
     }
+
     
+
 	/* (non-Javadoc)
-	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
 	 */
 	@Override
-	protected void doRun(SlingHttpServletRequest request,
-			HtmlResponse response, List<Modification> changes)
-			throws RepositoryException {
-
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes) throws RepositoryException {
 		//make sure user self-registration is enabled
 		if (!selfRegistrationEnabled) {
 			throw new RepositoryException("Sorry, registration of new users is not currently enabled.  Please try again later.");
@@ -155,6 +164,7 @@ public class CreateUserOperation extends AbstractAuthorizableOperation {
 
 				User user = userManager.createUser(principalName, digestPassword(pwd));
 				String userPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX + user.getID();
+				
 				response.setPath(userPath);
 				response.setLocation(externalizePath(request, userPath));
 				response.setParentLocation(externalizePath(request, AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PATH));
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableOperation.java
deleted file mode 100644
index 991cee0..0000000
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableOperation.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.jackrabbit.usermanager.post;
-
-import java.util.Iterator;
-import java.util.List;
-
-import javax.jcr.RepositoryException;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceNotFoundException;
-import org.apache.sling.api.servlets.HtmlResponse;
-import org.apache.sling.servlets.post.Modification;
-
-/**
- * Sling Post Operation implementation for deleting users and/or groups from the 
- * jackrabbit UserManager.
- * 
- * @scr.component metatype="no" immediate="true"
- * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
- * @scr.property name="sling.post.operation" value="deleteAuthorizable"
- */
-public class DeleteAuthorizableOperation extends AbstractAuthorizableOperation {
-
-	/* (non-Javadoc)
-	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
-	 */
-	@Override
-	protected void doRun(SlingHttpServletRequest request,
-			HtmlResponse response, List<Modification> changes)
-			throws RepositoryException {
-
-        Iterator<Resource> res = getApplyToResources(request);
-        if (res == null) {
-            Resource resource = request.getResource();
-            Authorizable item = resource.adaptTo(Authorizable.class);
-            if (item == null) {
-  	            String msg = "Missing source " + resource.getPath() + " for delete";
-                response.setStatus(HttpServletResponse.SC_NOT_FOUND, msg);
-               	throw new ResourceNotFoundException(msg);
-            }
-
-            item.remove();
-            changes.add(Modification.onDeleted(resource.getPath()));
-        } else {
-            while (res.hasNext()) {
-                Resource resource = res.next();
-                Authorizable item = resource.adaptTo(Authorizable.class);
-                if (item != null) {
-                    item.remove();
-                    changes.add(Modification.onDeleted(resource.getPath()));
-                }
-            }
-        }
-	}
-}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableServlet.java
new file mode 100644
index 0000000..39ac672
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableServlet.java
@@ -0,0 +1,159 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import javax.jcr.RepositoryException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Sling Post Operation implementation for deleting one or more users and/or groups from the 
+ * jackrabbit UserManager.
+ * 
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" values.0="sling/user" values.1="sling/group" values.2="sling/userManager"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="delete" 
+ */
+public class DeleteAuthorizableServlet extends AbstractAuthorizablePostServlet {
+	private static final long serialVersionUID = 5874621724096106496L;
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes)
+			throws RepositoryException {
+
+        Iterator<Resource> res = getApplyToResources(request);
+        if (res == null) {
+            Resource resource = request.getResource();
+            Authorizable item = resource.adaptTo(Authorizable.class);
+            if (item == null) {
+  	            String msg = "Missing source " + resource.getPath() + " for delete";
+  	            htmlResponse.setStatus(HttpServletResponse.SC_NOT_FOUND, msg);
+               	throw new ResourceNotFoundException(msg);
+            }
+
+            item.remove();
+            changes.add(Modification.onDeleted(resource.getPath()));
+        } else {
+            while (res.hasNext()) {
+                Resource resource = res.next();
+                Authorizable item = resource.adaptTo(Authorizable.class);
+                if (item != null) {
+                    item.remove();
+                    changes.add(Modification.onDeleted(resource.getPath()));
+                }
+            }
+        }
+	}
+	
+	
+    /**
+     * Returns an iterator on <code>Resource</code> instances addressed in the
+     * {@link SlingPostConstants#RP_APPLY_TO} request parameter. If the request
+     * parameter is not set, <code>null</code> is returned. If the parameter
+     * is set with valid resources an empty iterator is returned. Any resources
+     * addressed in the {@link SlingPostConstants#RP_APPLY_TO} parameter is
+     * ignored.
+     *
+     * @param request The <code>SlingHttpServletRequest</code> object used to
+     *            get the {@link SlingPostConstants#RP_APPLY_TO} parameter.
+     * @return The iterator of resources listed in the parameter or
+     *         <code>null</code> if the parameter is not set in the request.
+     */
+    protected Iterator<Resource> getApplyToResources(
+            SlingHttpServletRequest request) {
+
+        String[] applyTo = request.getParameterValues(SlingPostConstants.RP_APPLY_TO);
+        if (applyTo == null) {
+            return null;
+        }
+
+        return new ApplyToIterator(request, applyTo);
+    }
+
+    private static class ApplyToIterator implements Iterator<Resource> {
+
+        private final ResourceResolver resolver;
+        private final Resource baseResource;
+        private final String[] paths;
+
+        private int pathIndex;
+
+        private Resource nextResource;
+
+        ApplyToIterator(SlingHttpServletRequest request, String[] paths) {
+            this.resolver = request.getResourceResolver();
+            this.baseResource = request.getResource();
+            this.paths = paths;
+            this.pathIndex = 0;
+
+            nextResource = seek();
+        }
+
+        public boolean hasNext() {
+            return nextResource != null;
+        }
+
+        public Resource next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+
+            Resource result = nextResource;
+            nextResource = seek();
+
+            return result;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        private Resource seek() {
+            while (pathIndex < paths.length) {
+                String path = paths[pathIndex];
+                pathIndex++;
+
+                Resource res = resolver.getResource(baseResource, path);
+                if (res != null) {
+                    return res;
+                }
+            }
+
+            // no more elements in the array
+            return null;
+        }
+    }
+	
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateGroupServlet.java
similarity index 70%
copy from src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java
copy to src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateGroupServlet.java
index c88be1c..4e433a8 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateGroupServlet.java
@@ -25,26 +25,30 @@ import javax.jcr.Session;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.api.servlets.HtmlResponse;
 import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
 import org.apache.sling.servlets.post.Modification;
 
 /**
- * Sling Post Operation implementation for updating a user or group in the 
+ * Sling Post Operation implementation for updating a group in the 
  * jackrabbit UserManager.
  * 
  * @scr.component metatype="no" immediate="true"
- * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
- * @scr.property name="sling.post.operation" value="updateAuthorizable"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" values="sling/group"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="update" 
  */
-public class UpdateAuthorizableOperation extends AbstractAuthorizableOperation {
+public class UpdateGroupServlet extends AbstractGroupPostServlet {
+	private static final long serialVersionUID = -8292054361992488797L;
 
 	/* (non-Javadoc)
-	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
 	 */
 	@Override
-	protected void doRun(SlingHttpServletRequest request,
-			HtmlResponse response, List<Modification> changes)
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes)
 			throws RepositoryException {
 		Authorizable authorizable = null;
 		Resource resource = request.getResource();
@@ -54,7 +58,7 @@ public class UpdateAuthorizableOperation extends AbstractAuthorizableOperation {
 		
 		//check that the group was located.
 		if (authorizable == null) {
-			throw new RepositoryException("Authorizable to update could not be determined");
+			throw new ResourceNotFoundException("Group to update could not be determined");
 		}
 
 		Session session = request.getResourceResolver().adaptTo(Session.class);
@@ -62,7 +66,7 @@ public class UpdateAuthorizableOperation extends AbstractAuthorizableOperation {
 			throw new RepositoryException("JCR Session not found");
 		}
 
-		Map<String, RequestProperty> reqProperties = collectContent(request, response);
+		Map<String, RequestProperty> reqProperties = collectContent(request, htmlResponse);
 		try {
 	        // cleanup any old content (@Delete parameters)
 	        processDeletes(authorizable, reqProperties, changes);
@@ -75,7 +79,7 @@ public class UpdateAuthorizableOperation extends AbstractAuthorizableOperation {
 		        updateGroupMembership(request, authorizable, changes);
 			}
 		} catch (RepositoryException re) {
-			throw new RepositoryException("Failed to update authorizable.", re);
+			throw new RepositoryException("Failed to update group.", re);
 		}
 	}
 }
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateUserServlet.java
similarity index 68%
rename from src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java
rename to src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateUserServlet.java
index c88be1c..d0245c6 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateUserServlet.java
@@ -25,26 +25,30 @@ import javax.jcr.Session;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
 import org.apache.sling.api.servlets.HtmlResponse;
 import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
 import org.apache.sling.servlets.post.Modification;
 
 /**
- * Sling Post Operation implementation for updating a user or group in the 
+ * Sling Post Operation implementation for updating a user in the 
  * jackrabbit UserManager.
  * 
  * @scr.component metatype="no" immediate="true"
- * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
- * @scr.property name="sling.post.operation" value="updateAuthorizable"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" value="sling/user"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="update" 
  */
-public class UpdateAuthorizableOperation extends AbstractAuthorizableOperation {
+public class UpdateUserServlet extends AbstractUserPostServlet {
+	private static final long serialVersionUID = 5874621724096106496L;
 
 	/* (non-Javadoc)
-	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
 	 */
 	@Override
-	protected void doRun(SlingHttpServletRequest request,
-			HtmlResponse response, List<Modification> changes)
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes)
 			throws RepositoryException {
 		Authorizable authorizable = null;
 		Resource resource = request.getResource();
@@ -54,7 +58,7 @@ public class UpdateAuthorizableOperation extends AbstractAuthorizableOperation {
 		
 		//check that the group was located.
 		if (authorizable == null) {
-			throw new RepositoryException("Authorizable to update could not be determined");
+			throw new ResourceNotFoundException("User to update could not be determined");
 		}
 
 		Session session = request.getResourceResolver().adaptTo(Session.class);
@@ -62,20 +66,16 @@ public class UpdateAuthorizableOperation extends AbstractAuthorizableOperation {
 			throw new RepositoryException("JCR Session not found");
 		}
 
-		Map<String, RequestProperty> reqProperties = collectContent(request, response);
+		Map<String, RequestProperty> reqProperties = collectContent(request, htmlResponse);
 		try {
 	        // cleanup any old content (@Delete parameters)
 	        processDeletes(authorizable, reqProperties, changes);
 				
 	        // write content from form
 	        writeContent(session, authorizable, reqProperties, changes);
-	        
-	        //update the group memberships
-			if (authorizable.isGroup()) {
-		        updateGroupMembership(request, authorizable, changes);
-			}
+
 		} catch (RepositoryException re) {
-			throw new RepositoryException("Failed to update authorizable.", re);
+			throw new RepositoryException("Failed to update user.", re);
 		}
 	}
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 06/13: Use release parent pom

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 31646403acad35d8882e4589f2720b2060ecb2ac
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue May 5 15:06:21 2009 +0000

    Use release parent pom
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@771764 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index e1244fd..b6b347c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
 	<parent>
 		<groupId>org.apache.sling</groupId>
 		<artifactId>sling</artifactId>
-		<version>5-incubator-SNAPSHOT</version>
+		<version>5-incubator</version>
 		<relativePath>../../../parent/pom.xml</relativePath>
 	</parent>
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 11/13: [maven-release-plugin] copy for tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 8fd85d12a58c0050f3b3f58ba8f19e2c7dc5a043
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed May 6 13:15:57 2009 +0000

    [maven-release-plugin]  copy for tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator@772221 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                | 10 +++++-----
 src/main/resources/META-INF/DISCLAIMER |  7 +++++++
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/pom.xml b/pom.xml
index c22d4da..b56815e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,13 +23,13 @@
 	<parent>
 		<groupId>org.apache.sling</groupId>
 		<artifactId>sling</artifactId>
-		<version>6-incubator-SNAPSHOT</version>
+        <version>5-incubator</version>
 		<relativePath>../../../parent/pom.xml</relativePath>
 	</parent>
 
 	<artifactId>org.apache.sling.jcr.jackrabbit.usermanager</artifactId>
 	<packaging>bundle</packaging>
-	<version>2.0.1-incubator-SNAPSHOT</version>
+	<version>2.0.2-incubator</version>
 	<name>Apache Sling Jackrabbit UserManager Support</name>
 	<description>
 		Provides ResourceProvider and SlingPostOperations for the Jackrabbit
@@ -38,13 +38,13 @@
 
 	<scm>
 		<connection>
-			scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+			scm:svn:http://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
 		</connection>
 		<developerConnection>
-			scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+			scm:svn:https://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
 		</developerConnection>
 		<url>
-			http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+			http://svn.apache.org/viewvc/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
 		</url>
 	</scm>
 
diff --git a/src/main/resources/META-INF/DISCLAIMER b/src/main/resources/META-INF/DISCLAIMER
new file mode 100644
index 0000000..90850c2
--- /dev/null
+++ b/src/main/resources/META-INF/DISCLAIMER
@@ -0,0 +1,7 @@
+Apache Sling is an effort undergoing incubation at The Apache Software Foundation (ASF),
+sponsored by the Apache Jackrabbit PMC. Incubation is required of all newly accepted
+projects until a further review indicates that the infrastructure, communications,
+and decision making process have stabilized in a manner consistent with other
+successful ASF projects. While incubation status is not necessarily a reflection of
+the completeness or stability of the code, it does indicate that the project has yet
+to be fully endorsed by the ASF.
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 13/13: Move Sling to new TLP location

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit ef415cb91ca16077d38a50580103aa1f892ae395
Merge: c84c5b4 8fd85d1
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Thu Jun 18 09:21:02 2009 +0000

    Move Sling to new TLP location
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator@785979 13f79535-47bb-0310-9956-ffa450edef68


-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 12/13: Move Sling to new TLP location

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit c84c5b4547dc617bd777a68539fd15dc70665ade
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Thu Jun 18 09:21:02 2009 +0000

    Move Sling to new TLP location
    
    git-svn-id: https://svn.eu.apache.org/repos/asf/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator@785979 13f79535-47bb-0310-9956-ffa450edef68
---
 LICENSE                                            | 202 ++++++
 NOTICE                                             |   5 +
 README.txt                                         |  37 ++
 pom.xml                                            | 128 ++++
 .../post/AbstractAuthorizablePostServlet.java      | 717 +++++++++++++++++++++
 .../usermanager/post/AbstractGroupPostServlet.java |  95 +++
 .../usermanager/post/AbstractUserPostServlet.java  |  81 +++
 .../post/ChangeUserPasswordServlet.java            | 107 +++
 .../usermanager/post/CreateGroupServlet.java       | 100 +++
 .../usermanager/post/CreateUserServlet.java        | 184 ++++++
 .../post/DeleteAuthorizableServlet.java            | 159 +++++
 .../usermanager/post/UpdateGroupServlet.java       |  85 +++
 .../usermanager/post/UpdateUserServlet.java        |  81 +++
 .../usermanager/post/impl/DateParser.java          | 138 ++++
 .../usermanager/post/impl/RequestProperty.java     | 257 ++++++++
 .../usermanager/resource/AuthorizableResource.java | 119 ++++
 .../resource/AuthorizableResourceProvider.java     | 220 +++++++
 .../usermanager/resource/AuthorizableValueMap.java | 319 +++++++++
 src/main/resources/META-INF/DISCLAIMER             |   7 +
 src/main/resources/META-INF/LICENSE                | 202 ++++++
 src/main/resources/META-INF/NOTICE                 |   5 +
 .../OSGI-INF/metatype/metatype.properties          |  36 ++
 22 files changed, 3284 insertions(+)

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..75b5248
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..9f4ac5f
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache Sling Jackrabbit UserManager Support
+Copyright 2008-2009 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..046bab8
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,37 @@
+Apache Sling Jackrabbit UserManager Support
+
+Provides ResourceProvider and SlingPostOperations for the Jackrabbit UserManager.
+
+Disclaimer
+==========
+Apache Sling is an effort undergoing incubation at The Apache Software Foundation (ASF),
+sponsored by the Apache Jackrabbit PMC. Incubation is required of all newly accepted
+projects until a further review indicates that the infrastructure, communications,
+and decision making process have stabilized in a manner consistent with other
+successful ASF projects. While incubation status is not necessarily a reflection of
+the completeness or stability of the code, it does indicate that the project has yet
+to be fully endorsed by the ASF.
+
+Getting Started
+===============
+
+This component uses a Maven 2 (http://maven.apache.org/) build
+environment. It requires a Java 5 JDK (or higher) and Maven (http://maven.apache.org/)
+2.0.7 or later. We recommend to use the latest Maven version.
+
+If you have Maven 2 installed, you can compile and
+package the jar using the following command:
+
+    mvn package
+
+See the Maven 2 documentation for other build features.
+
+The latest source code for this component is available in the
+Subversion (http://subversion.tigris.org/) source repository of
+the Apache Software Foundation. If you have Subversion installed,
+you can checkout the latest source using the following command:
+
+    svn checkout http://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+
+See the Subversion documentation for other source control features.
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..b56815e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,128 @@
+<?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">
+	
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.sling</groupId>
+		<artifactId>sling</artifactId>
+        <version>5-incubator</version>
+		<relativePath>../../../parent/pom.xml</relativePath>
+	</parent>
+
+	<artifactId>org.apache.sling.jcr.jackrabbit.usermanager</artifactId>
+	<packaging>bundle</packaging>
+	<version>2.0.2-incubator</version>
+	<name>Apache Sling Jackrabbit UserManager Support</name>
+	<description>
+		Provides ResourceProvider and SlingPostOperations for the Jackrabbit
+		UserManager.
+	</description>
+
+	<scm>
+		<connection>
+			scm:svn:http://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
+		</connection>
+		<developerConnection>
+			scm:svn:https://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
+		</developerConnection>
+		<url>
+			http://svn.apache.org/viewvc/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
+		</url>
+	</scm>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-scr-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Private-Package>
+                            org.apache.sling.jackrabbit.usermanager.*
+						</Private-Package>
+						<Sling-Initial-Content />
+						<Sling-Nodetypes />
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<reporting>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<configuration>
+					<!-- No javadocs -->
+					<excludePackageNames>
+					    org.apache.sling.jackrabbit.usermanager.post.impl
+					</excludePackageNames>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<dependencies>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.api</artifactId>
+			<version>2.0.4-incubator</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.servlets.post</artifactId>
+			<version>2.0.4-incubator</version>
+		</dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-api</artifactId>
+            <version>1.5.0</version>
+        </dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.jcr.base</artifactId>
+			<version>2.0.4-incubator</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.jackrabbit</groupId>
+			<artifactId>jackrabbit-api</artifactId>
+			<version>1.5.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.osgi.core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.osgi.compendium</artifactId>
+		</dependency>
+	</dependencies>
+</project>
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizablePostServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizablePostServlet.java
new file mode 100644
index 0000000..ab1d5cf
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizablePostServlet.java
@@ -0,0 +1,717 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.api.wrappers.SlingRequestPaths;
+import org.apache.sling.commons.osgi.OsgiUtil;
+import org.apache.sling.jackrabbit.usermanager.post.impl.DateParser;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class for all the POST servlets for the UserManager operations 
+ */
+public abstract class AbstractAuthorizablePostServlet extends SlingAllMethodsServlet {
+	private static final long serialVersionUID = -5918670409789895333L;
+
+	/**
+     * default log
+     */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    /**
+     * @scr.property values.0="EEE MMM dd yyyy HH:mm:ss 'GMT'Z"
+     *               values.1="yyyy-MM-dd'T'HH:mm:ss.SSSZ"
+     *               values.2="yyyy-MM-dd'T'HH:mm:ss" values.3="yyyy-MM-dd"
+     *               values.4="dd.MM.yyyy HH:mm:ss" values.5="dd.MM.yyyy"
+     */
+    private static final String PROP_DATE_FORMAT = "servlet.post.dateFormats";
+	
+	private DateParser dateParser;
+	
+    // ---------- SCR Integration ----------------------------------------------
+
+    protected void activate(ComponentContext context) {
+        Dictionary<?, ?> props = context.getProperties();
+
+        dateParser = new DateParser();
+        String[] dateFormats = OsgiUtil.toStringArray(props.get(PROP_DATE_FORMAT));
+        for (String dateFormat : dateFormats) {
+            dateParser.register(dateFormat);
+        }
+    }
+
+    protected void deactivate(ComponentContext context) {
+        dateParser = null;
+    }
+	
+    
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.servlets.SlingAllMethodsServlet#doPost(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.SlingHttpServletResponse)
+	 */
+	@Override
+	protected void doPost(SlingHttpServletRequest request,
+			SlingHttpServletResponse httpResponse) throws ServletException,
+			IOException {
+        // prepare the response
+        HtmlResponse htmlResponse = new HtmlResponse();
+        htmlResponse.setReferer(request.getHeader("referer"));
+
+        // calculate the paths
+        String path = getItemPath(request);
+        htmlResponse.setPath(path);
+
+        // location
+        htmlResponse.setLocation(externalizePath(request, path));
+
+        // parent location
+        path = ResourceUtil.getParent(path);
+        if (path != null) {
+        	htmlResponse.setParentLocation(externalizePath(request, path));
+        }
+
+        Session session = request.getResourceResolver().adaptTo(Session.class);
+
+        final List<Modification> changes = new ArrayList<Modification>();
+        
+        try {
+            handleOperation(request, htmlResponse, changes);
+            
+            //TODO: maybe handle SlingAuthorizablePostProcessor handlers here
+            
+            // set changes on html response
+            for(Modification change : changes) {
+                switch ( change.getType() ) {
+                    case MODIFY : htmlResponse.onModified(change.getSource()); break;
+                    case DELETE : htmlResponse.onDeleted(change.getSource()); break;
+                    case MOVE :   htmlResponse.onMoved(change.getSource(), change.getDestination()); break;
+                    case COPY :   htmlResponse.onCopied(change.getSource(), change.getDestination()); break;
+                    case CREATE : htmlResponse.onCreated(change.getSource()); break;
+                    case ORDER : htmlResponse.onChange("ordered", change.getSource(), change.getDestination()); break;
+                }
+            }
+            
+            if (session.hasPendingChanges()) {
+                session.save();
+            }
+        } catch (ResourceNotFoundException rnfe) {
+            htmlResponse.setStatus(HttpServletResponse.SC_NOT_FOUND,
+                rnfe.getMessage());
+        } catch (Throwable throwable) {
+            log.debug("Exception while handling POST "
+                + request.getResource().getPath() + " with "
+                + getClass().getName(), throwable);
+            htmlResponse.setError(throwable);
+        } finally {
+            try {
+                if (session.hasPendingChanges()) {
+                    session.refresh(false);
+                }
+            } catch (RepositoryException e) {
+                log.warn("RepositoryException in finally block: {}",
+                    e.getMessage(), e);
+            }
+        }
+        
+        // check for redirect URL if processing succeeded
+        if (htmlResponse.isSuccessful()) {
+            String redirect = getRedirectUrl(request, htmlResponse);
+            if (redirect != null) {
+                httpResponse.sendRedirect(redirect);
+                return;
+            }
+        }
+
+        // create a html response and send if unsuccessful or no redirect
+        htmlResponse.send(httpResponse, isSetStatus(request));
+	}
+
+	/**
+	 * Extending Servlet should implement this operation to do the work
+	 * 
+	 * @param request the sling http request to process
+	 * @param htmlResponse the response 
+	 * @param changes 
+	 */
+	abstract protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes) throws RepositoryException;
+	
+	
+    /**
+     * compute redirect URL (SLING-126)
+     *
+     * @param ctx the post processor
+     * @return the redirect location or <code>null</code>
+     */
+    protected String getRedirectUrl(HttpServletRequest request, HtmlResponse ctx) {
+        // redirect param has priority (but see below, magic star)
+        String result = request.getParameter(SlingPostConstants.RP_REDIRECT_TO);
+        if (result != null && ctx.getPath() != null) {
+
+            // redirect to created/modified Resource
+            int star = result.indexOf('*');
+            if (star >= 0) {
+                StringBuffer buf = new StringBuffer();
+
+                // anything before the star
+                if (star > 0) {
+                    buf.append(result.substring(0, star));
+                }
+
+                // append the name of the manipulated node
+                buf.append(ResourceUtil.getName(ctx.getPath()));
+
+                // anything after the star
+                if (star < result.length() - 1) {
+                    buf.append(result.substring(star + 1));
+                }
+
+                // use the created path as the redirect result
+                result = buf.toString();
+
+            } else if (result.endsWith(SlingPostConstants.DEFAULT_CREATE_SUFFIX)) {
+                // if the redirect has a trailing slash, append modified node
+                // name
+                result = result.concat(ResourceUtil.getName(ctx.getPath()));
+            }
+
+            if (log.isDebugEnabled()) {
+                log.debug("Will redirect to " + result);
+            }
+        }
+        return result;
+    }
+
+    protected boolean isSetStatus(SlingHttpServletRequest request) {
+        String statusParam = request.getParameter(SlingPostConstants.RP_STATUS);
+        if (statusParam == null) {
+            log.debug(
+                "getStatusMode: Parameter {} not set, assuming standard status code",
+                SlingPostConstants.RP_STATUS);
+            return true;
+        }
+
+        if (SlingPostConstants.STATUS_VALUE_BROWSER.equals(statusParam)) {
+            log.debug(
+                "getStatusMode: Parameter {} asks for user-friendly status code",
+                SlingPostConstants.RP_STATUS);
+            return false;
+        }
+
+        if (SlingPostConstants.STATUS_VALUE_STANDARD.equals(statusParam)) {
+            log.debug(
+                "getStatusMode: Parameter {} asks for standard status code",
+                SlingPostConstants.RP_STATUS);
+            return true;
+        }
+
+        log.debug(
+            "getStatusMode: Parameter {} set to unknown value {}, assuming standard status code",
+            SlingPostConstants.RP_STATUS);
+        return true;
+    }
+	
+    
+    
+    // ------ The methods below are based on the private methods from the ModifyOperation class -----
+    
+    /**
+     * Collects the properties that form the content to be written back to the
+     * repository. 
+     * 
+     * NOTE: In the returned map, the key is the property name not a path.
+     *
+     * @throws RepositoryException if a repository error occurs
+     * @throws ServletException if an internal error occurs
+     */
+    protected Map<String, RequestProperty> collectContent(
+            SlingHttpServletRequest request, HtmlResponse response) {
+
+        boolean requireItemPrefix = requireItemPathPrefix(request);
+
+        // walk the request parameters and collect the properties
+        Map<String, RequestProperty> reqProperties = new HashMap<String, RequestProperty>();
+        for (Map.Entry<String, RequestParameter[]> e : request.getRequestParameterMap().entrySet()) {
+            final String paramName = e.getKey();
+
+            // do not store parameters with names starting with sling:post
+            if (paramName.startsWith(SlingPostConstants.RP_PREFIX)) {
+                continue;
+            }
+            // SLING-298: skip form encoding parameter
+            if (paramName.equals("_charset_")) {
+                continue;
+            }
+            // skip parameters that do not start with the save prefix
+            if (requireItemPrefix && !hasItemPathPrefix(paramName)) {
+                continue;
+            }
+
+            // ensure the paramName is an absolute property name
+            String propPath;
+            if (paramName.startsWith("./")) {
+            	propPath = paramName.substring(2);
+            } else {
+            	propPath = paramName;
+            }
+            if (propPath.indexOf('/') != -1) {
+            	//only one path segment is valid here, so this paramter can't be used.
+            	continue; //skip it.
+            }
+
+            // @TypeHint example
+            // <input type="text" name="./age" />
+            // <input type="hidden" name="./age@TypeHint" value="long" />
+            // causes the setProperty using the 'long' property type
+            if (propPath.endsWith(SlingPostConstants.TYPE_HINT_SUFFIX)) {
+                RequestProperty prop = getOrCreateRequestProperty(
+                    reqProperties, propPath,
+                    SlingPostConstants.TYPE_HINT_SUFFIX);
+
+                final RequestParameter[] rp = e.getValue();
+                if (rp.length > 0) {
+                    prop.setTypeHintValue(rp[0].getString());
+                }
+
+                continue;
+            }
+
+            // @DefaultValue
+            if (propPath.endsWith(SlingPostConstants.DEFAULT_VALUE_SUFFIX)) {
+                RequestProperty prop = getOrCreateRequestProperty(
+                    reqProperties, propPath,
+                    SlingPostConstants.DEFAULT_VALUE_SUFFIX);
+
+                prop.setDefaultValues(e.getValue());
+
+                continue;
+            }
+
+            // SLING-130: VALUE_FROM_SUFFIX means take the value of this
+            // property from a different field
+            // @ValueFrom example:
+            // <input name="./Text@ValueFrom" type="hidden" value="fulltext" />
+            // causes the JCR Text property to be set to the value of the
+            // fulltext form field.
+            if (propPath.endsWith(SlingPostConstants.VALUE_FROM_SUFFIX)) {
+                RequestProperty prop = getOrCreateRequestProperty(
+                    reqProperties, propPath,
+                    SlingPostConstants.VALUE_FROM_SUFFIX);
+
+                // @ValueFrom params must have exactly one value, else ignored
+                if (e.getValue().length == 1) {
+                    String refName = e.getValue()[0].getString();
+                    RequestParameter[] refValues = request.getRequestParameters(refName);
+                    if (refValues != null) {
+                        prop.setValues(refValues);
+                    }
+                }
+
+                continue;
+            }
+
+            // SLING-458: Allow Removal of properties prior to update
+            // @Delete example:
+            // <input name="./Text@Delete" type="hidden" />
+            // causes the JCR Text property to be deleted before update
+            if (propPath.endsWith(SlingPostConstants.SUFFIX_DELETE)) {
+                RequestProperty prop = getOrCreateRequestProperty(
+                    reqProperties, propPath, SlingPostConstants.SUFFIX_DELETE);
+
+                prop.setDelete(true);
+
+                continue;
+            }
+
+            // SLING-455: @MoveFrom means moving content to another location
+            // @MoveFrom example:
+            // <input name="./Text@MoveFrom" type="hidden" value="/tmp/path" />
+            // causes the JCR Text property to be set by moving the /tmp/path
+            // property to Text.
+            if (propPath.endsWith(SlingPostConstants.SUFFIX_MOVE_FROM)) {
+            	//don't support @MoveFrom here
+                continue;
+            }
+
+            // SLING-455: @CopyFrom means moving content to another location
+            // @CopyFrom example:
+            // <input name="./Text@CopyFrom" type="hidden" value="/tmp/path" />
+            // causes the JCR Text property to be set by copying the /tmp/path
+            // property to Text.
+            if (propPath.endsWith(SlingPostConstants.SUFFIX_COPY_FROM)) {
+            	//don't support @CopyFrom here
+                continue;
+            }
+
+            // plain property, create from values
+            RequestProperty prop = getOrCreateRequestProperty(reqProperties,
+                propPath, null);
+            prop.setValues(e.getValue());
+        }
+
+        return reqProperties;
+    }
+	
+	
+    /**
+     * Returns the request property for the given property path. If such a
+     * request property does not exist yet it is created and stored in the
+     * <code>props</code>.
+     *
+     * @param props The map of already seen request properties.
+     * @param paramName The absolute path of the property including the
+     *            <code>suffix</code> to be looked up.
+     * @param suffix The (optional) suffix to remove from the
+     *            <code>paramName</code> before looking it up.
+     * @return The {@link RequestProperty} for the <code>paramName</code>.
+     */
+    private RequestProperty getOrCreateRequestProperty(
+            Map<String, RequestProperty> props, String paramName, String suffix) {
+        if (suffix != null && paramName.endsWith(suffix)) {
+            paramName = paramName.substring(0, paramName.length()
+                - suffix.length());
+        }
+
+        RequestProperty prop = props.get(paramName);
+        if (prop == null) {
+            prop = new RequestProperty(paramName);
+            props.put(paramName, prop);
+        }
+
+        return prop;
+    }
+    
+    
+    /**
+     * Removes all properties listed as {@link RequestProperty#isDelete()} from
+     * the authorizable.
+     *
+     * @param authorizable The <code>org.apache.jackrabbit.api.security.user.Authorizable</code> 
+     * 				that should have properties deleted.
+     * @param reqProperties The map of request properties to check for
+     *            properties to be removed.
+     * @param response The <code>HtmlResponse</code> to be updated with
+     *            information on deleted properties.
+     * @throws RepositoryException Is thrown if an error occurrs checking or
+     *             removing properties.
+     */
+    protected void processDeletes(Authorizable resource, 
+            Map<String, RequestProperty> reqProperties,
+            List<Modification> changes) throws RepositoryException {
+
+        for (RequestProperty property : reqProperties.values()) {
+            if (property.isDelete()) {
+            	if (resource.hasProperty(property.getName())) {
+            		resource.removeProperty(property.getName());
+                    changes.add(Modification.onDeleted(property.getPath()));
+            	}
+            }
+        }
+    }
+
+    
+    /**
+     * Writes back the content
+     *
+     * @throws RepositoryException if a repository error occurs
+     * @throws ServletException if an internal error occurs
+     */
+    protected void writeContent(Session session, Authorizable authorizable,
+            Map<String, RequestProperty> reqProperties, List<Modification> changes)
+            throws RepositoryException {
+
+        for (RequestProperty prop : reqProperties.values()) {
+            if (prop.hasValues()) {
+                // skip jcr special properties
+                if (prop.getName().equals("jcr:primaryType")
+                    || prop.getName().equals("jcr:mixinTypes")) {
+                    continue;
+                }
+                if (authorizable.isGroup()) {
+                    if (prop.getName().equals("groupId")) {
+                    	//skip these
+                    	continue;
+                	}                	
+                } else {
+                    if (prop.getName().equals("userId") ||
+                    		prop.getName().equals("pwd") ||
+                    		prop.getName().equals("pwdConfirm")) {
+                    	//skip these
+                    	continue;
+                    }
+                }
+                if (prop.isFileUpload()) {
+                	//don't handle files for user properties for now.
+                	continue;
+                    //uploadHandler.setFile(parent, prop, changes);
+                } else {
+                	setPropertyAsIs(session, authorizable, prop, changes);
+                }
+            }
+        }
+    }
+    
+    /**
+     * set property without processing, except for type hints
+     *
+     * @param parent the parent node
+     * @param prop the request property
+     * @throws RepositoryException if a repository error occurs.
+     */
+    private void setPropertyAsIs(Session session, Authorizable parent, RequestProperty prop, List<Modification> changes)
+            throws RepositoryException {
+
+    	String parentPath;
+    	if (parent.isGroup()) {
+    		parentPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + parent.getID();
+    	} else {
+    		parentPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX + parent.getID();
+    	}
+
+
+        // no explicit typehint
+        int type = PropertyType.UNDEFINED;
+        if (prop.getTypeHint() != null) {
+            try {
+                type = PropertyType.valueFromName(prop.getTypeHint());
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+
+        String[] values = prop.getStringValues();
+		if (values == null) {
+            // remove property
+	        boolean removedProp = removePropertyIfExists(parent, prop.getName());
+	        if (removedProp) {
+	            changes.add(Modification.onDeleted(
+	            		parentPath + "/" + prop.getName()
+	            ));
+	        }
+        } else if (values.length == 0) {
+            // do not create new prop here, but clear existing
+            if (parent.hasProperty(prop.getName())) {
+            	Value val = session.getValueFactory().createValue("");
+            	parent.setProperty(prop.getName(), val);
+                changes.add(Modification.onModified(
+                	parentPath + "/" + prop.getName()
+                ));
+            }
+        } else if (values.length == 1) {
+            boolean removedProp = removePropertyIfExists(parent, prop.getName());
+            // if the provided value is the empty string, we don't have to do anything.
+            if ( values[0].length() == 0 ) {
+                if ( removedProp ) {
+                    changes.add(Modification.onDeleted(parentPath + "/" + prop.getName()));
+                }
+            } else {
+                // modify property
+                if (type == PropertyType.DATE) {
+                    // try conversion
+                    Calendar c = dateParser.parse(values[0]);
+                    if (c != null) {
+                        if ( prop.hasMultiValueTypeHint() ) {
+                            final Value[] array = new Value[1];
+                            array[0] = session.getValueFactory().createValue(c);
+                            parent.setProperty(prop.getName(), array);
+                            changes.add(Modification.onModified(
+                                parentPath + "/" + prop.getName()
+                            ));
+                        } else {
+                        	Value cVal = session.getValueFactory().createValue(c);
+                        	parent.setProperty(prop.getName(), cVal);
+                            changes.add(Modification.onModified(
+                                    parentPath + "/" + prop.getName()
+                                ));
+                        }
+                        return;
+                    }
+                    // fall back to default behaviour
+                }
+                if ( type == PropertyType.UNDEFINED ) {
+                	Value val = session.getValueFactory().createValue(values[0], PropertyType.STRING);
+                	parent.setProperty(prop.getName(), val);
+                } else {
+                    if ( prop.hasMultiValueTypeHint() ) {
+                        final Value[] array = new Value[1];
+                        array[0] = session.getValueFactory().createValue(values[0], type);
+                        parent.setProperty(prop.getName(), array);
+                    } else {
+                    	Value val = session.getValueFactory().createValue(values[0], type);
+                        parent.setProperty(prop.getName(), val);
+                    }
+                }
+                changes.add(Modification.onModified(parentPath + "/" + prop.getName()));
+            }
+        } else {
+            removePropertyIfExists(parent, prop.getName());
+            if (type == PropertyType.DATE) {
+                // try conversion
+                ValueFactory valFac = session.getValueFactory();
+                Value[] c = dateParser.parse(values, valFac);
+                if (c != null) {
+                	parent.setProperty(prop.getName(), c);
+                    changes.add(Modification.onModified(
+                    		parentPath + "/" + prop.getName()
+                    ));
+                    return;
+                }
+                // fall back to default behaviour
+            }
+
+            Value [] vals = new Value[values.length];
+            if ( type == PropertyType.UNDEFINED ) {
+            	for(int i=0; i < values.length; i++) {
+            		vals[i] = session.getValueFactory().createValue(values[i]);
+            	}
+            } else {
+            	for(int i=0; i < values.length; i++) {
+            		vals[i] = session.getValueFactory().createValue(values[i], type);
+            	}
+            }
+        	parent.setProperty(prop.getName(), vals);
+            changes.add(Modification.onModified(parentPath + "/" + prop.getName()));
+        }
+    
+    }
+
+    /**
+     * Removes the property with the given name from the parent resource if it
+     * exists.
+     *
+     * @param parent the parent resource
+     * @param name the name of the property to remove
+     * @return path of the property that was removed or <code>null</code> if
+     *         it was not removed
+     * @throws RepositoryException if a repository error occurs.
+     */
+	private boolean removePropertyIfExists(Authorizable resource, String name) throws RepositoryException {
+    	if (resource.getProperty(name) != null) {
+    		resource.removeProperty(name);
+    		return true;
+    	}
+    	return false;
+	}
+
+	
+	// ------ These methods were copied from AbstractSlingPostOperation ------
+
+    /**
+     * Returns the path of the resource of the request as the item path.
+     * <p>
+     * This method may be overwritten by extension if the operation has
+     * different requirements on path processing.
+     */
+    protected String getItemPath(SlingHttpServletRequest request) {
+        return request.getResource().getPath();
+    }
+
+    /**
+     * Returns an external form of the given path prepending the context path
+     * and appending a display extension.
+     *
+     * @param path the path to externalize
+     * @return the url
+     */
+    protected final String externalizePath(SlingHttpServletRequest request,
+            String path) {
+        StringBuffer ret = new StringBuffer();
+        ret.append(SlingRequestPaths.getContextPath(request));
+        ret.append(request.getResourceResolver().map(path));
+
+        // append optional extension
+        String ext = request.getParameter(SlingPostConstants.RP_DISPLAY_EXTENSION);
+        if (ext != null && ext.length() > 0) {
+            if (ext.charAt(0) != '.') {
+                ret.append('.');
+            }
+            ret.append(ext);
+        }
+
+        return ret.toString();
+    }
+	
+    /**
+     * Returns <code>true</code> if the <code>name</code> starts with either
+     * of the prefixes
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>},
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_PARENT <code>../</code>}
+     * and {@link SlingPostConstants#ITEM_PREFIX_ABSOLUTE <code>/</code>}.
+     */
+    protected boolean hasItemPathPrefix(String name) {
+        return name.startsWith(SlingPostConstants.ITEM_PREFIX_ABSOLUTE)
+            || name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_CURRENT)
+            || name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_PARENT);
+    }
+    
+    /**
+     * Returns true if any of the request parameters starts with
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>}.
+     * In this case only parameters starting with either of the prefixes
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>},
+     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_PARENT <code>../</code>}
+     * and {@link SlingPostConstants#ITEM_PREFIX_ABSOLUTE <code>/</code>} are
+     * considered as providing content to be stored. Otherwise all parameters
+     * not starting with the command prefix <code>:</code> are considered as
+     * parameters to be stored.
+     */
+    protected final boolean requireItemPathPrefix(
+            SlingHttpServletRequest request) {
+
+        boolean requirePrefix = false;
+
+        Enumeration<?> names = request.getParameterNames();
+        while (names.hasMoreElements() && !requirePrefix) {
+            String name = (String) names.nextElement();
+            requirePrefix = name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_CURRENT);
+        }
+
+        return requirePrefix;
+    }
+    
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractGroupPostServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractGroupPostServlet.java
new file mode 100644
index 0000000..675aeb8
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractGroupPostServlet.java
@@ -0,0 +1,95 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Base class for servlets manipulating groups
+ */
+public abstract class AbstractGroupPostServlet extends AbstractAuthorizablePostServlet {
+	private static final long serialVersionUID = 1159063041816944076L;
+
+	/**
+     * Update the group membership based on the ":member" request
+     * parameters.  If the ":member" value ends with @Delete it is removed
+     * from the group membership, otherwise it is added to the group membership.
+     * 
+     * @param request
+     * @param authorizable
+     * @throws RepositoryException
+     */
+	protected void updateGroupMembership(SlingHttpServletRequest request,
+			Authorizable authorizable, List<Modification> changes) throws RepositoryException {
+		if (authorizable.isGroup()) {
+			Group group = ((Group)authorizable);
+    		String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + group.getID(); 
+
+	    	ResourceResolver resolver = request.getResourceResolver();
+	    	Resource baseResource = request.getResource();
+	    	boolean changed = false;
+
+	    	//first remove any members posted as ":member@Delete"
+	    	String[] membersToDelete = request.getParameterValues(SlingPostConstants.RP_PREFIX + "member" + SlingPostConstants.SUFFIX_DELETE);
+	    	if (membersToDelete != null) {
+				for (String member : membersToDelete) {
+	                Resource res = resolver.getResource(baseResource, member);
+	                if (res != null) {
+	                	Authorizable memberAuthorizable = res.adaptTo(Authorizable.class);
+	                	if (memberAuthorizable != null) {
+	                		group.removeMember(memberAuthorizable);
+	                		changed = true;
+	                	}
+	                }
+					
+				}
+	    	}
+	    	
+	    	//second add any members posted as ":member"
+	    	String[] membersToAdd = request.getParameterValues(SlingPostConstants.RP_PREFIX + "member");
+	    	if (membersToAdd != null) {
+				for (String member : membersToAdd) {
+	                Resource res = resolver.getResource(baseResource, member);
+	                if (res != null) {
+	                	Authorizable memberAuthorizable = res.adaptTo(Authorizable.class);
+	                	if (memberAuthorizable != null) {
+	                		group.addMember(memberAuthorizable);
+	                		changed = true;
+	                	}
+	                }
+				}
+	    	}
+
+	    	if (changed) {
+        		//add an entry to the changes list to record the membership change
+        		changes.add(Modification.onModified(groupPath + "/members"));
+	    	}
+		}
+	}
+	
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractUserPostServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractUserPostServlet.java
new file mode 100644
index 0000000..8e32ae9
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractUserPostServlet.java
@@ -0,0 +1,81 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Dictionary;
+
+import org.apache.jackrabbit.util.Text;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Base class for servlets manipulating users
+ */
+public abstract class AbstractUserPostServlet extends AbstractAuthorizablePostServlet {
+	private static final long serialVersionUID = -8401210711297654453L;
+
+	/**
+     * To be used for the encryption. E.g. for passwords in
+     * {@link javax.jcr.SimpleCredentials#getPassword()}  SimpleCredentials} 
+     * @scr.property valueRef="DEFAULT_PASSWORD_DIGEST_ALGORITHM"
+     */
+    private static final String PROP_PASSWORD_DIGEST_ALGORITHM = "password.digest.algorithm";
+    private static final String DEFAULT_PASSWORD_DIGEST_ALGORITHM = "sha1";
+    private String passwordDigestAlgoritm = null;
+
+    // ---------- SCR Integration ----------------------------------------------
+
+    protected void activate(ComponentContext context) {
+        super.activate(context);
+        
+        Dictionary<?, ?> props = context.getProperties();
+
+        Object propValue = props.get(PROP_PASSWORD_DIGEST_ALGORITHM);
+        if (propValue instanceof String) {
+        	passwordDigestAlgoritm = (String)propValue;
+        } else {
+        	passwordDigestAlgoritm = DEFAULT_PASSWORD_DIGEST_ALGORITHM;
+        }
+    }
+
+    protected void deactivate(ComponentContext context) {
+        super.deactivate(context);
+        passwordDigestAlgoritm = null;
+    }
+    
+    /**
+     * Digest the given password using the configured digest algorithm
+     * 
+     * @param pwd the value to digest
+     * @return the digested value
+     * @throws IllegalArgumentException
+     */
+    protected String digestPassword(String pwd) throws IllegalArgumentException {
+        try {
+            StringBuffer password = new StringBuffer();
+            password.append("{").append(passwordDigestAlgoritm).append("}");
+            password.append(Text.digest(passwordDigestAlgoritm, pwd.getBytes("UTF-8")));
+            return password.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalArgumentException(e.toString());
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+    
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangeUserPasswordServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangeUserPasswordServlet.java
new file mode 100644
index 0000000..9feddec
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangeUserPasswordServlet.java
@@ -0,0 +1,107 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.servlets.post.Modification;
+
+/**
+ * Sling Post Operation implementation for updating the password of a user in the 
+ * jackrabbit UserManager.
+ * 
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" value="sling/user"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="changePassword" 
+ */
+public class ChangeUserPasswordServlet extends AbstractUserPostServlet {
+	private static final long serialVersionUID = 1923614318474654502L;
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes)
+			throws RepositoryException {
+		Authorizable authorizable = null;
+		Resource resource = request.getResource();
+		if (resource != null) {
+			authorizable = resource.adaptTo(Authorizable.class);
+		}
+		
+		//check that the user was located.
+		if (authorizable == null || authorizable.isGroup()) {
+			throw new ResourceNotFoundException("User to update could not be determined.");
+		}
+
+		if ("anonymous".equals(authorizable.getID())) {
+			throw new RepositoryException("Can not change the password of the anonymous user.");
+		}
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+
+		//check that the submitted parameter values have valid values.
+		String oldPwd = request.getParameter("oldPwd");
+		if (oldPwd == null || oldPwd.length() == 0) {
+			throw new RepositoryException("Old Password was not submitted");
+		}
+		String newPwd = request.getParameter("newPwd");
+		if (newPwd == null || newPwd.length() == 0) {
+			throw new RepositoryException("New Password was not submitted");
+		}
+		String newPwdConfirm = request.getParameter("newPwdConfirm");
+		if (!newPwd.equals(newPwdConfirm)) {
+			throw new RepositoryException("New Password does not match the confirmation password");
+		}
+		
+		try {
+			String digestedOldPwd = digestPassword(oldPwd);
+			Value[] pwdProperty = ((User)authorizable).getProperty("rep:password");
+			if (pwdProperty != null && pwdProperty.length > 0) {
+				String repPasswordValue = pwdProperty[0].getString();
+				if (!digestedOldPwd.equals(repPasswordValue)) {
+					//submitted oldPwd value is not correct.
+					throw new RepositoryException("Old Password does not match");
+				}
+			}
+				
+			((User)authorizable).changePassword(digestPassword(newPwd));
+			
+            changes.add(Modification.onModified(
+                	resource.getPath() + "/rep:password"
+                ));
+		} catch (RepositoryException re) {
+			throw new RepositoryException("Failed to change user password.", re);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupServlet.java
new file mode 100644
index 0000000..a7e162b
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupServlet.java
@@ -0,0 +1,100 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Sling Post Servlet implementation for creating a group in the jackrabbit
+ * UserManager.
+ * 
+ * @scr.component immediate="true" 
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" value="sling/groups"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="create" 
+ */
+public class CreateGroupServlet extends AbstractGroupPostServlet {
+	private static final long serialVersionUID = -1084915263933901466L;
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes) throws RepositoryException {
+		
+		//check that the submitted parameter values have valid values.
+		final String principalName = request.getParameter(SlingPostConstants.RP_NODE_NAME);
+		if (principalName == null) {
+			throw new RepositoryException("Group name was not submitted");
+		}
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+
+		try {
+			UserManager userManager = AccessControlUtil.getUserManager(session);
+			Authorizable authorizable = userManager.getAuthorizable(principalName);
+			
+			if (authorizable != null) {
+				//principal already exists!
+				throw new RepositoryException("A principal already exists with the requested name: " + principalName);
+			} else {
+				Map<String, RequestProperty> reqProperties = collectContent(request, response);
+
+				Group group = userManager.createGroup(new Principal() {
+					public String getName() {
+						return principalName;
+					}
+				});
+
+				String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + group.getID();
+				response.setPath(groupPath);
+				response.setLocation(externalizePath(request, groupPath));
+				response.setParentLocation(externalizePath(request, AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PATH));
+				changes.add(Modification.onCreated(groupPath));
+				
+		        // write content from form
+		        writeContent(session, group, reqProperties, changes);
+		        
+		        //update the group memberships
+		        updateGroupMembership(request, group, changes);
+			}
+		} catch (RepositoryException re) {
+			throw new RepositoryException("Failed to create new group.", re);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserServlet.java
new file mode 100644
index 0000000..c8259dc
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserServlet.java
@@ -0,0 +1,184 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+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.SlingHttpServletRequest;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Sling Post Servlet implementation for creating a user in the jackrabbit
+ * UserManager.
+ * 
+ * @scr.component immediate="true" label="%createUser.post.operation.name"
+ *                description="%createUser.post.operation.description"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" value="sling/users"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="create" 
+ */
+public class CreateUserServlet extends AbstractUserPostServlet {
+	private static final long serialVersionUID = 6871481922737658675L;
+
+	/**
+     * default log
+     */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    /** @scr.property label="%self.registration.enabled.name" 
+     * 					description="%self.registration.enabled.description" 
+     * 					valueRef="DEFAULT_SELF_REGISTRATION_ENABLED" 
+     */
+    private static final String PROP_SELF_REGISTRATION_ENABLED = "self.registration.enabled";
+    private static final Boolean DEFAULT_SELF_REGISTRATION_ENABLED = Boolean.TRUE;
+
+    private Boolean selfRegistrationEnabled = DEFAULT_SELF_REGISTRATION_ENABLED;
+
+    /**
+     * The JCR Repository we access to resolve resources
+     *
+     * @scr.reference
+     */
+    private SlingRepository repository;
+
+    /** Returns the JCR repository used by this service. */
+    protected SlingRepository getRepository() {
+        return repository;
+    }
+
+    /**
+     * Returns an administrative session to the default workspace.
+     */
+    private Session getSession() throws RepositoryException {
+        return getRepository().loginAdministrative(null);
+    }
+
+    /**
+     * Return the administrative session and close it.
+     */
+    private void ungetSession(final Session session) {
+        if ( session != null ) {
+            try {
+                session.logout();
+            } catch (Throwable t) {
+                log.error("Unable to log out of session: " + t.getMessage(), t);
+            }
+        }
+    }
+
+    // ---------- SCR integration ---------------------------------------------
+
+    /**
+     * Activates this component.
+     *
+     * @param componentContext The OSGi <code>ComponentContext</code> of this
+     *      component.
+     */
+    protected void activate(ComponentContext componentContext) {
+    	super.activate(componentContext);
+        Dictionary<?, ?> props = componentContext.getProperties();
+        Object propValue = props.get(PROP_SELF_REGISTRATION_ENABLED);
+        if (propValue instanceof String) {
+        	selfRegistrationEnabled = Boolean.parseBoolean((String)propValue);
+        } else {
+        	selfRegistrationEnabled = DEFAULT_SELF_REGISTRATION_ENABLED;
+        }
+    }
+
+    
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes) throws RepositoryException {
+		//make sure user self-registration is enabled
+		if (!selfRegistrationEnabled) {
+			throw new RepositoryException("Sorry, registration of new users is not currently enabled.  Please try again later.");
+		}
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+		
+		//check that the submitted parameter values have valid values.
+		String principalName = request.getParameter(SlingPostConstants.RP_NODE_NAME);
+		if (principalName == null) {
+			throw new RepositoryException("User name was not submitted");
+		}
+		String pwd = request.getParameter("pwd");
+		if (pwd == null) {
+			throw new RepositoryException("Password was not submitted");
+		}
+		String pwdConfirm = request.getParameter("pwdConfirm");
+		if (!pwd.equals(pwdConfirm)) {
+			throw new RepositoryException("Password value does not match the confirmation password");
+		}
+		
+		Session selfRegSession = null;
+		try {
+			selfRegSession = getSession();
+
+			UserManager userManager = AccessControlUtil.getUserManager(selfRegSession);
+			Authorizable authorizable = userManager.getAuthorizable(principalName);
+			
+			if (authorizable != null) {
+				//user already exists!
+				throw new RepositoryException("A principal already exists with the requested name: " + principalName);
+			} else {
+				Map<String, RequestProperty> reqProperties = collectContent(request, response);
+
+				User user = userManager.createUser(principalName, digestPassword(pwd));
+				String userPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX + user.getID();
+				
+				response.setPath(userPath);
+				response.setLocation(externalizePath(request, userPath));
+				response.setParentLocation(externalizePath(request, AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PATH));
+				changes.add(Modification.onCreated(userPath));
+				
+		        // write content from form
+		        writeContent(selfRegSession, user, reqProperties, changes);
+				
+				if (selfRegSession.hasPendingChanges()) {
+					selfRegSession.save();
+				}
+			}
+		} finally {
+			ungetSession(selfRegSession);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableServlet.java
new file mode 100644
index 0000000..39ac672
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableServlet.java
@@ -0,0 +1,159 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import javax.jcr.RepositoryException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Sling Post Operation implementation for deleting one or more users and/or groups from the 
+ * jackrabbit UserManager.
+ * 
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" values.0="sling/user" values.1="sling/group" values.2="sling/userManager"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="delete" 
+ */
+public class DeleteAuthorizableServlet extends AbstractAuthorizablePostServlet {
+	private static final long serialVersionUID = 5874621724096106496L;
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes)
+			throws RepositoryException {
+
+        Iterator<Resource> res = getApplyToResources(request);
+        if (res == null) {
+            Resource resource = request.getResource();
+            Authorizable item = resource.adaptTo(Authorizable.class);
+            if (item == null) {
+  	            String msg = "Missing source " + resource.getPath() + " for delete";
+  	            htmlResponse.setStatus(HttpServletResponse.SC_NOT_FOUND, msg);
+               	throw new ResourceNotFoundException(msg);
+            }
+
+            item.remove();
+            changes.add(Modification.onDeleted(resource.getPath()));
+        } else {
+            while (res.hasNext()) {
+                Resource resource = res.next();
+                Authorizable item = resource.adaptTo(Authorizable.class);
+                if (item != null) {
+                    item.remove();
+                    changes.add(Modification.onDeleted(resource.getPath()));
+                }
+            }
+        }
+	}
+	
+	
+    /**
+     * Returns an iterator on <code>Resource</code> instances addressed in the
+     * {@link SlingPostConstants#RP_APPLY_TO} request parameter. If the request
+     * parameter is not set, <code>null</code> is returned. If the parameter
+     * is set with valid resources an empty iterator is returned. Any resources
+     * addressed in the {@link SlingPostConstants#RP_APPLY_TO} parameter is
+     * ignored.
+     *
+     * @param request The <code>SlingHttpServletRequest</code> object used to
+     *            get the {@link SlingPostConstants#RP_APPLY_TO} parameter.
+     * @return The iterator of resources listed in the parameter or
+     *         <code>null</code> if the parameter is not set in the request.
+     */
+    protected Iterator<Resource> getApplyToResources(
+            SlingHttpServletRequest request) {
+
+        String[] applyTo = request.getParameterValues(SlingPostConstants.RP_APPLY_TO);
+        if (applyTo == null) {
+            return null;
+        }
+
+        return new ApplyToIterator(request, applyTo);
+    }
+
+    private static class ApplyToIterator implements Iterator<Resource> {
+
+        private final ResourceResolver resolver;
+        private final Resource baseResource;
+        private final String[] paths;
+
+        private int pathIndex;
+
+        private Resource nextResource;
+
+        ApplyToIterator(SlingHttpServletRequest request, String[] paths) {
+            this.resolver = request.getResourceResolver();
+            this.baseResource = request.getResource();
+            this.paths = paths;
+            this.pathIndex = 0;
+
+            nextResource = seek();
+        }
+
+        public boolean hasNext() {
+            return nextResource != null;
+        }
+
+        public Resource next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+
+            Resource result = nextResource;
+            nextResource = seek();
+
+            return result;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        private Resource seek() {
+            while (pathIndex < paths.length) {
+                String path = paths[pathIndex];
+                pathIndex++;
+
+                Resource res = resolver.getResource(baseResource, path);
+                if (res != null) {
+                    return res;
+                }
+            }
+
+            // no more elements in the array
+            return null;
+        }
+    }
+	
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateGroupServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateGroupServlet.java
new file mode 100644
index 0000000..4e433a8
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateGroupServlet.java
@@ -0,0 +1,85 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.servlets.post.Modification;
+
+/**
+ * Sling Post Operation implementation for updating a group in the 
+ * jackrabbit UserManager.
+ * 
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" values="sling/group"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="update" 
+ */
+public class UpdateGroupServlet extends AbstractGroupPostServlet {
+	private static final long serialVersionUID = -8292054361992488797L;
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes)
+			throws RepositoryException {
+		Authorizable authorizable = null;
+		Resource resource = request.getResource();
+		if (resource != null) {
+			authorizable = resource.adaptTo(Authorizable.class);
+		}
+		
+		//check that the group was located.
+		if (authorizable == null) {
+			throw new ResourceNotFoundException("Group to update could not be determined");
+		}
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+
+		Map<String, RequestProperty> reqProperties = collectContent(request, htmlResponse);
+		try {
+	        // cleanup any old content (@Delete parameters)
+	        processDeletes(authorizable, reqProperties, changes);
+				
+	        // write content from form
+	        writeContent(session, authorizable, reqProperties, changes);
+	        
+	        //update the group memberships
+			if (authorizable.isGroup()) {
+		        updateGroupMembership(request, authorizable, changes);
+			}
+		} catch (RepositoryException re) {
+			throw new RepositoryException("Failed to update group.", re);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateUserServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateUserServlet.java
new file mode 100644
index 0000000..d0245c6
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateUserServlet.java
@@ -0,0 +1,81 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.servlets.post.Modification;
+
+/**
+ * Sling Post Operation implementation for updating a user in the 
+ * jackrabbit UserManager.
+ * 
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="javax.servlet.Servlet"
+ * @scr.property name="sling.servlet.resourceTypes" value="sling/user"
+ * @scr.property name="sling.servlet.methods" value="POST" 
+ * @scr.property name="sling.servlet.selectors" value="update" 
+ */
+public class UpdateUserServlet extends AbstractUserPostServlet {
+	private static final long serialVersionUID = 5874621724096106496L;
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void handleOperation(SlingHttpServletRequest request,
+			HtmlResponse htmlResponse, List<Modification> changes)
+			throws RepositoryException {
+		Authorizable authorizable = null;
+		Resource resource = request.getResource();
+		if (resource != null) {
+			authorizable = resource.adaptTo(Authorizable.class);
+		}
+		
+		//check that the group was located.
+		if (authorizable == null) {
+			throw new ResourceNotFoundException("User to update could not be determined");
+		}
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+
+		Map<String, RequestProperty> reqProperties = collectContent(request, htmlResponse);
+		try {
+	        // cleanup any old content (@Delete parameters)
+	        processDeletes(authorizable, reqProperties, changes);
+				
+	        // write content from form
+	        writeContent(session, authorizable, reqProperties, changes);
+
+		} catch (RepositoryException re) {
+			throw new RepositoryException("Failed to update user.", re);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/DateParser.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/DateParser.java
new file mode 100644
index 0000000..227ea4c
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/DateParser.java
@@ -0,0 +1,138 @@
+/*
+ * 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.jackrabbit.usermanager.post.impl;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Takes a string representation of a time-date string and tries for parse it
+ * using different formats.
+ */
+public class DateParser {
+
+    /**
+     * default log
+     */
+    private static final Logger log = LoggerFactory.getLogger(DateParser.class);
+
+    /**
+     * lits of formats
+     */
+    private final List<DateFormat> formats = new LinkedList<DateFormat>();
+
+    /**
+     * Registers a format string to the list of internally checked ones.
+     * Uses the {@link SimpleDateFormat}.
+     * @param format format as in {@link SimpleDateFormat}
+     * @throws IllegalArgumentException if the format is not valid.
+     */
+    public void register(String format) {
+        register(new SimpleDateFormat(format, Locale.US));
+    }
+
+    /**
+     * Registers a date format to the list of internally checked ones.
+     * @param format date format
+     */
+    public void register(DateFormat format) {
+        formats.add(format);
+    }
+
+    /**
+     * Parses the given source string and returns the respective calendar
+     * instance. If no format matches returns <code>null</code>.
+     * <p/>
+     * Note: method is synchronized because SimpleDateFormat is not.
+     *
+     * @param source date time source string
+     * @return calendar representation of the source or <code>null</code>
+     */
+    public synchronized Calendar parse(String source) {
+        for (DateFormat fmt: formats) {
+            try {
+                Date d = fmt.parse(source);
+                if (log.isDebugEnabled()) {
+                    log.debug("Parsed " + source + " using " + fmt + " into " + d);
+                }
+                Calendar c = Calendar.getInstance();
+                c.setTime(d);
+                return c;
+            } catch (ParseException e) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Failed parsing " + source + " using " + fmt);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Parses the given source strings and returns the respective calendar
+     * instances. If no format matches for any of the sources
+     * returns <code>null</code>.
+     * <p/>
+     * Note: method is synchronized because SimpleDateFormat is not.
+     *
+     * @param sources date time source strings
+     * @return calendar representations of the source or <code>null</code>
+     */
+    public synchronized Calendar[] parse(String sources[]) {
+        Calendar ret[] = new Calendar[sources.length];
+        for (int i=0; i< sources.length; i++) {
+            if ((ret[i] = parse(sources[i])) == null) {
+                return null;
+            }
+        }
+        return ret;
+    }
+    
+    /**
+     * Parses the given source strings and returns the respective jcr date value
+     * instances. If no format matches for any of the sources
+     * returns <code>null</code>.
+     * <p/>
+     * Note: method is synchronized because SimpleDateFormat is not.
+     *
+     * @param sources date time source strings
+     * @param factory the value factory
+     * @return jcr date value representations of the source or <code>null</code>
+     */
+    public synchronized Value[] parse(String sources[], ValueFactory factory) {
+        Value ret[] = new Value[sources.length];
+        for (int i=0; i< sources.length; i++) {
+            Calendar c = parse(sources[i]);
+            if (c == null) {
+                return null;
+            }
+            ret[i] = factory.createValue(c);
+        }
+        return ret;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/RequestProperty.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/RequestProperty.java
new file mode 100644
index 0000000..cca1323
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/RequestProperty.java
@@ -0,0 +1,257 @@
+/*
+ * 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.jackrabbit.usermanager.post.impl;
+
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * This is a copy of the class from 'org.apache.sling.servlets.post.impl.helper' which is not exported.
+ * 
+ * Encapsulates all infos from the respective request parameters that are needed
+ * to create the repository property
+ */
+public class RequestProperty {
+
+    private static final RequestParameter[] EMPTY_PARAM_ARRAY = new RequestParameter[0];
+
+    public static final String DEFAULT_IGNORE = SlingPostConstants.RP_PREFIX
+        + "ignore";
+
+    public static final String DEFAULT_NULL = SlingPostConstants.RP_PREFIX
+        + "null";
+
+    private final String path;
+
+    private final String name;
+
+    private final String parentPath;
+
+    private RequestParameter[] values;
+
+    private String[] stringValues;
+
+    private String typeHint;
+
+    private boolean hasMultiValueTypeHint;
+
+    private RequestParameter[] defaultValues = EMPTY_PARAM_ARRAY;
+
+    private boolean isDelete;
+
+    private String repositoryResourcePath;
+
+    private boolean isRepositoryResourceMove;
+
+    public RequestProperty(String path) {
+        assert path.startsWith("/");
+        this.path = ResourceUtil.normalize(path);
+        this.parentPath = ResourceUtil.getParent(path);
+        this.name = ResourceUtil.getName(path);
+    }
+
+    public String getTypeHint() {
+        return typeHint;
+    }
+
+    public boolean hasMultiValueTypeHint() {
+        return this.hasMultiValueTypeHint;
+    }
+
+    public void setTypeHintValue(String typeHint) {
+        if ( typeHint != null && typeHint.endsWith("[]") ) {
+            this.typeHint = typeHint.substring(0, typeHint.length() - 2);
+            this.hasMultiValueTypeHint = true;
+        } else {
+            this.typeHint = typeHint;
+            this.hasMultiValueTypeHint = false;
+        }
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getParentPath() {
+        return parentPath;
+    }
+
+    public boolean hasValues() {
+        return values != null;
+    }
+
+    public RequestParameter[] getValues() {
+        return values;
+    }
+
+    public void setValues(RequestParameter[] values) {
+        this.values = values;
+    }
+
+    public RequestParameter[] getDefaultValues() {
+        return defaultValues;
+    }
+
+    public void setDefaultValues(RequestParameter[] defaultValues) {
+        if (defaultValues == null) {
+            this.defaultValues = EMPTY_PARAM_ARRAY;
+        } else {
+            this.defaultValues = defaultValues;
+        }
+    }
+
+    public boolean isFileUpload() {
+        return !values[0].isFormField();
+    }
+
+    /**
+     * Checks if this property provides any values. this is the case if one of
+     * the values is not empty or if the default handling is not 'ignore'
+     *
+     * @return <code>true</code> if this property provides values
+     */
+    public boolean providesValue() {
+        // should void double creation of string values
+        String[] sv = getStringValues();
+        if (sv == null) {
+            // is missleading return type. but means that property should not
+            // get auto-create values
+            return true;
+        }
+        for (String s : sv) {
+            if (!s.equals("")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the assembled string array out of the provided request values and
+     * default values.
+     *
+     * @return a String array or <code>null</code> if the property needs to be
+     *         removed.
+     */
+    public String[] getStringValues() {
+        if (stringValues == null) {
+            if (values.length > 1) {
+                // TODO: how the default values work for MV props is not very
+                // clear
+                stringValues = new String[values.length];
+                for (int i = 0; i < stringValues.length; i++) {
+                    stringValues[i] = values[i].getString();
+                }
+            } else {
+                String value = values[0].getString();
+                if (value.equals("")) {
+                    if (defaultValues.length == 1) {
+                        String defValue = defaultValues[0].getString();
+                        if (defValue.equals(DEFAULT_IGNORE)) {
+                            // ignore means, do not create empty values
+                            return new String[0];
+                        } else if (defValue.equals(DEFAULT_NULL)) {
+                            // null means, remove property if exist
+                            return null;
+                        }
+                        value = defValue;
+                    }
+                }
+                stringValues = new String[] { value };
+            }
+        }
+        return stringValues;
+    }
+
+    /**
+     * Specifies whether this property should be deleted before any new content
+     * is to be set according to the values stored.
+     *
+     * @param isDelete <code>true</code> if the repository item described by
+     *            this is to be deleted before any other operation.
+     */
+    public void setDelete(boolean isDelete) {
+        this.isDelete = isDelete;
+    }
+
+    /**
+     * Returns <code>true</code> if the repository item described by this is
+     * to be deleted before setting new content to it.
+     */
+    public boolean isDelete() {
+        return isDelete;
+    }
+
+    /**
+     * Sets the path of the repository item from which the content for this
+     * property is to be copied or moved. The path may be relative in which case
+     * it will be resolved relative to the absolute path of this property.
+     *
+     * @param sourcePath The path of the repository item to get the content from
+     * @param isMove <code>true</code> if the source content is to be moved,
+     *            otherwise the source content is copied from the repository
+     *            item.
+     */
+    public void setRepositorySource(String sourcePath, boolean isMove) {
+
+        // make source path absolute
+        if (!sourcePath.startsWith("/")) {
+            sourcePath = getParentPath() + "/" + sourcePath;
+            sourcePath = ResourceUtil.normalize(sourcePath);
+        }
+
+        this.repositoryResourcePath = sourcePath;
+        this.isRepositoryResourceMove = isMove;
+    }
+
+    /**
+     * Returns <code>true</code> if the content of this property is to be set
+     * by moving content from another repository item.
+     *
+     * @see #getRepositorySource()
+     */
+    public boolean hasRepositoryMoveSource() {
+        return isRepositoryResourceMove;
+    }
+
+    /**
+     * Returns <code>true</code> if the content of this property is to be set
+     * by copying content from another repository item.
+     *
+     * @see #getRepositorySource()
+     */
+    public boolean hasRepositoryCopySource() {
+        return getRepositorySource() != null && !hasRepositoryMoveSource();
+    }
+
+    /**
+     * Returns the absolute path of the repository item from which the content
+     * for this property is to be copied or moved.
+     *
+     * @see #hasRepositoryCopySource()
+     * @see #hasRepositoryMoveSource()
+     * @see #setRepositorySource(String, boolean)
+     */
+    public String getRepositorySource() {
+        return repositoryResourcePath;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResource.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResource.java
new file mode 100644
index 0000000..c158d46
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResource.java
@@ -0,0 +1,119 @@
+/*
+ * 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.jackrabbit.usermanager.resource;
+
+
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.adapter.SlingAdaptable;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+
+/**
+ * Resource implementation for Authorizable 
+ */
+public class AuthorizableResource extends SlingAdaptable implements Resource {
+	private Authorizable authorizable = null;
+	private ResourceResolver resourceResolver = null;
+    private final String path;
+    private final String resourceType;
+    private final ResourceMetadata metadata;
+	
+	public AuthorizableResource(Authorizable authorizable,
+			ResourceResolver resourceResolver, String path) {
+		super();
+
+		this.resourceResolver = resourceResolver;
+        this.authorizable = authorizable;
+        this.path = path;
+        if (authorizable.isGroup()) {
+        	this.resourceType = "sling:group";
+        } else {
+        	this.resourceType = "sling:user";
+        }
+
+        this.metadata = new ResourceMetadata();
+        metadata.setResolutionPath(path);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getPath()
+	 */
+	public String getPath() {
+		return path;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getResourceMetadata()
+	 */
+	public ResourceMetadata getResourceMetadata() {
+		return metadata;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getResourceResolver()
+	 */
+	public ResourceResolver getResourceResolver() {
+		return resourceResolver;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getResourceSuperType()
+	 */
+	public String getResourceSuperType() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getResourceType()
+	 */
+	public String getResourceType() {
+		return resourceType;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.adapter.Adaptable#adaptTo(java.lang.Class)
+	 */
+	@SuppressWarnings("unchecked")
+	public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+		if (type == Map.class || type == ValueMap.class) {
+			return (AdapterType) new AuthorizableValueMap(authorizable); // unchecked cast
+		} else if (type == Authorizable.class) {
+			return (AdapterType)authorizable;
+		}
+		
+		return super.adaptTo(type);
+	}
+
+    public String toString() {
+        String id = null;
+        if (authorizable != null) {
+            try {
+				id = authorizable.getID();
+			} catch (RepositoryException e) {
+				//ignore it.
+			}
+        }
+        return getClass().getSimpleName() + ", id=" + id
+            + ", path=" + getPath();
+    }
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResourceProvider.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResourceProvider.java
new file mode 100644
index 0000000..af864b6
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResourceProvider.java
@@ -0,0 +1,220 @@
+/*
+ * 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.jackrabbit.usermanager.resource;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+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.apache.sling.api.SlingException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.SyntheticResource;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Resource Provider implementation for jackrabbit UserManager resources.
+ * 
+ * @scr.component immediate="true" label="%authorizable.resourceprovider.name"
+ *                description="authorizable.resourceprovider.description"
+ * @scr.property name="service.description"
+ *                value="Resource provider implementation for UserManager resources"
+ * @scr.property name="service.vendor" value="The Apache Software Foundation"
+ * @scr.property name="provider.roots" value="/system/userManager/"
+ * @scr.service interface="org.apache.sling.api.resource.ResourceProvider"
+ */
+public class AuthorizableResourceProvider implements ResourceProvider {
+	
+    /**
+     * default log
+     */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+	public static final String SYSTEM_USER_MANAGER_PATH = "/system/userManager";
+
+	public static final String SYSTEM_USER_MANAGER_USER_PATH = SYSTEM_USER_MANAGER_PATH + "/user";
+	public static final String SYSTEM_USER_MANAGER_GROUP_PATH = SYSTEM_USER_MANAGER_PATH + "/group";
+
+	public static final String SYSTEM_USER_MANAGER_USER_PREFIX = SYSTEM_USER_MANAGER_USER_PATH + "/";
+	public static final String SYSTEM_USER_MANAGER_GROUP_PREFIX = SYSTEM_USER_MANAGER_GROUP_PATH + "/";
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, javax.servlet.http.HttpServletRequest, java.lang.String)
+	 */
+	public Resource getResource(ResourceResolver resourceResolver,
+			HttpServletRequest request, String path) {
+        return getResource(resourceResolver, path);
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, java.lang.String)
+	 */
+	public Resource getResource(ResourceResolver resourceResolver, String path) {
+		
+		//handle resources for the virtual container resources
+		if (path.equals(SYSTEM_USER_MANAGER_PATH)) {
+			return new SyntheticResource(resourceResolver, path, "sling:userManager");
+		} else if (path.equals(SYSTEM_USER_MANAGER_USER_PATH)) {
+			return new SyntheticResource(resourceResolver, path, "sling:users");
+		} else if (path.equals(SYSTEM_USER_MANAGER_GROUP_PATH)) {
+			return new SyntheticResource(resourceResolver, path, "sling:groups");
+		}
+		
+		// the principalId should be the first segment after the prefix
+		String pid = null;
+		if (path.startsWith(SYSTEM_USER_MANAGER_USER_PREFIX)) {
+			pid = path.substring(SYSTEM_USER_MANAGER_USER_PREFIX.length());
+		} else if (path.startsWith(SYSTEM_USER_MANAGER_GROUP_PREFIX)) {
+			pid = path.substring(SYSTEM_USER_MANAGER_GROUP_PREFIX.length());
+		}
+		
+		if (pid != null) {
+			if (pid.indexOf('/') != -1) {
+				return null; //something bogus on the end of the path so bail out now.
+			}
+			try {
+				Session session = resourceResolver.adaptTo(Session.class);
+				if (session != null) {
+					UserManager userManager = AccessControlUtil.getUserManager(session);
+					if (userManager != null) {
+						Authorizable authorizable = userManager.getAuthorizable(pid);
+						if (authorizable != null) {
+							//found the Authorizable, so return the resource that wraps it.
+							return new AuthorizableResource(authorizable, resourceResolver, path);
+						}
+					}
+				}
+			} catch (RepositoryException re) {
+				throw new SlingException("Error looking up Authorizable for principal: " + pid, re);
+			}
+		}
+        return null;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.ResourceProvider#listChildren(org.apache.sling.api.resource.Resource)
+	 */
+	public Iterator<Resource> listChildren(Resource parent) {
+		if (parent == null) {
+			throw new NullPointerException("parent is null");
+		}
+		try {
+			String path = parent.getPath();
+			ResourceResolver resourceResolver = parent.getResourceResolver();
+
+			//handle children of /system/userManager
+			if (SYSTEM_USER_MANAGER_PATH.equals(path)) {
+				List<Resource> resources = new ArrayList<Resource>();
+				if (resourceResolver != null) {
+					resources.add(getResource(resourceResolver, SYSTEM_USER_MANAGER_USER_PATH));	
+					resources.add(getResource(resourceResolver, SYSTEM_USER_MANAGER_GROUP_PATH));	
+				}
+				return resources.iterator();
+			}
+			
+			int searchType = -1;
+			if (SYSTEM_USER_MANAGER_USER_PATH.equals(path)) {
+				searchType = PrincipalManager.SEARCH_TYPE_NOT_GROUP;
+			} else if (SYSTEM_USER_MANAGER_GROUP_PATH.equals(path)) {
+				searchType = PrincipalManager.SEARCH_TYPE_GROUP;
+			}
+			if (searchType != -1) {
+				PrincipalIterator principals = null;
+
+				//TODO: this actually does not work correctly since the jackrabbit findPrincipals API 
+				// currently does an exact match of the search filter so it won't match a wildcard
+				Session session = resourceResolver.adaptTo(Session.class);
+				if (session != null) {
+					PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(session);
+					principals = principalManager.findPrincipals(".*", PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+				}
+
+				
+				if (principals != null) {
+					return new ChildrenIterator(parent, principals);
+				}
+			}
+		} catch (RepositoryException re) {
+			throw new SlingException("Error listing children of resource: " + parent.getPath(), re);
+		}
+
+		return null;
+	}
+	
+	
+
+	private final class ChildrenIterator implements Iterator<Resource> {
+		private PrincipalIterator principals;
+		private Resource parent;
+
+		public ChildrenIterator(Resource parent, PrincipalIterator principals) {
+			this.parent = parent;
+			this.principals = principals;
+		}
+
+		public boolean hasNext() {
+			return principals.hasNext();
+		}
+
+		public Resource next() {
+			Principal nextPrincipal = principals.nextPrincipal();
+			try {
+				ResourceResolver resourceResolver = parent.getResourceResolver();
+				if (resourceResolver != null) {
+					Session session = resourceResolver.adaptTo(Session.class);
+					if (session != null) {
+						UserManager userManager = AccessControlUtil.getUserManager(session);
+						if (userManager != null) {
+							Authorizable authorizable = userManager.getAuthorizable(nextPrincipal.getName());
+							if (authorizable != null) {
+								String path;
+								if (authorizable.isGroup()) {
+									path = SYSTEM_USER_MANAGER_GROUP_PREFIX + nextPrincipal.getName();
+								} else {
+									path = SYSTEM_USER_MANAGER_USER_PREFIX + nextPrincipal.getName();
+								}
+								return new AuthorizableResource(authorizable, resourceResolver, path);
+							}
+						}
+					}
+				}
+			} catch (RepositoryException re) {
+                log.error("Exception while looking up authorizable resource.", re);
+			}
+			return null;
+		}
+
+		public void remove() {
+			throw new UnsupportedOperationException();
+		}
+	}
+	
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableValueMap.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableValueMap.java
new file mode 100644
index 0000000..3dafa19
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableValueMap.java
@@ -0,0 +1,319 @@
+/*
+ * 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.jackrabbit.usermanager.resource;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.JcrResourceUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ValueMap implementation for Authorizable Resources
+ */
+public class AuthorizableValueMap implements ValueMap {
+    private Logger logger = LoggerFactory.getLogger(AuthorizableValueMap.class);
+    private Set<String> hiddenProperties = new HashSet<String>(Arrays.asList(new String[]{"rep:password", "jcr:uuid"}));
+	private boolean fullyRead;
+    private final Map<String, Object> cache;
+	private Authorizable authorizable;
+
+    public AuthorizableValueMap(Authorizable authorizable) {
+        this.authorizable = authorizable;
+        this.cache = new LinkedHashMap<String, Object>();
+        this.fullyRead = false;
+    }
+
+	@SuppressWarnings("unchecked")
+	public <T> T get(String name, Class<T> type) {
+        if (type == null) {
+            return (T) get(name);
+        }
+
+        return convertToType(name, type);
+	}
+
+	@SuppressWarnings("unchecked")
+	public <T> T get(String name, T defaultValue) {
+        if (defaultValue == null) {
+            return (T) get(name);
+        }
+
+        // special handling in case the default value implements one
+        // of the interface types supported by the convertToType method
+        Class<T> type = (Class<T>) normalizeClass(defaultValue.getClass());
+
+        T value = get(name, type);
+        if (value == null) {
+            value = defaultValue;
+        }
+
+        return value;
+	}
+
+	public boolean containsKey(Object key) {
+        return get(key) != null;
+	}
+
+	public boolean containsValue(Object value) {
+        readFully();
+        return cache.containsValue(value);
+	}
+
+	public Set<java.util.Map.Entry<String, Object>> entrySet() {
+        readFully();
+        return cache.entrySet();
+	}
+
+	public Object get(Object key) {
+        Object value = cache.get(key);
+        if (value == null) {
+            value = read((String) key);
+        }
+
+        return value;
+	}
+
+
+	public Set<String> keySet() {
+        readFully();
+        return cache.keySet();
+	}
+
+	public int size() {
+        readFully();
+        return cache.size();
+	}
+
+	public boolean isEmpty() {
+        return size() == 0;
+	}
+
+	public Collection<Object> values() {
+        readFully();
+        return cache.values();
+	}
+	
+    protected Object read(String key) {
+
+        // if the item has been completely read, we need not check
+        // again, as we certainly will not find the key
+        if (fullyRead) {
+            return null;
+        }
+
+        if (hiddenProperties.contains(key)) {
+        	return null;
+        }
+        
+        try {
+            if (authorizable.hasProperty(key)) {
+                Value[] property = authorizable.getProperty(key);
+                Object value = valuesToJavaObject(property);
+            	cache.put(key, value);
+                return value;
+            }
+        } catch (RepositoryException re) {
+            // TODO: log !!
+        }
+
+        // property not found or some error accessing it
+        return null;
+    }
+    
+    protected Object valuesToJavaObject(Value [] values) throws RepositoryException {
+        if (values == null) {
+        	return null;
+        } else if (values.length == 1) {
+        	return JcrResourceUtil.toJavaObject(values[0]);
+        } else {
+        	Object [] valuesObjs = new Object[values.length];
+        	for (int i=0; i < values.length; i++) {
+        		valuesObjs[i] = JcrResourceUtil.toJavaObject(values[i]);
+        	}
+        	return valuesObjs;
+        }
+    }
+	
+    @SuppressWarnings("unchecked")
+	protected void readFully() {
+        if (!fullyRead) {
+            try {
+                Iterator pi = authorizable.getPropertyNames();
+                while (pi.hasNext()) {
+                    String key = (String)pi.next();
+
+                    if (hiddenProperties.contains(key)) {
+                    	continue; //skip it.
+                    }
+
+                    if (!cache.containsKey(key)) {
+	                    Value[] property = authorizable.getProperty(key);
+	                    Object value = valuesToJavaObject(property);
+                    	cache.put(key, value);
+                    }
+                }
+                fullyRead = true;
+            } catch (RepositoryException re) {
+                // TODO: log !!
+            }
+        }
+    }
+	
+    // ---------- Unsupported Modification methods
+	
+	public Object remove(Object arg0) {
+        throw new UnsupportedOperationException();
+	}
+	public void clear() {
+        throw new UnsupportedOperationException();
+	}
+	public Object put(String arg0, Object arg1) {
+        throw new UnsupportedOperationException();
+	}
+
+	public void putAll(Map<? extends String, ? extends Object> arg0) {
+        throw new UnsupportedOperationException();
+	}	
+	
+	
+    // ---------- Implementation helper
+
+    @SuppressWarnings("unchecked")
+    private <T> T convertToType(String name, Class<T> type) {
+        T result = null;
+
+        try {
+            if (authorizable.hasProperty(name)) {
+                Value[] values = authorizable.getProperty(name);
+
+                if (values == null) {
+                	return null;
+                }
+                
+                boolean multiValue = values.length > 1;
+                boolean array = type.isArray();
+
+                if (multiValue) {
+                    if (array) {
+                        result = (T) convertToArray(values,
+                            type.getComponentType());
+                    } else if (values.length > 0) {
+                        result = convertToType(-1, values[0], type);
+                    }
+                } else {
+                    Value value = values[0];
+                    if (array) {
+                        result = (T) convertToArray(
+                            new Value[] { value }, type.getComponentType());
+                    } else {
+                        result = convertToType(-1, value, type);
+                    }
+                }
+            }
+
+        } catch (ValueFormatException vfe) {
+            logger.info("converToType: Cannot convert value of " + name
+                + " to " + type, vfe);
+        } catch (RepositoryException re) {
+            logger.info("converToType: Cannot get value of " + name, re);
+        }
+
+        // fall back to nothing
+        return result;
+    }
+	
+    private <T> T[] convertToArray(Value[] jcrValues, Class<T> type)
+    	throws ValueFormatException, RepositoryException {
+    	List<T> values = new ArrayList<T>();
+    	for (int i = 0; i < jcrValues.length; i++) {
+    		T value = convertToType(i, jcrValues[i], type);
+    		if (value != null) {
+    			values.add(value);
+    		}
+    	}
+
+    	@SuppressWarnings("unchecked")
+    	T[] result = (T[]) Array.newInstance(type, values.size());
+
+    	return values.toArray(result);
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <T> T convertToType(int index, Value jcrValue,
+            Class<T> type) throws ValueFormatException, RepositoryException {
+
+        if (String.class == type) {
+            return (T) jcrValue.getString();
+        } else if (Byte.class == type) {
+            return (T) new Byte((byte) jcrValue.getLong());
+        } else if (Short.class == type) {
+            return (T) new Short((short) jcrValue.getLong());
+        } else if (Integer.class == type) {
+            return (T) new Integer((int) jcrValue.getLong());
+        } else if (Long.class == type) {
+            return (T) new Long(jcrValue.getLong());
+        } else if (Float.class == type) {
+            return (T) new Float(jcrValue.getDouble());
+        } else if (Double.class == type) {
+            return (T) new Double(jcrValue.getDouble());
+        } else if (Boolean.class == type) {
+            return (T) Boolean.valueOf(jcrValue.getBoolean());
+        } else if (Date.class == type) {
+            return (T) jcrValue.getDate().getTime();
+        } else if (Calendar.class == type) {
+            return (T) jcrValue.getDate();
+        } else if (Value.class == type) {
+            return (T) jcrValue;
+        }
+
+        // fallback in case of unsupported type
+        return null;
+    }
+    
+    private Class<?> normalizeClass(Class<?> type) {
+        if (Calendar.class.isAssignableFrom(type)) {
+            type = Calendar.class;
+        } else if (Date.class.isAssignableFrom(type)) {
+            type = Date.class;
+        } else if (Value.class.isAssignableFrom(type)) {
+            type = Value.class;
+        } else if (Property.class.isAssignableFrom(type)) {
+            type = Property.class;
+        }
+        return type;
+    }
+	
+}
\ No newline at end of file
diff --git a/src/main/resources/META-INF/DISCLAIMER b/src/main/resources/META-INF/DISCLAIMER
new file mode 100644
index 0000000..90850c2
--- /dev/null
+++ b/src/main/resources/META-INF/DISCLAIMER
@@ -0,0 +1,7 @@
+Apache Sling is an effort undergoing incubation at The Apache Software Foundation (ASF),
+sponsored by the Apache Jackrabbit PMC. Incubation is required of all newly accepted
+projects until a further review indicates that the infrastructure, communications,
+and decision making process have stabilized in a manner consistent with other
+successful ASF projects. While incubation status is not necessarily a reflection of
+the completeness or stability of the code, it does indicate that the project has yet
+to be fully endorsed by the ASF.
\ No newline at end of file
diff --git a/src/main/resources/META-INF/LICENSE b/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..75b5248
--- /dev/null
+++ b/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/src/main/resources/META-INF/NOTICE b/src/main/resources/META-INF/NOTICE
new file mode 100644
index 0000000..9f4ac5f
--- /dev/null
+++ b/src/main/resources/META-INF/NOTICE
@@ -0,0 +1,5 @@
+Apache Sling Jackrabbit UserManager Support
+Copyright 2008-2009 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties
new file mode 100644
index 0000000..597ece1
--- /dev/null
+++ b/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -0,0 +1,36 @@
+#
+#  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.
+#
+
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor generated by the
+# the Sling SCR plugin
+
+authorizable.resourceprovider.name = Resolver for UserManager resources
+authorizable.resourceprovider.description = Handles resolving resources for the \
+ jackrabbit UserManager.
+
+createUser.post.operation.name = Create User Sling Post Operation
+createUser.post.operation.description = The Sling POST Operation to handle create user \
+ requests in Sling.
+ 
+self.registration.enabled.name = Self-Registration Enabled
+self.registration.enabled.description = When selected, the anonymous user is allowed to \
+ register a new user with the system.

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 05/13: Use jackrabbit api bundle instead of Sling's obsolete version.

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 72ad816a90787e1a21714b86a0c6c5a99bf5aec1
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue May 5 14:37:38 2009 +0000

    Use jackrabbit api bundle instead of Sling's obsolete version.
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@771746 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/pom.xml b/pom.xml
index 608c9c8..e1244fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -101,11 +101,11 @@
 			<artifactId>org.apache.sling.servlets.post</artifactId>
 			<version>2.0.3-incubator-SNAPSHOT</version>
 		</dependency>
-		<dependency>
-			<groupId>org.apache.sling</groupId>
-			<artifactId>org.apache.sling.jcr.jackrabbit.api</artifactId>
-			<version>2.0.2-incubator</version>
-		</dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-api</artifactId>
+            <version>1.5.0</version>
+        </dependency>
 		<dependency>
 			<groupId>org.apache.sling</groupId>
 			<artifactId>org.apache.sling.jcr.base</artifactId>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 01/13: SLING-875 add new jackrabbit-usermanager module (thanks Eric for providing)

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 8b60a665ec27a968f81036556048065dae9a63cb
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Fri Feb 27 09:19:41 2009 +0000

    SLING-875 add new jackrabbit-usermanager module (thanks Eric for providing)
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@748454 13f79535-47bb-0310-9956-ffa450edef68
---
 LICENSE                                            | 202 +++++++
 NOTICE                                             |   5 +
 README.txt                                         |  37 ++
 pom.xml                                            | 128 +++++
 .../post/AbstractAuthorizableOperation.java        | 634 +++++++++++++++++++++
 .../usermanager/post/ChangePasswordOperation.java  | 103 ++++
 .../usermanager/post/CreateGroupOperation.java     |  97 ++++
 .../usermanager/post/CreateUserOperation.java      | 174 ++++++
 .../post/DeleteAuthorizableOperation.java          |  73 +++
 .../post/UpdateAuthorizableOperation.java          |  81 +++
 .../usermanager/post/impl/DateParser.java          | 138 +++++
 .../usermanager/post/impl/RequestProperty.java     | 257 +++++++++
 .../usermanager/resource/AuthorizableResource.java | 119 ++++
 .../resource/AuthorizableResourceProvider.java     | 220 +++++++
 .../usermanager/resource/AuthorizableValueMap.java | 319 +++++++++++
 src/main/resources/META-INF/LICENSE                | 202 +++++++
 src/main/resources/META-INF/NOTICE                 |   5 +
 .../OSGI-INF/metatype/metatype.properties          |  36 ++
 18 files changed, 2830 insertions(+)

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..75b5248
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..9f4ac5f
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache Sling Jackrabbit UserManager Support
+Copyright 2008-2009 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..046bab8
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,37 @@
+Apache Sling Jackrabbit UserManager Support
+
+Provides ResourceProvider and SlingPostOperations for the Jackrabbit UserManager.
+
+Disclaimer
+==========
+Apache Sling is an effort undergoing incubation at The Apache Software Foundation (ASF),
+sponsored by the Apache Jackrabbit PMC. Incubation is required of all newly accepted
+projects until a further review indicates that the infrastructure, communications,
+and decision making process have stabilized in a manner consistent with other
+successful ASF projects. While incubation status is not necessarily a reflection of
+the completeness or stability of the code, it does indicate that the project has yet
+to be fully endorsed by the ASF.
+
+Getting Started
+===============
+
+This component uses a Maven 2 (http://maven.apache.org/) build
+environment. It requires a Java 5 JDK (or higher) and Maven (http://maven.apache.org/)
+2.0.7 or later. We recommend to use the latest Maven version.
+
+If you have Maven 2 installed, you can compile and
+package the jar using the following command:
+
+    mvn package
+
+See the Maven 2 documentation for other build features.
+
+The latest source code for this component is available in the
+Subversion (http://subversion.tigris.org/) source repository of
+the Apache Software Foundation. If you have Subversion installed,
+you can checkout the latest source using the following command:
+
+    svn checkout http://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+
+See the Subversion documentation for other source control features.
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..a39f834
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,128 @@
+<?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">
+	
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.sling</groupId>
+		<artifactId>sling</artifactId>
+		<version>5-incubator-SNAPSHOT</version>
+		<relativePath>../../../parent/pom.xml</relativePath>
+	</parent>
+
+	<artifactId>org.apache.sling.jcr.jackrabbit.usermanager</artifactId>
+	<packaging>bundle</packaging>
+	<version>2.0.0-incubator-SNAPSHOT</version>
+	<name>Apache Sling Jackrabbit UserManager Support</name>
+	<description>
+		Provides ResourceProvider and SlingPostOperations for the Jackrabbit
+		UserManager.
+	</description>
+
+	<scm>
+		<connection>
+			scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+		</connection>
+		<developerConnection>
+			scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+		</developerConnection>
+		<url>
+			http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
+		</url>
+	</scm>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-scr-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Private-Package>
+                            org.apache.sling.jackrabbit.usermanager.*
+						</Private-Package>
+						<Sling-Initial-Content></Sling-Initial-Content>
+						<Sling-Nodetypes></Sling-Nodetypes>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<reporting>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<configuration>
+					<!-- No javadocs -->
+					<excludePackageNames>
+					    org.apache.sling.jackrabbit.usermanager.post.impl
+					</excludePackageNames>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<dependencies>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.api</artifactId>
+			<version>2.0.3-incubator-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.servlets.post</artifactId>
+			<version>2.0.3-incubator-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.jcr.jackrabbit.api</artifactId>
+			<version>2.0.3-incubator-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.sling</groupId>
+			<artifactId>org.apache.sling.jcr.base</artifactId>
+			<version>2.0.3-incubator-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.jackrabbit</groupId>
+			<artifactId>jackrabbit-api</artifactId>
+			<version>1.5.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.osgi.core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.osgi.compendium</artifactId>
+		</dependency>
+	</dependencies>
+</project>
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizableOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizableOperation.java
new file mode 100644
index 0000000..06f6577
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/AbstractAuthorizableOperation.java
@@ -0,0 +1,634 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Calendar;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.servlet.ServletException;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.util.Text;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.commons.osgi.OsgiUtil;
+import org.apache.sling.jackrabbit.usermanager.post.impl.DateParser;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
+import org.apache.sling.servlets.post.AbstractSlingPostOperation;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+import org.osgi.service.component.ComponentContext;
+
+
+/**
+ * Base class for operations that do work on authorizable resources
+ */
+public abstract class AbstractAuthorizableOperation extends AbstractSlingPostOperation {
+	
+    /**
+     * @scr.property values.0="EEE MMM dd yyyy HH:mm:ss 'GMT'Z"
+     *               values.1="yyyy-MM-dd'T'HH:mm:ss.SSSZ"
+     *               values.2="yyyy-MM-dd'T'HH:mm:ss" values.3="yyyy-MM-dd"
+     *               values.4="dd.MM.yyyy HH:mm:ss" values.5="dd.MM.yyyy"
+     */
+    private static final String PROP_DATE_FORMAT = "servlet.post.dateFormats";
+	
+	private DateParser dateParser;
+
+
+	/**
+     * To be used for the encryption. E.g. for passwords in
+     * {@link javax.jcr.SimpleCredentials#getPassword()}  SimpleCredentials} 
+     * @scr.property valueRef="DEFAULT_PASSWORD_DIGEST_ALGORITHM"
+     */
+    private static final String PROP_PASSWORD_DIGEST_ALGORITHM = "password.digest.algorithm";
+    private static final String DEFAULT_PASSWORD_DIGEST_ALGORITHM = "sha1";
+    private String passwordDigestAlgoritm = null;
+
+    // ---------- SCR Integration ----------------------------------------------
+
+    protected void activate(ComponentContext context) {
+        Dictionary<?, ?> props = context.getProperties();
+
+        dateParser = new DateParser();
+        String[] dateFormats = OsgiUtil.toStringArray(props.get(PROP_DATE_FORMAT));
+        for (String dateFormat : dateFormats) {
+            dateParser.register(dateFormat);
+        }
+        Object propValue = props.get(PROP_PASSWORD_DIGEST_ALGORITHM);
+        if (propValue instanceof String) {
+        	passwordDigestAlgoritm = (String)propValue;
+        } else {
+        	passwordDigestAlgoritm = DEFAULT_PASSWORD_DIGEST_ALGORITHM;
+        }
+    }
+
+    protected void deactivate(ComponentContext context) {
+        dateParser = null;
+        passwordDigestAlgoritm = null;
+    }
+	
+    protected String digestPassword(String pwd) throws IllegalArgumentException {
+        try {
+            StringBuffer password = new StringBuffer();
+            password.append("{").append(passwordDigestAlgoritm).append("}");
+            password.append(Text.digest(passwordDigestAlgoritm, pwd.getBytes("UTF-8")));
+            return password.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalArgumentException(e.toString());
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+	
+
+    /**
+     * Update the group membership based on the ":member" request
+     * parameters.  If the ":member" value ends with @Delete it is removed
+     * from the group membership, otherwise it is added to the group membership.
+     * 
+     * @param request
+     * @param authorizable
+     * @throws RepositoryException
+     */
+	protected void updateGroupMembership(SlingHttpServletRequest request,
+			Authorizable authorizable, List<Modification> changes) throws RepositoryException {
+		if (authorizable.isGroup()) {
+			Group group = ((Group)authorizable);
+    		String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + group.getID(); 
+
+	    	ResourceResolver resolver = request.getResourceResolver();
+	    	Resource baseResource = request.getResource();
+	    	boolean changed = false;
+
+	    	//first remove any members posted as ":member@Delete"
+	    	String[] membersToDelete = request.getParameterValues(SlingPostConstants.RP_PREFIX + "member" + SlingPostConstants.SUFFIX_DELETE);
+	    	if (membersToDelete != null) {
+				for (String member : membersToDelete) {
+	                Resource res = resolver.getResource(baseResource, member);
+	                if (res != null) {
+	                	Authorizable memberAuthorizable = res.adaptTo(Authorizable.class);
+	                	if (memberAuthorizable != null) {
+	                		group.removeMember(memberAuthorizable);
+	                		changed = true;
+	                	}
+	                }
+					
+				}
+	    	}
+	    	
+	    	//second add any members posted as ":member"
+	    	String[] membersToAdd = request.getParameterValues(SlingPostConstants.RP_PREFIX + "member");
+	    	if (membersToAdd != null) {
+				for (String member : membersToAdd) {
+	                Resource res = resolver.getResource(baseResource, member);
+	                if (res != null) {
+	                	Authorizable memberAuthorizable = res.adaptTo(Authorizable.class);
+	                	if (memberAuthorizable != null) {
+	                		group.addMember(memberAuthorizable);
+	                		changed = true;
+	                	}
+	                }
+				}
+	    	}
+
+	    	if (changed) {
+        		//add an entry to the changes list to record the membership change
+        		changes.add(Modification.onModified(groupPath + "/members"));
+	    	}
+		}
+	}
+    
+    
+    
+    // ------ The methods below are based on the private methods from the ModifyOperation class -----
+    
+    /**
+     * Collects the properties that form the content to be written back to the
+     * repository. 
+     * 
+     * NOTE: In the returned map, the key is the property name not a path.
+     *
+     * @throws RepositoryException if a repository error occurs
+     * @throws ServletException if an internal error occurs
+     */
+    protected Map<String, RequestProperty> collectContent(
+            SlingHttpServletRequest request, HtmlResponse response) {
+
+        boolean requireItemPrefix = requireItemPathPrefix(request);
+
+        // walk the request parameters and collect the properties
+        Map<String, RequestProperty> reqProperties = new HashMap<String, RequestProperty>();
+        for (Map.Entry<String, RequestParameter[]> e : request.getRequestParameterMap().entrySet()) {
+            final String paramName = e.getKey();
+
+            // do not store parameters with names starting with sling:post
+            if (paramName.startsWith(SlingPostConstants.RP_PREFIX)) {
+                continue;
+            }
+            // SLING-298: skip form encoding parameter
+            if (paramName.equals("_charset_")) {
+                continue;
+            }
+            // skip parameters that do not start with the save prefix
+            if (requireItemPrefix && !hasItemPathPrefix(paramName)) {
+                continue;
+            }
+
+            // ensure the paramName is an absolute property name
+            String propPath;
+            if (paramName.startsWith("./")) {
+            	propPath = paramName.substring(2);
+            } else {
+            	propPath = paramName;
+            }
+            if (propPath.indexOf('/') != -1) {
+            	//only one path segment is valid here, so this paramter can't be used.
+            	continue; //skip it.
+            }
+
+            // @TypeHint example
+            // <input type="text" name="./age" />
+            // <input type="hidden" name="./age@TypeHint" value="long" />
+            // causes the setProperty using the 'long' property type
+            if (propPath.endsWith(SlingPostConstants.TYPE_HINT_SUFFIX)) {
+                RequestProperty prop = getOrCreateRequestProperty(
+                    reqProperties, propPath,
+                    SlingPostConstants.TYPE_HINT_SUFFIX);
+
+                final RequestParameter[] rp = e.getValue();
+                if (rp.length > 0) {
+                    prop.setTypeHintValue(rp[0].getString());
+                }
+
+                continue;
+            }
+
+            // @DefaultValue
+            if (propPath.endsWith(SlingPostConstants.DEFAULT_VALUE_SUFFIX)) {
+                RequestProperty prop = getOrCreateRequestProperty(
+                    reqProperties, propPath,
+                    SlingPostConstants.DEFAULT_VALUE_SUFFIX);
+
+                prop.setDefaultValues(e.getValue());
+
+                continue;
+            }
+
+            // SLING-130: VALUE_FROM_SUFFIX means take the value of this
+            // property from a different field
+            // @ValueFrom example:
+            // <input name="./Text@ValueFrom" type="hidden" value="fulltext" />
+            // causes the JCR Text property to be set to the value of the
+            // fulltext form field.
+            if (propPath.endsWith(SlingPostConstants.VALUE_FROM_SUFFIX)) {
+                RequestProperty prop = getOrCreateRequestProperty(
+                    reqProperties, propPath,
+                    SlingPostConstants.VALUE_FROM_SUFFIX);
+
+                // @ValueFrom params must have exactly one value, else ignored
+                if (e.getValue().length == 1) {
+                    String refName = e.getValue()[0].getString();
+                    RequestParameter[] refValues = request.getRequestParameters(refName);
+                    if (refValues != null) {
+                        prop.setValues(refValues);
+                    }
+                }
+
+                continue;
+            }
+
+            // SLING-458: Allow Removal of properties prior to update
+            // @Delete example:
+            // <input name="./Text@Delete" type="hidden" />
+            // causes the JCR Text property to be deleted before update
+            if (propPath.endsWith(SlingPostConstants.SUFFIX_DELETE)) {
+                RequestProperty prop = getOrCreateRequestProperty(
+                    reqProperties, propPath, SlingPostConstants.SUFFIX_DELETE);
+
+                prop.setDelete(true);
+
+                continue;
+            }
+
+            // SLING-455: @MoveFrom means moving content to another location
+            // @MoveFrom example:
+            // <input name="./Text@MoveFrom" type="hidden" value="/tmp/path" />
+            // causes the JCR Text property to be set by moving the /tmp/path
+            // property to Text.
+            if (propPath.endsWith(SlingPostConstants.SUFFIX_MOVE_FROM)) {
+            	//don't support @MoveFrom here
+                continue;
+            }
+
+            // SLING-455: @CopyFrom means moving content to another location
+            // @CopyFrom example:
+            // <input name="./Text@CopyFrom" type="hidden" value="/tmp/path" />
+            // causes the JCR Text property to be set by copying the /tmp/path
+            // property to Text.
+            if (propPath.endsWith(SlingPostConstants.SUFFIX_COPY_FROM)) {
+            	//don't support @CopyFrom here
+                continue;
+            }
+
+            // plain property, create from values
+            RequestProperty prop = getOrCreateRequestProperty(reqProperties,
+                propPath, null);
+            prop.setValues(e.getValue());
+        }
+
+        return reqProperties;
+    }
+	
+	
+    /**
+     * Returns the request property for the given property path. If such a
+     * request property does not exist yet it is created and stored in the
+     * <code>props</code>.
+     *
+     * @param props The map of already seen request properties.
+     * @param paramName The absolute path of the property including the
+     *            <code>suffix</code> to be looked up.
+     * @param suffix The (optional) suffix to remove from the
+     *            <code>paramName</code> before looking it up.
+     * @return The {@link RequestProperty} for the <code>paramName</code>.
+     */
+    private RequestProperty getOrCreateRequestProperty(
+            Map<String, RequestProperty> props, String paramName, String suffix) {
+        if (suffix != null && paramName.endsWith(suffix)) {
+            paramName = paramName.substring(0, paramName.length()
+                - suffix.length());
+        }
+
+        RequestProperty prop = props.get(paramName);
+        if (prop == null) {
+            prop = new RequestProperty(paramName);
+            props.put(paramName, prop);
+        }
+
+        return prop;
+    }
+    
+    
+    /**
+     * Removes all properties listed as {@link RequestProperty#isDelete()} from
+     * the authorizable.
+     *
+     * @param authorizable The <code>org.apache.jackrabbit.api.security.user.Authorizable</code> 
+     * 				that should have properties deleted.
+     * @param reqProperties The map of request properties to check for
+     *            properties to be removed.
+     * @param response The <code>HtmlResponse</code> to be updated with
+     *            information on deleted properties.
+     * @throws RepositoryException Is thrown if an error occurrs checking or
+     *             removing properties.
+     */
+    protected void processDeletes(Authorizable resource, 
+            Map<String, RequestProperty> reqProperties,
+            List<Modification> changes) throws RepositoryException {
+
+        for (RequestProperty property : reqProperties.values()) {
+            if (property.isDelete()) {
+            	if (resource.hasProperty(property.getName())) {
+            		resource.removeProperty(property.getName());
+                    changes.add(Modification.onDeleted(property.getPath()));
+            	}
+            }
+        }
+    }
+
+    
+    /**
+     * Writes back the content
+     *
+     * @throws RepositoryException if a repository error occurs
+     * @throws ServletException if an internal error occurs
+     */
+    protected void writeContent(Session session, Authorizable authorizable,
+            Map<String, RequestProperty> reqProperties, List<Modification> changes)
+            throws RepositoryException {
+
+        for (RequestProperty prop : reqProperties.values()) {
+            if (prop.hasValues()) {
+                // skip jcr special properties
+                if (prop.getName().equals("jcr:primaryType")
+                    || prop.getName().equals("jcr:mixinTypes")) {
+                    continue;
+                }
+                if (authorizable.isGroup()) {
+                    if (prop.getName().equals("groupId")) {
+                    	//skip these
+                    	continue;
+                	}                	
+                } else {
+                    if (prop.getName().equals("userId") ||
+                    		prop.getName().equals("pwd") ||
+                    		prop.getName().equals("pwdConfirm")) {
+                    	//skip these
+                    	continue;
+                    }
+                }
+                if (prop.isFileUpload()) {
+                	//don't handle files for user properties for now.
+                	continue;
+                    //uploadHandler.setFile(parent, prop, changes);
+                } else {
+                	setPropertyAsIs(session, authorizable, prop, changes);
+                }
+            }
+        }
+    }
+    
+    /**
+     * set property without processing, except for type hints
+     *
+     * @param parent the parent node
+     * @param prop the request property
+     * @throws RepositoryException if a repository error occurs.
+     */
+    private void setPropertyAsIs(Session session, Authorizable parent, RequestProperty prop, List<Modification> changes)
+            throws RepositoryException {
+
+    	String parentPath;
+    	if (parent.isGroup()) {
+    		parentPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + parent.getID();
+    	} else {
+    		parentPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX + parent.getID();
+    	}
+
+
+        // no explicit typehint
+        int type = PropertyType.UNDEFINED;
+        if (prop.getTypeHint() != null) {
+            try {
+                type = PropertyType.valueFromName(prop.getTypeHint());
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+
+        String[] values = prop.getStringValues();
+		if (values == null) {
+            // remove property
+	        boolean removedProp = removePropertyIfExists(parent, prop.getName());
+	        if (removedProp) {
+	            changes.add(Modification.onDeleted(
+	            		parentPath + "/" + prop.getName()
+	            ));
+	        }
+        } else if (values.length == 0) {
+            // do not create new prop here, but clear existing
+            if (parent.hasProperty(prop.getName())) {
+            	Value val = session.getValueFactory().createValue("");
+            	parent.setProperty(prop.getName(), val);
+                changes.add(Modification.onModified(
+                	parentPath + "/" + prop.getName()
+                ));
+            }
+        } else if (values.length == 1) {
+            boolean removedProp = removePropertyIfExists(parent, prop.getName());
+            // if the provided value is the empty string, we don't have to do anything.
+            if ( values[0].length() == 0 ) {
+                if ( removedProp ) {
+                    changes.add(Modification.onDeleted(parentPath + "/" + prop.getName()));
+                }
+            } else {
+                // modify property
+                if (type == PropertyType.DATE) {
+                    // try conversion
+                    Calendar c = dateParser.parse(values[0]);
+                    if (c != null) {
+                        if ( prop.hasMultiValueTypeHint() ) {
+                            final Value[] array = new Value[1];
+                            array[0] = session.getValueFactory().createValue(c);
+                            parent.setProperty(prop.getName(), array);
+                            changes.add(Modification.onModified(
+                                parentPath + "/" + prop.getName()
+                            ));
+                        } else {
+                        	Value cVal = session.getValueFactory().createValue(c);
+                        	parent.setProperty(prop.getName(), cVal);
+                            changes.add(Modification.onModified(
+                                    parentPath + "/" + prop.getName()
+                                ));
+                        }
+                        return;
+                    }
+                    // fall back to default behaviour
+                }
+                if ( type == PropertyType.UNDEFINED ) {
+                	Value val = session.getValueFactory().createValue(values[0], PropertyType.STRING);
+                	parent.setProperty(prop.getName(), val);
+                } else {
+                    if ( prop.hasMultiValueTypeHint() ) {
+                        final Value[] array = new Value[1];
+                        array[0] = session.getValueFactory().createValue(values[0], type);
+                        parent.setProperty(prop.getName(), array);
+                    } else {
+                    	Value val = session.getValueFactory().createValue(values[0], type);
+                        parent.setProperty(prop.getName(), val);
+                    }
+                }
+                changes.add(Modification.onModified(parentPath + "/" + prop.getName()));
+            }
+        } else {
+            removePropertyIfExists(parent, prop.getName());
+            if (type == PropertyType.DATE) {
+                // try conversion
+                ValueFactory valFac = session.getValueFactory();
+                Value[] c = dateParser.parse(values, valFac);
+                if (c != null) {
+                	parent.setProperty(prop.getName(), c);
+                    changes.add(Modification.onModified(
+                    		parentPath + "/" + prop.getName()
+                    ));
+                    return;
+                }
+                // fall back to default behaviour
+            }
+
+            Value [] vals = new Value[values.length];
+            if ( type == PropertyType.UNDEFINED ) {
+            	for(int i=0; i < values.length; i++) {
+            		vals[i] = session.getValueFactory().createValue(values[i]);
+            	}
+            } else {
+            	for(int i=0; i < values.length; i++) {
+            		vals[i] = session.getValueFactory().createValue(values[i], type);
+            	}
+            }
+        	parent.setProperty(prop.getName(), vals);
+            changes.add(Modification.onModified(parentPath + "/" + prop.getName()));
+        }
+    
+    }
+
+    /**
+     * Removes the property with the given name from the parent resource if it
+     * exists.
+     *
+     * @param parent the parent resource
+     * @param name the name of the property to remove
+     * @return path of the property that was removed or <code>null</code> if
+     *         it was not removed
+     * @throws RepositoryException if a repository error occurs.
+     */
+	private boolean removePropertyIfExists(Authorizable resource, String name) throws RepositoryException {
+    	if (resource.getProperty(name) != null) {
+    		resource.removeProperty(name);
+    		return true;
+    	}
+    	return false;
+	}
+
+	
+    /**
+     * Returns an iterator on <code>Resource</code> instances addressed in the
+     * {@link SlingPostConstants#RP_APPLY_TO} request parameter. If the request
+     * parameter is not set, <code>null</code> is returned. If the parameter
+     * is set with valid resources an empty iterator is returned. Any resources
+     * addressed in the {@link SlingPostConstants#RP_APPLY_TO} parameter is
+     * ignored.
+     *
+     * @param request The <code>SlingHttpServletRequest</code> object used to
+     *            get the {@link SlingPostConstants#RP_APPLY_TO} parameter.
+     * @return The iterator of resources listed in the parameter or
+     *         <code>null</code> if the parameter is not set in the request.
+     */
+    protected Iterator<Resource> getApplyToResources(
+            SlingHttpServletRequest request) {
+
+        String[] applyTo = request.getParameterValues(SlingPostConstants.RP_APPLY_TO);
+        if (applyTo == null) {
+            return null;
+        }
+
+        return new ApplyToIterator(request, applyTo);
+    }
+
+    private static class ApplyToIterator implements Iterator<Resource> {
+
+        private final ResourceResolver resolver;
+        private final Resource baseResource;
+        private final String[] paths;
+
+        private int pathIndex;
+
+        private Resource nextResource;
+
+        ApplyToIterator(SlingHttpServletRequest request, String[] paths) {
+            this.resolver = request.getResourceResolver();
+            this.baseResource = request.getResource();
+            this.paths = paths;
+            this.pathIndex = 0;
+
+            nextResource = seek();
+        }
+
+        public boolean hasNext() {
+            return nextResource != null;
+        }
+
+        public Resource next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+
+            Resource result = nextResource;
+            nextResource = seek();
+
+            return result;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        private Resource seek() {
+            while (pathIndex < paths.length) {
+                String path = paths[pathIndex];
+                pathIndex++;
+
+                Resource res = resolver.getResource(baseResource, path);
+                if (res != null) {
+                    return res;
+                }
+            }
+
+            // no more elements in the array
+            return null;
+        }
+    }
+	
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangePasswordOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangePasswordOperation.java
new file mode 100644
index 0000000..9972ede
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/ChangePasswordOperation.java
@@ -0,0 +1,103 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.servlets.post.Modification;
+
+/**
+ * Sling Post Operation implementation for updating the password of
+ * a user in the jackrabbit UserManager.
+ * 
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
+ * @scr.property name="sling.post.operation" value="changePassword"
+ */
+public class ChangePasswordOperation extends AbstractAuthorizableOperation {
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void doRun(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes)
+			throws RepositoryException {
+		Authorizable authorizable = null;
+		Resource resource = request.getResource();
+		if (resource != null) {
+			authorizable = resource.adaptTo(Authorizable.class);
+		}
+		
+		//check that the user was located.
+		if (authorizable == null || authorizable.isGroup()) {
+			throw new RepositoryException("User to update could not be determined.");
+		}
+
+		if ("anonymous".equals(authorizable.getID())) {
+			throw new RepositoryException("Can not change the password of the anonymous user.");
+		}
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+
+		//check that the submitted parameter values have valid values.
+		String oldPwd = request.getParameter("oldPwd");
+		if (oldPwd == null || oldPwd.length() == 0) {
+			throw new RepositoryException("Old Password was not submitted");
+		}
+		String newPwd = request.getParameter("newPwd");
+		if (newPwd == null || newPwd.length() == 0) {
+			throw new RepositoryException("New Password was not submitted");
+		}
+		String newPwdConfirm = request.getParameter("newPwdConfirm");
+		if (!newPwd.equals(newPwdConfirm)) {
+			throw new RepositoryException("New Password does not match the confirmation password");
+		}
+		
+		try {
+			String digestedOldPwd = digestPassword(oldPwd);
+			Value[] pwdProperty = ((User)authorizable).getProperty("rep:password");
+			if (pwdProperty != null && pwdProperty.length > 0) {
+				String repPasswordValue = pwdProperty[0].getString();
+				if (!digestedOldPwd.equals(repPasswordValue)) {
+					//submitted oldPwd value is not correct.
+					throw new RepositoryException("Old Password does not match");
+				}
+			}
+				
+			((User)authorizable).changePassword(digestPassword(newPwd));
+			
+            changes.add(Modification.onModified(
+                	resource.getPath() + "/rep:password"
+                ));
+		} catch (RepositoryException re) {
+			throw new RepositoryException("Failed to change user password.", re);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupOperation.java
new file mode 100644
index 0000000..08e2456
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateGroupOperation.java
@@ -0,0 +1,97 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Sling Post Operation implementation for creating a group in the jackrabbit
+ * UserManager.
+ *
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
+ * @scr.property name="sling.post.operation" value="createGroup"
+ */
+public class CreateGroupOperation extends AbstractAuthorizableOperation {
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void doRun(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes)
+			throws RepositoryException {
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+		
+		//check that the submitted parameter values have valid values.
+		final String principalName = request.getParameter(SlingPostConstants.RP_NODE_NAME);
+		if (principalName == null) {
+			throw new RepositoryException("Group name was not submitted");
+		}
+		
+		try {
+			UserManager userManager = AccessControlUtil.getUserManager(session);
+			Authorizable authorizable = userManager.getAuthorizable(principalName);
+			
+			if (authorizable != null) {
+				//principal already exists!
+				throw new RepositoryException("A principal already exists with the requested name: " + principalName);
+			} else {
+				Map<String, RequestProperty> reqProperties = collectContent(request, response);
+
+				Group group = userManager.createGroup(new Principal() {
+					public String getName() {
+						return principalName;
+					}
+				});
+
+				String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + group.getID();
+				response.setPath(groupPath);
+				response.setLocation(externalizePath(request, groupPath));
+				response.setParentLocation(externalizePath(request, AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PATH));
+				changes.add(Modification.onCreated(groupPath));
+				
+		        // write content from form
+		        writeContent(session, group, reqProperties, changes);
+		        
+		        //update the group memberships
+		        updateGroupMembership(request, group, changes);
+			}
+		} catch (RepositoryException re) {
+			throw new RepositoryException("Failed to create new group.", re);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserOperation.java
new file mode 100644
index 0000000..c0e385f
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/CreateUserOperation.java
@@ -0,0 +1,174 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+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.SlingHttpServletRequest;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.jackrabbit.usermanager.resource.AuthorizableResourceProvider;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.SlingPostConstants;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Sling Post Operation implementation for creating a user in the jackrabbit
+ * UserManager.
+ * 
+ * @scr.component immediate="true" label="%createUser.post.operation.name"
+ *                description="%createUser.post.operation.description"
+ * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
+ * @scr.property name="sling.post.operation" value="createUser"
+ */
+public class CreateUserOperation extends AbstractAuthorizableOperation {
+
+    /** @scr.property label="%self.registration.enabled.name" 
+     * 					description="%self.registration.enabled.description" 
+     * 					valueRef="DEFAULT_SELF_REGISTRATION_ENABLED" 
+     */
+    private static final String PROP_SELF_REGISTRATION_ENABLED = "self.registration.enabled";
+    private static final Boolean DEFAULT_SELF_REGISTRATION_ENABLED = Boolean.TRUE;
+
+    private Boolean selfRegistrationEnabled = DEFAULT_SELF_REGISTRATION_ENABLED;
+
+    /**
+     * The JCR Repository we access to resolve resources
+     *
+     * @scr.reference
+     */
+    private SlingRepository repository;
+
+    /** Returns the JCR repository used by this service. */
+    protected SlingRepository getRepository() {
+        return repository;
+    }
+
+    /**
+     * Returns an administrative session to the default workspace.
+     */
+    private Session getSession() throws RepositoryException {
+        return getRepository().loginAdministrative(null);
+    }
+
+    /**
+     * Return the administrative session and close it.
+     */
+    private void ungetSession(final Session session) {
+        if ( session != null ) {
+            try {
+                session.logout();
+            } catch (Throwable t) {
+                log.error("Unable to log out of session: " + t.getMessage(), t);
+            }
+        }
+    }
+    
+
+    // ---------- SCR integration ---------------------------------------------
+
+    /**
+     * Activates this component.
+     *
+     * @param componentContext The OSGi <code>ComponentContext</code> of this
+     *      component.
+     */
+    protected void activate(ComponentContext componentContext) {
+    	super.activate(componentContext);
+        Dictionary<?, ?> props = componentContext.getProperties();
+        Object propValue = props.get(PROP_SELF_REGISTRATION_ENABLED);
+        if (propValue instanceof String) {
+        	selfRegistrationEnabled = Boolean.parseBoolean((String)propValue);
+        } else {
+        	selfRegistrationEnabled = DEFAULT_SELF_REGISTRATION_ENABLED;
+        }
+    }
+    
+	/* (non-Javadoc)
+	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void doRun(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes)
+			throws RepositoryException {
+
+		//make sure user self-registration is enabled
+		if (!selfRegistrationEnabled) {
+			throw new RepositoryException("Sorry, registration of new users is not currently enabled.  Please try again later.");
+		}
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+		
+		//check that the submitted parameter values have valid values.
+		String principalName = request.getParameter(SlingPostConstants.RP_NODE_NAME);
+		if (principalName == null) {
+			throw new RepositoryException("User name was not submitted");
+		}
+		String pwd = request.getParameter("pwd");
+		if (pwd == null) {
+			throw new RepositoryException("Password was not submitted");
+		}
+		String pwdConfirm = request.getParameter("pwdConfirm");
+		if (!pwd.equals(pwdConfirm)) {
+			throw new RepositoryException("Password value does not match the confirmation password");
+		}
+		
+		Session selfRegSession = null;
+		try {
+			selfRegSession = getSession();
+
+			UserManager userManager = AccessControlUtil.getUserManager(selfRegSession);
+			Authorizable authorizable = userManager.getAuthorizable(principalName);
+			
+			if (authorizable != null) {
+				//user already exists!
+				throw new RepositoryException("A principal already exists with the requested name: " + principalName);
+			} else {
+				Map<String, RequestProperty> reqProperties = collectContent(request, response);
+
+				User user = userManager.createUser(principalName, digestPassword(pwd));
+				String userPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PREFIX + user.getID();
+				response.setPath(userPath);
+				response.setLocation(externalizePath(request, userPath));
+				response.setParentLocation(externalizePath(request, AuthorizableResourceProvider.SYSTEM_USER_MANAGER_USER_PATH));
+				changes.add(Modification.onCreated(userPath));
+				
+		        // write content from form
+		        writeContent(selfRegSession, user, reqProperties, changes);
+				
+				if (selfRegSession.hasPendingChanges()) {
+					selfRegSession.save();
+				}
+			}
+		} finally {
+			ungetSession(selfRegSession);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableOperation.java
new file mode 100644
index 0000000..991cee0
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/DeleteAuthorizableOperation.java
@@ -0,0 +1,73 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.servlets.post.Modification;
+
+/**
+ * Sling Post Operation implementation for deleting users and/or groups from the 
+ * jackrabbit UserManager.
+ * 
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
+ * @scr.property name="sling.post.operation" value="deleteAuthorizable"
+ */
+public class DeleteAuthorizableOperation extends AbstractAuthorizableOperation {
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void doRun(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes)
+			throws RepositoryException {
+
+        Iterator<Resource> res = getApplyToResources(request);
+        if (res == null) {
+            Resource resource = request.getResource();
+            Authorizable item = resource.adaptTo(Authorizable.class);
+            if (item == null) {
+  	            String msg = "Missing source " + resource.getPath() + " for delete";
+                response.setStatus(HttpServletResponse.SC_NOT_FOUND, msg);
+               	throw new ResourceNotFoundException(msg);
+            }
+
+            item.remove();
+            changes.add(Modification.onDeleted(resource.getPath()));
+        } else {
+            while (res.hasNext()) {
+                Resource resource = res.next();
+                Authorizable item = resource.adaptTo(Authorizable.class);
+                if (item != null) {
+                    item.remove();
+                    changes.add(Modification.onDeleted(resource.getPath()));
+                }
+            }
+        }
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java
new file mode 100644
index 0000000..c88be1c
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/UpdateAuthorizableOperation.java
@@ -0,0 +1,81 @@
+/*
+ * 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.jackrabbit.usermanager.post;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jackrabbit.usermanager.post.impl.RequestProperty;
+import org.apache.sling.servlets.post.Modification;
+
+/**
+ * Sling Post Operation implementation for updating a user or group in the 
+ * jackrabbit UserManager.
+ * 
+ * @scr.component metatype="no" immediate="true"
+ * @scr.service interface="org.apache.sling.servlets.post.SlingPostOperation"
+ * @scr.property name="sling.post.operation" value="updateAuthorizable"
+ */
+public class UpdateAuthorizableOperation extends AbstractAuthorizableOperation {
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.servlets.post.AbstractSlingPostOperation#doRun(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
+	 */
+	@Override
+	protected void doRun(SlingHttpServletRequest request,
+			HtmlResponse response, List<Modification> changes)
+			throws RepositoryException {
+		Authorizable authorizable = null;
+		Resource resource = request.getResource();
+		if (resource != null) {
+			authorizable = resource.adaptTo(Authorizable.class);
+		}
+		
+		//check that the group was located.
+		if (authorizable == null) {
+			throw new RepositoryException("Authorizable to update could not be determined");
+		}
+
+		Session session = request.getResourceResolver().adaptTo(Session.class);
+		if (session == null) {
+			throw new RepositoryException("JCR Session not found");
+		}
+
+		Map<String, RequestProperty> reqProperties = collectContent(request, response);
+		try {
+	        // cleanup any old content (@Delete parameters)
+	        processDeletes(authorizable, reqProperties, changes);
+				
+	        // write content from form
+	        writeContent(session, authorizable, reqProperties, changes);
+	        
+	        //update the group memberships
+			if (authorizable.isGroup()) {
+		        updateGroupMembership(request, authorizable, changes);
+			}
+		} catch (RepositoryException re) {
+			throw new RepositoryException("Failed to update authorizable.", re);
+		}
+	}
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/DateParser.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/DateParser.java
new file mode 100644
index 0000000..227ea4c
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/DateParser.java
@@ -0,0 +1,138 @@
+/*
+ * 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.jackrabbit.usermanager.post.impl;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Takes a string representation of a time-date string and tries for parse it
+ * using different formats.
+ */
+public class DateParser {
+
+    /**
+     * default log
+     */
+    private static final Logger log = LoggerFactory.getLogger(DateParser.class);
+
+    /**
+     * lits of formats
+     */
+    private final List<DateFormat> formats = new LinkedList<DateFormat>();
+
+    /**
+     * Registers a format string to the list of internally checked ones.
+     * Uses the {@link SimpleDateFormat}.
+     * @param format format as in {@link SimpleDateFormat}
+     * @throws IllegalArgumentException if the format is not valid.
+     */
+    public void register(String format) {
+        register(new SimpleDateFormat(format, Locale.US));
+    }
+
+    /**
+     * Registers a date format to the list of internally checked ones.
+     * @param format date format
+     */
+    public void register(DateFormat format) {
+        formats.add(format);
+    }
+
+    /**
+     * Parses the given source string and returns the respective calendar
+     * instance. If no format matches returns <code>null</code>.
+     * <p/>
+     * Note: method is synchronized because SimpleDateFormat is not.
+     *
+     * @param source date time source string
+     * @return calendar representation of the source or <code>null</code>
+     */
+    public synchronized Calendar parse(String source) {
+        for (DateFormat fmt: formats) {
+            try {
+                Date d = fmt.parse(source);
+                if (log.isDebugEnabled()) {
+                    log.debug("Parsed " + source + " using " + fmt + " into " + d);
+                }
+                Calendar c = Calendar.getInstance();
+                c.setTime(d);
+                return c;
+            } catch (ParseException e) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Failed parsing " + source + " using " + fmt);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Parses the given source strings and returns the respective calendar
+     * instances. If no format matches for any of the sources
+     * returns <code>null</code>.
+     * <p/>
+     * Note: method is synchronized because SimpleDateFormat is not.
+     *
+     * @param sources date time source strings
+     * @return calendar representations of the source or <code>null</code>
+     */
+    public synchronized Calendar[] parse(String sources[]) {
+        Calendar ret[] = new Calendar[sources.length];
+        for (int i=0; i< sources.length; i++) {
+            if ((ret[i] = parse(sources[i])) == null) {
+                return null;
+            }
+        }
+        return ret;
+    }
+    
+    /**
+     * Parses the given source strings and returns the respective jcr date value
+     * instances. If no format matches for any of the sources
+     * returns <code>null</code>.
+     * <p/>
+     * Note: method is synchronized because SimpleDateFormat is not.
+     *
+     * @param sources date time source strings
+     * @param factory the value factory
+     * @return jcr date value representations of the source or <code>null</code>
+     */
+    public synchronized Value[] parse(String sources[], ValueFactory factory) {
+        Value ret[] = new Value[sources.length];
+        for (int i=0; i< sources.length; i++) {
+            Calendar c = parse(sources[i]);
+            if (c == null) {
+                return null;
+            }
+            ret[i] = factory.createValue(c);
+        }
+        return ret;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/RequestProperty.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/RequestProperty.java
new file mode 100644
index 0000000..cca1323
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/post/impl/RequestProperty.java
@@ -0,0 +1,257 @@
+/*
+ * 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.jackrabbit.usermanager.post.impl;
+
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * This is a copy of the class from 'org.apache.sling.servlets.post.impl.helper' which is not exported.
+ * 
+ * Encapsulates all infos from the respective request parameters that are needed
+ * to create the repository property
+ */
+public class RequestProperty {
+
+    private static final RequestParameter[] EMPTY_PARAM_ARRAY = new RequestParameter[0];
+
+    public static final String DEFAULT_IGNORE = SlingPostConstants.RP_PREFIX
+        + "ignore";
+
+    public static final String DEFAULT_NULL = SlingPostConstants.RP_PREFIX
+        + "null";
+
+    private final String path;
+
+    private final String name;
+
+    private final String parentPath;
+
+    private RequestParameter[] values;
+
+    private String[] stringValues;
+
+    private String typeHint;
+
+    private boolean hasMultiValueTypeHint;
+
+    private RequestParameter[] defaultValues = EMPTY_PARAM_ARRAY;
+
+    private boolean isDelete;
+
+    private String repositoryResourcePath;
+
+    private boolean isRepositoryResourceMove;
+
+    public RequestProperty(String path) {
+        assert path.startsWith("/");
+        this.path = ResourceUtil.normalize(path);
+        this.parentPath = ResourceUtil.getParent(path);
+        this.name = ResourceUtil.getName(path);
+    }
+
+    public String getTypeHint() {
+        return typeHint;
+    }
+
+    public boolean hasMultiValueTypeHint() {
+        return this.hasMultiValueTypeHint;
+    }
+
+    public void setTypeHintValue(String typeHint) {
+        if ( typeHint != null && typeHint.endsWith("[]") ) {
+            this.typeHint = typeHint.substring(0, typeHint.length() - 2);
+            this.hasMultiValueTypeHint = true;
+        } else {
+            this.typeHint = typeHint;
+            this.hasMultiValueTypeHint = false;
+        }
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getParentPath() {
+        return parentPath;
+    }
+
+    public boolean hasValues() {
+        return values != null;
+    }
+
+    public RequestParameter[] getValues() {
+        return values;
+    }
+
+    public void setValues(RequestParameter[] values) {
+        this.values = values;
+    }
+
+    public RequestParameter[] getDefaultValues() {
+        return defaultValues;
+    }
+
+    public void setDefaultValues(RequestParameter[] defaultValues) {
+        if (defaultValues == null) {
+            this.defaultValues = EMPTY_PARAM_ARRAY;
+        } else {
+            this.defaultValues = defaultValues;
+        }
+    }
+
+    public boolean isFileUpload() {
+        return !values[0].isFormField();
+    }
+
+    /**
+     * Checks if this property provides any values. this is the case if one of
+     * the values is not empty or if the default handling is not 'ignore'
+     *
+     * @return <code>true</code> if this property provides values
+     */
+    public boolean providesValue() {
+        // should void double creation of string values
+        String[] sv = getStringValues();
+        if (sv == null) {
+            // is missleading return type. but means that property should not
+            // get auto-create values
+            return true;
+        }
+        for (String s : sv) {
+            if (!s.equals("")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the assembled string array out of the provided request values and
+     * default values.
+     *
+     * @return a String array or <code>null</code> if the property needs to be
+     *         removed.
+     */
+    public String[] getStringValues() {
+        if (stringValues == null) {
+            if (values.length > 1) {
+                // TODO: how the default values work for MV props is not very
+                // clear
+                stringValues = new String[values.length];
+                for (int i = 0; i < stringValues.length; i++) {
+                    stringValues[i] = values[i].getString();
+                }
+            } else {
+                String value = values[0].getString();
+                if (value.equals("")) {
+                    if (defaultValues.length == 1) {
+                        String defValue = defaultValues[0].getString();
+                        if (defValue.equals(DEFAULT_IGNORE)) {
+                            // ignore means, do not create empty values
+                            return new String[0];
+                        } else if (defValue.equals(DEFAULT_NULL)) {
+                            // null means, remove property if exist
+                            return null;
+                        }
+                        value = defValue;
+                    }
+                }
+                stringValues = new String[] { value };
+            }
+        }
+        return stringValues;
+    }
+
+    /**
+     * Specifies whether this property should be deleted before any new content
+     * is to be set according to the values stored.
+     *
+     * @param isDelete <code>true</code> if the repository item described by
+     *            this is to be deleted before any other operation.
+     */
+    public void setDelete(boolean isDelete) {
+        this.isDelete = isDelete;
+    }
+
+    /**
+     * Returns <code>true</code> if the repository item described by this is
+     * to be deleted before setting new content to it.
+     */
+    public boolean isDelete() {
+        return isDelete;
+    }
+
+    /**
+     * Sets the path of the repository item from which the content for this
+     * property is to be copied or moved. The path may be relative in which case
+     * it will be resolved relative to the absolute path of this property.
+     *
+     * @param sourcePath The path of the repository item to get the content from
+     * @param isMove <code>true</code> if the source content is to be moved,
+     *            otherwise the source content is copied from the repository
+     *            item.
+     */
+    public void setRepositorySource(String sourcePath, boolean isMove) {
+
+        // make source path absolute
+        if (!sourcePath.startsWith("/")) {
+            sourcePath = getParentPath() + "/" + sourcePath;
+            sourcePath = ResourceUtil.normalize(sourcePath);
+        }
+
+        this.repositoryResourcePath = sourcePath;
+        this.isRepositoryResourceMove = isMove;
+    }
+
+    /**
+     * Returns <code>true</code> if the content of this property is to be set
+     * by moving content from another repository item.
+     *
+     * @see #getRepositorySource()
+     */
+    public boolean hasRepositoryMoveSource() {
+        return isRepositoryResourceMove;
+    }
+
+    /**
+     * Returns <code>true</code> if the content of this property is to be set
+     * by copying content from another repository item.
+     *
+     * @see #getRepositorySource()
+     */
+    public boolean hasRepositoryCopySource() {
+        return getRepositorySource() != null && !hasRepositoryMoveSource();
+    }
+
+    /**
+     * Returns the absolute path of the repository item from which the content
+     * for this property is to be copied or moved.
+     *
+     * @see #hasRepositoryCopySource()
+     * @see #hasRepositoryMoveSource()
+     * @see #setRepositorySource(String, boolean)
+     */
+    public String getRepositorySource() {
+        return repositoryResourcePath;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResource.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResource.java
new file mode 100644
index 0000000..c158d46
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResource.java
@@ -0,0 +1,119 @@
+/*
+ * 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.jackrabbit.usermanager.resource;
+
+
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.adapter.SlingAdaptable;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+
+/**
+ * Resource implementation for Authorizable 
+ */
+public class AuthorizableResource extends SlingAdaptable implements Resource {
+	private Authorizable authorizable = null;
+	private ResourceResolver resourceResolver = null;
+    private final String path;
+    private final String resourceType;
+    private final ResourceMetadata metadata;
+	
+	public AuthorizableResource(Authorizable authorizable,
+			ResourceResolver resourceResolver, String path) {
+		super();
+
+		this.resourceResolver = resourceResolver;
+        this.authorizable = authorizable;
+        this.path = path;
+        if (authorizable.isGroup()) {
+        	this.resourceType = "sling:group";
+        } else {
+        	this.resourceType = "sling:user";
+        }
+
+        this.metadata = new ResourceMetadata();
+        metadata.setResolutionPath(path);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getPath()
+	 */
+	public String getPath() {
+		return path;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getResourceMetadata()
+	 */
+	public ResourceMetadata getResourceMetadata() {
+		return metadata;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getResourceResolver()
+	 */
+	public ResourceResolver getResourceResolver() {
+		return resourceResolver;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getResourceSuperType()
+	 */
+	public String getResourceSuperType() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.Resource#getResourceType()
+	 */
+	public String getResourceType() {
+		return resourceType;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.adapter.Adaptable#adaptTo(java.lang.Class)
+	 */
+	@SuppressWarnings("unchecked")
+	public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+		if (type == Map.class || type == ValueMap.class) {
+			return (AdapterType) new AuthorizableValueMap(authorizable); // unchecked cast
+		} else if (type == Authorizable.class) {
+			return (AdapterType)authorizable;
+		}
+		
+		return super.adaptTo(type);
+	}
+
+    public String toString() {
+        String id = null;
+        if (authorizable != null) {
+            try {
+				id = authorizable.getID();
+			} catch (RepositoryException e) {
+				//ignore it.
+			}
+        }
+        return getClass().getSimpleName() + ", id=" + id
+            + ", path=" + getPath();
+    }
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResourceProvider.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResourceProvider.java
new file mode 100644
index 0000000..af864b6
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableResourceProvider.java
@@ -0,0 +1,220 @@
+/*
+ * 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.jackrabbit.usermanager.resource;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+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.apache.sling.api.SlingException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.SyntheticResource;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Resource Provider implementation for jackrabbit UserManager resources.
+ * 
+ * @scr.component immediate="true" label="%authorizable.resourceprovider.name"
+ *                description="authorizable.resourceprovider.description"
+ * @scr.property name="service.description"
+ *                value="Resource provider implementation for UserManager resources"
+ * @scr.property name="service.vendor" value="The Apache Software Foundation"
+ * @scr.property name="provider.roots" value="/system/userManager/"
+ * @scr.service interface="org.apache.sling.api.resource.ResourceProvider"
+ */
+public class AuthorizableResourceProvider implements ResourceProvider {
+	
+    /**
+     * default log
+     */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+	public static final String SYSTEM_USER_MANAGER_PATH = "/system/userManager";
+
+	public static final String SYSTEM_USER_MANAGER_USER_PATH = SYSTEM_USER_MANAGER_PATH + "/user";
+	public static final String SYSTEM_USER_MANAGER_GROUP_PATH = SYSTEM_USER_MANAGER_PATH + "/group";
+
+	public static final String SYSTEM_USER_MANAGER_USER_PREFIX = SYSTEM_USER_MANAGER_USER_PATH + "/";
+	public static final String SYSTEM_USER_MANAGER_GROUP_PREFIX = SYSTEM_USER_MANAGER_GROUP_PATH + "/";
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, javax.servlet.http.HttpServletRequest, java.lang.String)
+	 */
+	public Resource getResource(ResourceResolver resourceResolver,
+			HttpServletRequest request, String path) {
+        return getResource(resourceResolver, path);
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, java.lang.String)
+	 */
+	public Resource getResource(ResourceResolver resourceResolver, String path) {
+		
+		//handle resources for the virtual container resources
+		if (path.equals(SYSTEM_USER_MANAGER_PATH)) {
+			return new SyntheticResource(resourceResolver, path, "sling:userManager");
+		} else if (path.equals(SYSTEM_USER_MANAGER_USER_PATH)) {
+			return new SyntheticResource(resourceResolver, path, "sling:users");
+		} else if (path.equals(SYSTEM_USER_MANAGER_GROUP_PATH)) {
+			return new SyntheticResource(resourceResolver, path, "sling:groups");
+		}
+		
+		// the principalId should be the first segment after the prefix
+		String pid = null;
+		if (path.startsWith(SYSTEM_USER_MANAGER_USER_PREFIX)) {
+			pid = path.substring(SYSTEM_USER_MANAGER_USER_PREFIX.length());
+		} else if (path.startsWith(SYSTEM_USER_MANAGER_GROUP_PREFIX)) {
+			pid = path.substring(SYSTEM_USER_MANAGER_GROUP_PREFIX.length());
+		}
+		
+		if (pid != null) {
+			if (pid.indexOf('/') != -1) {
+				return null; //something bogus on the end of the path so bail out now.
+			}
+			try {
+				Session session = resourceResolver.adaptTo(Session.class);
+				if (session != null) {
+					UserManager userManager = AccessControlUtil.getUserManager(session);
+					if (userManager != null) {
+						Authorizable authorizable = userManager.getAuthorizable(pid);
+						if (authorizable != null) {
+							//found the Authorizable, so return the resource that wraps it.
+							return new AuthorizableResource(authorizable, resourceResolver, path);
+						}
+					}
+				}
+			} catch (RepositoryException re) {
+				throw new SlingException("Error looking up Authorizable for principal: " + pid, re);
+			}
+		}
+        return null;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.api.resource.ResourceProvider#listChildren(org.apache.sling.api.resource.Resource)
+	 */
+	public Iterator<Resource> listChildren(Resource parent) {
+		if (parent == null) {
+			throw new NullPointerException("parent is null");
+		}
+		try {
+			String path = parent.getPath();
+			ResourceResolver resourceResolver = parent.getResourceResolver();
+
+			//handle children of /system/userManager
+			if (SYSTEM_USER_MANAGER_PATH.equals(path)) {
+				List<Resource> resources = new ArrayList<Resource>();
+				if (resourceResolver != null) {
+					resources.add(getResource(resourceResolver, SYSTEM_USER_MANAGER_USER_PATH));	
+					resources.add(getResource(resourceResolver, SYSTEM_USER_MANAGER_GROUP_PATH));	
+				}
+				return resources.iterator();
+			}
+			
+			int searchType = -1;
+			if (SYSTEM_USER_MANAGER_USER_PATH.equals(path)) {
+				searchType = PrincipalManager.SEARCH_TYPE_NOT_GROUP;
+			} else if (SYSTEM_USER_MANAGER_GROUP_PATH.equals(path)) {
+				searchType = PrincipalManager.SEARCH_TYPE_GROUP;
+			}
+			if (searchType != -1) {
+				PrincipalIterator principals = null;
+
+				//TODO: this actually does not work correctly since the jackrabbit findPrincipals API 
+				// currently does an exact match of the search filter so it won't match a wildcard
+				Session session = resourceResolver.adaptTo(Session.class);
+				if (session != null) {
+					PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(session);
+					principals = principalManager.findPrincipals(".*", PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+				}
+
+				
+				if (principals != null) {
+					return new ChildrenIterator(parent, principals);
+				}
+			}
+		} catch (RepositoryException re) {
+			throw new SlingException("Error listing children of resource: " + parent.getPath(), re);
+		}
+
+		return null;
+	}
+	
+	
+
+	private final class ChildrenIterator implements Iterator<Resource> {
+		private PrincipalIterator principals;
+		private Resource parent;
+
+		public ChildrenIterator(Resource parent, PrincipalIterator principals) {
+			this.parent = parent;
+			this.principals = principals;
+		}
+
+		public boolean hasNext() {
+			return principals.hasNext();
+		}
+
+		public Resource next() {
+			Principal nextPrincipal = principals.nextPrincipal();
+			try {
+				ResourceResolver resourceResolver = parent.getResourceResolver();
+				if (resourceResolver != null) {
+					Session session = resourceResolver.adaptTo(Session.class);
+					if (session != null) {
+						UserManager userManager = AccessControlUtil.getUserManager(session);
+						if (userManager != null) {
+							Authorizable authorizable = userManager.getAuthorizable(nextPrincipal.getName());
+							if (authorizable != null) {
+								String path;
+								if (authorizable.isGroup()) {
+									path = SYSTEM_USER_MANAGER_GROUP_PREFIX + nextPrincipal.getName();
+								} else {
+									path = SYSTEM_USER_MANAGER_USER_PREFIX + nextPrincipal.getName();
+								}
+								return new AuthorizableResource(authorizable, resourceResolver, path);
+							}
+						}
+					}
+				}
+			} catch (RepositoryException re) {
+                log.error("Exception while looking up authorizable resource.", re);
+			}
+			return null;
+		}
+
+		public void remove() {
+			throw new UnsupportedOperationException();
+		}
+	}
+	
+}
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableValueMap.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableValueMap.java
new file mode 100644
index 0000000..3dafa19
--- /dev/null
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/resource/AuthorizableValueMap.java
@@ -0,0 +1,319 @@
+/*
+ * 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.jackrabbit.usermanager.resource;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.JcrResourceUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ValueMap implementation for Authorizable Resources
+ */
+public class AuthorizableValueMap implements ValueMap {
+    private Logger logger = LoggerFactory.getLogger(AuthorizableValueMap.class);
+    private Set<String> hiddenProperties = new HashSet<String>(Arrays.asList(new String[]{"rep:password", "jcr:uuid"}));
+	private boolean fullyRead;
+    private final Map<String, Object> cache;
+	private Authorizable authorizable;
+
+    public AuthorizableValueMap(Authorizable authorizable) {
+        this.authorizable = authorizable;
+        this.cache = new LinkedHashMap<String, Object>();
+        this.fullyRead = false;
+    }
+
+	@SuppressWarnings("unchecked")
+	public <T> T get(String name, Class<T> type) {
+        if (type == null) {
+            return (T) get(name);
+        }
+
+        return convertToType(name, type);
+	}
+
+	@SuppressWarnings("unchecked")
+	public <T> T get(String name, T defaultValue) {
+        if (defaultValue == null) {
+            return (T) get(name);
+        }
+
+        // special handling in case the default value implements one
+        // of the interface types supported by the convertToType method
+        Class<T> type = (Class<T>) normalizeClass(defaultValue.getClass());
+
+        T value = get(name, type);
+        if (value == null) {
+            value = defaultValue;
+        }
+
+        return value;
+	}
+
+	public boolean containsKey(Object key) {
+        return get(key) != null;
+	}
+
+	public boolean containsValue(Object value) {
+        readFully();
+        return cache.containsValue(value);
+	}
+
+	public Set<java.util.Map.Entry<String, Object>> entrySet() {
+        readFully();
+        return cache.entrySet();
+	}
+
+	public Object get(Object key) {
+        Object value = cache.get(key);
+        if (value == null) {
+            value = read((String) key);
+        }
+
+        return value;
+	}
+
+
+	public Set<String> keySet() {
+        readFully();
+        return cache.keySet();
+	}
+
+	public int size() {
+        readFully();
+        return cache.size();
+	}
+
+	public boolean isEmpty() {
+        return size() == 0;
+	}
+
+	public Collection<Object> values() {
+        readFully();
+        return cache.values();
+	}
+	
+    protected Object read(String key) {
+
+        // if the item has been completely read, we need not check
+        // again, as we certainly will not find the key
+        if (fullyRead) {
+            return null;
+        }
+
+        if (hiddenProperties.contains(key)) {
+        	return null;
+        }
+        
+        try {
+            if (authorizable.hasProperty(key)) {
+                Value[] property = authorizable.getProperty(key);
+                Object value = valuesToJavaObject(property);
+            	cache.put(key, value);
+                return value;
+            }
+        } catch (RepositoryException re) {
+            // TODO: log !!
+        }
+
+        // property not found or some error accessing it
+        return null;
+    }
+    
+    protected Object valuesToJavaObject(Value [] values) throws RepositoryException {
+        if (values == null) {
+        	return null;
+        } else if (values.length == 1) {
+        	return JcrResourceUtil.toJavaObject(values[0]);
+        } else {
+        	Object [] valuesObjs = new Object[values.length];
+        	for (int i=0; i < values.length; i++) {
+        		valuesObjs[i] = JcrResourceUtil.toJavaObject(values[i]);
+        	}
+        	return valuesObjs;
+        }
+    }
+	
+    @SuppressWarnings("unchecked")
+	protected void readFully() {
+        if (!fullyRead) {
+            try {
+                Iterator pi = authorizable.getPropertyNames();
+                while (pi.hasNext()) {
+                    String key = (String)pi.next();
+
+                    if (hiddenProperties.contains(key)) {
+                    	continue; //skip it.
+                    }
+
+                    if (!cache.containsKey(key)) {
+	                    Value[] property = authorizable.getProperty(key);
+	                    Object value = valuesToJavaObject(property);
+                    	cache.put(key, value);
+                    }
+                }
+                fullyRead = true;
+            } catch (RepositoryException re) {
+                // TODO: log !!
+            }
+        }
+    }
+	
+    // ---------- Unsupported Modification methods
+	
+	public Object remove(Object arg0) {
+        throw new UnsupportedOperationException();
+	}
+	public void clear() {
+        throw new UnsupportedOperationException();
+	}
+	public Object put(String arg0, Object arg1) {
+        throw new UnsupportedOperationException();
+	}
+
+	public void putAll(Map<? extends String, ? extends Object> arg0) {
+        throw new UnsupportedOperationException();
+	}	
+	
+	
+    // ---------- Implementation helper
+
+    @SuppressWarnings("unchecked")
+    private <T> T convertToType(String name, Class<T> type) {
+        T result = null;
+
+        try {
+            if (authorizable.hasProperty(name)) {
+                Value[] values = authorizable.getProperty(name);
+
+                if (values == null) {
+                	return null;
+                }
+                
+                boolean multiValue = values.length > 1;
+                boolean array = type.isArray();
+
+                if (multiValue) {
+                    if (array) {
+                        result = (T) convertToArray(values,
+                            type.getComponentType());
+                    } else if (values.length > 0) {
+                        result = convertToType(-1, values[0], type);
+                    }
+                } else {
+                    Value value = values[0];
+                    if (array) {
+                        result = (T) convertToArray(
+                            new Value[] { value }, type.getComponentType());
+                    } else {
+                        result = convertToType(-1, value, type);
+                    }
+                }
+            }
+
+        } catch (ValueFormatException vfe) {
+            logger.info("converToType: Cannot convert value of " + name
+                + " to " + type, vfe);
+        } catch (RepositoryException re) {
+            logger.info("converToType: Cannot get value of " + name, re);
+        }
+
+        // fall back to nothing
+        return result;
+    }
+	
+    private <T> T[] convertToArray(Value[] jcrValues, Class<T> type)
+    	throws ValueFormatException, RepositoryException {
+    	List<T> values = new ArrayList<T>();
+    	for (int i = 0; i < jcrValues.length; i++) {
+    		T value = convertToType(i, jcrValues[i], type);
+    		if (value != null) {
+    			values.add(value);
+    		}
+    	}
+
+    	@SuppressWarnings("unchecked")
+    	T[] result = (T[]) Array.newInstance(type, values.size());
+
+    	return values.toArray(result);
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <T> T convertToType(int index, Value jcrValue,
+            Class<T> type) throws ValueFormatException, RepositoryException {
+
+        if (String.class == type) {
+            return (T) jcrValue.getString();
+        } else if (Byte.class == type) {
+            return (T) new Byte((byte) jcrValue.getLong());
+        } else if (Short.class == type) {
+            return (T) new Short((short) jcrValue.getLong());
+        } else if (Integer.class == type) {
+            return (T) new Integer((int) jcrValue.getLong());
+        } else if (Long.class == type) {
+            return (T) new Long(jcrValue.getLong());
+        } else if (Float.class == type) {
+            return (T) new Float(jcrValue.getDouble());
+        } else if (Double.class == type) {
+            return (T) new Double(jcrValue.getDouble());
+        } else if (Boolean.class == type) {
+            return (T) Boolean.valueOf(jcrValue.getBoolean());
+        } else if (Date.class == type) {
+            return (T) jcrValue.getDate().getTime();
+        } else if (Calendar.class == type) {
+            return (T) jcrValue.getDate();
+        } else if (Value.class == type) {
+            return (T) jcrValue;
+        }
+
+        // fallback in case of unsupported type
+        return null;
+    }
+    
+    private Class<?> normalizeClass(Class<?> type) {
+        if (Calendar.class.isAssignableFrom(type)) {
+            type = Calendar.class;
+        } else if (Date.class.isAssignableFrom(type)) {
+            type = Date.class;
+        } else if (Value.class.isAssignableFrom(type)) {
+            type = Value.class;
+        } else if (Property.class.isAssignableFrom(type)) {
+            type = Property.class;
+        }
+        return type;
+    }
+	
+}
\ No newline at end of file
diff --git a/src/main/resources/META-INF/LICENSE b/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..75b5248
--- /dev/null
+++ b/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/src/main/resources/META-INF/NOTICE b/src/main/resources/META-INF/NOTICE
new file mode 100644
index 0000000..9f4ac5f
--- /dev/null
+++ b/src/main/resources/META-INF/NOTICE
@@ -0,0 +1,5 @@
+Apache Sling Jackrabbit UserManager Support
+Copyright 2008-2009 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties
new file mode 100644
index 0000000..597ece1
--- /dev/null
+++ b/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -0,0 +1,36 @@
+#
+#  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.
+#
+
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor generated by the
+# the Sling SCR plugin
+
+authorizable.resourceprovider.name = Resolver for UserManager resources
+authorizable.resourceprovider.description = Handles resolving resources for the \
+ jackrabbit UserManager.
+
+createUser.post.operation.name = Create User Sling Post Operation
+createUser.post.operation.description = The Sling POST Operation to handle create user \
+ requests in Sling.
+ 
+self.registration.enabled.name = Self-Registration Enabled
+self.registration.enabled.description = When selected, the anonymous user is allowed to \
+ register a new user with the system.

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 09/13: [maven-release-plugin] prepare for next development iteration

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 70ae9d9adae35922ab369cc83e7bdba72d9680d6
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue May 5 16:20:52 2009 +0000

    [maven-release-plugin] prepare for next development iteration
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@771892 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pom.xml b/pom.xml
index 78ef32e..02e8827 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
 
 	<artifactId>org.apache.sling.jcr.jackrabbit.usermanager</artifactId>
 	<packaging>bundle</packaging>
-	<version>2.0.0-incubator</version>
+	<version>2.0.1-incubator-SNAPSHOT</version>
 	<name>Apache Sling Jackrabbit UserManager Support</name>
 	<description>
 		Provides ResourceProvider and SlingPostOperations for the Jackrabbit
@@ -38,13 +38,13 @@
 
 	<scm>
 		<connection>
-			scm:svn:http://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator
+			scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
 		</connection>
 		<developerConnection>
-			scm:svn:https://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator
+			scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
 		</developerConnection>
 		<url>
-			http://svn.apache.org/viewvc/incubator/sling/tags/org.apache.sling.jcr.jackrabbit.usermanager-2.0.0-incubator
+			http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager
 		</url>
 	</scm>
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 04/13: Use released version of jackrabbit api

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 2745b638cebb43150fd511a9479184d2b9e11cae
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue May 5 08:26:58 2009 +0000

    Use released version of jackrabbit api
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@771617 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index a39f834..608c9c8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -104,7 +104,7 @@
 		<dependency>
 			<groupId>org.apache.sling</groupId>
 			<artifactId>org.apache.sling.jcr.jackrabbit.api</artifactId>
-			<version>2.0.3-incubator-SNAPSHOT</version>
+			<version>2.0.2-incubator</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.sling</groupId>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-jcr-jackrabbit-usermanager] 07/13: Use released version as dependencies.

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.jackrabbit.usermanager-2.0.2-incubator
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git

commit 87d5271a24a1064ba8bcfc4bb8c17a18c6b673ef
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue May 5 15:25:58 2009 +0000

    Use released version as dependencies.
    
    git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk/bundles/jcr/jackrabbit-usermanager@771800 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pom.xml b/pom.xml
index b6b347c..3d4dff1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,12 +94,12 @@
 		<dependency>
 			<groupId>org.apache.sling</groupId>
 			<artifactId>org.apache.sling.api</artifactId>
-			<version>2.0.3-incubator-SNAPSHOT</version>
+			<version>2.0.4-incubator</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.sling</groupId>
 			<artifactId>org.apache.sling.servlets.post</artifactId>
-			<version>2.0.3-incubator-SNAPSHOT</version>
+			<version>2.0.4-incubator</version>
 		</dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
@@ -109,7 +109,7 @@
 		<dependency>
 			<groupId>org.apache.sling</groupId>
 			<artifactId>org.apache.sling.jcr.base</artifactId>
-			<version>2.0.3-incubator-SNAPSHOT</version>
+			<version>2.0.4-incubator</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.jackrabbit</groupId>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.