You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:00:57 UTC

[sling-org-apache-sling-resourceresolver] 13/24: SLING-2698 Add a minimal resource access gate, first shot

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

rombert pushed a commit to annotated tag org.apache.sling.resourceresolver-1.0.6
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git

commit 26732dab843e3be73618e453f18522532aec51c2
Author: Mike Müller <my...@apache.org>
AuthorDate: Mon Mar 4 14:23:34 2013 +0000

    SLING-2698 Add a minimal resource access gate, first shot
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/resourceresolver@1452322 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |   5 +-
 .../accessgate/ResourceAccessGateHandler.java      | 108 +++++++++++++++++++
 .../accessgate/ResourceAccessGateManager.java      |  28 +++++
 .../impl/AccessGateResourceDecorator.java          | 108 +++++++++++++++++++
 .../accessgate/impl/AccessGateResourceWrapper.java |  59 +++++++++++
 .../impl/ResourceAccessGateManagerImpl.java        |  87 ++++++++++++++++
 .../impl/ResourceAccessGateManagerTracker.java     |  38 +++++++
 .../accessgate/impl/ResourceAccessGateTracker.java | 114 +++++++++++++++++++++
 8 files changed, 545 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 2582aca..c917172 100644
--- a/pom.xml
+++ b/pom.xml
@@ -85,7 +85,8 @@
                             *
                         </Import-Package>
                         <Private-Package>
-                            org.apache.sling.resourceresolver.impl.*
+                            org.apache.sling.resourceresolver.impl.*,
+                            org.apache.sling.resourceresolver.accessgate.impl.*
                         </Private-Package>
                     </instructions>
                 </configuration>
@@ -124,7 +125,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.osgi</artifactId>
-            <version>2.1.0</version>
+            <version>2.2.1-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java b/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java
new file mode 100644
index 0000000..1606dd1
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java
@@ -0,0 +1,108 @@
+/*
+ * 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.sling.resourceresolver.accessgate;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.sling.api.resource.ResourceAccessGate;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.framework.ServiceReference;
+
+public class ResourceAccessGateHandler {
+    
+    private ResourceAccessGate resourceAccessGate;
+    
+    private Pattern pathPattern;
+    private List<ResourceAccessGate.Operation> operations = new ArrayList<ResourceAccessGate.Operation>();
+    private List<ResourceAccessGate.Operation> finalOperations = new ArrayList<ResourceAccessGate.Operation>();
+    
+    /**
+     * constructor
+     */
+    public ResourceAccessGateHandler ( ServiceReference resourceAccessGateRef ) {
+        
+        resourceAccessGate = (ResourceAccessGate) resourceAccessGateRef.getBundle().
+                getBundleContext().getService(resourceAccessGateRef);
+        /* extract the service property "path" */
+        String path = (String) resourceAccessGateRef.getProperty(ResourceAccessGate.PATH);
+        if ( path != null ) {
+            pathPattern = Pattern.compile(path);
+        }
+        else
+        {
+            pathPattern = Pattern.compile(".*");
+        }
+        
+        /* extract the service property "operations" */
+        String ops = (String) resourceAccessGateRef.getProperty(ResourceAccessGate.OPERATIONS);
+        if ( ops != null ) {
+            String[] opsArray = PropertiesUtil.toStringArray(ops);
+            for (String opAsString : opsArray) {
+                ResourceAccessGate.Operation operation = ResourceAccessGate.Operation.fromString(opAsString);
+                if ( operation != null )
+                {
+                    operations.add(operation);
+                }
+            }
+        }
+        else
+        {
+           for (ResourceAccessGate.Operation op : ResourceAccessGate.Operation.values() ) {
+               operations.add(op);
+           }
+        }
+        
+        /* extract the service property "finaloperations" */
+        String finOps = (String) resourceAccessGateRef.getProperty(ResourceAccessGate.FINALOPERATIONS);
+        if ( finOps != null ) {
+            String[] finOpsArray = PropertiesUtil.toStringArray(finOps);
+            for (String opAsString : finOpsArray) {
+                ResourceAccessGate.Operation operation = ResourceAccessGate.Operation.fromString(opAsString);
+                if ( operation != null )
+                {
+                    finalOperations.add(operation);
+                }
+            }
+        }
+
+    }
+    
+    public boolean matches ( String path, ResourceAccessGate.Operation operation ) {
+        boolean returnValue = false;
+        
+        if ( operations.contains( operation ) )
+        {
+            Matcher match = pathPattern.matcher(path);
+            returnValue = match.matches();
+        }
+        
+        return returnValue;
+    }
+    
+    public boolean isFinalOperation( ResourceAccessGate.Operation operation ) {
+        return finalOperations.contains(operation);
+    }
+    
+    public ResourceAccessGate getResourceAccessGate () {
+        return resourceAccessGate;
+    }
+    
+}
diff --git a/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java b/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java
new file mode 100644
index 0000000..ba05484
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java
@@ -0,0 +1,28 @@
+/*
+ * 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.sling.resourceresolver.accessgate;
+
+import java.util.List;
+
+import org.apache.sling.api.resource.ResourceAccessGate;
+
+public interface ResourceAccessGateManager {
+
+    public List<ResourceAccessGateHandler> getMatchingResourceAccessGateHandlers ( String path, ResourceAccessGate.Operation operation );
+}
diff --git a/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java
new file mode 100644
index 0000000..aff1a2d
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java
@@ -0,0 +1,108 @@
+/*
+ * 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.sling.resourceresolver.accessgate.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+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.References;
+import org.apache.sling.api.resource.NonExistingResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceDecorator;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceAccessGate;
+import org.apache.sling.api.resource.ResourceAccessGate.GateResult;
+import org.apache.sling.resourceresolver.accessgate.ResourceAccessGateHandler;
+import org.apache.sling.resourceresolver.accessgate.ResourceAccessGateManager;
+
+@References( {
+    @Reference(name = "ResourceAccessGateManager", referenceInterface = ResourceAccessGateManager.class, cardinality = ReferenceCardinality.MANDATORY_UNARY, policy = ReferencePolicy.DYNAMIC, bind = "setResourceAccessGateManager", unbind = "unsetResourceAccessGateManager") })
+
+public class AccessGateResourceDecorator implements ResourceDecorator {
+    
+    private ResourceAccessGateManagerTracker resAccessGateManagerTracker;
+    
+    public AccessGateResourceDecorator ( ResourceAccessGateManagerTracker resAccessGateManagerTracker ) {
+        this.resAccessGateManagerTracker = resAccessGateManagerTracker;
+    }
+
+    @Override
+    public Resource decorate(Resource resource) {
+        Resource returnValue = resource;
+        ResourceResolver resResolver = resource.getResourceResolver();
+        String user = resResolver.getUserID();
+        ResourceAccessGateManager resourceAccessGateManager = resAccessGateManagerTracker.getResourceAccessGateManager();
+        
+        if ( resourceAccessGateManager != null ) {
+            List<ResourceAccessGateHandler> accessGateHandlers =
+                    resourceAccessGateManager.getMatchingResourceAccessGateHandlers( resource.getPath(), ResourceAccessGate.Operation.READ );
+            
+            GateResult finalGateResult = null;
+            boolean canReadAllValues = false;
+            List<ResourceAccessGate> accessGatesForValues = null;
+            
+            for (ResourceAccessGateHandler resourceAccessGateHandler : accessGateHandlers) {
+                GateResult gateResult = resourceAccessGateHandler.getResourceAccessGate().canRead(resource, user);
+                if ( !canReadAllValues && gateResult == GateResult.GRANTED ) {
+                    if ( resourceAccessGateHandler.getResourceAccessGate().canReadAllValues(resource, user) ) {
+                        canReadAllValues = true;
+                        accessGatesForValues = null;
+                    }
+                    else {
+                        if ( accessGatesForValues == null ) {
+                            accessGatesForValues = new ArrayList<ResourceAccessGate>();
+                        }
+                        accessGatesForValues.add( resourceAccessGateHandler.getResourceAccessGate() );
+                    }
+                }
+                if ( finalGateResult == null ) {
+                    finalGateResult = gateResult;
+                }
+                else if ( finalGateResult == GateResult.DENIED ){
+                    finalGateResult = gateResult;
+                }
+                if ( resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.READ) ) {
+                    break;
+                }
+            }
+            
+            // wrap Resource if read access is not or partly (values) not granted 
+            if ( finalGateResult == GateResult.DENIED ) {
+                returnValue = new NonExistingResource( resResolver, resource.getPath() );
+            }
+            else if ( finalGateResult == GateResult.DONTCARE ) {
+                returnValue = resource;
+            }
+            else if ( !canReadAllValues ) {
+                returnValue = new AccessGateResourceWrapper( resource, accessGatesForValues );
+            }
+        }
+        
+        return returnValue;
+    }
+
+    @Override
+    public Resource decorate(Resource resource, HttpServletRequest request) {
+        return decorate( resource );
+    }
+    
+}
diff --git a/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java
new file mode 100644
index 0000000..f5b7e9c
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java
@@ -0,0 +1,59 @@
+/*
+ * 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.sling.resourceresolver.accessgate.impl;
+
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceAccessGate;
+import org.apache.sling.api.resource.ResourceWrapper;
+
+/**
+ * The <code>AccessGateResourceWrapper</code> wraps a <code>Resource</code> and 
+ * intercepts calls to adaptTo to wrap the adapted <code>ValueMap</code> or
+ * also a <code>ModifiableValueMap</code> to enforce access rules defined
+ * by implementations of <code>ResourceAccessGate</code>
+ *
+ */
+public class AccessGateResourceWrapper extends ResourceWrapper {
+    
+    private List<ResourceAccessGate> accessGatesForValues;
+    
+    /**
+     * Creates a new wrapper instance delegating all method calls to the given
+     * <code>resource</code>, but intercepts the calls with checks to the
+     * applied ResourceAccessGate instances.
+     */
+    public AccessGateResourceWrapper(final Resource resource, final List<ResourceAccessGate> accessGatesForValues) {
+        super( resource );
+        this.accessGatesForValues = accessGatesForValues;
+    }
+
+    /**
+     * Returns the value of calling <code>adaptTo</code> on the
+     * {@link #getResource() wrapped resource}.
+     */
+    @Override
+    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+        //TODO intercept adaptions of ValueMap
+        return getResource().adaptTo(type);
+    }
+
+
+}
diff --git a/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java
new file mode 100644
index 0000000..a3cd4f0
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java
@@ -0,0 +1,87 @@
+/*
+ * 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.sling.resourceresolver.accessgate.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.ResourceAccessGate;
+import org.apache.sling.resourceresolver.accessgate.ResourceAccessGateHandler;
+import org.apache.sling.resourceresolver.accessgate.ResourceAccessGateManager;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.ComponentContext;
+
+@Component(
+        name = "org.apache.sling.resourceresolver.accessgate.ResourceAccessGateManager",
+        immediate = true )
+@Service( value={ResourceAccessGateManager.class})
+   @Properties({
+       @Property(name = Constants.SERVICE_DESCRIPTION, value = "Apache Sling ResourceAccessGateManager"),
+       @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation")
+   })
+public class ResourceAccessGateManagerImpl implements ResourceAccessGateManager {
+    
+    private ResourceAccessGateTracker resourceAccessGateTracker;
+
+    // ---------- SCR Integration ---------------------------------------------
+
+    /** Activates this component, called by SCR before registering as a service */
+    @Activate
+    protected void activate(final ComponentContext componentContext) {
+        resourceAccessGateTracker = new ResourceAccessGateTracker( componentContext.getBundleContext() );
+        resourceAccessGateTracker.open();
+        
+    }
+
+    /**
+     * Deativates this component (called by SCR to take out of service)
+     */
+    @Deactivate
+    protected void deactivate() {
+        resourceAccessGateTracker.close();
+    }
+    
+    public List<ResourceAccessGateHandler> getMatchingResourceAccessGateHandlers ( String path, ResourceAccessGate.Operation operation ) {
+        /* TODO: maybe caching some frequent paths with read operation would be a good idea */
+        List<ResourceAccessGateHandler> returnValue = resourceAccessGateTracker.getResourceAccessGateHandlers();
+        
+        if ( returnValue.size() > 0 ) {
+            returnValue = new ArrayList<ResourceAccessGateHandler>();
+            
+            for (ResourceAccessGateHandler resourceAccessGateHandler : resourceAccessGateTracker.getResourceAccessGateHandlers() ) {
+                if ( resourceAccessGateHandler.matches(path, operation) ) {
+                    returnValue.add(resourceAccessGateHandler);
+                }
+            }
+        }
+        
+        return returnValue;
+    }
+    
+    public boolean areResourceAccessGatesRegistered () {
+        return (resourceAccessGateTracker.size() > 0 );
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java
new file mode 100644
index 0000000..67ed1cc
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java
@@ -0,0 +1,38 @@
+/*
+ * 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.sling.resourceresolver.accessgate.impl;
+
+import org.apache.sling.resourceresolver.accessgate.ResourceAccessGateManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class ResourceAccessGateManagerTracker extends ServiceTracker {
+
+    /**
+     * Constructor
+     */
+    public ResourceAccessGateManagerTracker(final BundleContext context) {
+        super(context, ResourceAccessGateManager.class.getName(), null);
+    }
+    
+    public ResourceAccessGateManager getResourceAccessGateManager () {
+        return (ResourceAccessGateManager) getService();
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java
new file mode 100644
index 0000000..304c264
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java
@@ -0,0 +1,114 @@
+/*
+ * 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.sling.resourceresolver.accessgate.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sling.api.resource.ResourceAccessGate;
+import org.apache.sling.api.resource.ResourceDecorator;
+import org.apache.sling.commons.osgi.SortingServiceTracker;
+import org.apache.sling.resourceresolver.accessgate.ResourceAccessGateHandler;
+import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ResourceAccessGateTracker extends SortingServiceTracker<ResourceAccessGate> {
+    
+    private List<ResourceAccessGateHandler> resourceAccessGateHandlers = null;
+    private ServiceRegistration decoratorRegistration = null;
+    private ResourceAccessGateManagerTracker resAccessGateManagerTracker = null;
+    
+    /**
+     * Constructor
+     */
+    public ResourceAccessGateTracker(final BundleContext context ) {
+        super(context, ResourceAccessGate.class.getName());
+    }
+
+    /**
+     * @see org.osgi.util.tracker.ServiceTracker#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
+     */
+    @Override
+    public void removedService(ServiceReference reference, Object service) {
+        super.removedService(reference, service);
+        resourceAccessGateHandlers = null;
+        registerAccessGateResourceDecorator( reference.getBundle().getBundleContext(), size() );
+    }
+
+    /**
+     * @see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
+     */
+    @Override
+    public void modifiedService(ServiceReference reference, Object service) {
+        super.modifiedService(reference, service);
+        resourceAccessGateHandlers = null;
+    }
+
+    /**
+     * @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
+     */
+    @Override
+    public Object addingService(ServiceReference reference) {
+        Object returnValue = super.addingService(reference);
+        resourceAccessGateHandlers = null;
+        registerAccessGateResourceDecorator( reference.getBundle().getBundleContext(), size() + 1 );
+        return returnValue;
+    }
+    
+    public List<ResourceAccessGateHandler> getResourceAccessGateHandlers () {
+        List<ResourceAccessGateHandler> returnValue = resourceAccessGateHandlers;
+        
+        if ( returnValue == null )
+        {
+            resourceAccessGateHandlers = new ArrayList<ResourceAccessGateHandler>();
+            for (ServiceReference serviceReference : getSortedServiceReferences()) {
+                resourceAccessGateHandlers.add( new ResourceAccessGateHandler(serviceReference) );
+            }
+            resourceAccessGateHandlers = Collections.unmodifiableList(resourceAccessGateHandlers);
+            returnValue = resourceAccessGateHandlers;
+        }
+        
+        return returnValue;
+    }
+    
+    private void registerAccessGateResourceDecorator ( BundleContext bundleContext, int nrOfServices ) {
+        if ( decoratorRegistration == null && nrOfServices > 0 ) {
+            synchronized( this ) {
+                resAccessGateManagerTracker = new ResourceAccessGateManagerTracker( bundleContext );
+                resAccessGateManagerTracker.open();
+                decoratorRegistration = bundleContext.registerService( ResourceDecorator.class.getName(), 
+                        new AccessGateResourceDecorator( resAccessGateManagerTracker ), null);
+            }
+        }
+        else if ( decoratorRegistration != null && nrOfServices == 0 )
+        {
+            synchronized( this ) {
+                decoratorRegistration.unregister();
+                resAccessGateManagerTracker.close();
+            }
+            decoratorRegistration = null;
+        }
+    }
+    
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.