### Eclipse Workspace Patch 1.0 #P oak-core Index: src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java (revision 1471334) +++ src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java (working copy) @@ -32,9 +32,12 @@ import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; +import com.google.common.collect.Ordering; + import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.Type; @@ -65,6 +68,8 @@ private Map repoEntries; private Map userEntries; private Map groupEntries; + + private boolean readStatusBuilt = false; CompiledPermissionImpl(@Nonnull Set principals, @Nonnull ImmutableTree permissionsTree, @@ -109,20 +114,31 @@ } //------------------------------------------------< CompiledPermissions >--- - @Override - public ReadStatus getReadStatus(@Nonnull Tree tree, @Nullable PropertyState property) { - long permission = (property == null) ? Permissions.READ_NODE : Permissions.READ_PROPERTY; - Iterator it = getEntryIterator(tree, property); - while (it.hasNext()) { - PermissionEntry entry = it.next(); - if (entry.readStatus != null) { - return entry.readStatus; - } else if (entry.privilegeBits.includesRead(permission)) { - return (entry.isAllow) ? ReadStatus.ALLOW_THIS : ReadStatus.DENY_THIS; - } - } - return ReadStatus.DENY_THIS; - } + @Override + public ReadStatus getReadStatus(@Nonnull Tree tree, @Nullable PropertyState property) { + long permission = (property == null) ? Permissions.READ_NODE : Permissions.READ_PROPERTY; + Iterator it = null; + + if (readStatusBuilt){ + it = getEntryIteratorForReadStatus(tree, property); + while (it.hasNext()) { + PermissionEntry entry = it.next(); + if (entry.readStatus != null) { + return entry.readStatus; + } + } + }else{ + it = getEntryIterator(tree, property); + while (it.hasNext()) { + PermissionEntry entry = it.next(); + if (entry.privilegeBits.includesRead(permission)) { + return (entry.isAllow) ? ReadStatus.ALLOW_THIS : ReadStatus.DENY_THIS; + } + } + return ReadStatus.DENY_THIS; + } + return ReadStatus.DENY_THIS; + } @Override public boolean isGranted(long permissions) { @@ -264,7 +280,7 @@ } return allowBits; } - + private Iterator getEntryIterator(@Nonnull Tree tree, @Nullable PropertyState property) { return Iterators.concat(new EntryIterator(userEntries, tree, property), new EntryIterator(groupEntries, tree, property)); } @@ -272,6 +288,11 @@ private Iterator getEntryIterator(@Nonnull String path) { return Iterators.concat(new EntryIterator(userEntries, path), new EntryIterator(groupEntries, path)); } + + private Iterator getEntryIteratorForReadStatus(@Nonnull Tree tree, @Nullable PropertyState property) { + return Iterators.mergeSorted(ImmutableList.of(new EntryIterator(userEntries, tree, property), new EntryIterator(groupEntries, tree, property)),Ordering.natural()); + } + private static final class Key implements Comparable { @@ -291,7 +312,7 @@ if (Objects.equal(path, key.path)) { if (index == key.index) { return 0; - } else if (index < key.index) { + } else if (index < key.index) { return 1; } else { return -1; @@ -323,12 +344,14 @@ } } - private static final class PermissionEntry { + private static final class PermissionEntry implements Comparable{ private final boolean isAllow; private final PrivilegeBits privilegeBits; private final String path; private final RestrictionPattern restriction; + private final long index; + private final int depth; private ReadStatus readStatus; private PermissionEntry next; @@ -338,6 +361,8 @@ privilegeBits = PrivilegeBits.getInstance(entryTree.getProperty(REP_PRIVILEGE_BITS)); path = accessControlledPath; restriction = restrictionsProvider.getPattern(accessControlledPath, entryTree); + index = checkNotNull(entryTree.getProperty(REP_INDEX).getValue(Type.LONG)).longValue(); + depth = (path == null) ? 0 : PathUtils.getDepth(path); } private boolean matches(@Nonnull Tree tree, @Nullable PropertyState property) { @@ -356,6 +381,26 @@ return false; } } + + @Override + public int compareTo(PermissionEntry permissionEntry) { + checkNotNull(permissionEntry); + if (Objects.equal(path, permissionEntry.path)) { + if (index == permissionEntry.index) { + return 0; + } else if (index < permissionEntry.index) { + return 1; + } else { + return -1; + } + } else { + if (depth == permissionEntry.depth) { + return path.compareTo(permissionEntry.path); + } else { + return (depth < permissionEntry.depth) ? 1 : -1; + } + } + } } /** Index: src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImplTest.java =================================================================== --- src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImplTest.java (revision 1471325) +++ src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImplTest.java (working copy) @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.List; +import java.util.Map; import java.util.Set; import javax.annotation.Nonnull; @@ -52,7 +53,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; - +import junitx.util.PrivateAccessor; import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE; import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED; import static org.junit.Assert.assertSame; @@ -60,7 +61,7 @@ /** * CompiledPermissionImplTest... TODO */ -@Ignore("work in progress") +//@Ignore("work in progress") public class CompiledPermissionImplTest extends AbstractSecurityTest implements PermissionConstants, PrivilegeConstants { @@ -211,7 +212,7 @@ allow(group2, node1Path, 0, REP_READ_NODES); CompiledPermissionImpl cp = createPermissions(ImmutableSet.of(userPrincipal, group2)); - + assertReadStatus(ReadStatus.ALLOW_PROPERTIES, cp, rootAndUsers); assertReadStatus(ReadStatus.ALLOW_ALL_REGULAR, cp, nodePaths); } @@ -330,6 +331,30 @@ assertReadStatus(ReadStatus.ALLOW_ALL_REGULAR, cp, node1Path); assertReadStatus(ReadStatus.ALLOW_ALL, cp, node2Path); } + + @Test + public void testGetReadStatus8_WithMocking() throws Exception { + allow(userPrincipal, "/", 0, REP_READ_PROPERTIES); + allow(group2, node1Path, 0, REP_READ_NODES); + + CompiledPermissionImpl cp = createPermissions(ImmutableSet.of(userPrincipal, group2)); + + + PrivateAccessor.setField(cp, "readStatusBuilt",true); + + Map userEntries =(Map)PrivateAccessor.getField(cp, "userEntries"); + for (Object userEntry: userEntries.values()){ + PrivateAccessor.setField(userEntry, "readStatus",ReadStatus.ALLOW_PROPERTIES); + } + + Map groupEntries =(Map)PrivateAccessor.getField(cp, "groupEntries"); + for (Object groupEntry: groupEntries.values()){ + PrivateAccessor.setField(groupEntry, "readStatus",ReadStatus.ALLOW_ALL_REGULAR); + } + + assertReadStatus(ReadStatus.ALLOW_PROPERTIES, cp, rootAndUsers); + assertReadStatus(ReadStatus.ALLOW_ALL_REGULAR, cp, nodePaths); + } // TODO: tests with restrictions // TODO: complex tests with entries for paths outside of the tested hierarchy @@ -422,4 +447,5 @@ return name; } } + } Index: pom.xml =================================================================== --- pom.xml (revision 1469718) +++ pom.xml (working copy) @@ -254,5 +254,11 @@ 1.5.5 test + + junit-addons + junit-addons + 1.4 + test +