Merge branch 'stable-2.16' into stable-3.0

* stable-2.16:
  Fix issue with Kafka topic alias resolving
  Replicate projects in local setup
  Cleanup unused forwarder interfaces

Change-Id: I4f5bb5be8375b1e3e35ffc03ab5a1829e795a198
diff --git a/setup_local_env/configs/replication.config b/setup_local_env/configs/replication.config
index ea9252f..cf7f66a 100644
--- a/setup_local_env/configs/replication.config
+++ b/setup_local_env/configs/replication.config
@@ -4,6 +4,9 @@
     timeout = 600
     rescheduleDelay = 15
     replicationDelay = $REPLICATION_DELAY_SEC
+    createMissingRepositories = true
+    replicateProjectDeletions = true
+    replicateHiddenProjects = true
 [gerrit]
     autoReload = true
     replicateOnStartup = false
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/events/EventTopic.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/events/EventTopic.java
index 24b29b7..7d42acc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/events/EventTopic.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/events/EventTopic.java
@@ -14,28 +14,32 @@
 
 package com.googlesource.gerrit.plugins.multisite.forwarder.events;
 
-import com.google.common.base.CaseFormat;
-
 public enum EventTopic {
-  INDEX_TOPIC("GERRIT.EVENT.INDEX"),
-  CACHE_TOPIC("GERRIT.EVENT.CACHE"),
-  PROJECT_LIST_TOPIC("GERRIT.EVENT.PROJECT.LIST"),
-  STREAM_EVENT_TOPIC("GERRIT.EVENT.STREAM");
+  INDEX_TOPIC("GERRIT.EVENT.INDEX", "indexEvent"),
+  CACHE_TOPIC("GERRIT.EVENT.CACHE", "cacheEvent"),
+  PROJECT_LIST_TOPIC("GERRIT.EVENT.PROJECT.LIST", "projectListEvent"),
+  STREAM_EVENT_TOPIC("GERRIT.EVENT.STREAM", "streamEvent");
 
   private final String topic;
+  private final String aliasKey;
 
-  private EventTopic(String topic) {
+  private EventTopic(String topic, String aliasKey) {
     this.topic = topic;
-  }
-
-  public String lowerCamelName() {
-    return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name());
+    this.aliasKey = aliasKey;
   }
 
   public String topic() {
     return topic;
   }
 
+  public String topicAliasKey() {
+    return aliasKey + "Topic";
+  }
+
+  public String enabledKey() {
+    return aliasKey + "Enabled";
+  }
+
   public static EventTopic of(String topicString) {
     EventTopic[] topics = EventTopic.values();
     for (EventTopic topic : topics) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/CacheEvictionEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/CacheEvictionEventRouter.java
index e07026d..a118bd3 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/CacheEvictionEventRouter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/CacheEvictionEventRouter.java
@@ -23,7 +23,7 @@
 import com.googlesource.gerrit.plugins.multisite.forwarder.events.CacheEvictionEvent;
 
 @Singleton
-public class CacheEvictionEventRouter implements ForwardedCacheEvictionEventRouter {
+public class CacheEvictionEventRouter implements ForwardedEventRouter<CacheEvictionEvent> {
   private final ForwardedCacheEvictionHandler cacheEvictionHanlder;
 
   @Inject
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedCacheEvictionEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedCacheEvictionEventRouter.java
deleted file mode 100644
index 79ab0b9..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedCacheEvictionEventRouter.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed 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 com.googlesource.gerrit.plugins.multisite.forwarder.router;
-
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.CacheEvictionEvent;
-
-public interface ForwardedCacheEvictionEventRouter
-    extends ForwardedEventRouter<CacheEvictionEvent> {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedIndexEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedIndexEventRouter.java
deleted file mode 100644
index a843fcc..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedIndexEventRouter.java
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed 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 com.googlesource.gerrit.plugins.multisite.forwarder.router;
-
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.IndexEvent;
-
-public interface ForwardedIndexEventRouter extends ForwardedEventRouter<IndexEvent> {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedProjectListUpdateRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedProjectListUpdateRouter.java
deleted file mode 100644
index 37cc3de..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedProjectListUpdateRouter.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed 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 com.googlesource.gerrit.plugins.multisite.forwarder.router;
-
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.ProjectListUpdateEvent;
-
-public interface ForwardedProjectListUpdateRouter
-    extends ForwardedEventRouter<ProjectListUpdateEvent> {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedStreamEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedStreamEventRouter.java
deleted file mode 100644
index 0e50ea9..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedStreamEventRouter.java
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed 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 com.googlesource.gerrit.plugins.multisite.forwarder.router;
-
-import com.google.gerrit.server.events.Event;
-
-public interface ForwardedStreamEventRouter extends ForwardedEventRouter<Event> {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/IndexEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/IndexEventRouter.java
index b8662a1..43480b8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/IndexEventRouter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/IndexEventRouter.java
@@ -34,7 +34,7 @@
 import java.util.Optional;
 
 @Singleton
-public class IndexEventRouter implements ForwardedIndexEventRouter {
+public class IndexEventRouter implements ForwardedEventRouter<IndexEvent> {
   private final ForwardedIndexAccountHandler indexAccountHandler;
   private final ForwardedIndexChangeHandler indexChangeHandler;
   private final ForwardedIndexGroupHandler indexGroupHandler;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ProjectListUpdateRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ProjectListUpdateRouter.java
index 2248c4c..0fcebc2 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ProjectListUpdateRouter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ProjectListUpdateRouter.java
@@ -21,7 +21,7 @@
 import java.io.IOException;
 
 @Singleton
-public class ProjectListUpdateRouter implements ForwardedProjectListUpdateRouter {
+public class ProjectListUpdateRouter implements ForwardedEventRouter<ProjectListUpdateEvent> {
   ForwardedProjectListUpdateHandler projectListUpdateHandler;
 
   @Inject
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/RouterModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/RouterModule.java
index 6f1572a..2c29d1f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/RouterModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/RouterModule.java
@@ -19,9 +19,9 @@
 public class RouterModule extends AbstractModule {
   @Override
   protected void configure() {
-    bind(ForwardedIndexEventRouter.class).to(IndexEventRouter.class);
-    bind(ForwardedCacheEvictionEventRouter.class).to(CacheEvictionEventRouter.class);
-    bind(ForwardedProjectListUpdateRouter.class).to(ProjectListUpdateRouter.class);
-    bind(ForwardedStreamEventRouter.class).to(StreamEventRouter.class);
+    bind(IndexEventRouter.class);
+    bind(CacheEvictionEventRouter.class);
+    bind(ProjectListUpdateRouter.class);
+    bind(StreamEventRouter.class);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/StreamEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/StreamEventRouter.java
index a330416..aa8752e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/StreamEventRouter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/StreamEventRouter.java
@@ -21,7 +21,7 @@
 import com.googlesource.gerrit.plugins.multisite.forwarder.ForwardedEventHandler;
 
 @Singleton
-public class StreamEventRouter implements ForwardedStreamEventRouter {
+public class StreamEventRouter implements ForwardedEventRouter<Event> {
   private final ForwardedEventHandler streamEventHandler;
 
   @Inject
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfiguration.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfiguration.java
index baec520..97528de 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfiguration.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfiguration.java
@@ -20,7 +20,6 @@
 import com.google.common.base.CaseFormat;
 import com.google.common.base.Strings;
 import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.googlesource.gerrit.plugins.multisite.Configuration;
@@ -110,13 +109,12 @@
       Supplier<Config> config, String subsection) {
     Map<EventTopic, Boolean> eventsEnabled = new HashMap<>();
     for (EventTopic topic : EventTopic.values()) {
-      String enabledConfigKey = topic.lowerCamelName() + "Enabled";
-
       eventsEnabled.put(
           topic,
           config
               .get()
-              .getBoolean(KAFKA_SECTION, subsection, enabledConfigKey, DEFAULT_ENABLE_PROCESSING));
+              .getBoolean(
+                  KAFKA_SECTION, subsection, topic.enabledKey(), DEFAULT_ENABLE_PROCESSING));
     }
     return eventsEnabled;
   }
@@ -147,28 +145,16 @@
     private final Map<EventTopic, String> eventTopics;
     private final String bootstrapServers;
 
-    private static final ImmutableMap<EventTopic, String> EVENT_TOPICS =
-        ImmutableMap.of(
-            EventTopic.INDEX_TOPIC,
-            "GERRIT.EVENT.INDEX",
-            EventTopic.STREAM_EVENT_TOPIC,
-            "GERRIT.EVENT.STREAM",
-            EventTopic.CACHE_TOPIC,
-            "GERRIT.EVENT.CACHE",
-            EventTopic.PROJECT_LIST_TOPIC,
-            "GERRIT.EVENT.PROJECT.LIST");
-
     Kafka(Supplier<Config> config) {
       this.bootstrapServers =
           getString(
               config, KAFKA_SECTION, null, "bootstrapServers", DEFAULT_KAFKA_BOOTSTRAP_SERVERS);
 
       this.eventTopics = new HashMap<>();
-      for (Map.Entry<EventTopic, String> topicDefault : EVENT_TOPICS.entrySet()) {
-        String topicConfigKey = topicDefault.getKey().lowerCamelName() + "Topic";
+      for (EventTopic eventTopic : EventTopic.values()) {
         eventTopics.put(
-            topicDefault.getKey(),
-            getString(config, KAFKA_SECTION, null, topicConfigKey, topicDefault.getValue()));
+            eventTopic,
+            getString(config, KAFKA_SECTION, null, eventTopic.topicAliasKey(), eventTopic.topic()));
       }
     }
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfigurationTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfigurationTest.java
index ba423ff..84e1dd8 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfigurationTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfigurationTest.java
@@ -22,6 +22,7 @@
 import static com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration.KafkaSubscriber.KAFKA_SUBSCRIBER_SUBSECTION;
 
 import com.googlesource.gerrit.plugins.multisite.Configuration;
+import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
 import org.eclipse.jgit.lib.Config;
 import org.junit.Before;
 import org.junit.Test;
@@ -121,4 +122,79 @@
 
     assertThat(property).isNull();
   }
+
+  @Test
+  public void shouldReturnKafkaTopicAliasForIndexTopic() {
+    setKafkaTopicAlias("indexEventTopic", "gerrit_index");
+    final String property = getConfiguration().getKafka().getTopicAlias(EventTopic.INDEX_TOPIC);
+
+    assertThat(property).isEqualTo("gerrit_index");
+  }
+
+  @Test
+  public void shouldReturnKafkaTopicAliasForStreamEventTopic() {
+    setKafkaTopicAlias("streamEventTopic", "gerrit_stream_events");
+    final String property =
+        getConfiguration().getKafka().getTopicAlias(EventTopic.STREAM_EVENT_TOPIC);
+
+    assertThat(property).isEqualTo("gerrit_stream_events");
+  }
+
+  @Test
+  public void shouldReturnKafkaTopicAliasForProjectListEventTopic() {
+    setKafkaTopicAlias("projectListEventTopic", "gerrit_project_list");
+    final String property =
+        getConfiguration().getKafka().getTopicAlias(EventTopic.PROJECT_LIST_TOPIC);
+
+    assertThat(property).isEqualTo("gerrit_project_list");
+  }
+
+  @Test
+  public void shouldReturnKafkaTopicAliasForCacheEventTopic() {
+    setKafkaTopicAlias("cacheEventTopic", "gerrit_cache");
+    final String property = getConfiguration().getKafka().getTopicAlias(EventTopic.CACHE_TOPIC);
+
+    assertThat(property).isEqualTo("gerrit_cache");
+  }
+
+  @Test
+  public void shouldReturnKafkaTopicEnabledForCacheEventTopic() {
+    setKafkaTopicEnabled("cacheEventEnabled", false);
+    final Boolean property =
+        getConfiguration().kafkaPublisher().enabledEvent(EventTopic.CACHE_TOPIC);
+    assertThat(property).isFalse();
+  }
+
+  @Test
+  public void shouldReturnKafkaTopicEnabledForIndexTopic() {
+    setKafkaTopicEnabled("indexEventEnabled", false);
+    final Boolean property =
+        getConfiguration().kafkaPublisher().enabledEvent(EventTopic.INDEX_TOPIC);
+    assertThat(property).isFalse();
+  }
+
+  @Test
+  public void shouldReturnKafkaTopicEnabledForStreamEventTopic() {
+    setKafkaTopicEnabled("streamEventEnabled", false);
+    final Boolean property =
+        getConfiguration().kafkaPublisher().enabledEvent(EventTopic.STREAM_EVENT_TOPIC);
+    assertThat(property).isFalse();
+  }
+
+  @Test
+  public void shouldReturnKafkaTopicEnabledForProjectListEventTopic() {
+    setKafkaTopicEnabled("projectListEventEnabled", false);
+    final Boolean property =
+        getConfiguration().kafkaPublisher().enabledEvent(EventTopic.PROJECT_LIST_TOPIC);
+    assertThat(property).isFalse();
+  }
+
+  private void setKafkaTopicAlias(String topicKey, String topic) {
+    globalPluginConfig.setString(KAFKA_SECTION, null, topicKey, topic);
+  }
+
+  private void setKafkaTopicEnabled(String topicEnabledKey, Boolean isEnabled) {
+    globalPluginConfig.setBoolean(
+        KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, topicEnabledKey, isEnabled);
+  }
 }