Package org.apache.jackrabbit.oak.security.authorization.permission

Source Code of org.apache.jackrabbit.oak.security.authorization.permission.CompiledPermissionImpl$DefaultReadPolicy

/*
* 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.security.authorization.permission;

import java.security.Principal;
import java.security.acl.Group;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.core.ImmutableRoot;
import org.apache.jackrabbit.oak.core.ImmutableTree;
import org.apache.jackrabbit.oak.core.TreeTypeProvider;
import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
import org.apache.jackrabbit.oak.plugins.version.VersionConstants;
import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.util.AbstractLazyIterator;
import org.apache.jackrabbit.oak.util.TreeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;

import static com.google.common.collect.Iterators.concat;

/**
* TODO: WIP
* FIXME: decide on where to filter out hidden items (OAK-753)
*/
final class CompiledPermissionImpl implements CompiledPermissions, PermissionConstants {

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

    private static final Map<Long, PrivilegeBits> READ_BITS = ImmutableMap.of(
            Permissions.READ, PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ),
            Permissions.READ_NODE, PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_READ_NODES),
            Permissions.READ_PROPERTY, PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_READ_PROPERTIES),
            Permissions.READ_ACCESS_CONTROL, PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ_ACCESS_CONTROL));

    private ImmutableRoot root;

    private final String workspaceName;

    private final ReadPolicy readPolicy;

    private PermissionStoreImpl store;
    private final PermissionEntryProvider userStore;
    private final PermissionEntryProvider groupStore;

    private PrivilegeBitsProvider bitsProvider;

    private CompiledPermissionImpl(@Nonnull PermissionEntryCache.Local cache,
                                   @Nonnull Set<Principal> principals,
                                   @Nonnull ImmutableRoot root, @Nonnull String workspaceName,
                                   @Nonnull RestrictionProvider restrictionProvider,
                                   @Nonnull Set<String> readPaths) {
        this.root = root;
        this.workspaceName = workspaceName;

        bitsProvider = new PrivilegeBitsProvider(root);
        readPolicy = (readPaths.isEmpty()) ? EmptyReadPolicy.INSTANCE : new DefaultReadPolicy(readPaths);

        // setup
        store = new PermissionStoreImpl(root, workspaceName, restrictionProvider);
        Set<String> userNames = new HashSet<String>(principals.size());
        Set<String> groupNames = new HashSet<String>(principals.size());
        for (Principal principal : principals) {
            if (principal instanceof Group) {
                groupNames.add(principal.getName());
            } else {
                userNames.add(principal.getName());
            }
        }

        userStore = new PermissionEntryProviderImpl(store, cache, userNames);
        groupStore = new PermissionEntryProviderImpl(store, cache, groupNames);
    }

    static CompiledPermissions create(@Nonnull ImmutableRoot root, @Nonnull String workspaceName,
                                      @Nonnull Set<Principal> principals,
                                      @Nonnull AuthorizationConfiguration acConfig,
                                      @Nonnull PermissionEntryCache.Local cache) {
        Tree permissionsTree = PermissionUtil.getPermissionsRoot(root, workspaceName);
        if (!permissionsTree.exists() || principals.isEmpty()) {
            return NoPermissions.getInstance();
        } else {
            Set<String> readPaths = acConfig.getParameters().getConfigValue(PARAM_READ_PATHS, DEFAULT_READ_PATHS);
            return new CompiledPermissionImpl(cache, principals, root, workspaceName, acConfig.getRestrictionProvider(), readPaths);
        }
    }

    //------------------------------------------------< CompiledPermissions >---
    @Override
    public void refresh(@Nonnull ImmutableRoot root, @Nonnull String workspaceName) {
        this.root = root;
        this.bitsProvider = new PrivilegeBitsProvider(root);
        store.flush(root);
        userStore.flush();
        groupStore.flush();
    }

    @Override
    public RepositoryPermission getRepositoryPermission() {
        return new RepositoryPermission() {
            @Override
            public boolean isGranted(long repositoryPermissions) {
                return hasPermissions(getEntryIterator(new EntryPredicate()), repositoryPermissions, null);
            }
        };
    }

    @Override
    public TreePermission getTreePermission(@Nonnull ImmutableTree tree, @Nonnull TreePermission parentPermission) {
        if (tree.isRoot()) {
            return new TreePermissionImpl(tree, TreeTypeProvider.TYPE_DEFAULT, TreePermission.EMPTY);
        }
        int type = tree.getType();
        switch (type) {
            case TreeTypeProvider.TYPE_HIDDEN:
                // TODO: OAK-753 decide on where to filter out hidden items.
                return TreePermission.ALL;
            case TreeTypeProvider.TYPE_VERSION:
                String ntName = TreeUtil.getPrimaryTypeName(tree);
                if (ntName == null) {
                    return TreePermission.EMPTY;
                }
                if (VersionConstants.VERSION_STORE_NT_NAMES.contains(ntName) || VersionConstants.NT_ACTIVITY.equals(ntName)) {
                    return new TreePermissionImpl(tree, TreeTypeProvider.TYPE_VERSION, parentPermission);
                } else {
                    ImmutableTree versionableTree = getVersionableTree(tree);
                    if (versionableTree == null) {
                        log.warn("Cannot retrieve versionable node for " + tree.getPath());
                        return TreePermission.EMPTY;
                    } else {
                        // TODO: may return wrong results in case of restrictions
                        // TODO that would match the path of the versionable node
                        // TODO (or item in the subtree) but that item no longer exists
                        // TODO -> evaluation by path would be more accurate (-> see #isGranted)
                        while (!versionableTree.exists()) {
                            versionableTree = versionableTree.getParent();
                        }
                        TreePermission pp = getParentPermission(versionableTree, TreeTypeProvider.TYPE_VERSION);
                        return new TreePermissionImpl(versionableTree, TreeTypeProvider.TYPE_VERSION, pp);
                    }
                }
            case TreeTypeProvider.TYPE_INTERNAL:
                return TreePermission.EMPTY;
            default:
                return new TreePermissionImpl(tree, type, parentPermission);
        }
    }

    @Nonnull
    private TreePermission getParentPermission(@Nonnull ImmutableTree tree, int type) {
        List<ImmutableTree> trees = new ArrayList<ImmutableTree>();
        while (!tree.isRoot()) {
            tree = tree.getParent();
            if (tree.exists()) {
                trees.add(0, tree);
            }
        }
        TreePermission pp = TreePermission.EMPTY;
        for (ImmutableTree tr : trees) {
            pp = new TreePermissionImpl(tr, type, pp);
        }
        return pp;
    }

    @Override
    public boolean isGranted(@Nonnull ImmutableTree tree, @Nullable PropertyState property, long permissions) {
        int type = PermissionUtil.getType(tree, property);
        switch (type) {
            case TreeTypeProvider.TYPE_HIDDEN:
                // TODO: OAK-753 decide on where to filter out hidden items.
                return true;
            case TreeTypeProvider.TYPE_VERSION:
                Tree versionableTree = getVersionableTree(tree);
                if (versionableTree == null) {
                    // unable to determine the location of the versionable item -> deny access.
                    return false;
                }
                if (versionableTree.exists()) {
                    return internalIsGranted(versionableTree, property, permissions);
                } else {
                    // versionable node does not exist (anymore) in this workspace;
                    // use best effort calculation based on the item path.
                    String path = versionableTree.getPath();
                    if (property != null) {
                        path = PathUtils.concat(path, property.getName());
                    }
                    return isGranted(path, permissions);
                }
            case TreeTypeProvider.TYPE_INTERNAL:
                return false;
            default:
                return internalIsGranted(tree, property, permissions);
        }
    }

    @Override
    public boolean isGranted(@Nonnull String path, long permissions) {
        Iterator<PermissionEntry> it = getEntryIterator(new EntryPredicate(path, Permissions.respectParentPermissions(permissions)));
        return hasPermissions(it, permissions, path);
    }

    @Override
    public Set<String> getPrivileges(@Nullable ImmutableTree tree) {
        return bitsProvider.getPrivilegeNames(internalGetPrivileges(tree));
    }

    @Override
    public boolean hasPrivileges(@Nullable ImmutableTree tree, @Nonnull String... privilegeNames) {
        return internalGetPrivileges(tree).includes(bitsProvider.getBits(privilegeNames));
    }

    //------------------------------------------------------------< private >---

    private boolean internalIsGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
        Iterator<PermissionEntry> it = getEntryIterator(tree, property, permissions);
        return hasPermissions(it, permissions, tree.getPath());
    }

    private boolean hasPermissions(@Nonnull Iterator<PermissionEntry> entries,
                                   long permissions, @Nullable String path) {
        // calculate readable paths if the given permissions includes any read permission.
        boolean isReadable = Permissions.diff(Permissions.READ, permissions) != Permissions.READ && readPolicy.isReadablePath(path, false);
        if (!entries.hasNext() && !isReadable) {
            return false;
        }

        boolean respectParent = (path != null) && Permissions.respectParentPermissions(permissions);

        long allows = (isReadable) ? Permissions.READ : Permissions.NO_PERMISSION;
        long denies = Permissions.NO_PERMISSION;

        PrivilegeBits allowBits = PrivilegeBits.getInstance();
        if (isReadable) {
            allowBits.add(bitsProvider.getBits(PrivilegeConstants.JCR_READ));
        }
        PrivilegeBits denyBits = PrivilegeBits.getInstance();
        PrivilegeBits parentAllowBits;
        PrivilegeBits parentDenyBits;
        String parentPath;

        if (respectParent) {
            parentAllowBits = PrivilegeBits.getInstance();
            parentDenyBits = PrivilegeBits.getInstance();
            parentPath = PermissionUtil.getParentPathOrNull(path);
        } else {
            parentAllowBits = PrivilegeBits.EMPTY;
            parentDenyBits = PrivilegeBits.EMPTY;
            parentPath = null;
        }

        while (entries.hasNext()) {
            PermissionEntry entry = entries.next();
            if (respectParent && (parentPath != null)) {
                boolean matchesParent = entry.matchesParent(parentPath);
                if (matchesParent) {
                    if (entry.isAllow) {
                        parentAllowBits.addDifference(entry.privilegeBits, parentDenyBits);
                    } else {
                        parentDenyBits.addDifference(entry.privilegeBits, parentAllowBits);
                    }
                }
            }

            if (entry.isAllow) {
                allowBits.addDifference(entry.privilegeBits, denyBits);
                long ap = PrivilegeBits.calculatePermissions(allowBits, parentAllowBits, true);
                allows |= Permissions.diff(ap, denies);
                if ((allows | ~permissions) == -1) {
                    return true;
                }
            } else {
                denyBits.addDifference(entry.privilegeBits, allowBits);
                long dp = PrivilegeBits.calculatePermissions(denyBits, parentDenyBits, false);
                denies |= Permissions.diff(dp, allows);
                if (Permissions.includes(denies, permissions)) {
                    return false;
                }
            }
        }

        return (allows | ~permissions) == -1;
    }

    @Nonnull PrivilegeBits internalGetPrivileges(@Nullable ImmutableTree tree) {
        int type = (tree == null) ? TreeTypeProvider.TYPE_DEFAULT : tree.getType();
        switch (type) {
            case TreeTypeProvider.TYPE_HIDDEN:
                return PrivilegeBits.EMPTY;
            case TreeTypeProvider.TYPE_VERSION:
                Tree versionableTree = getVersionableTree(tree);
                if (versionableTree == null || !versionableTree.exists()) {
                    // unable to determine the location of the versionable item -> deny access.
                    // TODO : add proper handling for cases where the versionable node does not exist (anymore)
                    return PrivilegeBits.EMPTY;
                else {
                    return getPrivilegeBits(versionableTree);
                }
            case TreeTypeProvider.TYPE_INTERNAL:
                return PrivilegeBits.EMPTY;
            default:
                return getPrivilegeBits(tree);
        }
    }

    @Nonnull
    private PrivilegeBits getPrivilegeBits(@Nullable Tree tree) {
        EntryPredicate pred = (tree == null)
                ? new EntryPredicate()
                : new EntryPredicate(tree, null, false);
        Iterator<PermissionEntry> entries = getEntryIterator(pred);

        PrivilegeBits allowBits = PrivilegeBits.getInstance();
        PrivilegeBits denyBits = PrivilegeBits.getInstance();

        while (entries.hasNext()) {
            PermissionEntry entry = entries.next();
            if (entry.isAllow) {
                allowBits.addDifference(entry.privilegeBits, denyBits);
            } else {
                denyBits.addDifference(entry.privilegeBits, allowBits);
            }
        }

        // special handling for paths that are always readable
        if (tree != null && readPolicy.isReadableTree(tree, false)) {
            allowBits.add(bitsProvider.getBits(PrivilegeConstants.JCR_READ));
        }
        return allowBits;
    }

    @Nonnull
    private Iterator<PermissionEntry> getEntryIterator(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
        return getEntryIterator(new EntryPredicate(tree, property, Permissions.respectParentPermissions(permissions)));
    }

    @Nonnull
    private Iterator<PermissionEntry> getEntryIterator(@Nonnull EntryPredicate predicate) {
        Iterator<PermissionEntry> userEntries = userStore.getEntryIterator(predicate);
        Iterator<PermissionEntry> groupEntries = groupStore.getEntryIterator(predicate);
        return concat(userEntries, groupEntries);
    }

    @CheckForNull
    private ImmutableTree getVersionableTree(@Nonnull ImmutableTree versionStoreTree) {
        String relPath = "";
        String versionablePath = null;
        Tree t = versionStoreTree;
        while (t.exists() && !t.isRoot() && !VersionConstants.VERSION_STORE_ROOT_NAMES.contains(t.getName())) {
            String ntName = TreeUtil.getPrimaryTypeName(t);
            if (VersionConstants.JCR_FROZENNODE.equals(t.getName()) && t != versionStoreTree) {
                relPath = PathUtils.relativize(t.getPath(), versionStoreTree.getPath());
            } else if (JcrConstants.NT_VERSIONHISTORY.equals(ntName)) {
                PropertyState prop = t.getProperty(workspaceName);
                if (prop != null) {
                    versionablePath = PathUtils.concat(prop.getValue(Type.PATH), relPath);
                }
                return (versionablePath == null) ? null : root.getTree(versionablePath);
            } else if (VersionConstants.NT_CONFIGURATION.equals(ntName)) {
                String rootId = TreeUtil.getString(t, VersionConstants.JCR_ROOT);
                if (rootId != null) {
                    versionablePath = new IdentifierManager(root).getPath(rootId);
                    return (versionablePath == null) ? null : root.getTree(versionablePath);
                } else {
                    log.error("Missing mandatory property jcr:root with configuration node.");
                    return null;
                }
            } else if (VersionConstants.NT_ACTIVITY.equals(ntName)) {
                return versionStoreTree;
            }
            t = t.getParent();
        }

        // intermediate node in the version, configuration or activity store that
        // matches none of the special conditions checked above -> regular permission eval.
        return versionStoreTree;
    }

    private final class TreePermissionImpl implements TreePermission {

        private final ImmutableTree tree;
        private final TreePermissionImpl parent;

        private final boolean isAcTree;
        private final boolean readableTree;

        private Collection<PermissionEntry> userEntries;
        private Collection<PermissionEntry> groupEntries;

        private boolean skipped;
        private ReadStatus readStatus;

        private TreePermissionImpl(ImmutableTree tree, int treeType, TreePermission parentPermission) {
            this.tree = tree;
            if (parentPermission instanceof TreePermissionImpl) {
                parent = (TreePermissionImpl) parentPermission;
            } else {
                parent = null;
            }
            readableTree = readPolicy.isReadableTree(tree, parent);
            isAcTree = (treeType == TreeTypeProvider.TYPE_AC);
        }

        //-------------------------------------------------< TreePermission >---
        @Override
        public TreePermission getChildPermission(String childName, NodeState childState) {
            ImmutableTree childTree = new ImmutableTree(tree, childName, childState);
            return getTreePermission(childTree, this);
        }

        @Override
        public boolean canRead() {
            if (!isAcTree && readableTree) {
                return true;
            }
            if (readStatus == null) {
                readStatus = ReadStatus.DENY_THIS;

                long permission = (isAcTree) ? Permissions.READ_ACCESS_CONTROL : Permissions.READ_NODE;
                PrivilegeBits requiredBits = READ_BITS.get(permission);

                Iterator<PermissionEntry> it = getIterator(null, permission);
                while (it.hasNext()) {
                    PermissionEntry entry = it.next();
                    if (entry.privilegeBits.includes(requiredBits)) {
                        readStatus = ReadStatus.create(entry, permission, skipped);
                        break;
                    } else if (permission == Permissions.READ_NODE &&
                            entry.privilegeBits.includes(READ_BITS.get(Permissions.READ_PROPERTY))) {
                        skipped = true;
                    }
                }
            }
            return readStatus.allowsThis();
        }

        @Override
        public boolean canRead(@Nonnull PropertyState property) {
            if (!isAcTree && readableTree) {
                return true;
            }
            if (readStatus != null && readStatus.allowsProperties()) {
                return true;
            }

            long permission = (isAcTree) ? Permissions.READ_ACCESS_CONTROL : Permissions.READ_PROPERTY;
            Iterator<PermissionEntry> it = getIterator(property, permission);
            while (it.hasNext()) {
                PermissionEntry entry = it.next();
                if (entry.privilegeBits.includes(READ_BITS.get(permission))) {
                    return (entry.isAllow);
                }
            }
            return false;
        }

        @Override
        public boolean canReadAll() {
            // TODO: best effort approach to detect full read-access within a given tree.
            return readStatus != null && readStatus.allowsAll();
        }

        @Override
        public boolean canReadProperties() {
                // TODO: best effort approach to detect full read-property permission
            return readStatus != null && readStatus.allowsProperties();
        }

        @Override
        public boolean isGranted(long permissions) {
            return hasPermissions(getIterator(null, permissions), permissions, tree.getPath());
        }

        @Override
        public boolean isGranted(long permissions, @Nonnull PropertyState property) {
            return hasPermissions(getIterator(property, permissions), permissions, tree.getPath());
        }

        //--------------------------------------------------------< private >---
        private Iterator<PermissionEntry> getIterator(@Nullable PropertyState property, long permissions) {
            EntryPredicate predicate = new EntryPredicate(tree, property, Permissions.respectParentPermissions(permissions));
            return concat(new LazyIterator(this, true, predicate), new LazyIterator(this, false, predicate));
        }

        private Iterator<PermissionEntry> getUserEntries() {
            if (userEntries == null) {
                userEntries = userStore.getEntries(tree);
            }
            return userEntries.iterator();
        }

        private Iterator<PermissionEntry> getGroupEntries() {
            if (groupEntries == null) {
                groupEntries = groupStore.getEntries(tree);
            }
            return groupEntries.iterator();
        }
    }

    private static final class LazyIterator extends AbstractLazyIterator<PermissionEntry> {

        private final TreePermissionImpl treePermission;
        private final boolean isUser;

        private final EntryPredicate predicate;

        // the ordered permission entries at a given path in the hierarchy
        private Iterator<PermissionEntry> nextEntries = Iterators.emptyIterator();

        private TreePermissionImpl tp;

        private LazyIterator(@Nonnull TreePermissionImpl treePermission, boolean isUser, @Nonnull EntryPredicate predicate) {
            this.treePermission = treePermission;
            this.isUser = isUser;
            this.predicate = predicate;

            tp = treePermission;
        }

        @Override
        protected PermissionEntry getNext() {
            PermissionEntry next = null;
            while (next == null) {
                if (nextEntries.hasNext()) {
                    PermissionEntry pe = nextEntries.next();
                    if (predicate.apply(pe)) {
                        next = pe;
                    } else {
                        treePermission.skipped  = true;
                    }
                } else {
                    if (tp == null) {
                        break;
                    }
                    nextEntries = (isUser) ? tp.getUserEntries() : tp.getGroupEntries();
                    tp = tp.parent;
                }
            }
            return next;
        }
    }

    private interface ReadPolicy {

        boolean isReadableTree(@Nonnull Tree tree, @Nullable TreePermissionImpl parent);
        boolean isReadableTree(@Nonnull Tree tree, boolean exactMatch);
        boolean isReadablePath(@Nullable String treePath, boolean exactMatch);
    }

    private static final class EmptyReadPolicy implements ReadPolicy {

        private static final ReadPolicy INSTANCE = new EmptyReadPolicy();

        private EmptyReadPolicy() {}

        @Override
        public boolean isReadableTree(@Nonnull Tree tree, @Nullable TreePermissionImpl parent) {
            return false;
        }

        public boolean isReadableTree(@Nonnull Tree tree, boolean exactMatch) {
            return false;
        }

        @Override
        public boolean isReadablePath(@Nullable String treePath, boolean exactMatch) {
            return false;
        }
    }

    private static final class DefaultReadPolicy implements ReadPolicy {

        private final String[] readPaths;
        private final String[] altReadPaths;
        private final boolean isDefaultPaths;

        private DefaultReadPolicy(Set<String> readPaths) {
            this.readPaths = readPaths.toArray(new String[readPaths.size()]);
            altReadPaths = new String[readPaths.size()];
            int i = 0;
            for (String p : this.readPaths) {
                altReadPaths[i++] = p + '/';
            }
            // optimize evaluation for default setup where all readable paths
            // are located underneath /jcr:system
            isDefaultPaths = (readPaths.size() == DEFAULT_READ_PATHS.size()) && readPaths.containsAll(DEFAULT_READ_PATHS);
        }

        public boolean isReadableTree(@Nonnull Tree tree, @Nullable TreePermissionImpl parent) {
            if (parent != null) {
                if (parent.readableTree) {
                    return true;
                } else if (!isDefaultPaths || parent.tree.getName().equals(JcrConstants.JCR_SYSTEM)) {
                    return isReadableTree(tree, true);
                } else  {
                    return false;
                }
            } else {
                return isReadableTree(tree, true);
            }
        }

        public boolean isReadableTree(@Nonnull Tree tree, boolean exactMatch) {
            String targetPath = tree.getPath();
            for (String path : readPaths) {
                if (targetPath.equals(path)) {
                    return true;
                }
            }
            if (!exactMatch) {
                for (String path : altReadPaths) {
                    if (targetPath.startsWith(path)) {
                        return true;
                    }
                }
            }
            return false;
        }

        public boolean isReadablePath(@Nullable String treePath, boolean exactMatch) {
            if (treePath != null) {
                for (String path : readPaths) {
                    if (treePath.equals(path)) {
                        return true;
                    }
                }
                if (!exactMatch) {
                    for (String path : altReadPaths) {
                        if (treePath.startsWith(path)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
    }
}
TOP

Related Classes of org.apache.jackrabbit.oak.security.authorization.permission.CompiledPermissionImpl$DefaultReadPolicy

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.