You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2021/11/03 17:13:00 UTC

[sling-org-apache-sling-resourceaccesssecurity] branch master updated: SLING-10904 update to parent 46 (#2)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceaccesssecurity.git


The following commit(s) were added to refs/heads/master by this push:
     new b6657c4  SLING-10904 update to parent 46 (#2)
b6657c4 is described below

commit b6657c40c506373c958acb3f88f1c08e9b6b4566
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Wed Nov 3 18:12:36 2021 +0100

    SLING-10904 update to parent 46 (#2)
    
    remove redundancy in canXXX operations
---
 README.md                                          |   2 +-
 bnd.bnd                                            |   0
 pom.xml                                            |  71 ++-----
 .../resourceaccesssecurity/ResourceAccessGate.java |  10 +-
 .../ApplicationResourceAccessSecurityImpl.java     |  35 ++--
 .../impl/ProviderResourceAccessSecurityImpl.java   |  33 +--
 .../impl/ResourceAccessGateHandler.java            |  20 +-
 .../impl/ResourceAccessSecurityImpl.java           | 226 +++------------------
 .../sling/resourceaccesssecurity/package-info.java |   2 +-
 .../impl/ResourceAccessSecurityImplTests.java      |  53 ++---
 10 files changed, 119 insertions(+), 333 deletions(-)

diff --git a/README.md b/README.md
index 16f5e95..51d41ef 100644
--- a/README.md
+++ b/README.md
@@ -6,4 +6,4 @@
 
 This module is part of the [Apache Sling](https://sling.apache.org) project.
 
-This bundle provides in implementation of the ResourceAccessSecurity
+This bundle provides an implementation of the [`ResourceAccessSecurity` service](https://sling.apache.org/documentation/bundles/resource-access-security.html).
diff --git a/bnd.bnd b/bnd.bnd
new file mode 100644
index 0000000..e69de29
diff --git a/pom.xml b/pom.xml
index 6ec4a78..2e35060 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,14 +21,13 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.sling</groupId>
-        <artifactId>sling</artifactId>
-        <version>26</version>
+        <artifactId>sling-bundle-parent</artifactId>
+        <version>46</version>
         <relativePath/>
     </parent>
 
     <artifactId>org.apache.sling.resourceaccesssecurity</artifactId>
     <version>1.0.1-SNAPSHOT</version>
-    <packaging>bundle</packaging>
 
     <name>Apache Sling Resource Access Security</name>
     <description>
@@ -44,54 +43,29 @@
     <properties>
         <site.javadoc.exclude>**.internal.**</site.javadoc.exclude>
         <sling.java.version>8</sling.java.version>
+        <project.build.outputTimestamp>1</project.build.outputTimestamp>
     </properties>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-scr-plugin</artifactId>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.sling</groupId>
-                <artifactId>maven-sling-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>generate-adapter-metadata</id>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>generate-adapter-metadata</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    
     <dependencies>
         <dependency>
             <groupId>javax.jcr</groupId>
             <artifactId>jcr</artifactId>
-            <version>2.0</version>
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
+            <artifactId>org.osgi.framework</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.api</artifactId>
-            <version>2.23.7-SNAPSHOT</version>
-            <scope>provided</scope>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.annotation.versioning</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.component</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.component.annotations</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
@@ -99,23 +73,16 @@
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.commons.osgi</artifactId>
-            <version>2.2.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-           <groupId>commons-collections</groupId>
-           <artifactId>commons-collections</artifactId>
-           <version>3.2.1</version>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.23.7-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
-            <artifactId>adapter-annotations</artifactId>
-            <version>1.0.0</version>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.2.0</version>
             <scope>provided</scope>
         </dependency>
-
         <!-- Testing -->
         <dependency>
             <groupId>junit</groupId>
@@ -124,7 +91,7 @@
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
-            <version>1.9.5</version>
+            <version>4.0.0</version>
             <scope>test</scope>
         </dependency>
      </dependencies>
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/ResourceAccessGate.java b/src/main/java/org/apache/sling/resourceaccesssecurity/ResourceAccessGate.java
index b6c1539..2eeff30 100644
--- a/src/main/java/org/apache/sling/resourceaccesssecurity/ResourceAccessGate.java
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/ResourceAccessGate.java
@@ -21,8 +21,8 @@ package org.apache.sling.resourceaccesssecurity;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.security.AccessSecurityException;
-
-import aQute.bnd.annotation.ConsumerType;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate.GateResult;
+import org.osgi.annotation.versioning.ConsumerType;
 
 /**
  * The <code>ResourceAccessGate</code> defines a service API which might be used
@@ -97,17 +97,17 @@ public interface ResourceAccessGate {
     String PATH = "path";
 
     /**
-     * The name of the service registration property containing the operations
+     * The name of the (multi-value) service registration property containing the operations
      * for which the service should be called, defaults to all the operations
      * (value is "operations").
      */
     String OPERATIONS = "operations";
 
     /**
-     * The name of the service registration property containing the operations
+     * The name of the (multi-value) service registration property containing the operations
      * for which the service should be called and no further service should be
      * called after this, except the services returns DONTCARE as result,
-     * default is empty (non of them are final) (value is "finaloperations").
+     * default is empty (none of them are final) (value is "finaloperations").
      */
     String FINALOPERATIONS = "finaloperations";
 
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ApplicationResourceAccessSecurityImpl.java b/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ApplicationResourceAccessSecurityImpl.java
index d4ac38e..296dd47 100644
--- a/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ApplicationResourceAccessSecurityImpl.java
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ApplicationResourceAccessSecurityImpl.java
@@ -18,25 +18,30 @@
  */
 package org.apache.sling.resourceaccesssecurity.impl;
 
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.Service;
+import java.util.List;
+
 import org.apache.sling.api.security.ResourceAccessSecurity;
 import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
 
-@Component
-@Service(value=ResourceAccessSecurity.class)
-@Property(name=ResourceAccessSecurity.CONTEXT, value=ResourceAccessSecurity.APPLICATION_CONTEXT)
-@Reference(name="ResourceAccessGate", referenceInterface=ResourceAccessGate.class,
-           cardinality=ReferenceCardinality.MANDATORY_MULTIPLE,
-           policy=ReferencePolicy.DYNAMIC,
-           target="(" + ResourceAccessGate.CONTEXT + "=" + ResourceAccessGate.APPLICATION_CONTEXT + ")")
+@Component(service = ResourceAccessSecurity.class, properties = {
+        ResourceAccessSecurity.CONTEXT+"="+ResourceAccessSecurity.APPLICATION_CONTEXT
+})
 public class ApplicationResourceAccessSecurityImpl extends ResourceAccessSecurityImpl {
 
-    public ApplicationResourceAccessSecurityImpl() {
-        super(false);
+    private static final String RESOURCE_ACCESS_GATE_REFERENCE_NAME = "resourceAccessGates";
+
+    @Activate
+    public ApplicationResourceAccessSecurityImpl(
+            @Reference(name = RESOURCE_ACCESS_GATE_REFERENCE_NAME, cardinality = ReferenceCardinality.AT_LEAST_ONE, policyOption = ReferencePolicyOption.GREEDY, target ="(" + ResourceAccessGate.CONTEXT + "=" + ResourceAccessGate.APPLICATION_CONTEXT + ")") 
+            List<ServiceReference<ResourceAccessGate>> resourceAccessGateRefs,
+            ComponentContext componentContext) {
+        super(false, resourceAccessGateRefs, componentContext, RESOURCE_ACCESS_GATE_REFERENCE_NAME);
     }
 }
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ProviderResourceAccessSecurityImpl.java b/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ProviderResourceAccessSecurityImpl.java
index 80fd43e..4070982 100644
--- a/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ProviderResourceAccessSecurityImpl.java
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ProviderResourceAccessSecurityImpl.java
@@ -18,25 +18,28 @@
  */
 package org.apache.sling.resourceaccesssecurity.impl;
 
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.Service;
+import java.util.List;
+
 import org.apache.sling.api.security.ResourceAccessSecurity;
 import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
 
-@Component
-@Service(value=ResourceAccessSecurity.class)
-@Property(name=ResourceAccessSecurity.CONTEXT, value=ResourceAccessSecurity.PROVIDER_CONTEXT)
-@Reference(name="ResourceAccessGate", referenceInterface=ResourceAccessGate.class,
-           cardinality=ReferenceCardinality.MANDATORY_MULTIPLE,
-           policy=ReferencePolicy.DYNAMIC,
-           target="(" + ResourceAccessGate.CONTEXT + "=" + ResourceAccessGate.PROVIDER_CONTEXT + ")")
+@Component(service = ResourceAccessSecurity.class, properties = ResourceAccessSecurity.CONTEXT + "=" + ResourceAccessSecurity.PROVIDER_CONTEXT)
 public class ProviderResourceAccessSecurityImpl extends ResourceAccessSecurityImpl {
 
-    public ProviderResourceAccessSecurityImpl() {
-        super(false);
+    private static final String RESOURCE_ACCESS_GATE_REFERENCE_NAME = "resourceAccessGates";
+
+    @Activate
+    public ProviderResourceAccessSecurityImpl(
+            @Reference(name = RESOURCE_ACCESS_GATE_REFERENCE_NAME, cardinality = ReferenceCardinality.AT_LEAST_ONE, policyOption = ReferencePolicyOption.GREEDY, target ="(" + ResourceAccessGate.CONTEXT + "=" + ResourceAccessGate.PROVIDER_CONTEXT + ")") 
+            List<ServiceReference<ResourceAccessGate>> resourceAccessGates,
+            ComponentContext componentContext) {
+        super(false, resourceAccessGates, componentContext, RESOURCE_ACCESS_GATE_REFERENCE_NAME);
     }
 }
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessGateHandler.java b/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessGateHandler.java
index f413fff..0d849d1 100644
--- a/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessGateHandler.java
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessGateHandler.java
@@ -27,24 +27,22 @@ import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
 import org.osgi.framework.ServiceReference;
 
-public class ResourceAccessGateHandler implements Comparable<ResourceAccessGateHandler> {
+public class ResourceAccessGateHandler {
 
     private final ResourceAccessGate resourceAccessGate;
 
-    private final ServiceReference reference;
+    private final ServiceReference<ResourceAccessGate> reference;
 
     private final Pattern pathPattern;
-    private final Set<ResourceAccessGate.Operation> operations = new HashSet<ResourceAccessGate.Operation>();
-    private final Set<ResourceAccessGate.Operation> finalOperations = new HashSet<ResourceAccessGate.Operation>();
+    private final Set<ResourceAccessGate.Operation> operations = new HashSet<>();
+    private final Set<ResourceAccessGate.Operation> finalOperations = new HashSet<>();
 
     /**
      * constructor
      */
-    public ResourceAccessGateHandler ( final ServiceReference resourceAccessGateRef ) {
+    public ResourceAccessGateHandler ( final ServiceReference<ResourceAccessGate> resourceAccessGateRef, final ResourceAccessGate resourceAccessGate ) {
         this.reference = resourceAccessGateRef;
-
-        resourceAccessGate = (ResourceAccessGate) resourceAccessGateRef.getBundle().
-                getBundleContext().getService(resourceAccessGateRef);
+        this.resourceAccessGate = resourceAccessGate;
         // extract the service property "path"
         final String path = (String) resourceAccessGateRef.getProperty(ResourceAccessGate.PATH);
         if ( path != null ) {
@@ -108,12 +106,6 @@ public class ResourceAccessGateHandler implements Comparable<ResourceAccessGateH
     }
 
     @Override
-    public int compareTo(final ResourceAccessGateHandler o) {
-        // services with higher service ranking should be the first in a list
-        return -this.reference.compareTo(o.reference);
-    }
-
-    @Override
     public boolean equals(final Object obj) {
         if ( obj instanceof ResourceAccessGateHandler ) {
             return ((ResourceAccessGateHandler)obj).reference.equals(this.reference);
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessSecurityImpl.java b/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessSecurityImpl.java
index 0fefab1..203821b 100644
--- a/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessSecurityImpl.java
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessSecurityImpl.java
@@ -23,6 +23,9 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
@@ -31,6 +34,7 @@ import org.apache.sling.api.security.ResourceAccessSecurity;
 import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
 import org.apache.sling.resourceaccesssecurity.ResourceAccessGate.GateResult;
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
 
 public abstract class ResourceAccessSecurityImpl implements ResourceAccessSecurity {
 
@@ -38,10 +42,14 @@ public abstract class ResourceAccessSecurityImpl implements ResourceAccessSecuri
 
     private final boolean defaultAllowIfNoGateMatches;
 
-    public ResourceAccessSecurityImpl(final boolean defaultAllowIfNoGateMatches) {
+    protected ResourceAccessSecurityImpl(final boolean defaultAllowIfNoGateMatches, List<ServiceReference<ResourceAccessGate>> resourceAccessGateRefs,
+            ComponentContext componentContext, String resourceAccessGateReferenceName) {
         this.defaultAllowIfNoGateMatches = defaultAllowIfNoGateMatches;
+        // sort from highest ranked service to lowest ranked (opposite of default sorting of ServiceReference)
+        this.allHandlers = resourceAccessGateRefs.stream().map(ref -> new ResourceAccessGateHandler(ref, componentContext.locateService(resourceAccessGateReferenceName, ref))).sorted(Collections.reverseOrder()).collect(Collectors.toList());
     }
 
+
     /**
      * This method returns either an iterator delivering the matching handlers
      * or <code>null</code>.
@@ -53,7 +61,7 @@ public abstract class ResourceAccessSecurityImpl implements ResourceAccessSecuri
         // a good idea
         //
         final List<ResourceAccessGateHandler> handlers = allHandlers;
-        if (handlers.size() > 0) {
+        if (!handlers.isEmpty()) {
 
             final Iterator<ResourceAccessGateHandler> iter = handlers.iterator();
             return new Iterator<ResourceAccessGateHandler>() {
@@ -129,14 +137,12 @@ public abstract class ResourceAccessSecurityImpl implements ResourceAccessSecuri
                         accessGatesForReadValues = null;
                     } else {
                         if (accessGatesForReadValues == null) {
-                            accessGatesForReadValues = new ArrayList<ResourceAccessGate>();
+                            accessGatesForReadValues = new ArrayList<>();
                         }
                         accessGatesForReadValues.add(resourceAccessGateHandler.getResourceAccessGate());
                     }
                 }
-                if (finalGateResult == null) {
-                    finalGateResult = gateResult;
-                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
+                if (finalGateResult == null || finalGateResult == GateResult.DENIED) {
                     finalGateResult = gateResult;
                 }
                 // stop checking if the operation is final and the result not GateResult.CANT_DECIDE
@@ -171,11 +177,9 @@ public abstract class ResourceAccessSecurityImpl implements ResourceAccessSecuri
         return returnValue;
     }
 
-    
-    @Override
-    public boolean canOrderChildren(Resource resource) {
+    private boolean canDoOperation(ResourceAccessGate.Operation operation, String path, Predicate<ResourceAccessGate> gatePredicate, Function<ResourceAccessGate, GateResult> gateResultFilter) {
         final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
-                resource.getPath(), ResourceAccessGate.Operation.ORDER_CHILDREN);
+                path, operation);
         boolean result = false;
         if ( handlers != null ) {
             GateResult finalGateResult = null;
@@ -185,191 +189,48 @@ public abstract class ResourceAccessSecurityImpl implements ResourceAccessSecuri
                 noGateMatched = false;
                 final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();
 
-                final GateResult gateResult = !resourceAccessGateHandler
-                        .getResourceAccessGate().hasOrderChildrenRestrictions(resource.getResourceResolver()) ? GateResult.GRANTED
-                        : resourceAccessGateHandler.getResourceAccessGate()
-                                .canOrderChildren(resource);
-                if (finalGateResult == null) {
-                    finalGateResult = gateResult;
-                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
+                final GateResult gateResult = !gatePredicate.test(resourceAccessGateHandler.getResourceAccessGate()) ? GateResult.GRANTED
+                        : gateResultFilter.apply(resourceAccessGateHandler.getResourceAccessGate());
+                if (finalGateResult == null || finalGateResult == GateResult.DENIED) {
                     finalGateResult = gateResult;
                 }
                 if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE && 
-                        resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.ORDER_CHILDREN)) {
+                        resourceAccessGateHandler.isFinalOperation(operation)) {
                     break;
                 }
             }
 
-            if ( finalGateResult == GateResult.GRANTED ) {
-                result = true;
-            } else if ( finalGateResult == GateResult.DENIED ) {
-                result = false;
-            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
-            {
+            if ( finalGateResult == GateResult.GRANTED || (noGateMatched && this.defaultAllowIfNoGateMatches)) {
                 result = true;
             }
         }
         return result;
     }
-
+    
+    
     @Override
-    public boolean canCreate(final String path,
-            final ResourceResolver resolver) {
-        final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
-                path, ResourceAccessGate.Operation.CREATE);
-        boolean result = false;
-        if ( handlers != null ) {
-            GateResult finalGateResult = null;
-            boolean noGateMatched = true;
-
-            while ( handlers.hasNext() ) {
-                noGateMatched = false;
-                final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();
-
-                final GateResult gateResult = !resourceAccessGateHandler
-                        .getResourceAccessGate().hasCreateRestrictions(resolver) ? GateResult.GRANTED
-                        : resourceAccessGateHandler.getResourceAccessGate()
-                                .canCreate(path, resolver);
-                if (finalGateResult == null) {
-                    finalGateResult = gateResult;
-                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
-                    finalGateResult = gateResult;
-                }
-                if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE && 
-                        resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.CREATE)) {
-                    break;
-                }
-            }
+    public boolean canOrderChildren(Resource resource) {
+        return canDoOperation(ResourceAccessGate.Operation.ORDER_CHILDREN, resource.getPath(), gate -> gate.hasOrderChildrenRestrictions(resource.getResourceResolver()), gate -> gate.canOrderChildren(resource));
+    }
 
-            if ( finalGateResult == GateResult.GRANTED ) {
-                result = true;
-            } else if ( finalGateResult == GateResult.DENIED ) {
-                result = false;
-            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
-            {
-                result = true;
-            }
-        }
-        return result;
+    @Override
+    public boolean canCreate(final String path, final ResourceResolver resolver) {
+        return canDoOperation(ResourceAccessGate.Operation.CREATE, path, gate -> gate.hasCreateRestrictions(resolver), gate -> gate.canCreate(path, resolver));
     }
 
     @Override
     public boolean canUpdate(final Resource resource) {
-        final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
-                resource.getPath(), ResourceAccessGate.Operation.UPDATE);
-        boolean result = this.defaultAllowIfNoGateMatches;
-        if ( handlers != null ) {
-            GateResult finalGateResult = null;
-            boolean noGateMatched = true;
-
-            while ( handlers.hasNext() ) {
-                noGateMatched = false;
-                final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();
-
-                final GateResult gateResult = !resourceAccessGateHandler
-                        .getResourceAccessGate().hasUpdateRestrictions(resource.getResourceResolver()) ? GateResult.GRANTED
-                        : resourceAccessGateHandler.getResourceAccessGate()
-                                .canUpdate(resource);
-                if (finalGateResult == null) {
-                    finalGateResult = gateResult;
-                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
-                    finalGateResult = gateResult;
-                }
-                if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE && 
-                        resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.UPDATE)) {
-                    break;
-                }
-            }
-
-            if ( finalGateResult == GateResult.GRANTED ) {
-                result = true;
-            } else if ( finalGateResult == GateResult.DENIED ) {
-                result = false;
-            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
-            {
-                result = true;
-            }
-        }
-        return result;
+        return canDoOperation(ResourceAccessGate.Operation.UPDATE, resource.getPath(), gate -> gate.hasUpdateRestrictions(resource.getResourceResolver()), gate -> gate.canUpdate(resource));
     }
 
     @Override
     public boolean canDelete(final Resource resource) {
-        final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
-                resource.getPath(), ResourceAccessGate.Operation.DELETE);
-        boolean result = this.defaultAllowIfNoGateMatches;
-        if ( handlers != null ) {
-            GateResult finalGateResult = null;
-            boolean noGateMatched = true;
-
-            while ( handlers.hasNext() ) {
-                noGateMatched = false;
-                final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();
-
-                final GateResult gateResult = !resourceAccessGateHandler
-                        .getResourceAccessGate().hasDeleteRestrictions(resource.getResourceResolver()) ? GateResult.GRANTED
-                        : resourceAccessGateHandler.getResourceAccessGate()
-                                .canDelete(resource);
-                if (finalGateResult == null) {
-                    finalGateResult = gateResult;
-                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
-                    finalGateResult = gateResult;
-                }
-                if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE && 
-                        resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.DELETE)) {
-                    break;
-                }
-            }
-
-            if ( finalGateResult == GateResult.GRANTED ) {
-                result = true;
-            } else if ( finalGateResult == GateResult.DENIED ) {
-                result = false;
-            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
-            {
-                result = true;
-            }
-        }
-        return result;
+        return canDoOperation(ResourceAccessGate.Operation.DELETE, resource.getPath(), gate -> gate.hasDeleteRestrictions(resource.getResourceResolver()), gate -> gate.canDelete(resource));
     }
 
     @Override
     public boolean canExecute(final Resource resource) {
-        final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
-                resource.getPath(), ResourceAccessGate.Operation.EXECUTE);
-        boolean result = this.defaultAllowIfNoGateMatches;
-        if ( handlers != null ) {
-            GateResult finalGateResult = null;
-            boolean noGateMatched = true;
-
-            while ( handlers.hasNext() ) {
-                noGateMatched = false;
-                final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();
-
-                final GateResult gateResult = !resourceAccessGateHandler
-                        .getResourceAccessGate().hasExecuteRestrictions(resource.getResourceResolver()) ? GateResult.GRANTED
-                        : resourceAccessGateHandler.getResourceAccessGate()
-                                .canExecute(resource);
-                if (finalGateResult == null) {
-                    finalGateResult = gateResult;
-                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
-                    finalGateResult = gateResult;
-                }
-                if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE && resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.EXECUTE)) {
-                    break;
-                }
-            }
-
-            if ( finalGateResult == GateResult.GRANTED ) {
-                result = true;
-            } else if ( finalGateResult == GateResult.DENIED ) {
-                result = false;
-            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
-            {
-                result = true;
-            }
-        }
-        return result;
+        return canDoOperation(ResourceAccessGate.Operation.EXECUTE, resource.getPath(), gate -> gate.hasExecuteRestrictions(resource.getResourceResolver()), gate -> gate.canExecute(resource));
     }
 
     @Override
@@ -410,31 +271,4 @@ public abstract class ResourceAccessSecurityImpl implements ResourceAccessSecuri
 
         return returnValue;
     }
-
-    /**
-     * Add a new resource access gate
-     */
-    protected void bindResourceAccessGate(final ServiceReference ref) {
-        synchronized ( this ) {
-            final List<ResourceAccessGateHandler> newList = new ArrayList<ResourceAccessGateHandler>(this.allHandlers);
-
-            final ResourceAccessGateHandler h = new ResourceAccessGateHandler(ref);
-            newList.add(h);
-            Collections.sort(newList);
-            this.allHandlers = newList;
-        }
-    }
-
-    /**
-     * Remove a resource access gate
-     */
-    protected void unbindResourceAccessGate(final ServiceReference ref) {
-        synchronized ( this ) {
-            final List<ResourceAccessGateHandler> newList = new ArrayList<ResourceAccessGateHandler>(this.allHandlers);
-
-            final ResourceAccessGateHandler h = new ResourceAccessGateHandler(ref);
-            newList.remove(h);
-            this.allHandlers = newList;
-        }
-    }
 }
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/package-info.java b/src/main/java/org/apache/sling/resourceaccesssecurity/package-info.java
index 8185f6d..26ed69e 100644
--- a/src/main/java/org/apache/sling/resourceaccesssecurity/package-info.java
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/package-info.java
@@ -20,5 +20,5 @@
 @Version("1.1.0")
 package org.apache.sling.resourceaccesssecurity;
 
-import aQute.bnd.annotation.Version;
+import org.osgi.annotation.versioning.Version;
 
diff --git a/src/test/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessSecurityImplTests.java b/src/test/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessSecurityImplTests.java
index b876151..ca5203a 100644
--- a/src/test/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessSecurityImplTests.java
+++ b/src/test/java/org/apache/sling/resourceaccesssecurity/impl/ResourceAccessSecurityImplTests.java
@@ -19,41 +19,32 @@
 package org.apache.sling.resourceaccesssecurity.impl;
 
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+
 import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.security.ResourceAccessSecurity;
 import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
-import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
-
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
-
-import static org.junit.Assert.assertTrue;
+import org.osgi.service.component.ComponentContext;
 
 public class ResourceAccessSecurityImplTests {
 
-    ServiceReference serviceReference;
+    ServiceReference<ResourceAccessGate> serviceReference;
     ResourceAccessSecurity resourceAccessSecurity;
     ResourceAccessGate resourceAccessGate;
 
-    @Before
-    public void setUp() {
-        resourceAccessSecurity = new ProviderResourceAccessSecurityImpl();
-    }
-
-
     @Test
     public void testCanUpdate(){
         initMocks("/content", new String[] { "update"} );
@@ -191,25 +182,19 @@ public class ResourceAccessSecurityImplTests {
 
     private void initMocks(String path, String[] operations){
         serviceReference = mock(ServiceReference.class);
-        Bundle bundle = mock(Bundle.class);
-        BundleContext bundleContext = mock(BundleContext.class);
         resourceAccessGate = mock(ResourceAccessGate.class);
 
-        when(serviceReference.getBundle()).thenReturn(bundle);
-        when(bundle.getBundleContext()).thenReturn(bundleContext);
-        when(bundleContext.getService(serviceReference)).thenReturn(resourceAccessGate);
-
-        when(resourceAccessGate.hasReadRestrictions(Mockito.any(ResourceResolver.class))).thenReturn(true);
-        when(resourceAccessGate.hasCreateRestrictions(Mockito.any(ResourceResolver.class))).thenReturn(true);
-        when(resourceAccessGate.hasUpdateRestrictions(Mockito.any(ResourceResolver.class))).thenReturn(true);
-        when(resourceAccessGate.hasOrderChildrenRestrictions(Mockito.any(ResourceResolver.class))).thenReturn(true);
+        when(resourceAccessGate.hasReadRestrictions(Mockito.any())).thenReturn(true);
+        when(resourceAccessGate.hasCreateRestrictions(Mockito.any())).thenReturn(true);
+        when(resourceAccessGate.hasUpdateRestrictions(Mockito.any())).thenReturn(true);
+        when(resourceAccessGate.hasOrderChildrenRestrictions(Mockito.any())).thenReturn(true);
 
         when(serviceReference.getProperty(ResourceAccessGate.PATH)).thenReturn(path);
         when(serviceReference.getProperty(ResourceAccessGate.OPERATIONS)).thenReturn(operations);
 
-        ((ProviderResourceAccessSecurityImpl) resourceAccessSecurity).bindResourceAccessGate(serviceReference);
+        ComponentContext context = mock(ComponentContext.class);
+        when(context.locateService(Mockito.anyString(), Mockito.eq(serviceReference))).thenReturn(resourceAccessGate);
+        resourceAccessSecurity = new ProviderResourceAccessSecurityImpl(Collections.singletonList(serviceReference), context);
     }
 
-
-
 }