Expose more API to enable plugin consumption as lib

In order to use replication plugin as a base for other replication
plugins more API needs to be exposed.

All classes bound in ReplicationModule are made public with package
protected constructors to enable extendability.

Also parts of the configuration API are exposed for supporting different
configuration sources than $site_path/replication.config eg. dynamically
load from 'master' server.

ReplicationSshSessionFactoryProvider was added to enable consumers to
configure SSH sessions by modifying credentials factory and/or set the
known_hosts repository.

Change-Id: I2e26fc976b04bd1ace5ddd695ef558c6d66a4716
Signed-off-by: Dariusz Luksza <dariusz@luksza.org>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/CredentialsFactory.java b/src/main/java/com/googlesource/gerrit/plugins/replication/CredentialsFactory.java
index 9ce4a54..e960533 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/CredentialsFactory.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/CredentialsFactory.java
@@ -13,7 +13,7 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.replication;
 
-interface CredentialsFactory {
+public interface CredentialsFactory {
 
   SecureCredentialsProvider create(String remoteName);
 
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 120c94c..1090fb6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
@@ -66,7 +66,7 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
-class Destination {
+public class Destination {
   private static final Logger repLog = ReplicationQueue.repLog;
   private final ReplicationStateListener stateLog;
 
@@ -98,7 +98,7 @@
     TRANSPORT_ERROR, COLLISION, REPOSITORY_MISSING;
   }
 
-  Destination(final Injector injector,
+  protected Destination(final Injector injector,
       final RemoteConfig rc,
       final Config cfg,
       final RemoteSiteUser.Factory replicationUserFactory,
@@ -203,11 +203,11 @@
     }
   }
 
-  void start(WorkQueue workQueue) {
+  public void start(WorkQueue workQueue) {
     pool = workQueue.createQueue(poolThreads, poolName);
   }
 
-  int shutdown() {
+  public int shutdown() {
     int cnt = 0;
     if (pool != null) {
       for (Runnable r : pool.getQueue()) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/OnStartStop.java b/src/main/java/com/googlesource/gerrit/plugins/replication/OnStartStop.java
index e868a01..5accf95 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/OnStartStop.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/OnStartStop.java
@@ -29,7 +29,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
-class OnStartStop implements LifecycleListener {
+public class OnStartStop implements LifecycleListener {
   private final AtomicReference<Future<?>> pushAllFuture;
   private final ServerInformation srvInfo;
   private final PushAll.Factory pushAll;
@@ -39,7 +39,7 @@
   private final SchemaFactory<ReviewDb> database;
 
   @Inject
-  OnStartStop(
+  protected OnStartStop(
       ServerInformation srvInfo,
       PushAll.Factory pushAll,
       ReplicationQueue queue,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/PushAll.java b/src/main/java/com/googlesource/gerrit/plugins/replication/PushAll.java
index 5ff4035..16e1678 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushAll.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushAll.java
@@ -24,10 +24,10 @@
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
-class PushAll implements Runnable {
+public class PushAll implements Runnable {
   private final ReplicationStateListener stateLog;
 
-  interface Factory {
+  public interface Factory {
     PushAll create(String urlMatch,
         ReplicationFilter filter,
         ReplicationState state);
@@ -41,7 +41,7 @@
   private final ReplicationState state;
 
   @Inject
-  PushAll(WorkQueue wq,
+  protected PushAll(WorkQueue wq,
       ProjectCache projectCache,
       ReplicationQueue rq,
       ReplicationStateListener stateLog,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/RemoteSiteUser.java b/src/main/java/com/googlesource/gerrit/plugins/replication/RemoteSiteUser.java
index f9aa668..2eacaed 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/RemoteSiteUser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/RemoteSiteUser.java
@@ -26,8 +26,8 @@
 import java.util.Collections;
 import java.util.Set;
 
-class RemoteSiteUser extends CurrentUser {
-  interface Factory {
+public class RemoteSiteUser extends CurrentUser {
+  public interface Factory {
     RemoteSiteUser create(@Assisted GroupMembership authGroups);
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java
index e813885..5a5f3b4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java
@@ -30,6 +30,7 @@
 import com.google.inject.assistedinject.FactoryModuleBuilder;
 import com.google.inject.internal.UniqueAnnotations;
 
+import org.eclipse.jgit.transport.SshSessionFactory;
 
 class ReplicationModule extends AbstractModule {
   @Override
@@ -65,5 +66,7 @@
 
     EventTypes.register(RefReplicatedEvent.TYPE, RefReplicatedEvent.class);
     EventTypes.register(RefReplicationDoneEvent.TYPE, RefReplicationDoneEvent.class);
+    bind(SshSessionFactory.class).toProvider(
+        ReplicationSshSessionFactoryProvider.class);
   }
 }
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 6c5376d..31f8c57 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -28,6 +28,7 @@
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 
 import com.googlesource.gerrit.plugins.replication.PushResultProcessing.GitUpdateProcessing;
 import com.googlesource.gerrit.plugins.replication.ReplicationConfig.FilterType;
@@ -55,7 +56,7 @@
 import java.util.Set;
 
 /** Manages automatic replication to remote repositories. */
-class ReplicationQueue implements
+public class ReplicationQueue implements
     LifecycleListener,
     GitReferenceUpdatedListener,
     NewProjectCreatedListener,
@@ -83,6 +84,7 @@
   private final SchemaFactory<ReviewDb> database;
   private final DynamicItem<EventDispatcher> dispatcher;
   private final ReplicationConfig config;
+  private final Provider<SshSessionFactory> sshSessionFactoryProvider;
   private volatile boolean running;
 
   @Inject
@@ -90,12 +92,14 @@
       ReplicationConfig rc,
       SchemaFactory<ReviewDb> db,
       DynamicItem<EventDispatcher> dis,
-      ReplicationStateListener sl) {
+      ReplicationStateListener sl,
+      Provider<SshSessionFactory> sshSessionFactoryProvider) {
     workQueue = wq;
     database = db;
     dispatcher = dis;
     config = rc;
     stateLog = sl;
+    this.sshSessionFactoryProvider = sshSessionFactoryProvider;
   }
 
   @Override
@@ -276,7 +280,7 @@
     }
   }
 
-  private static void createRemoteSsh(URIish uri, String head) {
+  private void createRemoteSsh(URIish uri, String head) {
     String quotedPath = QuotedString.BOURNE.quote(uri.getPath());
     String cmd = "mkdir -p " + quotedPath
             + " && cd " + quotedPath
@@ -339,7 +343,7 @@
     }
   }
 
-  private static void deleteRemoteSsh(URIish uri) {
+  private void deleteRemoteSsh(URIish uri) {
     String quotedPath = QuotedString.BOURNE.quote(uri.getPath());
     String cmd = "rm -rf " + quotedPath;
     OutputStream errStream = newErrorBufferStream();
@@ -368,7 +372,7 @@
     }
   }
 
-  private static void updateHeadRemoteSsh(URIish uri, String newHead) {
+  private void updateHeadRemoteSsh(URIish uri, String newHead) {
     String quotedPath = QuotedString.BOURNE.quote(uri.getPath());
     String cmd = "cd " + quotedPath
             + " && git symbolic-ref HEAD " + QuotedString.BOURNE.quote(newHead);
@@ -398,7 +402,7 @@
     }
   }
 
-  private static void executeRemoteSsh(URIish uri, String cmd,
+  private void executeRemoteSsh(URIish uri, String cmd,
       OutputStream errStream) throws IOException {
     RemoteSession ssh = connect(uri);
     Process proc = ssh.exec(cmd, 0);
@@ -419,8 +423,8 @@
     ssh.disconnect();
   }
 
-  private static RemoteSession connect(URIish uri) throws TransportException {
-    return SshSessionFactory.getInstance().getSession(uri, null, FS.DETECTED,
+  private RemoteSession connect(URIish uri) throws TransportException {
+    return sshSessionFactoryProvider.get().getSession(uri, null, FS.DETECTED,
         SSH_REMOTE_TIMEOUT);
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationSshSessionFactoryProvider.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationSshSessionFactoryProvider.java
new file mode 100644
index 0000000..42bc284
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationSshSessionFactoryProvider.java
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 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.replication;
+
+import com.google.inject.Provider;
+
+import org.eclipse.jgit.transport.SshSessionFactory;
+
+class ReplicationSshSessionFactoryProvider implements Provider<SshSessionFactory> {
+
+  @Override
+  public SshSessionFactory get() {
+    return SshSessionFactory.getInstance();
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/StartReplicationCapability.java b/src/main/java/com/googlesource/gerrit/plugins/replication/StartReplicationCapability.java
index 761be73..0cf0c2d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/StartReplicationCapability.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/StartReplicationCapability.java
@@ -16,8 +16,8 @@
 
 import com.google.gerrit.extensions.config.CapabilityDefinition;
 
-class StartReplicationCapability extends CapabilityDefinition {
-  static final String START_REPLICATION = "startReplication";
+public class StartReplicationCapability extends CapabilityDefinition {
+  public static final String START_REPLICATION = "startReplication";
 
   @Override
   public String getDescription() {