Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ACFilter.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ACFilter.java (revision 1743346) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ACFilter.java (working copy) @@ -33,10 +33,29 @@ * {@code EventTypeFilter} filters based on the access rights of the observing session. */ public class ACFilter implements EventFilter { - private final TreePermission treePermission; - private ACFilter(@Nonnull TreePermission treePermission) { - this.treePermission = checkNotNull(treePermission); + private final NodeState before; + + private final NodeState after; + + private final String name; + + private final ACFilter parentFilter; + + private final PermissionProvider permissionProvider; + + private TreePermission treePermission; + + private ACFilter(@Nonnull NodeState before, + @Nonnull NodeState after, + @Nonnull String name, + @Nonnull PermissionProvider permissionProvider, + @Nonnull ACFilter parentFilter) { + this.before = checkNotNull(before); + this.after = checkNotNull(after); + this.name = checkNotNull(name); + this.permissionProvider = checkNotNull(permissionProvider); + this.parentFilter = checkNotNull(parentFilter); } /** @@ -47,52 +66,71 @@ * @param after after state * @param permissionProvider permission provider for access control evaluation */ - public ACFilter(@Nonnull NodeState before, @Nonnull NodeState after, - @Nonnull PermissionProvider permissionProvider) { - this(permissionProvider.getTreePermission( - TreeFactory.createReadOnlyTree((after.exists() ? after : before)), TreePermission.EMPTY)); + public ACFilter(@Nonnull NodeState before, + @Nonnull NodeState after, + @Nonnull PermissionProvider permissionProvider) { + this.before = checkNotNull(before); + this.after = checkNotNull(after); + this.name = null; + this.permissionProvider = checkNotNull(permissionProvider); + this.parentFilter = null; } @Override public boolean includeAdd(PropertyState after) { - return treePermission.canRead(after); + return getTreePermission().canRead(after); } @Override public boolean includeChange(PropertyState before, PropertyState after) { - return treePermission.canRead(after); + return getTreePermission().canRead(after); } @Override public boolean includeDelete(PropertyState before) { - return treePermission.canRead(before); + return getTreePermission().canRead(before); } @Override public boolean includeAdd(String name, NodeState after) { - return treePermission.getChildPermission(name, after).canRead(); + return getTreePermission().getChildPermission(name, after).canRead(); } @Override public boolean includeDelete(String name, NodeState before) { - return treePermission.getChildPermission(name, before).canRead(); + return getTreePermission().getChildPermission(name, before).canRead(); } @Override public boolean includeMove(String sourcePath, String name, NodeState moved) { // TODO: check access to the source path, it might not be accessible - return treePermission.getChildPermission(name, moved).canRead(); + return getTreePermission().getChildPermission(name, moved).canRead(); } @Override public boolean includeReorder(String destName, String name, NodeState reordered) { // TODO: check access to the dest name, it might not be accessible - return treePermission.getChildPermission(name, reordered).canRead(); + return getTreePermission().getChildPermission(name, reordered).canRead(); } @Override public EventFilter create(String name, NodeState before, NodeState after) { - return new ACFilter(treePermission.getChildPermission(name, after)); + return new ACFilter(before, after, name, permissionProvider, this); } + //-----------------------------< internal >--------------------------------- + + private TreePermission getTreePermission() { + TreePermission tp = treePermission; + if (tp == null) { + if (parentFilter == null) { + tp = permissionProvider.getTreePermission( + TreeFactory.createReadOnlyTree((after.exists() ? after : before)), TreePermission.EMPTY); + } else { + tp = parentFilter.getTreePermission().getChildPermission(name, after); + } + treePermission = tp; + } + return tp; + } } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java (revision 1743346) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java (working copy) @@ -48,9 +48,15 @@ private final String workspaceName; + private final Set principals; + + private final RestrictionProvider restrictionProvider; + + private final ConfigurationParameters options; + private final Context ctx; - private final CompiledPermissions compiledPermissions; + private CompiledPermissions compiledPermissions; private Root immutableRoot; @@ -61,49 +67,46 @@ @Nonnull Context ctx) { this.root = root; this.workspaceName = workspaceName; + this.principals = principals; + this.restrictionProvider = restrictionProvider; + this.options = options; this.ctx = ctx; immutableRoot = RootFactory.createReadOnlyRoot(root); - - if (PermissionUtil.isAdminOrSystem(principals, options)) { - compiledPermissions = AllPermissions.getInstance(); - } else { - compiledPermissions = CompiledPermissionImpl.create(immutableRoot, workspaceName, principals, restrictionProvider, options, ctx); - } } @Override public void refresh() { immutableRoot = RootFactory.createReadOnlyRoot(root); - compiledPermissions.refresh(immutableRoot, workspaceName); + getCompiledPermissions().refresh(immutableRoot, workspaceName); } @Nonnull @Override public Set getPrivileges(@Nullable Tree tree) { - return compiledPermissions.getPrivileges(PermissionUtil.getImmutableTree(tree, immutableRoot)); + return getCompiledPermissions().getPrivileges(PermissionUtil.getImmutableTree(tree, immutableRoot)); } @Override public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) { - return compiledPermissions.hasPrivileges(PermissionUtil.getImmutableTree(tree, immutableRoot), privilegeNames); + return getCompiledPermissions().hasPrivileges(PermissionUtil.getImmutableTree(tree, immutableRoot), privilegeNames); } @Nonnull @Override public RepositoryPermission getRepositoryPermission() { - return compiledPermissions.getRepositoryPermission(); + return getCompiledPermissions().getRepositoryPermission(); } @Nonnull @Override public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreePermission parentPermission) { - return compiledPermissions.getTreePermission(PermissionUtil.getImmutableTree(tree, immutableRoot), parentPermission); + return getCompiledPermissions().getTreePermission(PermissionUtil.getImmutableTree(tree, immutableRoot), parentPermission); } @Override public boolean isGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) { - return compiledPermissions.isGranted(PermissionUtil.getImmutableTree(tree, immutableRoot), property, permissions); + return getCompiledPermissions().isGranted(PermissionUtil.getImmutableTree(tree, immutableRoot), property, permissions); } @Override @@ -145,11 +148,24 @@ @Nonnull @Override public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreeType type, @Nonnull TreePermission parentPermission) { - return compiledPermissions.getTreePermission(PermissionUtil.getImmutableTree(tree, immutableRoot), type, parentPermission); + return getCompiledPermissions().getTreePermission(PermissionUtil.getImmutableTree(tree, immutableRoot), type, parentPermission); } //-------------------------------------------------------------------------- + private CompiledPermissions getCompiledPermissions() { + CompiledPermissions cp = compiledPermissions; + if (cp == null) { + if (PermissionUtil.isAdminOrSystem(principals, options)) { + cp = AllPermissions.getInstance(); + } else { + cp = CompiledPermissionImpl.create(immutableRoot, workspaceName, principals, restrictionProvider, options, ctx); + } + compiledPermissions = cp; + } + return cp; + } + private static boolean isVersionStorePath(@Nonnull String oakPath) { return oakPath.startsWith(VersionConstants.VERSION_STORE_PATH); } @@ -161,7 +177,7 @@ if (tree != null) { isGranted = isGranted(tree, property, permissions); } else if (!isVersionStorePath(location.getPath())) { - isGranted = compiledPermissions.isGranted(oakPath, permissions); + isGranted = getCompiledPermissions().isGranted(oakPath, permissions); } return isGranted; }