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
+ * > 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.