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);
+ }
+}