You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by my...@apache.org on 2013/03/04 15:23:35 UTC

svn commit: r1452322 - in /sling/trunk/bundles: api/src/main/java/org/apache/sling/api/resource/ resourceresolver/ resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ resourceresolver/src/main/java/org/apache/sling/resourcereso...

Author: mykee
Date: Mon Mar  4 14:23:34 2013
New Revision: 1452322

URL: http://svn.apache.org/r1452322
Log:
SLING-2698 Add a minimal resource access gate, first shot

Added:
    sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/AccessGateException.java
    sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceAccessGate.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java
Modified:
    sling/trunk/bundles/resourceresolver/pom.xml

Added: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/AccessGateException.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/AccessGateException.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/AccessGateException.java (added)
+++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/AccessGateException.java Mon Mar  4 14:23:34 2013
@@ -0,0 +1,69 @@
+/*
+ * 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.api.resource;
+
+/**
+ * Exception thrown by
+ * <code>{@link ResourceAccessGate#sanitizeQuery(String, String, org.apache.sling.auth.core.spi.AuthenticationInfo)}</code>
+ * if the query is not allowed or illegal.
+ */
+public class AccessGateException extends Exception {
+
+    private static final long serialVersionUID = -8388988380137140280L;
+
+    /**
+     * Constructs a new instance of this class with <code>null</code> as its
+     * detail message.
+     */
+    public AccessGateException() {
+        super();
+    }
+
+    /**
+     * Constructs a new instance of this class with the specified detail
+     * message.
+     *
+     * @param message the detail message. The detail message is saved for later
+     *            retrieval by the {@link #getMessage()} method.
+     */
+    public AccessGateException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new instance of this class with the specified detail message
+     * and root cause.
+     *
+     * @param message the detail message. The detail message is saved for later
+     *            retrieval by the {@link #getMessage()} method.
+     * @param rootCause root failure cause
+     */
+    public AccessGateException(String message, Throwable rootCause) {
+        super(message, rootCause);
+    }
+
+    /**
+     * Constructs a new instance of this class with the specified root cause.
+     *
+     * @param rootCause root failure cause
+     */
+    public AccessGateException(Throwable rootCause) {
+        super(rootCause);
+    }
+}

Added: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceAccessGate.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceAccessGate.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceAccessGate.java (added)
+++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceAccessGate.java Mon Mar  4 14:23:34 2013
@@ -0,0 +1,145 @@
+/*
+ * 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.api.resource;
+
+
+/**
+ * The <code>ResourceAccessGate</code> defines a service API which might 
+ * be used to make some restrictions to accessing resources.
+ * 
+ * Implementations of this service interface must be registered like
+ * ResourceProvider with a path (like provider.roots). If different
+ * ResourceAccessGateService services match a path, not only the
+ * ResourceAccessGateService with the longest path should be called, but all
+ * of them, that's in contrast to the ResourceProvider, but in this case more
+ * logical (and secure!).
+
+ * service properties:
+ * <ul>
+ * <li><b>path</b>: regexp to define on which paths the service should be called
+ * (default .*)</li>
+ * <li><b>operations</b>: set of operations on which the service should be called
+ * ("read,create,update,delete,execute", default all of them)</li>
+ * <li><b>finaloperations</b>: set of operations on which the service answer is final an
+ * no other service should be called (default none of them)</li>
+ * </ul>
+ *
+ */
+public interface ResourceAccessGate {
+    
+    /**
+     * The service name to use when registering implementations of this
+     * interface as services (value is
+     * "org.apache.sling.api.resource.ResourceAccessGate").
+     */
+    String SERVICE_NAME = ResourceAccessGate.class.getName();
+
+    /**
+     * The name of the service registration property containing the path
+     * as a regular expression for which the service should be called 
+     * (value is "path").
+     */
+    String PATH = "path";
+
+    /**
+     * The name of the 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
+     * 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").
+     */
+    String FINALOPERATIONS = "finaloperations";
+
+    /**
+     * <code>GateResult</code> defines 3 possible states which can be returned
+     * by the different canXXX methods of this interface.
+     * <ul>
+     * <li>GRANTED: means no restrictions</li>
+     * <li>DENIED: means no permission for the requested action</li>
+     * <li>DONTCARE: means that the implementation of the service has no information
+     * or can't decide and therefore neither can't grant or deny access</li>
+     * </ul>
+     */
+    public enum GateResult { GRANTED, DENIED, DONTCARE };
+    
+    public enum Operation { READ("read"),
+                            CREATE("create"),
+                            UPDATE("update"),
+                            DELETE("delete"),
+                            EXECUTE("execute");
+    
+        private String text;
+    
+        Operation( String text ) {
+            this.text = text;
+        }
+        
+        public static Operation fromString( String opAsString ) {
+            Operation returnValue = null;
+            
+            for (Operation op : Operation.values()) {
+                if ( opAsString.equals(op.getText()))
+                {
+                    returnValue = op;
+                    break;
+                }
+            }
+            
+            return returnValue;
+        }
+        
+        public String getText(){
+            return this.text;
+        }
+    }
+    
+    
+    public GateResult canRead( Resource resource, String user );
+    public GateResult canCreate( String absPathName, String user );
+    public GateResult canUpdate( Resource resource, String user );
+    public GateResult canDelete( Resource resource, String user );
+    public GateResult canExecute( Resource resource, String user );
+
+    public GateResult canReadValue( Resource resource, String valueName, String user );
+    public GateResult canCreateValue( Resource resource, String valueName, String user );
+    public GateResult canUpdateValue( Resource resource, String valueName, String user );
+    public GateResult canDeleteValue( Resource resource, String valueName, String user );
+
+    public String sanitizeQuery( String query, String language, String user ) throws AccessGateException;
+
+    /* for convenience (and performance) */
+    public boolean hasReadRestrictions( String user );
+    public boolean hasCreateRestrictions( String user );
+    public boolean hasUpdateRestrictions( String user );
+    public boolean hasDeleteRestrictions( String user );
+    public boolean hasExecuteRestrictions( String user );
+
+    public boolean canReadAllValues( Resource resource, String user );
+    public boolean canCreateAllValues( Resource resource, String user );
+    public boolean canUpdateAllValues( Resource resource, String user );
+    public boolean canDeleteAllValues( Resource resource, String user );
+
+}

Modified: sling/trunk/bundles/resourceresolver/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/pom.xml?rev=1452322&r1=1452321&r2=1452322&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/pom.xml (original)
+++ sling/trunk/bundles/resourceresolver/pom.xml Mon Mar  4 14:23:34 2013
@@ -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>

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java Mon Mar  4 14:23:34 2013
@@ -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;
+    }
+    
+}

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java Mon Mar  4 14:23:34 2013
@@ -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 );
+}

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java Mon Mar  4 14:23:34 2013
@@ -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 );
+    }
+    
+}

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java Mon Mar  4 14:23:34 2013
@@ -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);
+    }
+
+
+}

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java Mon Mar  4 14:23:34 2013
@@ -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 );
+    }
+
+}

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java Mon Mar  4 14:23:34 2013
@@ -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();
+    }
+
+}

Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java?rev=1452322&view=auto
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java (added)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java Mon Mar  4 14:23:34 2013
@@ -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;
+        }
+    }
+    
+}



Re: svn commit: r1452322 - in /sling/trunk/bundles: api/src/main/java/org/apache/sling/api/resource/ resourceresolver/ resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ resourceresolver/src/main/java/org/apache/sling/resource...

Posted by Felix Meschberger <fm...@adobe.com>.
Hi

Apart from some conceptual discussion which we might lead on the issue or on different threads in the list, here are some concrete comments to the commit:


Am 04.03.2013 um 15:23 schrieb <my...@apache.org> <my...@apache.org>:

> sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/AccessGateException.java

If this exception is checked, it should probably extend from SecurityException.

>    sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceAccessGate.java

JavaDoc missing ... particularly just from looking at the method, I don't understand what "sanitizeQuery" does. The name sounds strange ...

Where is this service implemented ?

>    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/
>    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateHandler.java
>    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/ResourceAccessGateManager.java

Should these classes really be exported ? It looks wrong to export them, particularly because they are only used internally. 

Suggest to move them to impl.

ResourceAccessGateHandler should probably use Set<Operation> instead of List<Operation> to improve on "contains" and also because the indicated operations probably conceptually are sets of operations.

>    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/
>    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceDecorator.java

This class is confusing: It has a @Reference for ResourceAccessGateManager but no @Component but a constructor taking a ResourceAccessHateManagerTracker ...

Looks like the @Reference annotation is superfluous.

>    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/AccessGateResourceWrapper.java

accessGatesForValues is unused -- what is it intended for ?

>    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerImpl.java
>    

I have the impression that this does not need to be a service -- it does not even need to be a separate class: The singleton instance is created on first registration of a ResourceAccessGate and removed on unregistration of the last ResourceAccessGate. This singleton instance is then used by the singleton AccessGateResourceDecorator which is registered for the ResourceResolver to decorate resources.

Probably the AccessGateResourceDecorator could manage the ResourceAccessGate services itself and just register and unregister itself as a ResourceDecorator.


> sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateManagerTracker.java

As per the above, this is not needed.

>    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/accessgate/impl/ResourceAccessGateTracker.java
> Modified:
>    sling/trunk/bundles/resourceresolver/pom.xml

Regards
Felix