init: Refactor init to be small parts created through Guice
I was nuts when I wrote init. Making it all one giant program in a single class was simply insane. Instead we break it down into many smaller classes and use Guice to manage the creation, dependency injection, and control flow. Since init knew about most of the Files under the $site_path we put them all into a single immutable class called SitePaths and replace all references to these throughout the code base to use SitePaths and these well defined constants. init can now also import GerritServer.properties into the newer style gerrit.config and secure.config. This ensure the database settings are setup with the current defaults Change-Id: I4f5d8256497c1a97df35754dbe6193c78edde9e1 Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
		@@ -14,7 +14,7 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.sshd;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.server.config.SitePath;
 | 
			
		||||
import com.google.gerrit.server.config.SitePaths;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.ProvisionException;
 | 
			
		||||
@@ -22,26 +22,24 @@ import com.google.inject.ProvisionException;
 | 
			
		||||
import org.apache.sshd.common.KeyPairProvider;
 | 
			
		||||
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
 | 
			
		||||
import org.apache.sshd.common.util.SecurityUtils;
 | 
			
		||||
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
class HostKeyProvider implements Provider<KeyPairProvider> {
 | 
			
		||||
  private final File sitePath;
 | 
			
		||||
  private final SitePaths site;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  HostKeyProvider(@SitePath final File sitePath) {
 | 
			
		||||
    this.sitePath = sitePath;
 | 
			
		||||
  HostKeyProvider(final SitePaths site) {
 | 
			
		||||
    this.site = site;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public KeyPairProvider get() {
 | 
			
		||||
    final File etc = new File(sitePath, "etc");
 | 
			
		||||
    final File anyKey = new File(etc, "ssh_host_key");
 | 
			
		||||
    final File rsaKey = new File(etc, "ssh_host_rsa_key");
 | 
			
		||||
    final File dsaKey = new File(etc, "ssh_host_dsa_key");
 | 
			
		||||
    final File anyKey = site.ssh_key;
 | 
			
		||||
    final File rsaKey = site.ssh_rsa;
 | 
			
		||||
    final File dsaKey = site.ssh_dsa;
 | 
			
		||||
 | 
			
		||||
    final List<String> keys = new ArrayList<String>(2);
 | 
			
		||||
    if (rsaKey.exists()) {
 | 
			
		||||
@@ -60,18 +58,8 @@ class HostKeyProvider implements Provider<KeyPairProvider> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (keys.isEmpty()) {
 | 
			
		||||
      // No administrator created host key? Generate and save our own.
 | 
			
		||||
      //
 | 
			
		||||
      final SimpleGeneratorHostKeyProvider keyp;
 | 
			
		||||
 | 
			
		||||
      if (!etc.exists() && !etc.mkdirs()) {
 | 
			
		||||
        throw new ProvisionException("Cannot create directory " + etc);
 | 
			
		||||
      }
 | 
			
		||||
      keyp = new SimpleGeneratorHostKeyProvider();
 | 
			
		||||
      keyp.setPath(anyKey.getAbsolutePath());
 | 
			
		||||
      return keyp;
 | 
			
		||||
      throw new ProvisionException("No SSH keys under " + site.etc_dir);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!SecurityUtils.isBouncyCastleRegistered()) {
 | 
			
		||||
      throw new ProvisionException("Bouncy Castle Crypto not installed;"
 | 
			
		||||
          + " needed to read server host keys: " + keys + "");
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ import com.google.gerrit.lifecycle.LifecycleListener;
 | 
			
		||||
import com.google.gerrit.server.config.GerritServerConfig;
 | 
			
		||||
import com.google.gerrit.server.ssh.SshInfo;
 | 
			
		||||
import com.google.gerrit.server.util.IdGenerator;
 | 
			
		||||
import com.google.gerrit.server.util.SocketUtil;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Key;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
@@ -71,11 +72,8 @@ import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.Inet6Address;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.InetSocketAddress;
 | 
			
		||||
import java.net.SocketAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.security.InvalidKeyException;
 | 
			
		||||
import java.security.KeyPair;
 | 
			
		||||
import java.security.PublicKey;
 | 
			
		||||
@@ -112,28 +110,6 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
 | 
			
		||||
 | 
			
		||||
  private static final Logger log = LoggerFactory.getLogger(SshDaemon.class);
 | 
			
		||||
 | 
			
		||||
  private static String format(final SocketAddress addr) {
 | 
			
		||||
    if (addr instanceof InetSocketAddress) {
 | 
			
		||||
      final InetSocketAddress inetAddr = (InetSocketAddress) addr;
 | 
			
		||||
      final InetAddress hostAddr = inetAddr.getAddress();
 | 
			
		||||
      String host;
 | 
			
		||||
      if (hostAddr.isAnyLocalAddress()) {
 | 
			
		||||
        host = "*";
 | 
			
		||||
      } else if (inetAddr.getPort() == IANA_SSH_PORT && !isIPv6(hostAddr)) {
 | 
			
		||||
        return inetAddr.getHostName();
 | 
			
		||||
      } else {
 | 
			
		||||
        host = "[" + hostAddr.getHostName() + "]";
 | 
			
		||||
      }
 | 
			
		||||
      return host + ":" + inetAddr.getPort();
 | 
			
		||||
    }
 | 
			
		||||
    return addr.toString();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static boolean isIPv6(final InetAddress ip) {
 | 
			
		||||
    return ip instanceof Inet6Address
 | 
			
		||||
        && ip.getHostName().equals(ip.getHostAddress());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private final List<SocketAddress> listen;
 | 
			
		||||
  private final boolean keepAlive;
 | 
			
		||||
  private final List<HostKey> hostKeys;
 | 
			
		||||
@@ -256,7 +232,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
          r.add(new HostKey(format(inetAddr), keyBin));
 | 
			
		||||
          r.add(new HostKey(SocketUtil.format(inetAddr, IANA_SSH_PORT), keyBin));
 | 
			
		||||
        } catch (JSchException e) {
 | 
			
		||||
          log.warn("Cannot format SSHD host key", e);
 | 
			
		||||
        }
 | 
			
		||||
@@ -284,7 +260,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
 | 
			
		||||
  private String addressList() {
 | 
			
		||||
    final StringBuilder r = new StringBuilder();
 | 
			
		||||
    for (Iterator<SocketAddress> i = listen.iterator(); i.hasNext();) {
 | 
			
		||||
      r.append(format(i.next()));
 | 
			
		||||
      r.append(SocketUtil.format(i.next(), IANA_SSH_PORT));
 | 
			
		||||
      if (i.hasNext()) {
 | 
			
		||||
        r.append(", ");
 | 
			
		||||
      }
 | 
			
		||||
@@ -302,7 +278,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
 | 
			
		||||
 | 
			
		||||
    for (final String desc : want) {
 | 
			
		||||
      try {
 | 
			
		||||
        bind.add(toSocketAddress(desc));
 | 
			
		||||
        bind.add(SocketUtil.resolve(desc, DEFAULT_PORT));
 | 
			
		||||
      } catch (IllegalArgumentException e) {
 | 
			
		||||
        log.error("Bad sshd.listenaddress: " + desc + ": " + e.getMessage());
 | 
			
		||||
      }
 | 
			
		||||
@@ -310,57 +286,6 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
 | 
			
		||||
    return bind;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private SocketAddress toSocketAddress(final String desc) {
 | 
			
		||||
    String hostStr;
 | 
			
		||||
    String portStr;
 | 
			
		||||
 | 
			
		||||
    if (desc.startsWith("[")) {
 | 
			
		||||
      // IPv6, as a raw IP address.
 | 
			
		||||
      //
 | 
			
		||||
      final int hostEnd = desc.indexOf(']');
 | 
			
		||||
      if (hostEnd < 0) {
 | 
			
		||||
        throw new IllegalArgumentException("invalid IPv6 representation");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      hostStr = desc.substring(1, hostEnd);
 | 
			
		||||
      portStr = desc.substring(hostEnd + 1);
 | 
			
		||||
    } else {
 | 
			
		||||
      // IPv4, or a host name.
 | 
			
		||||
      //
 | 
			
		||||
      final int hostEnd = desc.indexOf(':');
 | 
			
		||||
      hostStr = 0 <= hostEnd ? desc.substring(0, hostEnd) : desc;
 | 
			
		||||
      portStr = 0 <= hostEnd ? desc.substring(hostEnd) : "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ("*".equals(hostStr)) {
 | 
			
		||||
      hostStr = "";
 | 
			
		||||
    }
 | 
			
		||||
    if (portStr.startsWith(":")) {
 | 
			
		||||
      portStr = portStr.substring(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    final int port;
 | 
			
		||||
    if (portStr.length() > 0) {
 | 
			
		||||
      try {
 | 
			
		||||
        port = Integer.parseInt(portStr);
 | 
			
		||||
      } catch (NumberFormatException e) {
 | 
			
		||||
        throw new IllegalArgumentException("invalid port");
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      port = DEFAULT_PORT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (hostStr.length() > 0) {
 | 
			
		||||
      try {
 | 
			
		||||
        return new InetSocketAddress(InetAddress.getByName(hostStr), port);
 | 
			
		||||
      } catch (UnknownHostException e) {
 | 
			
		||||
        throw new IllegalArgumentException(e.getMessage(), e);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      return new InetSocketAddress(port);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unchecked")
 | 
			
		||||
  private void initProviderBouncyCastle() {
 | 
			
		||||
    setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>> asList(
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user