jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r1335373 - /jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/
Date Tue, 08 May 2012 07:55:59 GMT
Author: angela
Date: Tue May  8 07:55:58 2012
New Revision: 1335373

URL: http://svn.apache.org/viewvc?rev=1335373&view=rev
Log:
OAK-50 : User management (WIP)

Added:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableIterator.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableTypePredicate.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/InheritingAuthorizableIterator.java
Modified:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/MembershipManager.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/diff.txt

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableImpl.java?rev=1335373&r1=1335372&r2=1335373&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableImpl.java
Tue May  8 07:55:58 2012
@@ -50,6 +50,7 @@ abstract class AuthorizableImpl implemen
     static final String NT_REP_AUTHORIZABLE = "rep:Authorizable";
     static final String NT_REP_USER = "rep:User";
     static final String NT_REP_GROUP = "rep:Group";
+    static final String NT_REP_MEMBERS = "rep:Members";
     static final String REP_PRINCIPAL_NAME = "rep:principalName";
     static final String REP_PASSWORD = "rep:password";
     static final String REP_DISABLED = "rep:disabled";
@@ -414,10 +415,6 @@ abstract class AuthorizableImpl implemen
         }
 
         MembershipManager membershipManager = userManager.getMembershipManager();
-        if (includeInherited) {
-            return membershipManager.getMembership(this);
-        } else {
-            return membershipManager.getDeclaredMembership(this);
-        }
+        return membershipManager.getMembership(this, includeInherited);
     }
 }
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableIterator.java?rev=1335373&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableIterator.java
(added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableIterator.java
Tue May  8 07:55:58 2012
@@ -0,0 +1,122 @@
+/*
+ * 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.jackrabbit.oak.jcr.security.user;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.commons.flat.PropertySequence;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * AuthorizableIterator...
+ */
+class AuthorizableIterator implements Iterator {
+
+    private static final Logger log = LoggerFactory.getLogger(AuthorizableIterator.class);
+
+    private final Iterator<?> nodeIds;
+    private final AuthorizableTypePredicate predicate;
+    private final UserManagerImpl userManager;
+    private final long size;
+
+    private Authorizable next;
+
+    AuthorizableIterator(Value[] authorizableNodeIds, int authorizableType, UserManagerImpl
userManager) {
+        this(Arrays.asList(authorizableNodeIds).iterator(), authorizableType, userManager,
authorizableNodeIds.length);
+    }
+
+    AuthorizableIterator(PropertySequence authorizableNodeIds, int authorizableType, UserManagerImpl
userManager) {
+        this(authorizableNodeIds.iterator(), authorizableType, userManager, -1);  // TODO
calculate size here
+    }
+
+    AuthorizableIterator(PropertyIterator authorizableNodeIds, int authorizableType, UserManagerImpl
userManager) {
+        this(authorizableNodeIds, authorizableType, userManager, authorizableNodeIds.getSize());
+    }
+
+    private AuthorizableIterator(Iterator<?> nodeIds, int authorizableType,
+                                 UserManagerImpl userManager, long size) {
+        this.nodeIds = nodeIds;
+        this.predicate = new AuthorizableTypePredicate(authorizableType);
+        this.userManager = userManager;
+        this.size = size;
+
+        next = fetchNext();
+    }
+
+    //-----------------------------------------------------------< Iterator >---
+    @Override
+    public boolean hasNext() {
+        return next != null;
+    }
+
+    @Override
+    public Authorizable next() {
+        if (next == null) {
+            throw new NoSuchElementException();
+        }
+
+        Authorizable a = next;
+        next = fetchNext();
+        return a;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+    //--------------------------------------------------------------------------
+    long getSize() {
+        return size;
+    }
+
+    private Authorizable fetchNext() {
+        while (nodeIds.hasNext()) {
+            try {
+                String nid = getNodeId(nodeIds.next());
+                Node n = userManager.getSession().getNodeByIdentifier(nid);
+                Authorizable a = userManager.getAuthorizable(n);
+                if (a != null && predicate.evaluate(a)) {
+                    return a;
+                }
+            } catch (RepositoryException e) {
+                log.debug(e.getMessage());
+            }
+        }
+
+        return null;
+    }
+
+    private static String getNodeId(Object o) throws RepositoryException {
+        if (o instanceof Value) {
+            return ((Value) o).getString();
+        } else if (o instanceof Property) {
+            return ((Property) o).getString();
+        } else {
+            return o.toString();
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableTypePredicate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableTypePredicate.java?rev=1335373&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableTypePredicate.java
(added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/AuthorizableTypePredicate.java
Tue May  8 07:55:58 2012
@@ -0,0 +1,59 @@
+/*
+ * 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.jackrabbit.oak.jcr.security.user;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.commons.predicate.Predicate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * AuthorizableTypePredicate...
+ */
+class AuthorizableTypePredicate implements Predicate {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(AuthorizableTypePredicate.class);
+
+    private final int authorizableType;
+
+    AuthorizableTypePredicate(int authorizableType) {
+        this.authorizableType = authorizableType;
+    }
+
+    @Override
+    public boolean evaluate(Object object) {
+        if (object instanceof Authorizable) {
+            Authorizable a = (Authorizable) object;
+            switch (authorizableType) {
+            case UserManager.SEARCH_TYPE_AUTHORIZABLE:
+                return true;
+            case UserManager.SEARCH_TYPE_GROUP:
+                return a.isGroup();
+            case UserManager.SEARCH_TYPE_USER:
+                return !a.isGroup();
+            default:
+                log.warn("Illegal authorizable type " + authorizableType);
+                return false;
+        }
+        }
+        return false;
+    }
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImpl.java?rev=1335373&r1=1335372&r2=1335373&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImpl.java
Tue May  8 07:55:58 2012
@@ -118,15 +118,20 @@ class GroupImpl extends AuthorizableImpl
         if (authorizableImpl.isGroup()) {
             if (getID().equals(authorizableImpl.getID())) {
                 String msg = "Attempt to add a group as member of itself (" + getID() + ").";
-                log.warn(msg);
+                log.debug(msg);
                 return false;
             }
             if (((Group) authorizableImpl).isMember(this)) {
-                log.warn("Attempt to create circular group membership.");
+                log.debug("Attempt to create circular group membership.");
                 return false;
             }
         }
 
+        if (isDeclaredMember(authorizable)) {
+            log.debug("Authorizable {} is already declared member of {}", authorizable.getID(),
getID());
+            return false;
+        }
+
         return getUserManager().getMembershipManager().addMember(this, authorizableImpl);
     }
 
@@ -141,9 +146,9 @@ class GroupImpl extends AuthorizableImpl
         }
         if (isEveryone()) {
             return false;
+        } else {
+            return getUserManager().getMembershipManager().removeMember(this, (AuthorizableImpl)
authorizable);
         }
-
-        return getUserManager().getMembershipManager().removeMember(this, (AuthorizableImpl)
authorizable);
     }
 
     //--------------------------------------------------------------------------
@@ -158,10 +163,9 @@ class GroupImpl extends AuthorizableImpl
     private Iterator<Authorizable> getMembers(boolean includeInherited) throws RepositoryException
{
         if (isEveryone()) {
             return getUserManager().findAuthorizables(AuthorizableImpl.REP_PRINCIPAL_NAME,
null, UserManager.SEARCH_TYPE_AUTHORIZABLE);
-        } else if (includeInherited) {
-            return getUserManager().getMembershipManager().getMembers(this);
         } else {
-            return getUserManager().getMembershipManager().getDeclaredMembers(this);
+            MembershipManager mMgr = getUserManager().getMembershipManager();
+            return mMgr.getMembers(this, UserManager.SEARCH_TYPE_AUTHORIZABLE, includeInherited);
         }
     }
 
@@ -178,14 +182,15 @@ class GroupImpl extends AuthorizableImpl
     private boolean isMember(Authorizable authorizable, boolean includeInherited) throws
RepositoryException {
         if (!isValidAuthorizableImpl(authorizable)) {
             return false;
-        } else if (getNode().isSame(((AuthorizableImpl) authorizable).getNode())) {
-            return false;
-        } else if (isEveryone()) {
+        }
+
+        if (isEveryone()) {
             return true;
-        } else if (includeInherited) {
-            return getUserManager().getMembershipManager().hasMember(this, (AuthorizableImpl)
authorizable);
+        } else if (getID().equals(authorizable.getID())) {
+            return false;
         } else {
-            return getUserManager().getMembershipManager().hasDeclaredMember(this, (AuthorizableImpl)
authorizable);
+            AuthorizableImpl authorizableImpl = (AuthorizableImpl) authorizable;
+            return getUserManager().getMembershipManager().isMember(this, authorizableImpl,
includeInherited);
         }
     }
 

Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/InheritingAuthorizableIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/InheritingAuthorizableIterator.java?rev=1335373&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/InheritingAuthorizableIterator.java
(added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/InheritingAuthorizableIterator.java
Tue May  8 07:55:58 2012
@@ -0,0 +1,64 @@
+/*
+ * 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.jackrabbit.oak.jcr.security.user;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.commons.iterator.FilterIterator;
+import org.apache.jackrabbit.commons.iterator.LazyIteratorChain;
+import org.apache.jackrabbit.commons.predicate.Predicate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.RepositoryException;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * InheritingAuthorizableIterator...
+ */
+public class InheritingAuthorizableIterator<T extends Authorizable> extends FilterIterator
{
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(InheritingAuthorizableIterator.class);
+
+    InheritingAuthorizableIterator(Iterator<Iterator<T>> inheritingIterator)
{
+        super(new LazyIteratorChain<T>(inheritingIterator), new ProcessedIdPredicate());
+    }
+
+    /**
+     *
+     */
+    private static final class ProcessedIdPredicate implements Predicate {
+
+        private final HashSet<String> processedIds = new HashSet<String>();
+
+        @Override
+        public boolean evaluate(Object object) {
+            if (object instanceof Group) {
+                try {
+                    return processedIds.add(((Group) object).getID());
+                } catch (RepositoryException e) {
+                    // TODO
+                }
+            }
+            return false;
+        }
+    }
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/MembershipManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/MembershipManager.java?rev=1335373&r1=1335372&r2=1335373&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/MembershipManager.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/MembershipManager.java
Tue May  8 07:55:58 2012
@@ -16,14 +16,32 @@
  */
 package org.apache.jackrabbit.oak.jcr.security.user;
 
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.IteratorChain;
+import org.apache.commons.collections.iterators.SingletonIterator;
 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.jackrabbit.commons.flat.BTreeManager;
+import org.apache.jackrabbit.commons.flat.ItemSequence;
+import org.apache.jackrabbit.commons.flat.PropertySequence;
+import org.apache.jackrabbit.commons.flat.Rank;
+import org.apache.jackrabbit.commons.flat.TreeManager;
+import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
 import org.apache.jackrabbit.oak.jcr.SessionDelegate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  * MembershipManager...
@@ -34,49 +52,245 @@ class MembershipManager {
 
     private final UserManagerImpl userManager;
     private final SessionDelegate sessionDelegate;
+    private final int memberSplitSize;
 
-    MembershipManager(UserManagerImpl userManager, SessionDelegate sessionDelegate) {
+    private final String repMembers;
+
+    MembershipManager(UserManagerImpl userManager, int memberSplitSize, SessionDelegate sessionDelegate)
{
         this.userManager = userManager;
         this.sessionDelegate = sessionDelegate;
-    }
+        this.memberSplitSize = memberSplitSize;
 
-    Iterator<Group> getDeclaredMembership(AuthorizableImpl authorizable) throws RepositoryException
{
-        // TODO
-        return null;
+        repMembers = sessionDelegate.getNamePathMapper().getJcrName(AuthorizableImpl.REP_MEMBERS);
     }
 
-    Iterator<Group> getMembership(AuthorizableImpl authorizable) throws RepositoryException
{
-        // TODO
-        return null;
+    Iterator<Group> getMembership(AuthorizableImpl authorizable, boolean includeInherited)
throws RepositoryException {
+        PropertyIterator refs = null;
+        try {
+            String nodeID = authorizable.getNode().getIdentifier();
+            refs = authorizable.getNode().getWeakReferences(null);
+        } catch (RepositoryException e) {
+            log.error("Failed to retrieve membership references of " + authorizable.getID(),
e);
+            // TODO retrieve by traversing
+        }
+
+        if (refs != null) {
+            AuthorizableIterator iterator = new AuthorizableIterator(refs, UserManager.SEARCH_TYPE_GROUP,
userManager);
+            if (includeInherited) {
+                return getAllMembership(iterator);
+            } else {
+                return new RangeIteratorAdapter(iterator, iterator.getSize());
+            }
+        } else {
+            return RangeIteratorAdapter.EMPTY;
+        }
+
     }
 
-    boolean hasDeclaredMember(GroupImpl group, AuthorizableImpl authorizable) throws RepositoryException
{
-        // TODO
+    boolean isMember(GroupImpl group, AuthorizableImpl authorizable, boolean includeInherited)
throws RepositoryException {
+        Node node = group.getNode();
+
+        if (includeInherited) {
+            Iterator<Group> groups = getMembership(authorizable, true);
+            String id = group.getID();
+            while (groups.hasNext()) {
+                if (id.equals(groups.next().getID())) {
+                    return true;
+                }
+            }
+        } else {
+            if (useMemberNode(node)) {
+                if (node.hasNode(repMembers)) {
+                    // TODO: fix.. testing for property name isn't correct.
+                    PropertySequence propertySequence = getPropertySequence(node.getNode(repMembers));
+                    return propertySequence.hasItem(authorizable.getID());
+                }
+            } else {
+                if (node.hasProperty(repMembers)) {
+                    Value[] members = node.getProperty(repMembers).getValues();
+                    for (Value v : members) {
+                        if (authorizable.getNode().getIdentifier().equals(v.getString()))
{
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        // no a member of the specified group
         return false;
     }
 
-    boolean hasMember(GroupImpl group, AuthorizableImpl authorizable) throws RepositoryException
{
-        // TODO
+    Iterator<Authorizable> getMembers(GroupImpl group, int authorizableType,
+                                      boolean includeInherited) throws RepositoryException
{
+        Node node = group.getNode();
+        AuthorizableIterator iterator = null;
+        if (useMemberNode(node)) {
+            if (node.hasNode(repMembers)) {
+                PropertySequence propertySequence = getPropertySequence(node.getNode(repMembers));
+                iterator = new AuthorizableIterator(propertySequence, authorizableType, userManager);
+            }
+        } else {
+            if (node.hasProperty(repMembers)) {
+                Value[] members = node.getProperty(repMembers).getValues();
+                iterator = new AuthorizableIterator(members, authorizableType, userManager);
+            }
+        }
+
+        if (iterator != null) {
+            if (includeInherited) {
+                return getAllMembers(iterator, authorizableType);
+            } else {
+                return new RangeIteratorAdapter(iterator, iterator.getSize());
+            }
+        } else {
+            return RangeIteratorAdapter.EMPTY;
+        }
+    }
+
+    boolean addMember(GroupImpl group, AuthorizableImpl authorizable) throws RepositoryException
{
+        Node node = group.getNode();
+        if (useMemberNode(node)) {
+            // TODO: modify items on oak-api directly
+        } else {
+            Node memberNode = authorizable.getNode();
+            Value[] values;
+            Value toAdd = sessionDelegate.getValueFactory().createValue(memberNode, true);
+            if (node.hasProperty(repMembers)) {
+                Value[] old = node.getProperty(repMembers).getValues();
+                values = new Value[old.length + 1];
+                System.arraycopy(old, 0, values, 0, old.length);
+            } else {
+                values = new Value[1];
+            }
+            values[values.length - 1] = toAdd;
+
+            userManager.setInternalProperty(node, repMembers, values);
+        }
+        return true;
+    }
+
+    boolean removeMember(GroupImpl group, AuthorizableImpl authorizable) throws RepositoryException
{
+        Node node = group.getNode();
+
+        if (useMemberNode(node)) {
+            if (node.hasNode(repMembers)) {
+                Node nMembers = node.getNode(repMembers);
+                PropertySequence properties = getPropertySequence(nMembers);
+                String propName = authorizable.getNode().getName();
+                // TODO: fix.. testing for property name isn't correct.
+                if (properties.hasItem(propName)) {
+                    Property p = properties.getItem(propName);
+                    userManager.removeInternalProperty(p.getParent(), propName);
+                }
+                return true;
+            }
+        } else {
+            if (node.hasProperty(repMembers)) {
+                Value toRemove = sessionDelegate.getValueFactory().createValue((authorizable).getNode(),
true);
+                Property property = node.getProperty(repMembers);
+                List<Value> valList = new ArrayList<Value>(Arrays.asList(property.getValues()));
+
+                if (valList.remove(toRemove)) {
+                    if (valList.isEmpty()) {
+                        userManager.removeInternalProperty(node, repMembers);
+                    } else {
+                        Value[] values = valList.toArray(new Value[valList.size()]);
+                        userManager.setInternalProperty(node, repMembers, values);
+                    }
+                    return true;
+                }
+            }
+        }
+
+        // nothing changed
+        log.debug("Authorizable {} was not member of {}", authorizable.getID(), group.getID());
         return false;
     }
 
-    Iterator<Authorizable> getDeclaredMembers(GroupImpl group) throws RepositoryException
{
-        // TODO
-        return null;
+    //--------------------------------------------------------------------------
+    private boolean useMemberNode(Node n) throws RepositoryException {
+        return memberSplitSize >= 4 && !n.hasProperty(repMembers);
     }
 
-    Iterator<Authorizable> getMembers(GroupImpl group) throws RepositoryException {
-        // TODO
-        return null;
+    private PropertySequence getPropertySequence(Node nMembers) throws RepositoryException
{
+        Comparator<String> order = Rank.comparableComparator();
+        int minChildren = memberSplitSize / 2;
+        TreeManager treeManager = new BTreeManager(nMembers, minChildren, memberSplitSize,
order, false);
+        return ItemSequence.createPropertySequence(treeManager);
     }
 
-    boolean addMember(GroupImpl group, AuthorizableImpl authorizable) throws RepositoryException
{
-       // todo
-        return false;
+    /**
+     * Returns an iterator of authorizables which includes all indirect members
+     * of the given iterator of authorizables.
+     *
+     * @param authorizables
+     * @param authorizableType
+     * @return Iterator of Authorizable objects
+     */
+    private Iterator<Authorizable> getAllMembers(final Iterator<Authorizable>
authorizables,
+                                                 final int authorizableType) {
+        Iterator<Iterator<Authorizable>> inheritedMembers = new Iterator<Iterator<Authorizable>>()
{
+            @Override
+            public boolean hasNext() {
+                return authorizables.hasNext();
+            }
+
+            @Override
+            public Iterator<Authorizable> next() {
+                Authorizable next = authorizables.next();
+                return new IteratorChain(new SingletonIterator(next), inherited(next));
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+
+            private Iterator<Authorizable> inherited(Authorizable authorizable) {
+                if (authorizable.isGroup()) {
+                    try {
+                        return getMembers(((GroupImpl) authorizable), authorizableType, true);
+                    } catch (RepositoryException e) {
+                        log.warn("Could not determine members of " + authorizable, e);
+                    }
+                }
+                return EmptyIterator.INSTANCE;
+            }
+        };
+
+        return new InheritingAuthorizableIterator(inheritedMembers);
     }
 
-    boolean removeMember(GroupImpl group, AuthorizableImpl authorizable) throws RepositoryException
{
-        // todo
-        return false;
+    private Iterator<Group> getAllMembership(final AuthorizableIterator membership)
{
+        Iterator<Iterator<Group>> inheritedMembership = new Iterator<Iterator<Group>>()
{
+            @Override
+            public boolean hasNext() {
+                return membership.hasNext();
+            }
+
+            @Override
+            public Iterator<Group> next() {
+                Group next = (Group) membership.next();
+                return new IteratorChain(new SingletonIterator(next), inherited((AuthorizableImpl)
next));
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+
+            private Iterator<Group> inherited(AuthorizableImpl authorizable) {
+                if (authorizable.isGroup()) {
+                    try {
+                        return getMembership(authorizable, true);
+                    } catch (RepositoryException e) {
+                        log.warn("Could not determine members of " + authorizable, e);
+                    }
+                }
+                return EmptyIterator.INSTANCE;
+            }
+        };
+
+        return new InheritingAuthorizableIterator(inheritedMembership);
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java?rev=1335373&r1=1335372&r2=1335373&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerConfig.java
Tue May  8 07:55:58 2012
@@ -30,6 +30,17 @@ public class UserManagerConfig {
     private static final Logger log = LoggerFactory.getLogger(UserManagerImpl.class);
 
     /**
+     * If this parameter is present group members are collected in a node
+     * structure below a {@link AuthorizableImpl#REP_MEMBERS} node instead of the
+     * default multi valued property {@link AuthorizableImpl#REP_MEMBERS}.
+     * Its value determines the maximum number of member properties until
+     * additional intermediate nodes are inserted. Valid values are integers
+     * &gt; 4. The default value is 0 and indicates that the
+     * {@link AuthorizableImpl#REP_MEMBERS} property is used to record group members.
+     */
+    public static final String PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE = "groupMembershipSplitSize";
+
+    /**
      * Configuration parameter to change the default algorithm used to generate
      * password hashes. The default value is {@link PasswordUtility#DEFAULT_ALGORITHM}.
      */

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java?rev=1335373&r1=1335372&r2=1335373&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/UserManagerImpl.java
Tue May  8 07:55:58 2012
@@ -36,6 +36,7 @@ import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
 import java.io.UnsupportedEncodingException;
 import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
@@ -342,6 +343,11 @@ public class UserManagerImpl implements 
         sessionDelegate.getNode(getInternalPath(userNode)).setProperty(name, cvs);
     }
 
+    void setInternalProperty(Node userNode, String name, Value[] values) throws RepositoryException
{
+        List<CoreValue> cvs = ValueConverter.toCoreValues(values, sessionDelegate);
+        sessionDelegate.getNode(getInternalPath(userNode)).setProperty(name, cvs);
+    }
+
     void removeInternalProperty(Node userNode, String name) throws RepositoryException {
         sessionDelegate.getNode(getInternalPath(userNode)).getProperty(name).remove();
     }
@@ -352,12 +358,17 @@ public class UserManagerImpl implements 
 
     MembershipManager getMembershipManager() {
         if (membershipManager == null) {
-            membershipManager = new MembershipManager(this, sessionDelegate);
+            int splitSize = config.getConfigValue(UserManagerConfig.PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE,
0);
+            if (splitSize < 4) {
+                log.warn("Invalid value {} for {}. Expected integer >= 4", splitSize,
UserManagerConfig.PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE);
+                splitSize = 0;
+            }
+            membershipManager = new MembershipManager(this, splitSize, sessionDelegate);
         }
         return membershipManager;
     }
 
-    private Authorizable getAuthorizable(Node node) throws RepositoryException {
+    Authorizable getAuthorizable(Node node) throws RepositoryException {
         if (node.isNodeType(AuthorizableImpl.NT_REP_USER)) {
             return new UserImpl(node, this);
         } else if (node.isNodeType(AuthorizableImpl.NT_REP_GROUP)) {

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/diff.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/diff.txt?rev=1335373&r1=1335372&r2=1335373&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/diff.txt
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/security/user/diff.txt
Tue May  8 07:55:58 2012
@@ -18,7 +18,6 @@ UserManager:
 Authorizable:
 - setProperty, removeProperty executes no extra shortcut check for protected properties
 - not relying on rep:principalName to exist -> using ID as fallback
--
 
 User:
 
@@ -32,6 +31,7 @@ TODO:
 
 - Configuration based on oak-core implementation
 
+- check if node type definition with rep:members child node and/or rep:members child prop
still works.
 
 
 



Mime
View raw message