Make createMissingRepositories = false take effect on project-created event

Previously "createMissingRepositories = false" would prevent the
replication plugin from trying to create a new project when a ref-updated
event was fired, but when a project-created event was fired the
replication plugin would try to create a project on the remote.

"createMissingRepositories = false" should prevent all attempts of remote
project creation.

Change-Id: Ie616ee87de5d8e05cb99299a634ffcc6d50a0f32
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java b/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java
index 19ee28e..62cad2c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java
@@ -73,9 +73,9 @@
   }
 
   @Override
-  public synchronized List<Destination> getDestinations() {
+  public synchronized List<Destination> getDestinations(FilterType filterType) {
     reloadIfNeeded();
-    return currentConfig.getDestinations();
+    return currentConfig.getDestinations(filterType);
   }
 
   private void reloadIfNeeded() {
@@ -89,7 +89,7 @@
         this.currentConfig = newConfig;
         this.currentConfigTs = currentConfig.getCfgPath().lastModified();
         log.info("Configuration reloaded: "
-            + currentConfig.getDestinations().size() + " destinations, "
+            + currentConfig.getDestinations(FilterType.ALL).size() + " destinations, "
             + discarded + " replication events discarded");
 
       } catch (Exception e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationConfig.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationConfig.java
index 5c18f75..241c881 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationConfig.java
@@ -19,7 +19,13 @@
 
 public interface ReplicationConfig {
 
-  List<Destination> getDestinations();
+  enum FilterType {
+    PROJECT_CREATION,
+    PROJECT_DELETION,
+    ALL
+  }
+
+  List<Destination> getDestinations(FilterType filterType);
 
   boolean isReplicateAllOnPluginStart();
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationFileBasedConfig.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationFileBasedConfig.java
index 574778e..f56185d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationFileBasedConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationFileBasedConfig.java
@@ -13,6 +13,8 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.replication;
 
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.gerrit.server.PluginUser;
@@ -69,14 +71,47 @@
     this.destinations = allDestinations();
   }
 
-  /* (non-Javadoc)
-   * @see com.googlesource.gerrit.plugins.replication.ReplicationConfig#getDestinations()
+  /*
+   * (non-Javadoc)
+   * @see
+   * com.googlesource.gerrit.plugins.replication.ReplicationConfig#getDestinations
+   * (com.googlesource.gerrit.plugins.replication.ReplicationConfig.FilterType)
    */
   @Override
-  public List<Destination> getDestinations() {
-    return destinations;
-  }
+  public List<Destination> getDestinations(FilterType filterType) {
+    Predicate<Destination> filter;
+    switch (filterType) {
+      case PROJECT_CREATION :
+        filter = new Predicate<Destination>() {
 
+          @Override
+          public boolean apply(Destination dest) {
+            if (dest == null || !dest.isCreateMissingRepos()) {
+              return false;
+            }
+            return true;
+          }
+        };
+        break;
+      case PROJECT_DELETION :
+        filter = new Predicate<Destination>() {
+
+          @Override
+          public boolean apply(Destination dest) {
+            if (dest == null || !dest.isReplicateProjectDeletions()) {
+              return false;
+            }
+            return true;
+          }
+        };
+        break;
+      case ALL :
+        return destinations;
+      default :
+        return destinations;
+    }
+    return FluentIterable.from(destinations).filter(filter).toList();
+  }
   private List<Destination> allDestinations()
       throws ConfigInvalidException, IOException {
     if (!config.getFile().exists()) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
index 4c36eb0..789e26a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -29,6 +29,7 @@
 import com.google.inject.Inject;
 
 import com.googlesource.gerrit.plugins.replication.PushResultProcessing.GitUpdateProcessing;
+import com.googlesource.gerrit.plugins.replication.ReplicationConfig.FilterType;
 
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.storage.file.FileRepository;
@@ -115,7 +116,7 @@
       return;
     }
 
-    for (Destination cfg : config.getDestinations()) {
+    for (Destination cfg : config.getDestinations(FilterType.ALL)) {
       if (cfg.wouldPushProject(project)) {
         for (URIish uri : cfg.getURIs(project, urlMatch)) {
           cfg.schedule(project, PushOne.ALL_REFS, uri, state);
@@ -133,7 +134,7 @@
     }
 
     Project.NameKey project = new Project.NameKey(event.getProjectName());
-    for (Destination cfg : config.getDestinations()) {
+    for (Destination cfg : config.getDestinations(FilterType.ALL)) {
       if (cfg.wouldPushProject(project) && cfg.wouldPushRef(event.getRefName())) {
         for (URIish uri : cfg.getURIs(project, null)) {
           cfg.schedule(project, event.getRefName(), uri, state);
@@ -145,28 +146,31 @@
 
   @Override
   public void onNewProjectCreated(NewProjectCreatedListener.Event event) {
-    for (URIish uri : getURIs(new Project.NameKey(event.getProjectName()), false)) {
+    for (URIish uri : getURIs(new Project.NameKey(event.getProjectName()),
+        FilterType.PROJECT_CREATION)) {
       createProject(uri, event.getHeadName());
     }
   }
 
   @Override
   public void onProjectDeleted(ProjectDeletedListener.Event event) {
-    for (URIish uri : getURIs(new Project.NameKey(event.getProjectName()), true)) {
+    for (URIish uri : getURIs(new Project.NameKey(event.getProjectName()),
+        FilterType.PROJECT_DELETION)) {
       deleteProject(uri);
     }
   }
 
   @Override
   public void onHeadUpdated(HeadUpdatedListener.Event event) {
-    for (URIish uri : getURIs(new Project.NameKey(event.getProjectName()), false)) {
+    for (URIish uri : getURIs(new Project.NameKey(event.getProjectName()),
+        FilterType.ALL)) {
       updateHead(uri, event.getNewHeadName());
     }
   }
 
   private Set<URIish> getURIs(Project.NameKey projectName,
-      boolean forProjectDeletion) {
-    if (config.getDestinations().isEmpty()) {
+      FilterType filterType) {
+    if (config.getDestinations(filterType).isEmpty()) {
       return Collections.emptySet();
     }
     if (!running) {
@@ -175,13 +179,11 @@
     }
 
     Set<URIish> uris = Sets.newHashSet();
-    for (Destination config : this.config.getDestinations()) {
+    for (Destination config : this.config.getDestinations(filterType)) {
       if (!config.wouldPushProject(projectName)) {
         continue;
       }
-      if (forProjectDeletion && !config.isReplicateProjectDeletions()) {
-        continue;
-      }
+
       List<URIish> uriList = config.getURIs(projectName, "*");
       String[] adminUrls = config.getAdminUrls();
       boolean adminURLUsed = false;
@@ -230,7 +232,7 @@
 
   public boolean createProject(Project.NameKey project, String head) {
     boolean success = false;
-    for (URIish uri : getURIs(project, false)) {
+    for (URIish uri : getURIs(project, FilterType.PROJECT_CREATION)) {
       success &= createProject(uri, head);
     }
     return success;
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 94b8473..bea2d92 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -238,12 +238,13 @@
 	everything to all remotes.
 
 remote.NAME.createMissingRepositories
-:	If true, a repository is automatically created on the remote site
-	if during the replication of a ref it is found to be missing.
-	E.g. a repository can be missing on the remote site if the remote
-	site was not available at the moment when a new project was created
-	and hence the repository for the new project could not be created on
-	the remote site.
+:	If true, a repository is automatically created on the remote site.
+	If the remote site was not available at the moment when a new
+	project was created, it will be created if during the replication
+	of a ref it is found to be missing.
+	
+	If false, repositories are never created automatically on this
+	remote.
 
 	By default, true, missing repositories are created.