Package org.apache.jackrabbit.oak.jcr.security.user

Source Code of org.apache.jackrabbit.oak.jcr.security.user.MembershipManager

/*
* 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.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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Iterators;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

/**
* MembershipManager...
*/
class MembershipManager {

    private static final Logger log = LoggerFactory.getLogger(MembershipManager.class);

    private final UserManagerImpl userManager;
    private final ValueFactory valueFactory;
    private final int memberSplitSize;

    private final String repMembers;

    MembershipManager(UserManagerImpl userManager, int memberSplitSize, ValueFactory valueFactory) {
        this.userManager = userManager;
        this.valueFactory = valueFactory;
        this.memberSplitSize = memberSplitSize;

        repMembers = userManager.getJcrName(UserConstants.REP_MEMBERS);
    }

    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 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;
    }

    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 = valueFactory.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 = valueFactory.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;
    }

    //--------------------------------------------------------------------------
    private boolean useMemberNode(Node n) throws RepositoryException {
        return memberSplitSize >= 4 && !n.hasProperty(repMembers);
    }

    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);
    }

    /**
     * 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 Iterators.concat(
                        Iterators.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 Iterators.emptyIterator();
            }
        };

        return new InheritingAuthorizableIterator(inheritedMembers);
    }

    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 Iterators.concat(
                        Iterators.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 Iterators.emptyIterator();
            }
        };

        return new InheritingAuthorizableIterator(inheritedMembership);
    }
}
TOP

Related Classes of org.apache.jackrabbit.oak.jcr.security.user.MembershipManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.