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 + 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,29 @@ } //------------------------------------------------< 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 = getEntryIterator(tree, property); + + if (readStatusBuilt){ + while (it.hasNext()) { + PermissionEntry entry = it.next(); + if (entry.readStatus != null) { + return entry.readStatus; + } + } + }else{ + 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) { @@ -265,13 +279,27 @@ return allowBits; } - private Iterator getEntryIterator(@Nonnull Tree tree, @Nullable PropertyState property) { - return Iterators.concat(new EntryIterator(userEntries, tree, property), new EntryIterator(groupEntries, tree, property)); - } + private Iterator getEntryIterator(@Nonnull Tree tree, @Nullable PropertyState property) { + EntryIterator userEntryIterator = new EntryIterator(userEntries, tree, property); + EntryIterator groupEntryIterator = new EntryIterator(groupEntries, tree, property); + + if (readStatusBuilt){ + return Iterators.mergeSorted(ImmutableList.of(userEntryIterator,groupEntryIterator),Ordering.natural()); + }else{ + return Iterators.concat(userEntryIterator, groupEntryIterator ); + } + } - private Iterator getEntryIterator(@Nonnull String path) { - return Iterators.concat(new EntryIterator(userEntries, path), new EntryIterator(groupEntries, path)); - } + private Iterator getEntryIterator(@Nonnull String path) { + EntryIterator userEntryIterator =new EntryIterator(userEntries, path); + EntryIterator groupEntryIterator = new EntryIterator(groupEntries, path); + + if (readStatusBuilt){ + return Iterators.mergeSorted(ImmutableList.of(userEntryIterator,groupEntryIterator),Ordering.natural()); + }else{ + return Iterators.concat(userEntryIterator, groupEntryIterator ); + } + } private static final class Key implements Comparable { @@ -323,7 +351,7 @@ } } - private static final class PermissionEntry { + private static final class PermissionEntry implements Comparable{ private final boolean isAllow; private final PrivilegeBits privilegeBits; @@ -356,6 +384,11 @@ return false; } } + + @Override + public int compareTo(PermissionEntry permissionEntry) { + return permissionEntry.path.compareTo( path); + } } /** 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; } } + }