Merge branch 'stable-2.10'

* stable-2.10
  Remove unneeded 'throws NoSuchChangeException'

Change-Id: I69f9b1a92ee1d75487e95d1ef644b461d6656386
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 83b97c6..19ee28e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java
@@ -22,8 +22,6 @@
 import com.google.inject.Injector;
 import com.google.inject.Singleton;
 
-import com.googlesource.gerrit.plugins.replication.RemoteSiteUser;
-
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
index 14337d6..c75ec31 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
@@ -14,7 +14,7 @@
 
 package com.googlesource.gerrit.plugins.replication;
 
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
@@ -116,7 +116,7 @@
         cfg.getBoolean("remote", rc.getName(), "replicatePermissions", true);
     replicateProjectDeletions =
         cfg.getBoolean("remote", rc.getName(), "replicateProjectDeletions", false);
-    remoteNameStyle = Objects.firstNonNull(
+    remoteNameStyle = MoreObjects.firstNonNull(
         cfg.getString("remote", rc.getName(), "remoteNameStyle"), "slash");
     projects = cfg.getStringList("remote", rc.getName(), "projects");
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
index b699e0d..53393e8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
@@ -22,7 +22,6 @@
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
 import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
-import com.google.gerrit.extensions.events.NewProjectCreatedListener;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -348,21 +347,14 @@
     if (pool.isCreateMissingRepos()) {
       try {
         final Ref head = git.getRef(Constants.HEAD);
-        NewProjectCreatedListener.Event event =
-            new NewProjectCreatedListener.Event() {
-              @Override
-              public String getProjectName() {
-                return projectName.get();
-              }
-
-              @Override
-              public String getHeadName() {
-                return head != null ? head.getName() : null;
-              }
-            };
-        replicationQueue.onNewProjectCreated(event);
-        repLog.warn("Missing repository created; retry replication to " + uri);
-        pool.reschedule(this, Destination.RetryReason.REPOSITORY_MISSING);
+        if (replicationQueue.createProject(projectName, head != null ? head.getName() : null)) {
+          repLog.warn("Missing repository created; retry replication to " + uri);
+          pool.reschedule(this, Destination.RetryReason.REPOSITORY_MISSING);
+        } else {
+          repLog.warn("Missing repository could not be created when replicating " + uri +
+              ". You can only create missing repositories locally, over SSH or when " +
+              "using adminUrl in replication.config. See documentation for more information.");
+        }
       } catch (IOException ioe) {
         stateLog.error("Cannot replicate to " + uri + "; failed to create missing repository",
             ioe, getStatesAsArray());
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationLogFile.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationLogFile.java
index aeb0519..d4fab3f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationLogFile.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationLogFile.java
@@ -15,6 +15,7 @@
 package com.googlesource.gerrit.plugins.replication;
 
 import com.google.gerrit.extensions.events.LifecycleListener;
+import com.google.gerrit.extensions.systemstatus.ServerInformation;
 import com.google.gerrit.server.util.SystemLog;
 import com.google.inject.Inject;
 
@@ -25,25 +26,40 @@
 public class ReplicationLogFile implements LifecycleListener {
 
   private final SystemLog systemLog;
+  private final ServerInformation serverInfo;
+  private static boolean started = false;
 
   @Inject
-  public ReplicationLogFile(final SystemLog systemLog) {
+  public ReplicationLogFile(final SystemLog systemLog,
+      ServerInformation serverInfo) {
     this.systemLog = systemLog;
+    this.serverInfo = serverInfo;
   }
 
   @Override
   public void start() {
-    Logger replicationLogger =
-        LogManager.getLogger(ReplicationQueue.REPLICATION_LOG_NAME);
-    replicationLogger.removeAllAppenders();
-    replicationLogger.addAppender(systemLog.createAsyncAppender(
-        replicationLogger.getName(), new PatternLayout("[%d] [%X{"
-            + PushOne.ID_MDC_KEY + "}] %m%n")));
-    replicationLogger.setAdditivity(false);
+    if (!started) {
+      Logger replicationLogger =
+          LogManager.getLogger(ReplicationQueue.REPLICATION_LOG_NAME);
+      replicationLogger.removeAllAppenders();
+      replicationLogger.addAppender(systemLog.createAsyncAppender(
+          replicationLogger.getName(), new PatternLayout("[%d] [%X{"
+              + PushOne.ID_MDC_KEY + "}] %m%n")));
+      replicationLogger.setAdditivity(false);
+      started = true;
+    }
   }
 
   @Override
   public void stop() {
-    LogManager.getLogger(ReplicationQueue.repLog.getName()).removeAllAppenders();
+    // stop is called when plugin is unloaded or when the server shutdown.
+    // Only clean up when the server is shutting down to prevent issue when a
+    // plugin is reloaded. The issue is that gerrit load the new plugin and then
+    // unload the old one so because loggers are static, the unload of the old
+    // plugin would remove the appenders just created by the new plugin.
+    if (serverInfo.getState() == ServerInformation.State.SHUTDOWN) {
+      LogManager.getLogger(ReplicationQueue.repLog.getName())
+          .removeAllAppenders();
+    }
   }
 }
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 8be6b21..a976d74 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -230,7 +230,15 @@
     return uris;
   }
 
-  private void createProject(URIish replicateURI, String head) {
+  public boolean createProject(Project.NameKey project, String head) {
+    boolean success = false;
+    for (URIish uri : getURIs(project, false)) {
+      success &= createProject(uri, head);
+    }
+    return success;
+  }
+
+  private boolean createProject(URIish replicateURI, String head) {
     if (!replicateURI.isRemote()) {
       createLocally(replicateURI, head);
       repLog.info("Created local repository: " + replicateURI);
@@ -241,7 +249,9 @@
       repLog.warn(String.format("Cannot create new project on remote site %s."
           + " Only local paths and SSH URLs are supported"
           + " for remote repository creation", replicateURI));
+      return false;
     }
+    return true;
   }
 
   private static void createLocally(URIish uri, String head) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/GitUpdateProcessingTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/GitUpdateProcessingTest.java
index 93ea562..6b6e616 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/GitUpdateProcessingTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/GitUpdateProcessingTest.java
@@ -91,7 +91,7 @@
 
     reset(changeHooksMock);
     RefReplicatedEvent expectedEvent =
-        new RefReplicatedEvent("someProject", "refs/changes/1/1/1", "someHost",
+        new RefReplicatedEvent("someProject", "refs/changes/01/1/1", "someHost",
             RefPushResult.FAILED);
     changeHooksMock.postEvent(eq(expectedChange),
         RefReplicatedEventEquals.eqEvent(expectedEvent),
@@ -100,7 +100,7 @@
     replay(changeHooksMock);
 
     gitUpdateProcessing.onRefReplicatedToOneNode("someProject",
-        "refs/changes/1/1/1", new URIish("git://someHost/someProject.git"),
+        "refs/changes/01/1/1", new URIish("git://someHost/someProject.git"),
         RefPushResult.FAILED);
     verify(changeHooksMock);
   }