From af5c830eb3b1bad6f7fc963836174ac29665e271 Mon Sep 17 00:00:00 2001
From: Robert Munteanu <rombert@apache.org>
Date: Tue, 5 May 2015 12:34:31 +0300
Subject: [PATCH 1/4] OAK-2828 - Jcr builder class does not allow overriding
 most of its dependencies

Defer configuring the Oak instance until the createRepository method is
invoked.
---
 .../java/org/apache/jackrabbit/oak/jcr/Jcr.java    | 223 ++++++++++++++++-----
 1 file changed, 170 insertions(+), 53 deletions(-)

diff --git a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
index a926746..d9005a7 100644
--- a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
+++ b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
@@ -17,9 +17,12 @@
 package org.apache.jackrabbit.oak.jcr;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Lists.newArrayList;
 import static org.apache.jackrabbit.oak.plugins.commit.JcrConflictHandler.createJcrConflictHandler;
 
+import java.util.List;
 import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ScheduledExecutorService;
 
 import javax.annotation.Nonnull;
@@ -59,46 +62,46 @@ import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
 import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
-
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+
+/**
+ * Builder class which encapsulates the details of building a JCR <tt>Repository</tt> backed
+ * by an Oak <tt>ContentRepository</tt> instance
+ * 
+ * <p>By default the backing <tt>ContentRepository</tt> instance will be constructed with
+ * reasonable defaults, but these can be overridden. Note that once one type of dependency is
+ * overridden all dependencies must of that type must be overridden. As an example, once {@link #with(EditorProvider)} 
+ * is invoked, all desired <tt>EditorProvider</tt>s must be provided.</p>
+ */
 public class Jcr {
     public static final int DEFAULT_OBSERVATION_QUEUE_LENGTH = 1000;
 
     private final Oak oak;
-    private final CompositeConflictHandler conflictHandler = createJcrConflictHandler();
-
+    
+    private final List<RepositoryInitializer> repositoryInitializers = newArrayList();
+    private final List<QueryIndexProvider> queryIndexProviders = newArrayList();
+    private final List<CommitHook> commitHooks = newArrayList();
+    private final List<IndexEditorProvider> indexEditorProviders = newArrayList();
+    private final List<EditorProvider> editorProviders = newArrayList();
+    private final List<Editor> editors = newArrayList();
+    private final List<Observer> observers = newArrayList();
+    
+    private CompositeConflictHandler conflictHandler;
     private SecurityProvider securityProvider;
+    private CommitRateLimiter commitRateLimiter;
+    private ScheduledExecutorService scheduledExecutor;
+    private Executor executor;
+    private QueryEngineSettings queryEngineSettings;
+    private String defaultWorkspaceName;
+    private Whiteboard whiteboard;
+    
     private int observationQueueLength = DEFAULT_OBSERVATION_QUEUE_LENGTH;
-    private CommitRateLimiter commitRateLimiter = null;
+    
 
     private Repository repository;
 
     public Jcr(Oak oak) {
         this.oak = oak;
-
-        with(new InitialContent());
-
-        oak.with(conflictHandler);
-        with(new EditorHook(new VersionEditorProvider()));
-
-        with(new SecurityProviderImpl());
-
-        with(new ItemSaveValidatorProvider());
-        with(new NameValidatorProvider());
-        with(new NamespaceEditorProvider());
-        with(new TypeEditorProvider());
-        with(new ConflictValidatorProvider());
-        with(new AtomicCounterEditorProvider());
-        with(new ReferenceEditorProvider());
-        with(new ReferenceIndexProvider());
-
-        with(new PropertyIndexEditorProvider());
-        with(new NodeCounterEditorProvider());
-
-        with(new PropertyIndexProvider());
-        with(new OrderedPropertyIndexProvider());
-        with(new NodeTypeIndexProvider());
-        
-        with(new OrderedPropertyIndexEditorProvider());
     }
 
     public Jcr() {
@@ -111,44 +114,43 @@ public class Jcr {
 
     @Nonnull
     public final Jcr with(@Nonnull RepositoryInitializer initializer) {
-       oak.with(checkNotNull(initializer));
-       return this;
+    	repositoryInitializers.add(checkNotNull(initializer));
+        return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull QueryIndexProvider provider) {
-        oak.with(checkNotNull(provider));
+    	queryIndexProviders.add(checkNotNull(provider));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull IndexEditorProvider indexEditorProvider) {
-        oak.with(checkNotNull(indexEditorProvider));
+    	indexEditorProviders.add(checkNotNull(indexEditorProvider));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull CommitHook hook) {
-        oak.with(checkNotNull(hook));
+    	commitHooks.add(checkNotNull(hook));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull EditorProvider provider) {
-        oak.with(checkNotNull(provider));
+    	editorProviders.add(checkNotNull(provider));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull Editor editor) {
-        oak.with(checkNotNull(editor));
+        editors.add(checkNotNull(editor));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull SecurityProvider securityProvider) {
-        oak.with(checkNotNull(securityProvider));
-        this.securityProvider = securityProvider;
+        this.securityProvider = checkNotNull(securityProvider);
         return this;
     }
 
@@ -160,19 +162,19 @@ public class Jcr {
 
     @Nonnull
     public final Jcr with(@Nonnull ScheduledExecutorService executor) {
-        oak.with(checkNotNull(executor));
+        this.scheduledExecutor = checkNotNull(executor);
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull Executor executor) {
-        oak.with(checkNotNull(executor));
+        this.executor = checkNotNull(executor);
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull Observer observer) {
-        oak.with(checkNotNull(observer));
+        observers.add(checkNotNull(observer));
         return this;
     }
 
@@ -190,31 +192,146 @@ public class Jcr {
 
     @Nonnull
     public Jcr with(CommitRateLimiter commitRateLimiter) {
-        oak.with(commitRateLimiter);
-        this.commitRateLimiter = commitRateLimiter;
+        this.commitRateLimiter = checkNotNull(commitRateLimiter);
         return this;
     }
     
     @Nonnull
-    public Jcr with(QueryEngineSettings qs) {
-        oak.with(qs);
+    public Jcr with(@Nonnull QueryEngineSettings qs) {
+        this.queryEngineSettings = checkNotNull(qs);
         return this;
     }
+    
+    @Nonnull
+    public Jcr with(@Nonnull String defaultWorkspaceName) {
+        this.defaultWorkspaceName = checkNotNull(defaultWorkspaceName);
+    	return this;
+    }
+    
+    @Nonnull
+    public Jcr with(@Nonnull Whiteboard whiteboard) {
+    	this.whiteboard = checkNotNull(whiteboard);
+    	return this;
+    }
 
     public ContentRepository createContentRepository() {
         return oak.createContentRepository();
     }
 
     public Repository createRepository() {
-        if (repository == null) {
-            repository = new RepositoryImpl(
-                    oak.createContentRepository(),
-                    oak.getWhiteboard(),
-                    securityProvider,
-                    observationQueueLength,
-                    commitRateLimiter);
-        }
 
+        if (repository != null) {
+            return repository;
+        }
+        
+        // whiteboard
+        if ( whiteboard != null ) {
+            oak.with(whiteboard);
+        }
+    	
+    	// repository initializers
+    	if ( repositoryInitializers.isEmpty() ) {
+    		repositoryInitializers.add(new InitialContent());
+    	}
+    	for ( RepositoryInitializer repositoryInitializer : repositoryInitializers ) {
+    		oak.with(repositoryInitializer);
+    	}
+    	
+    	// query index providers
+    	if ( queryIndexProviders.isEmpty() ) {
+    		with(new ReferenceIndexProvider());
+            with(new PropertyIndexProvider());
+            with(new OrderedPropertyIndexProvider());
+            with(new NodeTypeIndexProvider());
+    	}
+    	for ( QueryIndexProvider queryIndexProvider : queryIndexProviders ) {
+    		oak.with(queryIndexProvider);
+    	}
+    	
+    	// commit hooks
+    	if ( commitHooks.isEmpty() ) {
+    		commitHooks.add(new EditorHook(new VersionEditorProvider()));
+    	}
+    	for ( CommitHook commitHook : commitHooks) {
+    		oak.with(commitHook);
+    	}
+    	
+    	// conflict handlers
+    	if ( conflictHandler == null ) {
+    		conflictHandler = createJcrConflictHandler();
+    	}
+    	oak.with(conflictHandler);
+    	
+    	// index editor providers
+    	if ( indexEditorProviders.isEmpty() ) {
+    		indexEditorProviders.add(new ReferenceEditorProvider());
+    		indexEditorProviders.add(new PropertyIndexEditorProvider());
+    		indexEditorProviders.add(new NodeCounterEditorProvider());
+    		indexEditorProviders.add(new OrderedPropertyIndexEditorProvider());
+    	}
+    	for ( IndexEditorProvider indexEditorProvider : indexEditorProviders ) {
+    		oak.with(indexEditorProvider);
+    	}
+    	
+    	// editors
+    	for ( Editor editor : editors ) {
+    	    oak.with(editor);
+    	}
+    	
+    	// editor providers
+    	if ( editorProviders.isEmpty() ) {
+            editorProviders.add(new ItemSaveValidatorProvider());
+            editorProviders.add(new NameValidatorProvider());
+            editorProviders.add(new NamespaceEditorProvider());
+            editorProviders.add(new TypeEditorProvider());
+            editorProviders.add(new ConflictValidatorProvider());
+            editorProviders.add(new AtomicCounterEditorProvider());
+    	}
+    	for ( EditorProvider editorProvider : editorProviders) {
+    		oak.with(editorProvider);
+    	}
+    	
+    	// securityProvider
+    	if ( securityProvider == null ) {
+    		securityProvider = new SecurityProviderImpl();
+    	}
+    	oak.with(securityProvider);
+    	
+    	// executors
+    	if ( scheduledExecutor != null ) {
+    	    oak.with(scheduledExecutor);
+    	}
+    	if ( executor != null ) {
+    	    oak.with(executor);
+    	}
+    	
+    	// observers
+    	for ( Observer observer: observers ) {
+    	    oak.with(observer);
+    	}
+    	
+    	// commit rate limiter
+    	if ( commitRateLimiter != null ) {
+    	    oak.with(commitRateLimiter);
+    	}
+    	
+    	// query engine settings
+    	if ( queryEngineSettings != null ) {
+    	    oak.with(queryEngineSettings);
+    	}
+    	
+    	// default workspace name
+    	if ( defaultWorkspaceName != null ) {
+    	    oak.with(defaultWorkspaceName);
+    	}
+    	
+        repository = new RepositoryImpl(
+                oak.createContentRepository(), 
+                oak.getWhiteboard(),
+                securityProvider,
+                observationQueueLength,
+                commitRateLimiter);
+        
         return repository;
     }
 
-- 
2.4.6


From 6bfd3bdba3e0c35a36a0f34cd74af3520b7d0ca7 Mon Sep 17 00:00:00 2001
From: Robert Munteanu <rombert@apache.org>
Date: Mon, 10 Aug 2015 12:22:18 +0300
Subject: [PATCH 2/4] OAK-2828 - Jcr builder class does not allow overriding
 most of its dependencies

Use sets instead of lists for collections to ensure no duplicates are
added.
---
 .../main/java/org/apache/jackrabbit/oak/jcr/Jcr.java  | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
index d9005a7..59e0563 100644
--- a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
+++ b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
@@ -17,12 +17,11 @@
 package org.apache.jackrabbit.oak.jcr;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Sets.newLinkedHashSet;
 import static org.apache.jackrabbit.oak.plugins.commit.JcrConflictHandler.createJcrConflictHandler;
 
-import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ScheduledExecutorService;
 
 import javax.annotation.Nonnull;
@@ -78,13 +77,13 @@ public class Jcr {
 
     private final Oak oak;
     
-    private final List<RepositoryInitializer> repositoryInitializers = newArrayList();
-    private final List<QueryIndexProvider> queryIndexProviders = newArrayList();
-    private final List<CommitHook> commitHooks = newArrayList();
-    private final List<IndexEditorProvider> indexEditorProviders = newArrayList();
-    private final List<EditorProvider> editorProviders = newArrayList();
-    private final List<Editor> editors = newArrayList();
-    private final List<Observer> observers = newArrayList();
+    private final Set<RepositoryInitializer> repositoryInitializers = newLinkedHashSet();
+    private final Set<QueryIndexProvider> queryIndexProviders = newLinkedHashSet();
+    private final Set<CommitHook> commitHooks = newLinkedHashSet();
+    private final Set<IndexEditorProvider> indexEditorProviders = newLinkedHashSet();
+    private final Set<EditorProvider> editorProviders = newLinkedHashSet();
+    private final Set<Editor> editors = newLinkedHashSet();
+    private final Set<Observer> observers = newLinkedHashSet();
     
     private CompositeConflictHandler conflictHandler;
     private SecurityProvider securityProvider;
-- 
2.4.6


From 366f6b6dd1063e84960be06ce9b2fff416c3997d Mon Sep 17 00:00:00 2001
From: Robert Munteanu <rombert@apache.org>
Date: Tue, 11 Aug 2015 13:59:15 +0300
Subject: [PATCH 3/4] OAK-2828 - Jcr builder class does not allow overriding
 most of its dependencies

Initialise all dependencies in the constructor, to make the behaviour
more intuitive.
---
 .../java/org/apache/jackrabbit/oak/jcr/Jcr.java    | 77 ++++++++++------------
 1 file changed, 34 insertions(+), 43 deletions(-)

diff --git a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
index 59e0563..76927e9 100644
--- a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
+++ b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
@@ -18,7 +18,6 @@ package org.apache.jackrabbit.oak.jcr;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.Sets.newLinkedHashSet;
-import static org.apache.jackrabbit.oak.plugins.commit.JcrConflictHandler.createJcrConflictHandler;
 
 import java.util.Set;
 import java.util.concurrent.Executor;
@@ -30,7 +29,9 @@ import javax.jcr.Repository;
 import org.apache.jackrabbit.oak.Oak;
 import org.apache.jackrabbit.oak.api.ContentRepository;
 import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
+import org.apache.jackrabbit.oak.plugins.atomic.AtomicCounterEditorProvider;
 import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
+import org.apache.jackrabbit.oak.plugins.commit.JcrConflictHandler;
 import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.counter.NodeCounterEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.nodetype.NodeTypeIndexProvider;
@@ -49,14 +50,12 @@ import org.apache.jackrabbit.oak.plugins.observation.CommitRateLimiter;
 import org.apache.jackrabbit.oak.plugins.version.VersionEditorProvider;
 import org.apache.jackrabbit.oak.query.QueryEngineSettings;
 import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
-import org.apache.jackrabbit.oak.plugins.atomic.AtomicCounterEditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
-import org.apache.jackrabbit.oak.spi.commit.CompositeConflictHandler;
+import org.apache.jackrabbit.oak.spi.commit.ConflictHandler;
 import org.apache.jackrabbit.oak.spi.commit.Editor;
 import org.apache.jackrabbit.oak.spi.commit.EditorHook;
 import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.Observer;
-import org.apache.jackrabbit.oak.spi.commit.PartialConflictHandler;
 import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
 import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
@@ -67,10 +66,9 @@ import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
  * Builder class which encapsulates the details of building a JCR <tt>Repository</tt> backed
  * by an Oak <tt>ContentRepository</tt> instance
  * 
- * <p>By default the backing <tt>ContentRepository</tt> instance will be constructed with
- * reasonable defaults, but these can be overridden. Note that once one type of dependency is
- * overridden all dependencies must of that type must be overridden. As an example, once {@link #with(EditorProvider)} 
- * is invoked, all desired <tt>EditorProvider</tt>s must be provided.</p>
+ * <p>The backing <tt>ContentRepository</tt> instance will be constructed with
+ * reasonable defaults and additional components can be registered by calling the <tt>with</tt>
+ * methods. Note that it is not possible to remove components once registered.</p> 
  */
 public class Jcr {
     public static final int DEFAULT_OBSERVATION_QUEUE_LENGTH = 1000;
@@ -85,7 +83,7 @@ public class Jcr {
     private final Set<Editor> editors = newLinkedHashSet();
     private final Set<Observer> observers = newLinkedHashSet();
     
-    private CompositeConflictHandler conflictHandler;
+    private ConflictHandler conflictHandler;
     private SecurityProvider securityProvider;
     private CommitRateLimiter commitRateLimiter;
     private ScheduledExecutorService scheduledExecutor;
@@ -101,6 +99,31 @@ public class Jcr {
 
     public Jcr(Oak oak) {
         this.oak = oak;
+
+        with(new InitialContent());
+
+        with(JcrConflictHandler.createJcrConflictHandler());
+        with(new EditorHook(new VersionEditorProvider()));
+
+        with(new SecurityProviderImpl());
+
+        with(new ItemSaveValidatorProvider());
+        with(new NameValidatorProvider());
+        with(new NamespaceEditorProvider());
+        with(new TypeEditorProvider());
+        with(new ConflictValidatorProvider());
+        with(new AtomicCounterEditorProvider());
+        with(new ReferenceEditorProvider());
+        with(new ReferenceIndexProvider());
+
+        with(new PropertyIndexEditorProvider());
+        with(new NodeCounterEditorProvider());
+
+        with(new PropertyIndexProvider());
+        with(new OrderedPropertyIndexProvider());
+        with(new NodeTypeIndexProvider());
+        
+        with(new OrderedPropertyIndexEditorProvider());
     }
 
     public Jcr() {
@@ -154,8 +177,8 @@ public class Jcr {
     }
 
     @Nonnull
-    public final Jcr with(@Nonnull PartialConflictHandler conflictHandler) {
-        this.conflictHandler.addHandler(checkNotNull(conflictHandler));
+    public final Jcr with(@Nonnull ConflictHandler conflictHandler) {
+        this.conflictHandler = checkNotNull(conflictHandler);
         return this;
     }
 
@@ -229,45 +252,24 @@ public class Jcr {
         }
     	
     	// repository initializers
-    	if ( repositoryInitializers.isEmpty() ) {
-    		repositoryInitializers.add(new InitialContent());
-    	}
     	for ( RepositoryInitializer repositoryInitializer : repositoryInitializers ) {
     		oak.with(repositoryInitializer);
     	}
     	
     	// query index providers
-    	if ( queryIndexProviders.isEmpty() ) {
-    		with(new ReferenceIndexProvider());
-            with(new PropertyIndexProvider());
-            with(new OrderedPropertyIndexProvider());
-            with(new NodeTypeIndexProvider());
-    	}
     	for ( QueryIndexProvider queryIndexProvider : queryIndexProviders ) {
     		oak.with(queryIndexProvider);
     	}
     	
     	// commit hooks
-    	if ( commitHooks.isEmpty() ) {
-    		commitHooks.add(new EditorHook(new VersionEditorProvider()));
-    	}
     	for ( CommitHook commitHook : commitHooks) {
     		oak.with(commitHook);
     	}
     	
     	// conflict handlers
-    	if ( conflictHandler == null ) {
-    		conflictHandler = createJcrConflictHandler();
-    	}
     	oak.with(conflictHandler);
     	
     	// index editor providers
-    	if ( indexEditorProviders.isEmpty() ) {
-    		indexEditorProviders.add(new ReferenceEditorProvider());
-    		indexEditorProviders.add(new PropertyIndexEditorProvider());
-    		indexEditorProviders.add(new NodeCounterEditorProvider());
-    		indexEditorProviders.add(new OrderedPropertyIndexEditorProvider());
-    	}
     	for ( IndexEditorProvider indexEditorProvider : indexEditorProviders ) {
     		oak.with(indexEditorProvider);
     	}
@@ -278,22 +280,11 @@ public class Jcr {
     	}
     	
     	// editor providers
-    	if ( editorProviders.isEmpty() ) {
-            editorProviders.add(new ItemSaveValidatorProvider());
-            editorProviders.add(new NameValidatorProvider());
-            editorProviders.add(new NamespaceEditorProvider());
-            editorProviders.add(new TypeEditorProvider());
-            editorProviders.add(new ConflictValidatorProvider());
-            editorProviders.add(new AtomicCounterEditorProvider());
-    	}
     	for ( EditorProvider editorProvider : editorProviders) {
     		oak.with(editorProvider);
     	}
     	
     	// securityProvider
-    	if ( securityProvider == null ) {
-    		securityProvider = new SecurityProviderImpl();
-    	}
     	oak.with(securityProvider);
     	
     	// executors
-- 
2.4.6


From a014cc1d7d14117d040a88f4aa6d2db538b85c14 Mon Sep 17 00:00:00 2001
From: Robert Munteanu <rombert@apache.org>
Date: Tue, 11 Aug 2015 14:15:49 +0300
Subject: [PATCH 4/4] OAK-2828 - Jcr builder class does not allow overriding
 most of its dependencies

Fail fast if trying to configure an already-created repository instance.
---
 .../java/org/apache/jackrabbit/oak/jcr/Jcr.java    | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
index 76927e9..8e58c68 100644
--- a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
+++ b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
@@ -136,110 +136,135 @@ public class Jcr {
 
     @Nonnull
     public final Jcr with(@Nonnull RepositoryInitializer initializer) {
+        ensureRepositoryIsNotCreated();
     	repositoryInitializers.add(checkNotNull(initializer));
         return this;
     }
 
+    private void ensureRepositoryIsNotCreated() {
+        if ( repository != null ) {
+            throw new IllegalStateException("Repository already created");
+        }
+    }
+
     @Nonnull
     public final Jcr with(@Nonnull QueryIndexProvider provider) {
+        ensureRepositoryIsNotCreated();
     	queryIndexProviders.add(checkNotNull(provider));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull IndexEditorProvider indexEditorProvider) {
+        ensureRepositoryIsNotCreated();
     	indexEditorProviders.add(checkNotNull(indexEditorProvider));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull CommitHook hook) {
+        ensureRepositoryIsNotCreated();
     	commitHooks.add(checkNotNull(hook));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull EditorProvider provider) {
+        ensureRepositoryIsNotCreated();
     	editorProviders.add(checkNotNull(provider));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull Editor editor) {
+        ensureRepositoryIsNotCreated();
         editors.add(checkNotNull(editor));
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull SecurityProvider securityProvider) {
+        ensureRepositoryIsNotCreated();
         this.securityProvider = checkNotNull(securityProvider);
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull ConflictHandler conflictHandler) {
+        ensureRepositoryIsNotCreated();
         this.conflictHandler = checkNotNull(conflictHandler);
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull ScheduledExecutorService executor) {
+        ensureRepositoryIsNotCreated();
         this.scheduledExecutor = checkNotNull(executor);
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull Executor executor) {
+        ensureRepositoryIsNotCreated();
         this.executor = checkNotNull(executor);
         return this;
     }
 
     @Nonnull
     public final Jcr with(@Nonnull Observer observer) {
+        ensureRepositoryIsNotCreated();
         observers.add(checkNotNull(observer));
         return this;
     }
 
     @Nonnull
     public Jcr withAsyncIndexing() {
+        ensureRepositoryIsNotCreated();
         oak.withAsyncIndexing();
         return this;
     }
 
     @Nonnull
     public Jcr withObservationQueueLength(int observationQueueLength) {
+        ensureRepositoryIsNotCreated();
         this.observationQueueLength = observationQueueLength;
         return this;
     }
 
     @Nonnull
     public Jcr with(CommitRateLimiter commitRateLimiter) {
+        ensureRepositoryIsNotCreated();
         this.commitRateLimiter = checkNotNull(commitRateLimiter);
         return this;
     }
     
     @Nonnull
     public Jcr with(@Nonnull QueryEngineSettings qs) {
+        ensureRepositoryIsNotCreated();
         this.queryEngineSettings = checkNotNull(qs);
         return this;
     }
     
     @Nonnull
     public Jcr with(@Nonnull String defaultWorkspaceName) {
+        ensureRepositoryIsNotCreated();
         this.defaultWorkspaceName = checkNotNull(defaultWorkspaceName);
     	return this;
     }
     
     @Nonnull
     public Jcr with(@Nonnull Whiteboard whiteboard) {
+        ensureRepositoryIsNotCreated();
     	this.whiteboard = checkNotNull(whiteboard);
     	return this;
     }
 
+    @Nonnull
     public ContentRepository createContentRepository() {
         return oak.createContentRepository();
     }
 
+    @Nonnull
     public Repository createRepository() {
 
         if (repository != null) {
-- 
2.4.6

