You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2016/01/28 12:50:32 UTC

svn commit: r1727312 - in /sling/trunk: bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/ bundles/jcr/base/ bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/ bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/ launchpad/builder/src/...

Author: bdelacretaz
Date: Thu Jan 28 11:50:32 2016
New Revision: 1727312

URL: http://svn.apache.org/viewvc?rev=1727312&view=rev
Log:
SLING-5456 - implement SlingRepositoryInitializer extension points, with tests

Added:
    sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/SlingRepositoryInitializer.java
    sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java
    sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepositoryManager.java
    sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/RepositoryInitializersTest.java
    sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/TestInitializer.java
    sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/repository/RepositoryInitializersTest.java
    sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/
    sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/FirstRepositoryInitializer.java
    sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/SecondRepositoryInitializer.java
Modified:
    sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/package-info.java
    sling/trunk/bundles/jcr/base/pom.xml
    sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java
    sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/SessionProxyHandlerTest.java
    sling/trunk/launchpad/builder/src/main/provisioning/sling.txt
    sling/trunk/launchpad/integration-tests/pom.xml
    sling/trunk/launchpad/test-services/pom.xml

Added: sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/SlingRepositoryInitializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/SlingRepositoryInitializer.java?rev=1727312&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/SlingRepositoryInitializer.java (added)
+++ sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/SlingRepositoryInitializer.java Thu Jan 28 11:50:32 2016
@@ -0,0 +1,42 @@
+/*
+ * 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.jcr.api;
+
+import aQute.bnd.annotation.ConsumerType;
+
+/**
+ * All active <code>SlingRepositoryInitializer</code> services are called before 
+ * making the <code>SlingRepository</code> service available, and can perform
+ * initializations on it, like creating service users, setting up initial access
+ * control, migrating content in upgrades, etc.
+ * 
+ * The <code>SlingRepositoryInitializer</code> services need to be aware of any
+ * repository clustering scenarios as well as multiple Sling instances accessing
+ * the same repository. They might need to implement locking to avoid conflicts. 
+ */
+@ConsumerType
+public interface SlingRepositoryInitializer {
+    /** Process the content repository before it is 
+     *  registered as an OSGi service.
+     *  @param repo the repository to process
+     *  @throws Exception If anything happens that should prevent
+     *      the SlingRepository service from being registered.
+     */
+    public void processRepository(SlingRepository repo) throws Exception;
+}

Modified: sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/package-info.java?rev=1727312&r1=1727311&r2=1727312&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/package-info.java (original)
+++ sling/trunk/bundles/jcr/api/src/main/java/org/apache/sling/jcr/api/package-info.java Thu Jan 28 11:50:32 2016
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("2.3")
+@Version("2.4.0")
 package org.apache.sling.jcr.api;
 
 import aQute.bnd.annotation.Version;

Modified: sling/trunk/bundles/jcr/base/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/pom.xml?rev=1727312&r1=1727311&r2=1727312&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/base/pom.xml (original)
+++ sling/trunk/bundles/jcr/base/pom.xml Thu Jan 28 11:50:32 2016
@@ -149,6 +149,18 @@
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.osgi-mock</artifactId>
+            <version>1.6.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.sling-mock</artifactId>
+            <version>1.6.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.testing.jcr-mock</artifactId>
             <version>1.1.8</version>
             <scope>test</scope>

Modified: sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java?rev=1727312&r1=1727311&r2=1727312&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java (original)
+++ sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepositoryManager.java Thu Jan 28 11:50:32 2016
@@ -18,16 +18,20 @@
  */
 package org.apache.sling.jcr.base;
 
+import java.util.Arrays;
 import java.util.Dictionary;
 
 import javax.jcr.Repository;
 
 import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.api.SlingRepositoryInitializer;
 import org.apache.sling.serviceusermapping.ServiceUserMapper;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -91,6 +95,8 @@ public abstract class AbstractSlingRepos
     private volatile String defaultWorkspace;
 
     private volatile boolean disableLoginAdministrative;
+    
+    private volatile ServiceTracker repoInitializerTracker;
 
     /**
      * Returns the default workspace, which may be <code>null</code> meaning to
@@ -300,6 +306,9 @@ public abstract class AbstractSlingRepos
         this.bundleContext = bundleContext;
         this.defaultWorkspace = defaultWorkspace;
         this.disableLoginAdministrative = disableLoginAdministrative;
+        
+        this.repoInitializerTracker = new ServiceTracker(bundleContext, SlingRepositoryInitializer.class.getName(), null);
+        this.repoInitializerTracker.open();
 
         try {
             log.debug("start: calling acquireRepository()");
@@ -314,6 +323,20 @@ public abstract class AbstractSlingRepos
                 log.debug("start: setting up NamespaceMapping support");
                 this.setup(this.bundleContext, this.masterSlingRepository);
 
+                log.debug("start: calling SlingRepositoryInitializer");
+                Throwable t = null;
+                try {
+                    executeRepositoryInitializers(this.masterSlingRepository);
+                } catch(Exception e) {
+                    t = e;
+                } catch(Error e) {
+                    t = e;
+                }
+                if(t != null) {
+                    log.error("Exception in a SlingRepositoryInitializer, SlingRepository service registration aborted", t);
+                    return false;
+                }
+                
                 log.debug("start: calling registerService()");
                 this.repositoryService = registerService();
 
@@ -331,11 +354,33 @@ public abstract class AbstractSlingRepos
         // fallback to failure to start the repository
         return false;
     }
+    
+    private void executeRepositoryInitializers(SlingRepository repo) throws Exception {
+        final ServiceReference [] refs = repoInitializerTracker.getServiceReferences();
+        if(refs == null || refs.length == 0) {
+            log.debug("No SlingRepositoryInitializer services found");
+        }
+        Arrays.sort(refs);
+        for(ServiceReference ref : refs) {
+            final SlingRepositoryInitializer sri = (SlingRepositoryInitializer)bundleContext.getService(ref);
+            log.debug("Executing {}", sri);
+            try {
+                sri.processRepository(repo);
+            } finally {
+                bundleContext.ungetService(ref);
+            }
+        }
+    }
 
     /**
      * This method must be called if overwritten by implementations !!
      */
     protected final void stop() {
+        if(repoInitializerTracker != null) {
+            repoInitializerTracker.close();
+            repoInitializerTracker = null;
+        }
+        
         // ensure the repository is really disposed off
         if (repository != null || repositoryService != null) {
             log.info("stop: Repository still running, forcing shutdown");

Added: sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java?rev=1727312&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java (added)
+++ sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java Thu Jan 28 11:50:32 2016
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.jcr.base;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.osgi.framework.Bundle;
+
+/** Minimal AbstractSlingRepositoryManager used for testing */ 
+class MockSlingRepository2 extends AbstractSlingRepository2 {
+
+    MockSlingRepository2(MockSlingRepositoryManager manager, Bundle usingBundle, Session session) {
+        super(manager, usingBundle);
+    }
+    
+    @Override
+    protected Session createAdministrativeSession(String workspace) throws RepositoryException {
+        // Assuming we run on a test repo with no access control
+        return getRepository().login();
+    }
+}
\ No newline at end of file

Added: sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepositoryManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepositoryManager.java?rev=1727312&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepositoryManager.java (added)
+++ sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepositoryManager.java Thu Jan 28 11:50:32 2016
@@ -0,0 +1,81 @@
+/*
+ * 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.jcr.base;
+
+import static org.junit.Assert.fail;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+
+import org.apache.sling.jcr.api.NamespaceMapper;
+import org.apache.sling.serviceusermapping.ServiceUserMapper;
+import org.osgi.framework.Bundle;
+
+/** Minimal AbstractSlingRepositoryManager used for testing */ 
+class MockSlingRepositoryManager extends AbstractSlingRepositoryManager {
+    
+    private final Repository repository;
+    
+    MockSlingRepositoryManager(Repository repository) {
+        this.repository = repository;
+    }
+    
+    @Override
+    protected ServiceUserMapper getServiceUserMapper() {
+        return null;
+    }
+
+    @Override
+    protected Repository acquireRepository() {
+        return repository;
+    }
+
+    @Override
+    protected Dictionary<String, Object> getServiceRegistrationProperties() {
+        return new Hashtable<String, Object>();
+    }
+
+    @Override
+    protected AbstractSlingRepository2 create(Bundle usingBundle) {
+        if(repository != null) {
+            try {
+                return new MockSlingRepository2(this, usingBundle, repository.login());
+            } catch(RepositoryException rex) {
+                fail(rex.toString());
+            }
+        }
+        return null;
+    }
+
+    @Override
+    protected void destroy(AbstractSlingRepository2 repositoryServiceInstance) {
+    }
+
+    @Override
+    protected void disposeRepository(Repository repository) {
+    }
+
+    @Override
+    protected NamespaceMapper[] getNamespaceMapperServices() {
+        return new NamespaceMapper[0];
+    }
+}
\ No newline at end of file

Added: sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/RepositoryInitializersTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/RepositoryInitializersTest.java?rev=1727312&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/RepositoryInitializersTest.java (added)
+++ sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/RepositoryInitializersTest.java Thu Jan 28 11:50:32 2016
@@ -0,0 +1,165 @@
+/*
+ * 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.jcr.base;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Hashtable;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.commons.osgi.SortingServiceTracker;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.api.SlingRepositoryInitializer;
+import org.apache.sling.testing.mock.jcr.MockJcr;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/** Test the SlingRepositoryInitializer mechanism */
+public class RepositoryInitializersTest {
+
+    @Rule
+    public final SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK);
+    
+    private static final String DEFAULT_WORKSPACE = "defws";
+    private AbstractSlingRepositoryManager asrm;
+    private Repository repository;
+    private Session session;
+    private SortingServiceTracker<SlingRepository> repoTracker;
+    
+    /** We initially get a SlingRepository service from the Sling Mocks, and we're
+     *  interested to find out whether the repository manager also registers one
+     *  in our tests.
+     */
+    private int initialRepoServicesCount;
+    
+    @Before
+    public void setup() throws RepositoryException {
+        repoTracker = new SortingServiceTracker<SlingRepository>(context.bundleContext(), SlingRepository.class.getName());
+        repoTracker.open();
+        repository = MockJcr.newRepository();
+        session = repository.login();
+        asrm = new MockSlingRepositoryManager(repository);
+        
+        initialRepoServicesCount = countRepositoryServices();
+        assertAdditionalRepositoryServices(0);
+    }
+    
+    @After
+    public void cleanup() {
+        repoTracker.close();
+        asrm.stop();
+        session.logout();
+    }
+    
+    private void registerInitializer(String id, int serviceRanking) {
+        final SlingRepositoryInitializer init = new TestInitializer(id);
+        final Hashtable<String, Object> props = new Hashtable<String, Object>();
+        props.put(Constants.SERVICE_RANKING, new Integer(serviceRanking));
+        context.bundleContext().registerService(SlingRepositoryInitializer.class.getName(), init, props);
+    }
+    
+    private void assertTestInitializerProperty(String expected) throws RepositoryException {
+        final String path = TestInitializer.getPropertyPath();
+        assertTrue("Expecting property at " + path, session.propertyExists(path));
+        assertEquals("Expecting correct value at " + path, expected, session.getProperty(path).getString());
+    }
+    
+    private int countRepositoryServices() {
+        final ServiceReference [] refs = repoTracker.getServiceReferences();
+        return (refs == null ? 0 : refs.length);
+    }
+    
+    private void assertAdditionalRepositoryServices(int expected) {
+        assertEquals("Expecting " + expected + " SlingRepository services", 
+                expected + initialRepoServicesCount, countRepositoryServices());
+    }
+    
+    private void assertStart(boolean expected) {
+        final boolean actual = asrm.start(context.bundleContext(), DEFAULT_WORKSPACE, false);
+        assertEquals("Expecting start to return " + expected, expected, actual);
+    }
+    
+    @Test
+    public void inOrderInitializers() throws RepositoryException {
+        for(int i=1; i < 4; i++) {
+            registerInitializer(String.valueOf(i), i * 100);
+        }
+        
+        assertStart(true);
+        
+        // TODO this should really be 1,2,3 but it looks like
+        // the Sling OSGi mocks sort in the wrong order w.r.t the
+        // service ranking. As demonstrated by the integration test
+        // under launchpad/test-services which comes out in the correct
+        // order.
+        assertTestInitializerProperty("3,2,1,");
+        assertAdditionalRepositoryServices(1);
+    }
+    
+    @Test
+    public void reverseOrderInitializers() throws RepositoryException {
+        for(int i=1; i < 4; i++) {
+            registerInitializer(String.valueOf(i), i * -100);
+        }
+        
+        assertStart(true);
+        
+        // TODO see comment in inOrderInitializers, this should really
+        // be 3,2,1
+        assertTestInitializerProperty("1,2,3,");
+        assertAdditionalRepositoryServices(1);
+    }
+    
+    @Test
+    public void noRepositoryOnException() throws RepositoryException {
+        registerInitializer("a", 1);
+        registerInitializer("EXCEPTION", 2);
+        registerInitializer("c", 3);
+
+        assertStart(false);
+        
+        // The repository manager does not register a service in this case 
+        assertAdditionalRepositoryServices(0);
+    }
+    
+    @Test
+    public void noRepositoryOnError() throws RepositoryException {
+        registerInitializer("a", 1);
+        registerInitializer("ERROR", 2);
+        registerInitializer("c", 3);
+        
+        assertStart(false);
+        
+        // The repository manager does not register a service in this case 
+        assertAdditionalRepositoryServices(0);
+    }
+}
\ No newline at end of file

Modified: sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/SessionProxyHandlerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/SessionProxyHandlerTest.java?rev=1727312&r1=1727311&r2=1727312&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/SessionProxyHandlerTest.java (original)
+++ sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/SessionProxyHandlerTest.java Thu Jan 28 11:50:32 2016
@@ -18,20 +18,19 @@
  */
 package org.apache.sling.jcr.base;
 
-import org.apache.sling.jcr.api.NamespaceMapper;
-import org.apache.sling.serviceusermapping.ServiceUserMapper;
-import org.apache.sling.testing.mock.jcr.MockJcr;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.osgi.framework.Bundle;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.doReturn;
 
-import javax.jcr.*;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;
-import java.util.Dictionary;
 
-import static org.mockito.Mockito.*;
-import static org.junit.Assert.*;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.testing.mock.jcr.MockJcr;
+import org.junit.Test;
+import org.mockito.Mockito;
 
 public class SessionProxyHandlerTest {
 
@@ -50,7 +49,7 @@ public class SessionProxyHandlerTest {
         doReturn(imperSession).when(session).impersonate(null);
 
         //Create a proxy handle and proxy session
-        SessionProxyHandler proxyHandler = new SessionProxyHandler(new CustomSlingRepositoryManager());
+        SessionProxyHandler proxyHandler = new SessionProxyHandler(new MockSlingRepositoryManager(null));
         Session proxySession = proxyHandler.createProxy(session);
 
         //sessionForTest is a proxy which contains a link to the imperSession object
@@ -66,46 +65,4 @@ public class SessionProxyHandlerTest {
         assertNotNull(sessionForTest.getRootNode());
         assertNotNull(sessionForTest.getRepository());
     }
-
-    /**
-     * Create custom RepositoryManager to support namespace mapping, since the only one
-     * available <code>OakSlingRepositoryManager</code> lies under <code>org.apache.sling.jcr.oak.server</code>
-     * what creates circular dependencies with this module.
-     */
-    private static final class CustomSlingRepositoryManager extends AbstractSlingRepositoryManager{
-        @Override
-        protected ServiceUserMapper getServiceUserMapper() {
-            return null;
-        }
-
-        @Override
-        protected Repository acquireRepository() {
-            return null;
-        }
-
-        @Override
-        protected Dictionary<String, Object> getServiceRegistrationProperties() {
-            return null;
-        }
-
-        @Override
-        protected AbstractSlingRepository2 create(Bundle usingBundle) {
-            return null;
-        }
-
-        @Override
-        protected void destroy(AbstractSlingRepository2 repositoryServiceInstance) {
-
-        }
-
-        @Override
-        protected void disposeRepository(Repository repository) {
-
-        }
-
-        @Override
-        protected NamespaceMapper[] getNamespaceMapperServices() {
-            return new NamespaceMapper[0];
-        }
-    }
 }

Added: sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/TestInitializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/TestInitializer.java?rev=1727312&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/TestInitializer.java (added)
+++ sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/TestInitializer.java Thu Jan 28 11:50:32 2016
@@ -0,0 +1,78 @@
+/*
+ * 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.jcr.base;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.api.SlingRepositoryInitializer;
+
+/** SlingRepositoryInitializer used to test that all initializers are 
+ *  called in the right order.
+ */
+class TestInitializer implements SlingRepositoryInitializer {
+
+    private final String id;
+    private static final String NODE_NAME = TestInitializer.class.getName();
+    private static final String NODE_PATH = "/" + NODE_NAME;
+    private static final String PROP = "value";
+    
+    TestInitializer(String id) {
+        this.id = id;
+    }
+    
+    @Override
+    public void processRepository(SlingRepository repo) throws Exception {
+        if(id.equals("EXCEPTION")) {
+            throw new Exception("Failing due to id=" + id);
+        }
+        if(id.equals("ERROR")) {
+            throw new Error("Erroring due to id=" + id);
+        }
+        
+        final Session s = repo.loginAdministrative(null);
+        try {
+            Node n = null;
+            if(s.nodeExists(NODE_PATH)) {
+                n = s.getNode(NODE_PATH);
+            } else {
+                n = s.getRootNode().addNode(NODE_NAME);
+            }
+            final String value = n.hasProperty(PROP) ? n.getProperty(PROP).getString() : "";
+            n.setProperty(PROP, value + id + ",");
+            n.getSession().save();
+        } finally {
+            s.logout();
+        }
+    }
+    
+    static String getPropertyPath() {
+        return NODE_PATH + "/" + PROP;
+    }
+    
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " " + id;
+    }
+    
+    public String getId() {
+        return id;
+    }
+}

Modified: sling/trunk/launchpad/builder/src/main/provisioning/sling.txt
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/builder/src/main/provisioning/sling.txt?rev=1727312&r1=1727311&r2=1727312&view=diff
==============================================================================
--- sling/trunk/launchpad/builder/src/main/provisioning/sling.txt (original)
+++ sling/trunk/launchpad/builder/src/main/provisioning/sling.txt Thu Jan 28 11:50:32 2016
@@ -110,8 +110,8 @@
 
 [artifacts startLevel=15]
     org.apache.sling/org.apache.sling.jcr.jcr-wrapper/2.0.0
-    org.apache.sling/org.apache.sling.jcr.api/2.3.0
-    org.apache.sling/org.apache.sling.jcr.base/2.3.0
+    org.apache.sling/org.apache.sling.jcr.api/2.3.1-SNAPSHOT
+    org.apache.sling/org.apache.sling.jcr.base/2.3.1-SNAPSHOT
     org.apache.sling/org.apache.sling.jcr.registration/1.0.2
     org.apache.jackrabbit/jackrabbit-api/${jackrabbit.version}
     org.apache.jackrabbit/jackrabbit-jcr-commons/${jackrabbit.version}

Modified: sling/trunk/launchpad/integration-tests/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/pom.xml?rev=1727312&r1=1727311&r2=1727312&view=diff
==============================================================================
--- sling/trunk/launchpad/integration-tests/pom.xml (original)
+++ sling/trunk/launchpad/integration-tests/pom.xml Thu Jan 28 11:50:32 2016
@@ -291,6 +291,11 @@
       <artifactId>org.apache.sling.launchpad.api</artifactId>
       <version>1.2.0</version>
     </dependency>
+     <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.jcr.api</artifactId>
+      <version>2.3.1-SNAPSHOT</version>
+    </dependency>
     <dependency>
       <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.installer.core</artifactId>

Added: sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/repository/RepositoryInitializersTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/repository/RepositoryInitializersTest.java?rev=1727312&view=auto
==============================================================================
--- sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/repository/RepositoryInitializersTest.java (added)
+++ sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/repository/RepositoryInitializersTest.java Thu Jan 28 11:50:32 2016
@@ -0,0 +1,58 @@
+/*
+ * 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.launchpad.webapp.integrationtest.repository;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.apache.sling.commons.testing.integration.HttpTest;
+import org.apache.sling.launchpad.testservices.repository.FirstRepositoryInitializer;
+import org.apache.sling.launchpad.testservices.repository.SecondRepositoryInitializer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/** Verify that the SlingRepositoryInitializer provided by our test
+ *  services bundle have run.
+ */
+public class RepositoryInitializersTest {
+
+    private final HttpTest H = new HttpTest();
+    
+    @Before
+    public void setup() throws Exception {
+        H.setUp();
+    }
+    
+    @After
+    public void cleanup() throws Exception {
+        H.tearDown();
+    }
+    
+    @Test
+    public void checkSignalProperty() throws IOException {
+        final String path = 
+                FirstRepositoryInitializer.SIGNAL_NODE_PATH 
+                + "/" + SecondRepositoryInitializer.class.getSimpleName() 
+                + ".txt";
+        
+        final String url = HttpTest.HTTP_BASE_URL + path;
+        final String content = H.getContent(url, HttpTest.CONTENT_TYPE_PLAIN);
+        assertTrue("Expecting a numeric value at " + path + ", got " + content, Long.valueOf(content) > 0);
+    }
+}
\ No newline at end of file

Modified: sling/trunk/launchpad/test-services/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/test-services/pom.xml?rev=1727312&r1=1727311&r2=1727312&view=diff
==============================================================================
--- sling/trunk/launchpad/test-services/pom.xml (original)
+++ sling/trunk/launchpad/test-services/pom.xml Thu Jan 28 11:50:32 2016
@@ -144,7 +144,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.jcr.api</artifactId>
-            <version>2.1.0</version>
+            <version>2.3.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>

Added: sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/FirstRepositoryInitializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/FirstRepositoryInitializer.java?rev=1727312&view=auto
==============================================================================
--- sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/FirstRepositoryInitializer.java (added)
+++ sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/FirstRepositoryInitializer.java Thu Jan 28 11:50:32 2016
@@ -0,0 +1,62 @@
+/*
+ * 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.launchpad.testservices.repository;
+
+import javax.jcr.Session;
+
+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.jcr.api.SlingRepository;
+import org.apache.sling.jcr.api.SlingRepositoryInitializer;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SlingRepositoryInitializer that creates a node to which SecondRepositoryInitializer
+ * can add a property, to verify that they are executed in order of their service ranking.
+ */
+@Component
+@Service(SlingRepositoryInitializer.class)
+@Properties({
+    // Execute this before SecondRepositoryInitializer
+    @Property(name=Constants.SERVICE_RANKING, intValue=100)
+})
+public class FirstRepositoryInitializer implements SlingRepositoryInitializer {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    
+    public static final String SIGNAL_NODE_PATH = "/" + FirstRepositoryInitializer.class.getName();
+    
+    @Override
+    public void processRepository(SlingRepository repo) throws Exception {
+        final Session s = repo.loginAdministrative(null);
+        try {
+            if(s.itemExists(SIGNAL_NODE_PATH)) {
+                log.warn("{} already exists, these tests expect to run on an empty repository", SIGNAL_NODE_PATH);
+            } else {
+                s.getRootNode().addNode(SIGNAL_NODE_PATH.substring(1));
+                log.info("{} created", SIGNAL_NODE_PATH);
+                s.save();
+            }
+        } finally {
+            s.logout();
+        }
+    }
+}

Added: sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/SecondRepositoryInitializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/SecondRepositoryInitializer.java?rev=1727312&view=auto
==============================================================================
--- sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/SecondRepositoryInitializer.java (added)
+++ sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/repository/SecondRepositoryInitializer.java Thu Jan 28 11:50:32 2016
@@ -0,0 +1,63 @@
+/*
+ * 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.launchpad.testservices.repository;
+
+import javax.jcr.Session;
+
+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.jcr.api.SlingRepository;
+import org.apache.sling.jcr.api.SlingRepositoryInitializer;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SlingRepositoryInitializer that adds a property to the node created by 
+ * FirstRepositoryInitializer.
+ */
+@Component
+@Service(SlingRepositoryInitializer.class)
+@Properties({
+    // Execute this after FirstRepositoryInitializer
+    @Property(name=Constants.SERVICE_RANKING, intValue=200)
+})
+public class SecondRepositoryInitializer implements SlingRepositoryInitializer {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    
+    public static final String SIGNAL_PROPERTY_NAME = SecondRepositoryInitializer.class.getSimpleName();
+    
+    @Override
+    public void processRepository(SlingRepository repo) throws Exception {
+        final Session s = repo.loginAdministrative(null);
+        try {
+            final String path = FirstRepositoryInitializer.SIGNAL_NODE_PATH;
+            if(!s.itemExists(path)) {
+                log.warn("{} not found, should have been created by another initializer", path);
+            } else {
+                s.getNode(path).setProperty(SIGNAL_PROPERTY_NAME, System.currentTimeMillis());
+                log.info("Property {} added to {}", SIGNAL_PROPERTY_NAME, path);
+                s.save();
+            }
+        } finally {
+            s.logout();
+        }
+    }
+}