SLING-3435 - ResourceAccessSecurity does not secure access for update operations

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1578141 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..df72294
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>18</version>
+        <relativePath>../../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.resourceaccesssecurity.it</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Resource Access Security Integration Tests</name>
+    <description>
+        Project hat tests functionality for org.apache.sling.resourceaccesssecurity and org.apache.sling.jcr.resourcesecurity bundles.
+    </description>
+    
+    <!-- 
+        To keep the instance under test running and run individual tests
+        against it, use:
+        
+            mvn clean verify -DkeepJarRunning=true -Dhttp.port=8080
+            
+        optionally using jar.executor.vm.options to enable remote debugging,
+        and in another console:
+        
+            mvn -o verify -Dtests.to.run=**/**Test.java -Dtest.server.url=http://localhost:8080
+            
+        optionally using -Dmaven.surefire.debug to enable debugging.            
+     -->
+    <properties>
+        <!-- Set this to run the server on a specific port
+        <http.port></http.port>
+         -->
+         
+        <!-- Set this to run tests against an existing server instance -->
+        <keepJarRunning>false</keepJarRunning>
+        
+        <!-- URL of a server against which to run tests -->
+        <!-- <test.server.url>http://localhost:8080</test.server.url> -->
+        <test.server.url />
+        
+         <!-- Set this to run tests against a specific hostname, if test.server.url is not set-->
+         <test.server.hostname />
+
+        <!-- Set this to use a different username for remote execution of sling junit tests -->
+        <test.server.username />
+
+        <!-- Set this to use a different password for remote execution of sling junit tests -->
+        <test.server.password />
+        
+        <!-- Options for the VM that executes our runnable jar -->
+        <!--<jar.executor.vm.options>-Xmx512m -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -Xnoagent -Djava.compiler=NONE</jar.executor.vm.options>  -->
+         <jar.executor.vm.options>-Xmx512m</jar.executor.vm.options> 
+        
+        <!-- Change this to use longer or shorter timeouts for testing -->
+        <sling.testing.timeout.multiplier>1.0</sling.testing.timeout.multiplier>
+        
+        <!-- Set this to run the executable jar in a specified filesystem folder -->
+        <jar.executor.work.folder />
+        
+        <!-- Options for the jar to execute. $JAREXEC_SERVER_PORT$ is replaced by the
+            selected port number -->
+        <jar.executor.jar.options>-p $JAREXEC_SERVER_PORT$</jar.executor.jar.options>
+        
+        <!-- Change this to run selected tests only -->
+        <tests.to.run>**/**Test.java</tests.to.run>
+    </properties>
+    
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/testing/samples/integration-tests</connection>
+        <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/testing/samples/integration-tests</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/testing/samples/integration-tests</url>
+    </scm>
+
+    <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>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>org.apache.sling.resourceaccesssecurity.it</Bundle-SymbolicName>
+                        <Sling-Initial-Content>SLING-CONTENT/content/test;path:=/content/test;overwrite:=true,
+                            SLING-CONTENT/libs/test;path:=/libs/test;overwrite:=true</Sling-Initial-Content>
+                        <Export-Package>
+                            org.apache.sling.resourceaccesssecurity.it
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+            </plugin>
+
+           <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>${basedir}</directory>
+                            <includes>
+                                <!-- sling folder is the workdir of the executable jar that we test -->
+                                <include>sling/**</include>
+                            </includes>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-runnable-jar</id>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                            <phase>process-resources</phase>
+                        <configuration>
+                            <includeArtifactIds>org.apache.sling.launchpad</includeArtifactIds>
+                            <excludeTransitive>true</excludeTransitive>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>false</overWriteSnapshots>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <!-- 
+                            Consider all dependencies as candidates to be installed
+                            as additional bundles. We use system properties to define
+                            which bundles to install in which order.  
+                        -->
+                        <id>copy-additional-bundles</id>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                            <phase>process-resources</phase>
+                        <configuration>
+                            <outputDirectory>${project.build.directory}/sling/additional-bundles</outputDirectory>
+                            <excludeTransitive>true</excludeTransitive>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>false</overWriteSnapshots>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <!-- Find free ports to run our server -->
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>reserve-server-port</id>
+                        <goals>
+                            <goal>reserve-network-port</goal>
+                        </goals>
+                        <phase>process-resources</phase>
+                        <configuration>
+                            <portNames>
+                                <portName>http.port</portName>
+                            </portNames>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <!-- We run all tests in the integration-tests phase -->
+                    <excludes>
+                        <exclude>**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>integration-test</id>
+                        <goals>
+                            <goal>integration-test</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>verify</id>
+                        <goals>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <debugForkedProcess>${maven.surefire.debug}</debugForkedProcess>
+                    <includes>
+                        <include>${tests.to.run}</include>
+                    </includes>
+                    <systemPropertyVariables>
+                        <test.server.url>${test.server.url}</test.server.url>
+                        <test.server.hostname>${test.server.hostname}</test.server.hostname>
+                        <test.server.username>${test.server.username}</test.server.username>
+                        <test.server.password>${test.server.password}</test.server.password>
+                        <server.ready.timeout.seconds>300</server.ready.timeout.seconds>
+                        <jar.executor.server.port>${http.port}</jar.executor.server.port>
+                        <jar.executor.vm.options>${jar.executor.vm.options}</jar.executor.vm.options>
+                        <jar.executor.jar.folder>${project.basedir}/target/dependency</jar.executor.jar.folder>
+                        <jar.executor.jar.name.regexp>org.apache.sling.launchpad.*jar$</jar.executor.jar.name.regexp>
+                        <jar.executor.work.folder>${jar.executor.work.folder}</jar.executor.work.folder>
+                        <jar.executor.jar.options>${jar.executor.jar.options}</jar.executor.jar.options>
+                        <additional.bundles.path>${project.build.directory},${project.build.directory}/sling/additional-bundles</additional.bundles.path>
+                        <keepJarRunning>${keepJarRunning}</keepJarRunning>
+                        <sling.testing.timeout.multiplier>${sling.testing.timeout.multiplier}</sling.testing.timeout.multiplier>
+                        <server.ready.path.1>/:script src="system/sling.js"</server.ready.path.1>
+                        <server.ready.path.2>/.explorer.html:href="/libs/sling/explorer/css/explorer.css"</server.ready.path.2>
+                        <server.ready.path.3>/sling-test/sling/sling-test.html:Sling client library tests</server.ready.path.3>
+                        <start.bundles.timeout.seconds>30</start.bundles.timeout.seconds>
+                        <bundle.install.timeout.seconds>20</bundle.install.timeout.seconds>
+                        
+                        <!-- 
+                            Define additional bundles to install by specifying the beginning of their artifact name.
+                            The bundles are installed in lexical order of these property names.
+                            All bundles must be listed as dependencies in this pom, or they won't be installed. 
+                        -->
+
+                        <sling.additional.bundle.5>org.apache.sling.resourceaccesssecurity-</sling.additional.bundle.5>
+                        <sling.additional.bundle.6>org.apache.sling.jcr.resourcesecurity-</sling.additional.bundle.6>
+                        <sling.additional.bundle.7>${project.build.finalName}.jar</sling.additional.bundle.7>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+         </plugins>
+    </build>
+
+    <dependencies>
+        <!-- Additional bundles needed by the Sling instance under test -->
+
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.tools</artifactId>
+            <version>1.0.7-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        
+        <!-- sling testing tools bundles requires httpclient -->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient-osgi</artifactId>
+            <version>4.1.2</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore-osgi</artifactId>
+            <version>4.1.2</version>
+            <scope>provided</scope>
+        </dependency>
+        
+        <!-- actual dependencies -->
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.json</artifactId>
+            <version>2.0.6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.launchpad</artifactId>
+            <classifier>standalone</classifier>
+            <version>7-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.5.11</version>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>1.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.5.11</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.6.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-api</artifactId>
+            <version>2.7.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-jcr-commons</artifactId>
+            <version>2.7.2</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.jcr</groupId>
+            <artifactId>jcr</artifactId>
+            <version>2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.resourceaccesssecurity</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+
+    </dependencies>
+</project>
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/Init.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/Init.java
new file mode 100644
index 0000000..e8a40b3
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/Init.java
@@ -0,0 +1,68 @@
+/*
+ * 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.resourceaccesssecurity.it.impl;
+
+import java.security.Principal;
+
+import javax.jcr.Session;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+
+@Component(metatype = false)
+public class Init extends SlingAllMethodsServlet {
+
+
+    @Reference
+    ResourceResolverFactory resourceResolverFactory;
+
+    @Activate
+    protected void activate() {
+
+
+        try {
+            ResourceResolver resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(null);
+
+            Session session = resourceResolver.adaptTo(Session.class);
+
+            JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
+
+            UserManager userManager =  jackrabbitSession.getUserManager();
+
+
+            if (userManager.getAuthorizable("testUser") == null) {
+                userManager.createUser("testUser", "password");
+            }
+
+
+            final Principal testUserPrincipal = new Principal() {
+                public String getName() {
+                    return "testUser";
+                }};
+
+        } catch (Exception e) {
+            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/AResourceAccessGate.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/AResourceAccessGate.java
new file mode 100644
index 0000000..075e9fb
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/AResourceAccessGate.java
@@ -0,0 +1,89 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate.GateResult;
+
+import java.util.Map;
+
+public abstract class AResourceAccessGate extends AllowingResourceAccessGate implements ResourceAccessGate {
+
+
+    @Activate
+    protected void activate(final Map<String, Object> props) {
+    }
+    
+    /**
+     * gets the gate id which will be used to distinguish the different implementations
+     * of the gate
+     * @return
+     */
+    protected abstract String getGateId ();
+
+    @Override
+    public GateResult canRead(Resource resource) {
+        GateResult returnValue = GateResult.DONTCARE;
+        
+        if ( resource.getPath().contains( getGateId() + "-denyread") )
+        {
+            returnValue = GateResult.DENIED;
+        }
+        else if ( resource.getPath().contains( getGateId() + "-allowread") )
+        {
+            returnValue = GateResult.GRANTED;
+        }
+        
+        return returnValue;
+    }
+
+    @Override
+    public boolean hasReadRestrictions(ResourceResolver resourceResolver) {
+        return true;
+    }
+    
+    @Override
+    public GateResult canUpdate(Resource resource) {
+        GateResult returnValue = GateResult.DONTCARE;
+        
+        if ( resource.getPath().contains( getGateId() + "-denyupdate") )
+        {
+            returnValue = GateResult.DENIED;
+        }
+        else if ( resource.getPath().contains( getGateId() + "-allowupdate") )
+        {
+            returnValue = GateResult.GRANTED;
+        }
+        
+        return returnValue;
+    }
+
+    @Override
+    public boolean hasUpdateRestrictions(ResourceResolver resourceResolver) {
+        return true;
+    }
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ApplicationGate1.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ApplicationGate1.java
new file mode 100644
index 0000000..dc5982f
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ApplicationGate1.java
@@ -0,0 +1,50 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+
+import java.util.Map;
+
+@Component
+@Service(value=ResourceAccessGate.class)
+@Properties({
+        @Property(name=ResourceAccessGate.PATH, label="Path",
+                description="The path is a regular expression for which resources the service should be called"),
+        @Property(name=ResourceAccessGate.OPERATIONS, value="read,update", propertyPrivate=true),
+        @Property(name=ResourceAccessGate.CONTEXT, value=ResourceAccessGate.APPLICATION_CONTEXT, propertyPrivate=true)
+})
+public class ApplicationGate1 extends AResourceAccessGate implements ResourceAccessGate {
+
+    public static String GATE_ID = "appgate1";
+    
+    @Override
+    protected String getGateId() {
+        return GATE_ID;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ApplicationGate2.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ApplicationGate2.java
new file mode 100644
index 0000000..d927be0
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ApplicationGate2.java
@@ -0,0 +1,50 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+
+import java.util.Map;
+
+@Component
+@Service(value=ResourceAccessGate.class)
+@Properties({
+        @Property(name=ResourceAccessGate.PATH, label="Path",
+                description="The path is a regular expression for which resources the service should be called"),
+        @Property(name=ResourceAccessGate.OPERATIONS, value="read,update", propertyPrivate=true),
+        @Property(name=ResourceAccessGate.CONTEXT, value=ResourceAccessGate.APPLICATION_CONTEXT, propertyPrivate=true)
+})
+public class ApplicationGate2 extends AResourceAccessGate implements ResourceAccessGate {
+
+    public static String GATE_ID = "appgate2";
+    
+    @Override
+    protected String getGateId() {
+        return GATE_ID;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalApplicationGate1.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalApplicationGate1.java
new file mode 100644
index 0000000..47b4c97
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalApplicationGate1.java
@@ -0,0 +1,50 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+
+import java.util.Map;
+
+@Component
+@Service(value=ResourceAccessGate.class)
+@Properties({
+        @Property(name=ResourceAccessGate.PATH, label="Path",
+                description="The path is a regular expression for which resources the service should be called"),
+        @Property(name=ResourceAccessGate.FINALOPERATIONS, value="read,update", propertyPrivate=true),
+        @Property(name=ResourceAccessGate.CONTEXT, value=ResourceAccessGate.APPLICATION_CONTEXT, propertyPrivate=true)
+})
+public class FinalApplicationGate1 extends AResourceAccessGate implements ResourceAccessGate {
+
+    public static String GATE_ID = "finalappgate1";
+    
+    @Override
+    protected String getGateId() {
+        return GATE_ID;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalApplicationGate2.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalApplicationGate2.java
new file mode 100644
index 0000000..7a95703
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalApplicationGate2.java
@@ -0,0 +1,50 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+
+import java.util.Map;
+
+@Component
+@Service(value=ResourceAccessGate.class)
+@Properties({
+        @Property(name=ResourceAccessGate.PATH, label="Path",
+                description="The path is a regular expression for which resources the service should be called"),
+        @Property(name=ResourceAccessGate.FINALOPERATIONS, value="read,update", propertyPrivate=true),
+        @Property(name=ResourceAccessGate.CONTEXT, value=ResourceAccessGate.APPLICATION_CONTEXT, propertyPrivate=true)
+})
+public class FinalApplicationGate2 extends AResourceAccessGate implements ResourceAccessGate {
+
+    public static String GATE_ID = "finalappgate2";
+    
+    @Override
+    protected String getGateId() {
+        return GATE_ID;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalProviderGate1.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalProviderGate1.java
new file mode 100644
index 0000000..445a706
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalProviderGate1.java
@@ -0,0 +1,52 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+import org.osgi.framework.Constants;
+
+import java.util.Map;
+
+@Component
+@Service(value=ResourceAccessGate.class)
+@Properties({
+        @Property(name=ResourceAccessGate.PATH, label="Path",
+                description="The path is a regular expression for which resources the service should be called"),
+        @Property(name=ResourceAccessGate.FINALOPERATIONS, value="read,update", propertyPrivate=true),
+        @Property(name = Constants.SERVICE_RANKING, intValue = 10, propertyPrivate = false),
+        @Property(name=ResourceAccessGate.CONTEXT, value=ResourceAccessGate.PROVIDER_CONTEXT, propertyPrivate=true)
+})
+public class FinalProviderGate1 extends AResourceAccessGate implements ResourceAccessGate {
+
+    public static String GATE_ID = "finalprovidergate1";
+    
+    @Override
+    protected String getGateId() {
+        return GATE_ID;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalProviderGate2.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalProviderGate2.java
new file mode 100644
index 0000000..ff86ff9
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/FinalProviderGate2.java
@@ -0,0 +1,52 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+import org.osgi.framework.Constants;
+
+import java.util.Map;
+
+@Component
+@Service(value=ResourceAccessGate.class)
+@Properties({
+        @Property(name=ResourceAccessGate.PATH, label="Path",
+                description="The path is a regular expression for which resources the service should be called"),
+        @Property(name=ResourceAccessGate.FINALOPERATIONS, value="read,update", propertyPrivate=true),
+        @Property(name = Constants.SERVICE_RANKING, intValue = 5, propertyPrivate = false),
+        @Property(name=ResourceAccessGate.CONTEXT, value=ResourceAccessGate.PROVIDER_CONTEXT, propertyPrivate=true)
+})
+public class FinalProviderGate2 extends AResourceAccessGate implements ResourceAccessGate {
+
+    public static String GATE_ID = "finalprovidergate2";
+    
+    @Override
+    protected String getGateId() {
+        return GATE_ID;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ProviderGate1.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ProviderGate1.java
new file mode 100644
index 0000000..7b6d773
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ProviderGate1.java
@@ -0,0 +1,44 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.resourceaccesssecurity.ResourceAccessGate;
+
+@Component
+@Service(value=ResourceAccessGate.class)
+@Properties({
+        @Property(name=ResourceAccessGate.PATH, label="Path",
+                description="The path is a regular expression for which resources the service should be called"),
+        @Property(name=ResourceAccessGate.OPERATIONS, value="read,update", propertyPrivate=true),
+        @Property(name=ResourceAccessGate.CONTEXT, value=ResourceAccessGate.PROVIDER_CONTEXT, propertyPrivate=true)
+})
+public class ProviderGate1 extends AResourceAccessGate implements ResourceAccessGate {
+
+    public static String GATE_ID = "providergate1";
+    
+    @Override
+    protected String getGateId() {
+        return GATE_ID;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ProviderGate2.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ProviderGate2.java
new file mode 100644
index 0000000..8dda05d
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/gates/ProviderGate2.java
@@ -0,0 +1,50 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.gates;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+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.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
+import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+
+import java.util.Map;
+
+@Component
+@Service(value=ResourceAccessGate.class)
+@Properties({
+        @Property(name=ResourceAccessGate.PATH, label="Path",
+                description="The path is a regular expression for which resources the service should be called"),
+        @Property(name=ResourceAccessGate.OPERATIONS, value="read,update", propertyPrivate=true),
+        @Property(name=ResourceAccessGate.CONTEXT, value=ResourceAccessGate.PROVIDER_CONTEXT, propertyPrivate=true)
+})
+public class ProviderGate2 extends AResourceAccessGate implements ResourceAccessGate {
+
+    public static String GATE_ID = "providergate2";
+    
+    @Override
+    protected String getGateId() {
+        return GATE_ID;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/SimpleModifiableResourceProvider.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/SimpleModifiableResourceProvider.java
new file mode 100644
index 0000000..5b6cdb6
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/SimpleModifiableResourceProvider.java
@@ -0,0 +1,72 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.providers;
+
+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.ResourceWrapper;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.wrappers.ModifiableValueMapDecorator;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SimpleModifiableResourceProvider extends SimpleResourceProvider {
+    static Map<String, Object> properties = new ConcurrentHashMap<String, Object>();
+
+    static {
+        properties.put("initialProperty", "initialValue");
+    }
+
+
+    @Override
+    public Resource getResource(ResourceResolver resourceResolver, String path) {
+        Resource resource = super.getResource(resourceResolver, path);
+
+        if (resource != null) {
+            resource = new ModifiableResource(resource);
+        }
+
+        return resource;
+    }
+
+
+    public class ModifiableResource extends ResourceWrapper {
+        /**
+         * Creates a new wrapper instance delegating all method calls to the given
+         * <code>resource</code>.
+         */
+        public ModifiableResource(Resource resource) {
+            super(resource);
+        }
+
+        @Override
+        public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+            if (type.equals(ModifiableValueMap.class)) {
+                return (AdapterType) new ModifiableValueMapDecorator(properties);
+            }
+            else if (type.equals(Map.class) || type.equals(ValueMap.class)) {
+                return (AdapterType) new ValueMapDecorator(properties);
+            }
+
+            return super.adaptTo(type);    //To change body of overridden methods use File | Settings | File Templates.
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/SimpleResourceProvider.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/SimpleResourceProvider.java
new file mode 100644
index 0000000..a81c898
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/SimpleResourceProvider.java
@@ -0,0 +1,67 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.providers;
+
+
+import org.apache.sling.api.adapter.AdapterManager;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.SyntheticResource;
+
+import javax.servlet.http.HttpServletRequest;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Iterator;
+
+public class SimpleResourceProvider {
+    public Resource getResource(ResourceResolver resourceResolver, HttpServletRequest httpServletRequest, String path) {
+        return getResource(resourceResolver, path);
+    }
+
+    public Resource getResource(ResourceResolver resourceResolver, String path) {
+        if (path.contains("/nonexisting/")) {
+            return null;
+        }
+        return new SyntheticResource(resourceResolver, path, "test/resource"){
+            @SuppressWarnings("unchecked")
+            public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+                AdapterType result = super.adaptTo(type);
+                
+                if ( result == null && type == InputStream.class )
+                {
+                    try {
+                        result = (AdapterType) new ByteArrayInputStream("Test".getBytes("UTF-8") );
+                    } catch (UnsupportedEncodingException e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    }
+                }
+                
+                return result;
+            }
+            
+        };
+    }
+
+    public Iterator<Resource> listChildren(Resource resource) {
+        return null;
+    }
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/secured/SecuredReadAndUpdateResourceProvider.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/secured/SecuredReadAndUpdateResourceProvider.java
new file mode 100644
index 0000000..9a75601
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/secured/SecuredReadAndUpdateResourceProvider.java
@@ -0,0 +1,47 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.providers.secured;
+
+
+import org.apache.felix.scr.annotations.Component;
+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.ModifiableValueMap;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceWrapper;
+import org.apache.sling.api.wrappers.ModifiableValueMapDecorator;
+import org.apache.sling.resourceaccesssecurity.it.impl.providers.SimpleModifiableResourceProvider;
+import org.apache.sling.resourceaccesssecurity.it.impl.providers.SimpleResourceProvider;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component(metatype = true, label = "Secured ResourceProvider")
+@Service(value = ResourceProvider.class)
+@Properties({
+        @Property(name = ResourceProvider.ROOTS, value = "/providers/secured/read-update" ),
+        @Property(name = ResourceProvider.USE_RESOURCE_ACCESS_SECURITY, boolValue=true, propertyPrivate=true),
+        @Property(name = ResourceProvider.OWNS_ROOTS, boolValue=true, propertyPrivate=true)
+})
+public class SecuredReadAndUpdateResourceProvider extends SimpleModifiableResourceProvider implements ResourceProvider {
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/secured/SecuredReadResourceProvider.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/secured/SecuredReadResourceProvider.java
new file mode 100644
index 0000000..a6dcddd
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/secured/SecuredReadResourceProvider.java
@@ -0,0 +1,37 @@
+/*
+ * 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.resourceaccesssecurity.it.impl.providers.secured;
+
+
+import org.apache.felix.scr.annotations.Component;
+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.ResourceProvider;
+import org.apache.sling.resourceaccesssecurity.it.impl.providers.SimpleResourceProvider;
+
+@Component(metatype = true, label = "Secured ResourceProvider")
+@Service(value = ResourceProvider.class)
+@Properties({
+        @Property(name = ResourceProvider.ROOTS, value = "/providers/secured/read" ),
+        @Property(name = ResourceProvider.USE_RESOURCE_ACCESS_SECURITY, boolValue=true, propertyPrivate=true),
+        @Property(name = ResourceProvider.OWNS_ROOTS, boolValue=true, propertyPrivate=true)
+})
+public class SecuredReadResourceProvider extends SimpleResourceProvider implements ResourceProvider {
+
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/unsecured/UnsecuredReadAndUpdateProvider.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/unsecured/UnsecuredReadAndUpdateProvider.java
new file mode 100644
index 0000000..a34ef8c
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/unsecured/UnsecuredReadAndUpdateProvider.java
@@ -0,0 +1,19 @@
+package org.apache.sling.resourceaccesssecurity.it.impl.providers.unsecured;
+
+
+import org.apache.felix.scr.annotations.Component;
+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.ResourceProvider;
+import org.apache.sling.resourceaccesssecurity.it.impl.providers.SimpleModifiableResourceProvider;
+import org.apache.sling.resourceaccesssecurity.it.impl.providers.SimpleResourceProvider;
+
+@Component(metatype = true, label = "Unsecured ResourceProvider")
+@Service(value = ResourceProvider.class)
+@Properties({
+        @Property(name = ResourceProvider.ROOTS, value = "/providers/unsecured/read-update" )
+
+})
+public class UnsecuredReadAndUpdateProvider extends SimpleModifiableResourceProvider implements ResourceProvider {
+}
diff --git a/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/unsecured/UnsecuredReadProvider.java b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/unsecured/UnsecuredReadProvider.java
new file mode 100644
index 0000000..7ee83c2
--- /dev/null
+++ b/src/main/java/org/apache/sling/resourceaccesssecurity/it/impl/providers/unsecured/UnsecuredReadProvider.java
@@ -0,0 +1,18 @@
+package org.apache.sling.resourceaccesssecurity.it.impl.providers.unsecured;
+
+
+import org.apache.felix.scr.annotations.Component;
+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.ResourceProvider;
+import org.apache.sling.resourceaccesssecurity.it.impl.providers.SimpleResourceProvider;
+
+@Component(metatype = true, label = "Unsecured ResourceProvider")
+@Service(value = ResourceProvider.class)
+@Properties({
+        @Property(name = ResourceProvider.ROOTS, value = "/providers/unsecured/read" )
+
+})
+public class UnsecuredReadProvider extends SimpleResourceProvider implements ResourceProvider {
+}
diff --git a/src/test/java/org/apache/sling/resourceaccesssecurity/it/ResourceAccessSecurityTestBase.java b/src/test/java/org/apache/sling/resourceaccesssecurity/it/ResourceAccessSecurityTestBase.java
new file mode 100644
index 0000000..fb6c35e
--- /dev/null
+++ b/src/test/java/org/apache/sling/resourceaccesssecurity/it/ResourceAccessSecurityTestBase.java
@@ -0,0 +1,98 @@
+/*
+ * 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.resourceaccesssecurity.it;
+
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.sling.testing.tools.sling.SlingTestBase;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class ResourceAccessSecurityTestBase extends SlingTestBase {
+
+    public static final String TEST_USERNAME = "testUser";
+    public static final String TEST_PASSWORD = "password";
+
+
+    protected String getTestUsername() {
+        return TEST_USERNAME;
+    }
+
+    protected String getTestPassword() {
+        return TEST_PASSWORD;
+    }
+
+
+    protected void testRead(String username, String password,
+                                String path, int expectedStatus,
+                                String... expectedContent) throws Exception {
+        if ( username == null )
+        {
+            // call without credentials
+            getRequestExecutor().execute(
+                    getRequestBuilder().buildGetRequest(path)
+            ).assertStatus(expectedStatus).assertContentContains(expectedContent);
+        }
+        else
+        {
+            // call with credentials
+            getRequestExecutor().execute(
+                    getRequestBuilder().buildGetRequest(path)
+                           .withCredentials(username, password)
+            ).assertStatus(expectedStatus).assertContentContains(expectedContent);
+            
+        }
+    }
+
+    protected String testUpdate(String username, String password,
+                              String path, int expectedStatus,
+                              String... expectedContent) throws Exception {
+        String addedValue = "addedValue" + UUID.randomUUID().toString();
+        List<NameValuePair> params = new ArrayList<NameValuePair>();
+        params.add(new BasicNameValuePair("addedProperty", addedValue));
+
+        if ( username == null )
+        {
+            // call without credentials
+            getRequestExecutor().execute(
+                    getRequestBuilder().buildPostRequest(path)
+                            .withEntity(new UrlEncodedFormEntity(params))
+            ).assertStatus(expectedStatus).assertContentContains(expectedContent);
+        }
+        else
+        {
+            // call with credentials
+            getRequestExecutor().execute(
+                    getRequestBuilder().buildPostRequest(path)
+                            .withEntity(new UrlEncodedFormEntity(params))
+            ).assertStatus(expectedStatus).assertContentContains(expectedContent);
+           
+        }
+
+        return addedValue;
+    }
+
+}
diff --git a/src/test/java/org/apache/sling/resourceaccesssecurity/it/SecuredProviderResourceAccessSecurityTest.java b/src/test/java/org/apache/sling/resourceaccesssecurity/it/SecuredProviderResourceAccessSecurityTest.java
new file mode 100644
index 0000000..4029002
--- /dev/null
+++ b/src/test/java/org/apache/sling/resourceaccesssecurity/it/SecuredProviderResourceAccessSecurityTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.resourceaccesssecurity.it;
+
+
+import org.junit.Test;
+
+public class SecuredProviderResourceAccessSecurityTest extends ResourceAccessSecurityTestBase {
+
+    @Test
+    public void testNonExistingResource() throws Exception {
+        String path = "/providers/secured/noresource.json";
+
+        testRead(getServerUsername(), getServerPassword(), path, 404);
+        testRead(getTestUsername(), getTestPassword(), path, 404);
+    }
+
+    @Test
+    public void testAllowedReadAccess() throws Exception {
+        String path = "/providers/secured/read/providergate1-allowread_providergate2-denyread/test.json";
+
+        testRead(getServerUsername(), getServerPassword(), path, 200);
+        testRead(getTestUsername(), getTestPassword(), path, 200);
+        testRead(null, null, path, 200);
+    }
+
+    @Test
+    public void testDeniedReadAccessFromNonModifiableProvider() throws Exception {
+        String path = "/providers/secured/read/providergate1-denyread/test.json";
+
+        testRead(getServerUsername(), getServerPassword(), path, 404);
+        testRead(getTestUsername(), getTestPassword(), path, 404);
+        testRead(null, null, path, 404);
+    }
+
+    @Test
+    public void testDeniedReadAccessFromModifiableProvider() throws Exception {
+        String path = "/providers/secured/read-update/providergate1-denyread/test.json";
+
+        testRead(getServerUsername(), getServerPassword(), path, 404);
+        testRead(getTestUsername(), getTestPassword(), path, 404);
+    }
+
+
+    @Test
+    public void testNotDefinedReadAccess() throws Exception {
+        String path = "/providers/secured/read-update/providergate2-denyupdate/test.json";
+
+        testRead(getServerUsername(), getServerPassword(), path, 404);
+        testRead(getTestUsername(), getTestPassword(), path, 404);
+        testRead(null, null, path, 404);
+    }
+
+
+    @Test
+    public void testAllowedReadAndUpdate() throws Exception {
+        String path = "/providers/secured/read-update/providergate2-allowupdate_providergate1-allowread/test.json";
+
+        testRead(getTestUsername(), getTestPassword(), path, 200);
+        testUpdate(getTestUsername(), getTestPassword(), path, 200);
+    }
+
+
+    @Test
+    public void testUpdateAllowedUpdateAllowedRead() throws Exception {
+        String allowPath = "/providers/secured/read-update/providergate1-allowread_providergate1-allowupdate/test.json";
+
+        testUpdate(getTestUsername(), getTestPassword(), allowPath, 200);
+    }
+
+    @Test
+    public void testUpdateAllowedUpdateDeniedRead() throws Exception {
+        String path = "/providers/secured/read-update/providergate2-allowupdate_providergate1-denyread/test.json";
+
+        testRead(getTestUsername(), getTestPassword(), path, 404);
+        testUpdate(getTestUsername(), getTestPassword(), path, 500, "UnsupportedOperationException");
+    }
+
+    @Test
+    public void testUpdateDeniedUpdateDeniedRead() throws Exception {
+        String path = "/providers/secured/read-update/providergate2-denyupdate_providergate1-denyread/test.json";
+
+        testRead(getTestUsername(), getTestPassword(), path, 404);
+        testUpdate(getTestUsername(), getTestPassword(), path, 500, "UnsupportedOperationException");
+    }
+
+    @Test
+    public void testUpdateDeniedUpdateAllowedRead() throws Exception {
+        String path = "/providers/secured/read-update/providergate2-denyupdate_providergate1-allowread_appgate1-denyupdate/test.json";
+
+        testRead(getTestUsername(), getTestPassword(), path, 200);
+        testUpdate(getTestUsername(), getTestPassword(), path, 500, "is not modifiable");
+    }
+    
+}
diff --git a/src/test/java/org/apache/sling/resourceaccesssecurity/it/UnsecuredProviderResourceAccessSecurityTest.java b/src/test/java/org/apache/sling/resourceaccesssecurity/it/UnsecuredProviderResourceAccessSecurityTest.java
new file mode 100644
index 0000000..7895dc6
--- /dev/null
+++ b/src/test/java/org/apache/sling/resourceaccesssecurity/it/UnsecuredProviderResourceAccessSecurityTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.resourceaccesssecurity.it;
+
+
+import org.junit.Test;
+
+public class UnsecuredProviderResourceAccessSecurityTest extends ResourceAccessSecurityTestBase {
+
+    @Test
+    public void testDeniedReadAccess() throws Exception {
+        String path = "/providers/unsecured/read/providergate1-denyread/test.json";
+
+        // can be read anyway
+        testRead(getTestUsername(), getTestPassword(), path, 200);
+
+    }
+
+    @Test
+    public void testReadNonExistingResource() throws Exception {
+        String path = "/providers/unsecured/nonexisting/test.json";
+
+        testRead(getTestUsername(), getTestPassword(), path, 404);
+    }
+
+    @Test
+    public void testReadFromNonExistingProvider() throws Exception {
+        String path = "/providers/nonexisting/test.json";
+
+        testRead(getTestUsername(), getTestPassword(), path, 404);
+    }
+}