You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2013/07/23 15:28:41 UTC

svn commit: r1506037 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/ oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/ oak-core/src/main/java/org/apache/jackrabbit/oak/security/a...

Author: angela
Date: Tue Jul 23 13:28:41 2013
New Revision: 1506037

URL: http://svn.apache.org/r1506037
Log:
OAK-923 : Runtime exception while creating a group (part 2: runtime exception. see comments in the issue for details)

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java Tue Jul 23 13:28:41 2013
@@ -34,6 +34,7 @@ import java.util.Collection;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
@@ -63,21 +64,21 @@ public class IndexUtils {
     /**
      * Create a new property index definition below the given {@code indexNode}.
      *
-     * @param index         The oak:index node builder
-     * @param indexDefName  The name of the new property index.
-     * @param reindex       {@code true} if the the reindex flag should be turned on.
-     * @param unique        {@code true} if the index is expected the assert property
-     *                      uniqueness.
-     * @param propertyNames The property names that should be indexed.
+     * @param index                  The oak:index node builder
+     * @param indexDefName           The name of the new property index.
+     * @param reindex                {@code true} if the the reindex flag should be turned on.
+     * @param unique                 {@code true} if the index is expected the assert property
+     *                               uniqueness.
+     * @param propertyNames          The property names that should be indexed.
      * @param declaringNodeTypeNames The declaring node type names or {@code null}.
      * @return the NodeBuilder of the new index definition.
      */
     public static NodeBuilder createIndexDefinition(@Nonnull NodeBuilder index,
-                                             @Nonnull String indexDefName,
-                                             boolean reindex,
-                                             boolean unique,
-                                             @Nonnull Collection<String> propertyNames,
-                                             @Nullable Collection<String> declaringNodeTypeNames) {
+                                                    @Nonnull String indexDefName,
+                                                    boolean reindex,
+                                                    boolean unique,
+                                                    @Nonnull Collection<String> propertyNames,
+                                                    @Nullable Collection<String> declaringNodeTypeNames) {
         NodeBuilder entry = index.child(indexDefName)
                 .setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE, NAME)
                 .setProperty(TYPE_PROPERTY_NAME, PropertyIndexEditorProvider.TYPE)
@@ -105,7 +106,7 @@ public class IndexUtils {
                                              @Nonnull String indexDefName,
                                              boolean unique,
                                              @Nonnull String[] propertyNames,
-                                             @Nullable String[] declaringNodeTypeNames) {
+                                             @Nullable String[] declaringNodeTypeNames) throws RepositoryException {
         NodeUtil entry = indexNode.getOrAddChild(indexDefName, INDEX_DEFINITIONS_NODE_TYPE);
         entry.setString(TYPE_PROPERTY_NAME, PropertyIndexEditorProvider.TYPE);
         entry.setBoolean(REINDEX_PROPERTY_NAME, true);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java Tue Jul 23 13:28:41 2013
@@ -16,9 +16,6 @@
  */
 package org.apache.jackrabbit.oak.security.authentication.token;
 
-import static org.apache.jackrabbit.oak.api.Type.STRING;
-import static org.apache.jackrabbit.oak.core.IdentifierManager.getIdentifier;
-
 import java.io.UnsupportedEncodingException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
@@ -32,9 +29,9 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
 import javax.jcr.RepositoryException;
 import javax.jcr.SimpleCredentials;
@@ -63,13 +60,16 @@ import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.jackrabbit.oak.api.Type.STRING;
+import static org.apache.jackrabbit.oak.core.IdentifierManager.getIdentifier;
+
 /**
  * Default implementation of the {@code TokenProvider} interface that keeps login
  * tokens in the content repository. As a precondition the configured the user
  * management implementation must provide paths for all
  * {@link org.apache.jackrabbit.api.security.user.User users} that refer to
  * a valid {@link Tree} in the content repository.
- *
+ * <p/>
  * <h3>Backwards compatibility with Jackrabbit 2.x</h3>
  * For security reasons the nodes storing the token information now have a
  * dedicated node type (rep:Token) which has the following definition:
@@ -81,7 +81,7 @@ import org.slf4j.LoggerFactory;
  * Consequently the hash of the token and the expiration time of tokens generated
  * by this provider can no longer be manipulated using regular JCR item
  * modifications.<p>
- *
+ * <p/>
  * Existing login tokens generated by Jackrabbit 2.x which are migrated to
  * OAK will still be valid (unless they expire) due to the fact that
  * {@link #getTokenInfo(String)} and the implementation of the {@link TokenInfo}
@@ -114,6 +114,7 @@ public class TokenProviderImpl implement
     private static final char DELIM = '_';
 
     private static final Set<String> RESERVED_ATTRIBUTES = new HashSet(2);
+
     static {
         RESERVED_ATTRIBUTES.add(TOKEN_ATTRIBUTE);
         RESERVED_ATTRIBUTES.add(TOKEN_ATTRIBUTE_EXPIRY);
@@ -145,9 +146,9 @@ public class TokenProviderImpl implement
      *
      * @param credentials The current credentials.
      * @return {@code true} if the specified credentials are {@link SimpleCredentials}
-     * or {@link ImpersonationCredentials} and if the (extracted) simple credentials
-     * object contain a {@link #TOKEN_ATTRIBUTE} attribute with an empty value;
-     * {@code false} otherwise.
+     *         or {@link ImpersonationCredentials} and if the (extracted) simple credentials
+     *         object contain a {@link #TOKEN_ATTRIBUTE} attribute with an empty value;
+     *         {@code false} otherwise.
      */
     @Override
     public boolean doCreateToken(Credentials credentials) {
@@ -168,7 +169,7 @@ public class TokenProviderImpl implement
      *
      * @param credentials The current credentials.
      * @return A new {@code TokenInfo} or {@code null} if the token could not
-     * be created.
+     *         be created.
      */
     @Override
     public TokenInfo createToken(Credentials credentials) {
@@ -196,11 +197,11 @@ public class TokenProviderImpl implement
      * expiration time and additional mandatory attributes that will be verified
      * during login.
      *
-     * @param userId The identifier of the user for which a new token should
-     * be created.
+     * @param userId     The identifier of the user for which a new token should
+     *                   be created.
      * @param attributes The attributes associated with the new token.
      * @return A new {@code TokenInfo} or {@code null} if the token could not
-     * be created.
+     *         be created.
      */
     @Override
     public TokenInfo createToken(String userId, Map<String, ?> attributes) {
@@ -242,6 +243,8 @@ public class TokenProviderImpl implement
             } catch (CommitFailedException e) {
                 // conflict while committing changes
                 log.warn(error, e.getMessage());
+            } catch (AccessDeniedException e) {
+                log.warn(error, e.getMessage());
             }
         } else {
             log.warn("Unable to get/create token store for user " + userId);
@@ -256,8 +259,8 @@ public class TokenProviderImpl implement
      *
      * @param token A valid login token.
      * @return The {@code TokenInfo} associated with the specified token or
-     * {@code null} of the corresponding information does not exist or is not
-     * associated with a valid user.
+     *         {@code null} of the corresponding information does not exist or is not
+     *         associated with a valid user.
      */
     @Override
     public TokenInfo getTokenInfo(String token) {
@@ -299,7 +302,7 @@ public class TokenProviderImpl implement
                 return false;
             }
 
-            if (expTime - loginTime <= tokenExpiration/2) {
+            if (expTime - loginTime <= tokenExpiration / 2) {
                 long expirationTime = loginTime + tokenExpiration;
                 try {
                     tokenNode.setDate(TOKEN_ATTRIBUTE_EXPIRY, expirationTime);
@@ -398,7 +401,7 @@ public class TokenProviderImpl implement
         } catch (RepositoryException e) {
             // error while accessing user.
             log.debug("Error while accessing user " + userId + '.', e);
-        }  catch (CommitFailedException e) {
+        } catch (CommitFailedException e) {
             // conflict while creating token store for this user -> refresh and
             // try to get the tree from the updated root.
             log.debug("Conflict while creating token store -> retrying", e.getMessage());
@@ -414,6 +417,7 @@ public class TokenProviderImpl implement
     }
 
     //--------------------------------------------------------------------------
+
     /**
      * TokenInfo
      */
@@ -518,7 +522,7 @@ public class TokenProviderImpl implement
          *
          * @param attributeName The attribute name.
          * @return {@code true} if the specified {@code attributeName}
-         * starts with or equals {@link #TOKEN_ATTRIBUTE}.
+         *         starts with or equals {@link #TOKEN_ATTRIBUTE}.
          */
         private static boolean isMandatoryAttribute(String attributeName) {
             return attributeName != null && attributeName.startsWith(TOKEN_ATTRIBUTE);
@@ -530,9 +534,9 @@ public class TokenProviderImpl implement
          * a lazy evaluation in order to avoid testing the defining node type of
          * the associated jcr property.
          *
-         * @param attributeName  The attribute name.
+         * @param attributeName The attribute name.
          * @return {@code true} if the specified property name doesn't seem
-         * to represent repository internal information.
+         *         to represent repository internal information.
          */
         private static boolean isInfoAttribute(String attributeName) {
             String prefix = Text.getNamespacePrefix(attributeName);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java Tue Jul 23 13:28:41 2013
@@ -489,13 +489,13 @@ public class AccessControlManagerImpl im
     }
 
     /**
-     *
      * @param oakPath the Oak path as specified with the ac mgr call.
      * @param tree    the access controlled node.
      * @return the new acl tree.
+     * @throws AccessDeniedException In case the new acl tree is not accessible.
      */
     @Nonnull
-    private Tree createAclTree(@Nullable String oakPath, @Nonnull Tree tree) {
+    private Tree createAclTree(@Nullable String oakPath, @Nonnull Tree tree) throws AccessDeniedException {
         if (!AccessControlUtils.isAccessControlled(oakPath, tree, ntMgr)) {
             PropertyState mixins = tree.getProperty(JcrConstants.JCR_MIXINTYPES);
             String mixinName = AccessControlUtils.getMixinName(oakPath);
@@ -814,7 +814,8 @@ public class AccessControlManagerImpl im
 
         private static final NamedAccessControlPolicy INSTANCE = new ReadPolicy();
 
-        private ReadPolicy() {}
+        private ReadPolicy() {
+        }
 
         @Override
         public String getName() {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriter.java Tue Jul 23 13:28:41 2013
@@ -20,8 +20,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
-
-import javax.jcr.AccessDeniedException;
 import javax.jcr.RepositoryException;
 
 import com.google.common.collect.ImmutableMap;
@@ -122,7 +120,7 @@ class PrivilegeDefinitionWriter implemen
         }
     }
 
-    private void writePrivilegeNode(NodeUtil privilegesNode, PrivilegeDefinition definition) {
+    private void writePrivilegeNode(NodeUtil privilegesNode, PrivilegeDefinition definition) throws RepositoryException {
         String name = definition.getName();
         NodeUtil privNode = privilegesNode.addChild(name, NT_REP_PRIVILEGE);
         if (definition.isAbstract()) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java Tue Jul 23 13:28:41 2013
@@ -22,6 +22,7 @@ import java.util.Iterator;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
@@ -50,30 +51,30 @@ import static org.apache.jackrabbit.oak.
  * with the {@code Tree} associated with a given {@link org.apache.jackrabbit.api.security.user.Group}.
  * Depending on the configuration there are two variants on how group members
  * are recorded:
- *
+ * <p/>
  * <h3>Membership stored in multi-valued property</h3>
  * This is the default way of storing membership information with the following
  * characteristics:
  * <ul>
- *     <li>Multivalued property {@link #REP_MEMBERS}</li>
- *     <li>Property type: {@link javax.jcr.PropertyType#WEAKREFERENCE}</li>
- *     <li>Used if the config option {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} is missing or &lt;4</li>
+ * <li>Multivalued property {@link #REP_MEMBERS}</li>
+ * <li>Property type: {@link javax.jcr.PropertyType#WEAKREFERENCE}</li>
+ * <li>Used if the config option {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} is missing or &lt;4</li>
  * </ul>
- *
+ * <p/>
  * <h3>Membership stored in individual properties</h3>
  * Variant to store group membership based on the
  * {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} configuration parameter:
- *
+ * <p/>
  * <ul>
- *     <li>Membership information stored underneath a {@link #REP_MEMBERS} node hierarchy</li>
- *     <li>Individual member information is stored each in a {@link javax.jcr.PropertyType#WEAKREFERENCE}
- *     property</li>
- *     <li>Node hierarchy is split based on the {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE}
- *     configuration parameter.</li>
- *     <li>{@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} must be greater than 4
- *     in order to turn on this behavior</li>
+ * <li>Membership information stored underneath a {@link #REP_MEMBERS} node hierarchy</li>
+ * <li>Individual member information is stored each in a {@link javax.jcr.PropertyType#WEAKREFERENCE}
+ * property</li>
+ * <li>Node hierarchy is split based on the {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE}
+ * configuration parameter.</li>
+ * <li>{@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} must be greater than 4
+ * in order to turn on this behavior</li>
  * </ul>
- *
+ * <p/>
  * <h3>Compatibility</h3>
  * This membership provider is able to deal with both options being present in
  * the content. If the {@link org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE} configuration
@@ -102,7 +103,7 @@ class MembershipProvider extends Authori
         Set<String> groupPaths = new HashSet<String>();
         Set<String> refPaths = identifierManager.getReferences(true, authorizableTree, REP_MEMBERS, NT_REP_GROUP, NT_REP_MEMBERS);
         for (String propPath : refPaths) {
-            int index = propPath.indexOf('/'+REP_MEMBERS);
+            int index = propPath.indexOf('/' + REP_MEMBERS);
             if (index > 0) {
                 groupPaths.add(propPath.substring(0, index));
             } else {
@@ -181,11 +182,11 @@ class MembershipProvider extends Authori
         return false;
     }
 
-    boolean addMember(Tree groupTree, Tree newMemberTree) {
+    boolean addMember(Tree groupTree, Tree newMemberTree) throws RepositoryException {
         return addMember(groupTree, newMemberTree.getName(), getContentID(newMemberTree));
     }
 
-    boolean addMember(Tree groupTree, String treeName, String memberContentId) {
+    boolean addMember(Tree groupTree, String treeName, String memberContentId) throws RepositoryException {
         if (useMemberNode(groupTree)) {
             NodeUtil groupNode = new NodeUtil(groupTree);
             NodeUtil membersNode = groupNode.getOrAddChild(REP_MEMBERS, NT_REP_MEMBERS);
@@ -233,10 +234,10 @@ class MembershipProvider extends Authori
      * Returns {@code true} if the given {@code newMember} is a Group
      * and contains {@code this} Group as declared or inherited member.
      *
-     * @param newMemberTree The new member to be tested for cyclic membership.
+     * @param newMemberTree  The new member to be tested for cyclic membership.
      * @param groupContentId The content ID of the group.
      * @return true if the 'newMember' is a group and 'this' is an declared or
-     * inherited member of it.
+     *         inherited member of it.
      */
     boolean isCyclicMembership(Tree newMemberTree, String groupContentId) {
         if (UserUtility.isType(newMemberTree, AuthorizableType.GROUP)) {
@@ -271,8 +272,7 @@ class MembershipProvider extends Authori
      * Returns an iterator of authorizables which includes all indirect members
      * of the given iterator of authorizables.
      *
-     *
-     * @param declaredMembers Iterator containing the paths to the declared members.
+     * @param declaredMembers  Iterator containing the paths to the declared members.
      * @param authorizableType Flag used to filter the result by authorizable type.
      * @return Iterator of Authorizable objects
      */
@@ -344,6 +344,7 @@ class MembershipProvider extends Authori
 
     private static final class ProcessedPathPredicate implements Predicate<String> {
         private final Set<String> processed = new HashSet<String>();
+
         @Override
         public boolean apply(@Nullable String path) {
             return processed.add(path);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java Tue Jul 23 13:28:41 2013
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.jcr.AccessDeniedException;
 import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.query.Query;
@@ -32,6 +33,7 @@ import org.apache.jackrabbit.oak.api.Res
 import org.apache.jackrabbit.oak.api.ResultRow;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
@@ -272,21 +274,24 @@ class UserProvider extends AuthorizableB
     private NodeUtil createFolderNodes(String authorizableId, String nodeName,
                                        boolean isGroup, String intermediatePath) throws RepositoryException {
         String authRoot = (isGroup) ? groupPath : userPath;
+        String folderPath = new StringBuilder()
+                .append(authRoot)
+                .append(getFolderPath(authorizableId, intermediatePath, authRoot)).toString();
         NodeUtil folder;
-        Tree authTree = root.getTree(authRoot);
-        if (!authTree.exists()) {
-            folder = new NodeUtil(root.getTree("/"));
-            for (String name : Text.explode(authRoot, '/', false)) {
-                folder = folder.getOrAddChild(name, NT_REP_AUTHORIZABLE_FOLDER);
+        Tree tree = root.getTree(folderPath);
+        while (!tree.isRoot() && !tree.exists()) {
+            tree = tree.getParent();
+        }
+        if (tree.exists()) {
+            folder = new NodeUtil(tree);
+            String relativePath = PathUtils.relativize(tree.getPath(), folderPath);
+            if (!relativePath.isEmpty()) {
+                folder = folder.getOrAddTree(relativePath, NT_REP_AUTHORIZABLE_FOLDER);
             }
         } else {
-            folder = new NodeUtil(authTree);
+            throw new AccessDeniedException("Missing permission to create intermediate authorizable folders.");
         }
 
-        // verification of hierarchy and node types is delegated to UserValidator upon commit
-        String folderPath = getFolderPath(authorizableId, intermediatePath, authRoot);
-        folder = folder.getOrAddTree(folderPath, NT_REP_AUTHORIZABLE_FOLDER);
-
         // test for colliding folder child node.
         while (folder.hasChild(nodeName)) {
             NodeUtil colliding = folder.getChild(nodeName);
@@ -315,7 +320,7 @@ class UserProvider extends AuthorizableB
 
         StringBuilder sb = new StringBuilder();
         if (intermediatePath != null && !intermediatePath.isEmpty()) {
-            sb.append(intermediatePath);
+            sb.append(DELIMITER).append(intermediatePath);
         } else {
             int idLength = authorizableId.length();
             StringBuilder segment = new StringBuilder();

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/AbstractRestrictionProvider.java Tue Jul 23 13:28:41 2013
@@ -22,6 +22,7 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import javax.annotation.Nonnull;
+import javax.jcr.AccessDeniedException;
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
@@ -129,7 +130,7 @@ public abstract class AbstractRestrictio
     }
 
     @Override
-    public void writeRestrictions(String oakPath, Tree aceTree, Set<Restriction> restrictions) {
+    public void writeRestrictions(String oakPath, Tree aceTree, Set<Restriction> restrictions) throws AccessDeniedException {
         // validation of the restrictions is delegated to the commit hook
         // see #validateRestrictions below
         if (!restrictions.isEmpty()) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java Tue Jul 23 13:28:41 2013
@@ -30,6 +30,7 @@ import java.util.List;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.jcr.AccessDeniedException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
@@ -68,11 +69,6 @@ public class NodeUtil {
     }
 
     @Nonnull
-    public NameMapper getNameMapper() {
-        return mapper;
-    }
-
-    @Nonnull
     public Tree getTree() {
         return tree;
     }
@@ -101,16 +97,42 @@ public class NodeUtil {
         return child.exists() ? new NodeUtil(child, mapper) : null;
     }
 
+    /**
+     * Adds a new child tree with the given name and primary type name.
+     * This method is a shortcut for calling {@link Tree#addChild(String)} and
+     * {@link Tree#setProperty(String, Object, org.apache.jackrabbit.oak.api.Type)}
+     * where the property name is {@link JcrConstants#JCR_PRIMARYTYPE}.
+     * Note, that this method in addition verifies if the created tree exists
+     * and is accessible in order to avoid {@link IllegalStateException} upon
+     * subsequent modification of the new child.
+     *
+     * @param name            The name of the child item.
+     * @param primaryTypeName The name of the primary node type.
+     * @return The new child node with the specified name and primary type.
+     * @throws AccessDeniedException If the child does not exist after creation.
+     */
     @Nonnull
-    public NodeUtil addChild(String name, String primaryNodeTypeName) {
+    public NodeUtil addChild(String name, String primaryTypeName) throws AccessDeniedException {
         Tree child = tree.addChild(name);
+        if (!child.exists()) {
+            throw new AccessDeniedException();
+        }
         NodeUtil childUtil = new NodeUtil(child, mapper);
-        childUtil.setName(JcrConstants.JCR_PRIMARYTYPE, primaryNodeTypeName);
+        childUtil.setName(JcrConstants.JCR_PRIMARYTYPE, primaryTypeName);
         return childUtil;
     }
 
+    /**
+     * Combination of {@link #getChild(String)} and {@link #addChild(String, String)}
+     * in case no tree exists with the specified name.
+     *
+     * @param name            The name of the child item.
+     * @param primaryTypeName The name of the primary node type.
+     * @return The new child node with the specified name and primary type.
+     * @throws AccessDeniedException If the child does not exist after creation.
+     */
     @Nonnull
-    public NodeUtil getOrAddChild(String name, String primaryTypeName) {
+    public NodeUtil getOrAddChild(String name, String primaryTypeName) throws AccessDeniedException {
         NodeUtil child = getChild(name);
         return (child != null) ? child : addChild(name, primaryTypeName);
     }
@@ -130,9 +152,11 @@ public class NodeUtil {
      * @param primaryTypeName A oak name of a primary node type that is used
      *                        to create the missing trees.
      * @return The node util of the tree at the specified {@code relativePath}.
+     * @throws AccessDeniedException If the any intermediate tree does not exist
+     *                               and cannot be created.
      */
     @Nonnull
-    public NodeUtil getOrAddTree(String relativePath, String primaryTypeName) {
+    public NodeUtil getOrAddTree(String relativePath, String primaryTypeName) throws AccessDeniedException {
         if (relativePath.indexOf('/') == -1) {
             return getOrAddChild(relativePath, primaryTypeName);
         } else {
@@ -176,8 +200,8 @@ public class NodeUtil {
      *
      * @param name The name of the property.
      * @return the boolean representation of the property state with the given
-     * name. This utility returns {@code false} if the property does not exist
-     * or is an multivalued property.
+     *         name. This utility returns {@code false} if the property does not exist
+     *         or is an multivalued property.
      */
     public boolean getBoolean(String name) {
         return TreeUtil.getBoolean(tree, name);

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/UniquePropertyTest.java Tue Jul 23 13:28:41 2013
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.oak.api;
 
-import static org.junit.Assert.fail;
-
 import java.util.UUID;
 
 import org.apache.jackrabbit.JcrConstants;
@@ -28,13 +26,15 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.junit.Test;
 
+import static org.junit.Assert.fail;
+
 /**
  * UniquePropertyTest...
  */
 public class UniquePropertyTest {
 
     @Test
-    public void testUniqueness() throws CommitFailedException {
+    public void testUniqueness() throws Exception {
 
         Root root = new Oak()
                 .with(new OpenSecurityProvider())
@@ -42,7 +42,7 @@ public class UniquePropertyTest {
                 .with(new InitialContent()).createRoot();
 
         NodeUtil node = new NodeUtil(root.getTree("/"));
-        String uuid =  UUID.randomUUID().toString();
+        String uuid = UUID.randomUUID().toString();
         node.setString(JcrConstants.JCR_UUID, uuid);
         root.commit();
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidatorTest.java Tue Jul 23 13:28:41 2013
@@ -18,6 +18,8 @@ package org.apache.jackrabbit.oak.securi
 
 import java.security.Principal;
 
+import javax.jcr.AccessDeniedException;
+
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -71,7 +73,7 @@ public class AccessControlValidatorTest 
         return new NodeUtil(root.getTree(testPath));
     }
 
-    private NodeUtil createAcl() {
+    private NodeUtil createAcl() throws AccessDeniedException {
         NodeUtil testRoot = getTestRoot();
         testRoot.setNames(JcrConstants.JCR_MIXINTYPES, MIX_REP_ACCESS_CONTROLLABLE);
 
@@ -81,7 +83,7 @@ public class AccessControlValidatorTest 
         return acl;
     }
 
-    private static NodeUtil createACE(NodeUtil acl, String aceName, String ntName, String principalName, String... privilegeNames) {
+    private static NodeUtil createACE(NodeUtil acl, String aceName, String ntName, String principalName, String... privilegeNames) throws AccessDeniedException {
         NodeUtil ace = acl.addChild(aceName, ntName);
         ace.setString(REP_PRINCIPAL_NAME, principalName);
         ace.setNames(REP_PRIVILEGES, privilegeNames);
@@ -89,7 +91,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testPolicyWithOutChildOrder() {
+    public void testPolicyWithOutChildOrder() throws AccessDeniedException {
         NodeUtil testRoot = getTestRoot();
         testRoot.setNames(JcrConstants.JCR_MIXINTYPES, MIX_REP_ACCESS_CONTROLLABLE);
         testRoot.addChild(REP_POLICY, NT_REP_ACL);
@@ -119,7 +121,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testAddInvalidRepoPolicy() {
+    public void testAddInvalidRepoPolicy() throws Exception {
         NodeUtil testRoot = getTestRoot();
         testRoot.setNames(JcrConstants.JCR_MIXINTYPES, MIX_REP_ACCESS_CONTROLLABLE);
         NodeUtil policy = getTestRoot().addChild(REP_REPO_POLICY, NT_REP_ACL);
@@ -135,7 +137,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testAddPolicyWithAcContent() {
+    public void testAddPolicyWithAcContent() throws Exception {
         NodeUtil acl = createAcl();
         NodeUtil ace = acl.getChild(aceName);
 
@@ -155,7 +157,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testAddRepoPolicyWithAcContent() {
+    public void testAddRepoPolicyWithAcContent() throws Exception {
         NodeUtil acl = createAcl();
         NodeUtil ace = acl.getChild(aceName);
 
@@ -175,7 +177,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testAddAceWithAcContent() {
+    public void testAddAceWithAcContent() throws Exception {
         NodeUtil acl = createAcl();
         NodeUtil ace = acl.getChild(aceName);
 
@@ -195,7 +197,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testAddRestrictionWithAcContent() {
+    public void testAddRestrictionWithAcContent() throws Exception {
         NodeUtil acl = createAcl();
         NodeUtil ace = acl.getChild(aceName);
 
@@ -215,7 +217,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testAddIsolatedPolicy() {
+    public void testAddIsolatedPolicy() throws Exception {
         String[] policyNames = new String[]{"isolatedACL", REP_POLICY, REP_REPO_POLICY};
         NodeUtil node = getTestRoot();
 
@@ -236,7 +238,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testAddIsolatedAce() {
+    public void testAddIsolatedAce() throws Exception {
         String[] ntNames = new String[]{NT_REP_DENY_ACE, NT_REP_GRANT_ACE};
         NodeUtil node = getTestRoot();
 
@@ -256,7 +258,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testAddIsolatedRestriction() {
+    public void testAddIsolatedRestriction() throws Exception {
         NodeUtil node = getTestRoot();
         NodeUtil restriction = node.addChild("isolatedRestriction", NT_REP_RESTRICTIONS);
         try {
@@ -272,7 +274,7 @@ public class AccessControlValidatorTest 
     }
 
     @Test
-    public void testInvalidPrivilege() {
+    public void testInvalidPrivilege() throws Exception {
         NodeUtil acl = createAcl();
 
         String privName = "invalidPrivilegeName";

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImplTest.java Tue Jul 23 13:28:41 2013
@@ -73,13 +73,13 @@ public class RestrictionProviderImplTest
                 assertEquals(Type.NAMES, def.getRequiredType());
                 assertFalse(def.isMandatory());
             } else {
-                fail("unexpected restriction "+def.getName());
+                fail("unexpected restriction " + def.getName());
             }
         }
     }
 
     @Test
-    public void testGetRestrictionPattern() {
+    public void testGetRestrictionPattern() throws Exception {
         Map<PropertyState, RestrictionPattern> map = newHashMap();
         map.put(PropertyStates.createProperty(REP_GLOB, "/*/jcr:content"), GlobPattern.create("/testPath", "/*/jcr:content"));
         List<String> ntNames = ImmutableList.of(JcrConstants.NT_FOLDER, JcrConstants.NT_LINKEDFILE);

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java?rev=1506037&r1=1506036&r2=1506037&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/UserManagementTest.java Tue Jul 23 13:28:41 2013
@@ -21,6 +21,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import javax.jcr.AccessDeniedException;
+import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.query.Query;
 import javax.jcr.security.AccessControlEntry;
@@ -32,7 +33,9 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.apache.jackrabbit.util.Text;
@@ -43,8 +46,8 @@ import org.junit.Test;
  * Testing permission evaluation for user management operations.
  *
  * @since OAK 1.0 As of OAK user mgt related operations require a specific
- * user management permission (unless the system in configured to behave like
- * jackrabbit 2x).
+ *        user management permission (unless the system in configured to behave like
+ *        jackrabbit 2x).
  */
 public class UserManagementTest extends AbstractEvaluationTest {
 
@@ -132,7 +135,7 @@ public class UserManagementTest extends 
     @Test
     public void testCreateUser2() throws Exception {
         UserManager testUserMgr = getUserManager(testSession);
-        Privilege[] privs = privilegesFromNames(new String[] {PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+        Privilege[] privs = privilegesFromNames(new String[]{PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
         allow("/", privs);
 
         // creating user should succeed
@@ -153,7 +156,7 @@ public class UserManagementTest extends 
     @Test
     public void testCreateGroup2() throws Exception {
         UserManager testUserMgr = getUserManager(testSession);
-        Privilege[] privs = privilegesFromNames(new String[] {PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+        Privilege[] privs = privilegesFromNames(new String[]{PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
         allow("/", privs);
 
         // creating group should succeed
@@ -162,6 +165,71 @@ public class UserManagementTest extends 
     }
 
     @Test
+    public void testCreateWithoutReadAccess() throws Exception {
+        UserManager testUserMgr = getUserManager(testSession);
+        deny("/", privilegesFromName(PrivilegeConstants.JCR_READ));
+        allow("/", privilegesFromName(PrivilegeConstants.REP_USER_MANAGEMENT));
+
+        try {
+            Group gr = testUserMgr.createGroup(groupId);
+            testSession.save();
+            fail("Creating group without read-access on the folder node should fail");
+        } catch (AccessDeniedException e) {
+            // success
+        }
+    }
+
+    @Test
+    public void testCreateWithIntermediateReadDeny() throws Exception {
+        String path = UserConstants.DEFAULT_GROUP_PATH + "/a/b/c";
+        Node groupRoot = JcrUtils.getOrCreateByPath(path, UserConstants.NT_REP_AUTHORIZABLE_FOLDER, superuser);
+        superuser.save();
+
+        try {
+            deny(UserConstants.DEFAULT_GROUP_PATH, privilegesFromName(Privilege.JCR_READ));
+
+            Privilege[] privs = privilegesFromNames(new String[]{Privilege.JCR_READ, PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+            allow(path, privs);
+
+            Group gr = getUserManager(testSession).createGroup(groupId, new PrincipalImpl(groupId), "a/b/c");
+            testSession.save();
+        } finally {
+            superuser.refresh(false);
+            superuser.getNode(UserConstants.DEFAULT_GROUP_PATH + "/a").remove();
+            JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, UserConstants.DEFAULT_GROUP_PATH);
+            if (acl != null) {
+                acMgr.removePolicy(UserConstants.DEFAULT_GROUP_PATH, acl);
+            }
+            superuser.save();
+        }
+    }
+
+    @Test
+    public void testCreateWithIntermediateReadDeny2() throws Exception {
+        String path = UserConstants.DEFAULT_GROUP_PATH + "/a";
+        JcrUtils.getOrCreateByPath(path, UserConstants.NT_REP_AUTHORIZABLE_FOLDER, superuser);
+        superuser.save();
+
+        try {
+            deny(UserConstants.DEFAULT_GROUP_PATH, privilegesFromName(Privilege.JCR_READ));
+
+            Privilege[] privs = privilegesFromNames(new String[]{Privilege.JCR_READ, PrivilegeConstants.REP_USER_MANAGEMENT, PrivilegeConstants.REP_WRITE});
+            allow(path, privs);
+
+            Group gr = getUserManager(testSession).createGroup(groupId, new PrincipalImpl(groupId), "a/b/c");
+            testSession.save();
+        } finally {
+            superuser.refresh(false);
+            superuser.getNode(UserConstants.DEFAULT_GROUP_PATH + "/a").remove();
+            JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, UserConstants.DEFAULT_GROUP_PATH);
+            if (acl != null) {
+                acMgr.removePolicy(UserConstants.DEFAULT_GROUP_PATH, acl);
+            }
+            superuser.save();
+        }
+    }
+
+    @Test
     public void testChangePasswordWithoutPermission() throws Exception {
         createUser(userId);
 
@@ -297,7 +365,7 @@ public class UserManagementTest extends 
         createUser(userId);
 
         // testSession has user-mgt permission -> removal should succeed.
-        Privilege[] privs = privilegesFromNames(new String[] {
+        Privilege[] privs = privilegesFromNames(new String[]{
                 PrivilegeConstants.REP_USER_MANAGEMENT,
                 PrivilegeConstants.REP_WRITE});
         allow("/", privs);
@@ -364,8 +432,8 @@ public class UserManagementTest extends 
 
     /**
      * @see <a href="https://issues.apache.org/jira/browse/JCR-3412">JCR-3412 :
-     * UserManager.findAuthorizables() does not work, if session does not have
-     * read access to common root of all user and groups. </a>
+     *      UserManager.findAuthorizables() does not work, if session does not have
+     *      read access to common root of all user and groups. </a>
      */
     @Test
     public void testFindAuthorizables() throws Exception {