blob: 33918bd0f251c35f99cbb9b009f09e79827609da [file] [log] [blame]
// Copyright (C) 2009 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.google.gerrit.pgm;
import static com.google.gerrit.pgm.util.DataSourceProvider.Context.SINGLE_USER;
import static com.google.gerrit.pgm.util.DataSourceProvider.Type.H2;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.main.GerritLauncher;
import com.google.gerrit.pgm.util.ConsoleUI;
import com.google.gerrit.pgm.util.DataSourceProvider;
import com.google.gerrit.pgm.util.ErrorLogFile;
import com.google.gerrit.pgm.util.IoUtil;
import com.google.gerrit.pgm.util.LibraryDownloader;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.reviewdb.AuthType;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.reviewdb.Project.SubmitType;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.mail.SmtpEmailSender.Encryption;
import com.google.gwtjsonrpc.server.SignedToken;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileBasedConfig;
import org.eclipse.jgit.lib.LockFile;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.util.SystemReader;
import org.h2.util.StartBrowser;
import org.kohsuke.args4j.Option;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** Initialize a new Gerrit installation. */
public class Init extends SiteProgram {
@Option(name = "--batch", usage = "Batch mode; skip interactive prompting")
private boolean batchMode;
@Option(name = "--import-projects", usage = "Import git repositories as projects")
private boolean importProjects;
@Inject
private GitRepositoryManager repositoryManager;
@Inject
private SchemaFactory<ReviewDb> schema;
private boolean deleteOnFailure;
private ConsoleUI ui;
private Injector dbInjector;
private Injector sysInjector;
private File site_path;
private File bin_dir;
private File cache_dir;
private File etc_dir;
private File lib_dir;
private File logs_dir;
private File static_dir;
private File gerrit_sh;
private File gerrit_config;
private File secure_config;
private File replication_config;
@Override
public int run() throws Exception {
ErrorLogFile.errorOnlyConsole();
ui = ConsoleUI.getInstance(batchMode);
initPathLocations();
final boolean isNew = !site_path.exists();
try {
upgradeFrom_Pre2_0_25();
initSitePath();
deleteOnFailure = false;
inject();
initGit();
} catch (Exception failure) {
if (deleteOnFailure) {
recursiveDelete(getSitePath());
}
throw failure;
} catch (Error failure) {
if (deleteOnFailure) {
recursiveDelete(getSitePath());
}
throw failure;
}
System.err.println("Initialized " + getSitePath().getCanonicalPath());
if (isNew) {
if (IoUtil.isWin32()) {
System.err.println("Automatic startup not supported on this platform.");
} else {
start();
openBrowser();
}
}
return 0;
}
private void initPathLocations() {
site_path = getSitePath();
bin_dir = new File(site_path, "bin");
cache_dir = new File(site_path, "cache");
etc_dir = new File(site_path, "etc");
lib_dir = new File(site_path, "lib");
logs_dir = new File(site_path, "logs");
static_dir = new File(site_path, "static");
gerrit_sh = new File(bin_dir, "gerrit.sh");
gerrit_config = new File(etc_dir, "gerrit.config");
secure_config = new File(etc_dir, "secure.config");
replication_config = new File(etc_dir, "replication.config");
}
private void upgradeFrom_Pre2_0_25() throws IOException {
boolean isPre2_0_25 = false;
final String[] etcFiles =
{"gerrit.config", "secure.config", "replication.config",
"ssh_host_rsa_key", "ssh_host_rsa_key.pub", "ssh_host_dsa_key",
"ssh_host_dsa_key.pub", "ssh_host_key", "contact_information.pub",
"gitweb_config.perl", "keystore", "GerritSite.css",
"GerritSiteFooter.html", "GerritSiteHeader.html"};
for (String name : etcFiles) {
if (new File(site_path, name).exists()) {
isPre2_0_25 = true;
break;
}
}
if (isPre2_0_25) {
if (!ui.yesno("Upgrade '%s'", site_path.getCanonicalPath())) {
throw die("aborted by user");
}
if (!etc_dir.exists() && !etc_dir.mkdirs()) {
throw die("Cannot create directory " + etc_dir);
}
for (String name : etcFiles) {
final File src = new File(site_path, name);
final File dst = new File(etc_dir, name);
if (src.exists()) {
if (dst.exists()) {
throw die("File " + src + " would overwrite " + dst);
}
if (!src.renameTo(dst)) {
throw die("Cannot rename " + src + " to " + dst);
}
}
}
}
}
private void initSitePath() throws IOException, InterruptedException {
if (gerrit_config.exists()) {
} else if (!gerrit_config.exists()) {
ui.header("Gerrit Code Review %s", version());
if (!ui.yesno("Initialize '%s'", site_path.getCanonicalPath())) {
throw die("aborted by user");
}
if (!site_path.mkdirs()) {
throw die("Cannot make directory " + site_path);
}
if (!etc_dir.mkdir()) {
throw die("Cannot make directory " + etc_dir);
}
deleteOnFailure = true;
final FileBasedConfig cfg = new FileBasedConfig(gerrit_config);
final FileBasedConfig sec = new FileBasedConfig(secure_config);
init_gerrit_basepath(cfg);
init_database(cfg, sec);
init_auth(cfg, sec);
init_sendemail(cfg, sec);
init_container(cfg);
init_sshd(cfg, sec);
init_httpd(cfg, sec);
cache_dir.mkdir();
set(cfg, "cache", "directory", cache_dir.getName());
cfg.save();
saveSecureConfig(sec);
if (ui != null) {
System.err.println();
}
}
bin_dir.mkdir();
etc_dir.mkdir();
lib_dir.mkdir();
logs_dir.mkdir();
static_dir.mkdir();
if (!secure_config.exists()) {
chmod(0600, secure_config);
}
if (!replication_config.exists()) {
replication_config.createNewFile();
}
if (!gerrit_sh.exists()) {
extract(gerrit_sh, "WEB-INF/extra/bin/gerrit.sh");
chmod(0755, gerrit_sh);
}
}
private void initGit() throws OrmException, IOException {
final File root = repositoryManager.getBasePath();
if (root != null && importProjects) {
System.err.println("Scanning projects under " + root);
final ReviewDb db = schema.open();
try {
final HashSet<String> have = new HashSet<String>();
for (Project p : db.projects().all()) {
have.add(p.getName());
}
importProjects(root, "", db, have);
} finally {
db.close();
}
}
}
private void importProjects(final File dir, final String prefix,
final ReviewDb db, final Set<String> have) throws OrmException,
IOException {
final File[] ls = dir.listFiles();
if (ls == null) {
return;
}
for (File f : ls) {
if (".".equals(f.getName()) || "..".equals(f.getName())) {
} else if (FileKey.isGitRepository(f)) {
String name = f.getName();
if (name.equals(".git")) {
name = prefix.substring(0, prefix.length() - 1);
} else if (name.endsWith(".git")) {
name = prefix + name.substring(0, name.length() - 4);
} else {
name = prefix + name;
System.err.println("Ignoring non-standard name '" + name + "'");
continue;
}
if (have.contains(name)) {
continue;
}
final Project.NameKey nameKey = new Project.NameKey(name);
final Project.Id idKey = new Project.Id(db.nextProjectId());
final Project p = new Project(nameKey, idKey);
p.setDescription(repositoryManager.getProjectDescription(name));
p.setSubmitType(SubmitType.MERGE_IF_NECESSARY);
p.setUseContributorAgreements(false);
p.setUseSignedOffBy(false);
db.projects().insert(Collections.singleton(p));
} else if (f.isDirectory()) {
importProjects(f, prefix + f.getName() + "/", db, have);
}
}
}
private void saveSecureConfig(final FileBasedConfig sec) throws IOException {
final byte[] out = Constants.encode(sec.toText());
final File path = sec.getFile();
final LockFile lf = new LockFile(path);
if (!lf.lock()) {
throw new IOException("Cannot lock " + path);
}
try {
chmod(0600, new File(path.getParentFile(), path.getName() + ".lock"));
lf.write(out);
if (!lf.commit()) {
throw new IOException("Cannot commit write to " + path);
}
} finally {
lf.unlock();
}
}
private static void chmod(final int mode, final File path) throws IOException {
if (!path.exists() && !path.createNewFile()) {
throw new IOException("Cannot create " + path);
}
path.setReadable(false, false /* all */);
path.setWritable(false, false /* all */);
path.setExecutable(false, false /* all */);
path.setReadable((mode & 0400) == 0400, true /* owner only */);
path.setWritable((mode & 0200) == 0200, true /* owner only */);
if (path.isDirectory() || (mode & 0100) == 0100) {
path.setExecutable(true, true /* owner only */);
}
if ((mode & 0044) == 0044) {
path.setReadable(true, false /* all */);
}
if ((mode & 0011) == 0011) {
path.setExecutable(true, false /* all */);
}
}
private void init_gerrit_basepath(final Config cfg) {
ui.header("Git Repositories");
File d = new File(ui.readString("git", "Location of Git repositories"));
set(cfg, "gerrit", "basePath", d.getPath());
if (d.exists()) {
if (!importProjects && d.list() != null && d.list().length > 0) {
importProjects = ui.yesno("Import existing repositories");
}
} else if (!d.mkdirs()) {
throw die("Cannot create " + d);
}
}
private void init_database(final Config cfg, final Config sec) {
ui.header("SQL Database");
DataSourceProvider.Type db_type = ui.readEnum(H2, "Database server type");
if (db_type == DataSourceProvider.Type.DEFAULT) {
db_type = H2;
}
set(cfg, "database", "type", db_type, null);
switch (db_type) {
case MYSQL:
createDownloader()
.setRequired(true)
.setName("MySQL Connector/J 5.1.10")
.setJarUrl(
"http://repo2.maven.org/maven2/mysql/mysql-connector-java/5.1.10/mysql-connector-java-5.1.10.jar")
.setSHA1("b83574124f1a00d6f70d56ba64aa52b8e1588e6d").download();
loadSiteLib();
break;
}
final boolean userPassAuth;
switch (db_type) {
case H2:
userPassAuth = false;
new File(site_path, "db").mkdirs();
break;
case JDBC: {
userPassAuth = true;
String driver = ui.readString("", "Driver class name");
String url = ui.readString("", "url");
set(cfg, "database", "driver", driver);
set(cfg, "database", "url", url);
break;
}
case POSTGRES:
case POSTGRESQL:
case MYSQL: {
userPassAuth = true;
String def_port = "(" + db_type.toString() + " default)";
String hostname = ui.readString("localhost", "Server hostname");
String port = ui.readString(def_port, "Server port");
String database = ui.readString("reviewdb", "Database name");
set(cfg, "database", "hostname", hostname);
set(cfg, "database", "port", port != def_port ? port : null);
set(cfg, "database", "database", database);
break;
}
default:
throw die("internal bug, database " + db_type + " not supported");
}
if (userPassAuth) {
String user = ui.readString(username(), "Database username");
String pass = user != null ? ui.password("%s's password", user) : null;
set(cfg, "database", "username", user);
set(sec, "database", "password", pass);
}
}
private void init_auth(final Config cfg, final Config sec) {
ui.header("User Authentication");
AuthType auth_type = ui.readEnum(AuthType.OPENID, "Authentication method");
set(cfg, "auth", "type", auth_type, null);
switch (auth_type) {
case HTTP:
case HTTP_LDAP: {
String def_hdr = "(HTTP Basic)";
String hdr = ui.readString(def_hdr, "Username HTTP header");
String logoutUrl = ui.readString("", "Single-sign-on logout URL");
set(cfg, "auth", "httpHeader", hdr != def_hdr ? hdr : null);
set(cfg, "auth", "logoutUrl", logoutUrl);
break;
}
}
switch (auth_type) {
case LDAP:
case HTTP_LDAP: {
String server = ui.readString("ldap://localhost", "LDAP server");
if (server != null && !server.startsWith("ldap://")
&& !server.startsWith("ldaps://")) {
if (ui.yesno("Use SSL")) {
server = "ldaps://" + server;
} else {
server = "ldap://" + server;
}
}
final String def_dn = dnOf(server);
String accountBase = ui.readString(def_dn, "Account BaseDN");
String groupBase = ui.readString(accountBase, "Group BaseDN");
String user = ui.readString(null, "LDAP username");
String pass = user != null ? ui.password("%s's password", user) : null;
set(cfg, "ldap", "server", server);
set(cfg, "ldap", "username", user);
set(sec, "ldap", "password", pass);
set(cfg, "ldap", "accountBase", accountBase);
set(cfg, "ldap", "groupBase", groupBase);
break;
}
}
}
private void init_sendemail(final Config cfg, final Config sec) {
ui.header("Email Delivery");
String def_port = "(default)";
String smtpserver = ui.readString("localhost", "SMTP server hostname");
String port = ui.readString(def_port, "SMTP server port");
Encryption enc = ui.readEnum(Encryption.NONE, "SMTP encryption");
String username = null;
if (enc != Encryption.NONE || !isLocal(smtpserver)) {
username = username();
}
username = ui.readString(username, "SMTP username");
String password =
username != null ? ui.password("%s's password", username) : null;
set(cfg, "sendemail", "smtpServer", smtpserver);
set(cfg, "sendemail", "smtpServerPort", port != def_port ? port : null);
set(cfg, "sendemail", "smtpEncryption", enc, Encryption.NONE);
set(cfg, "sendemail", "smtpUser", username);
set(sec, "sendemail", "smtpPass", password);
}
private void init_container(final Config cfg) throws IOException {
ui.header("Container Process");
String javaHome = System.getProperty("java.home");
if (!ui.yesno("Use %s", javaHome)) {
final String guess = "AUTO SELECT";
javaHome = ui.readString(guess, "Path of JAVA_HOME");
if (javaHome == guess) {
javaHome = null;
}
}
set(cfg, "container", "javaHome", javaHome);
String user = ui.readString(username(), "Local username to run as");
set(cfg, "container", "user", user);
File mywar;
try {
mywar = GerritLauncher.getDistributionArchive();
} catch (FileNotFoundException e) {
System.err.println("warn: Cannot find gerrit.war; skipping java.start");
mywar = null;
}
if (mywar != null) {
String war = null;
if (ui.yesno("Run from %s", mywar.getAbsolutePath())) {
war = mywar.getAbsolutePath();
} else {
if (!ui.isBatch()) {
System.err.format("Copying gerrit.war to %s", bin_dir);
System.err.println();
}
copy(new File(bin_dir, "gerrit.war"), new FileInputStream(mywar));
}
set(cfg, "container", "war", war);
}
}
private void init_sshd(final Config cfg, final Config sec)
throws IOException, InterruptedException {
ui.header("SSH Daemon");
String sshd_hostname = ui.readString("*", "Gerrit SSH listens on address");
String sshd_port = ui.readString("29418", "Gerrit SSH listens on port");
set(cfg, "sshd", "listenAddress", sshd_hostname + ":" + sshd_port);
// Download and install BouncyCastle if the user wants to use it.
//
createDownloader().setRequired(false).setName("Bouncy Castle Crypto v144")
.setJarUrl("http://www.bouncycastle.org/download/bcprov-jdk16-144.jar")
.setSHA1("6327a5f7a3dc45e0fd735adb5d08c5a74c05c20c").download();
loadSiteLib();
final File etc_dir = new File(getSitePath(), "etc");
System.err.print("Generating SSH host key ...");
System.err.flush();
if (SecurityUtils.isBouncyCastleRegistered()) {
// Generate the SSH daemon host key using ssh-keygen.
//
final String comment = "gerrit-code-review@" + hostname();
final File rsa = new File(etc_dir, "ssh_host_rsa_key");
final File dsa = new File(etc_dir, "ssh_host_dsa_key");
System.err.print(" rsa...");
System.err.flush();
Runtime.getRuntime().exec(new String[] {"ssh-keygen", //
"-q" /* quiet */, //
"-t", "rsa", //
"-P", "", //
"-C", comment, //
"-f", rsa.getAbsolutePath() //
}).waitFor();
System.err.print(" dsa...");
System.err.flush();
Runtime.getRuntime().exec(new String[] {"ssh-keygen", //
"-q" /* quiet */, //
"-t", "dsa", //
"-P", "", //
"-C", comment, //
"-f", dsa.getAbsolutePath() //
}).waitFor();
} else {
// Generate the SSH daemon host key ourselves. This is complex
// because SimpleGeneratorHostKeyProvider doesn't mark the data
// file as only readable by us, exposing the private key for a
// short period of time. We try to reduce that risk by creating
// the key within a temporary directory.
//
final File tmpdir = new File(etc_dir, "tmp.sshkeygen");
if (!tmpdir.mkdir()) {
throw die("Cannot create directory " + tmpdir);
}
chmod(0600, tmpdir);
final String keyname = "ssh_host_key";
final File tmpkey = new File(tmpdir, keyname);
final SimpleGeneratorHostKeyProvider p;
System.err.print(" rsa(simple)...");
System.err.flush();
p = new SimpleGeneratorHostKeyProvider();
p.setPath(tmpkey.getAbsolutePath());
p.setAlgorithm("RSA");
p.loadKeys(); // forces the key to generate.
chmod(0600, tmpkey);
final File key = new File(etc_dir, keyname);
if (!tmpkey.renameTo(key)) {
throw die("Cannot rename " + tmpkey + " to " + key);
}
if (!tmpdir.delete()) {
throw die("Cannot delete " + tmpdir);
}
}
System.err.println(" done");
}
private void init_httpd(final Config cfg, final Config sec)
throws IOException, InterruptedException {
ui.header("HTTP Daemon");
final boolean useProxy;
final String proxyName, proxyPort;
if (ui.isBatch()) {
useProxy = false;
proxyName = null;
proxyPort = null;
} else {
useProxy = ui.yesno("Behind reverse HTTP proxy (e.g. Apache mod_proxy)");
proxyName = ui.readString(hostname(), "Proxy server name");
proxyPort = ui.readString("443", "Proxy server port");
}
final boolean useSSL;
if (ui.isBatch()) {
useSSL = false;
} else if (useProxy) {
useSSL = ui.yesno("Proxy uses https:// (SSL)");
} else {
useSSL = ui.yesno("Use https:// (SSL)");
}
final String scheme = useSSL ? "https" : "http";
final String port_def = useSSL ? "8443" : "8080";
String httpd_hostname = ui.readString(useProxy ? "localhost" : "*", //
"Gerrit HTTP listens on address");
String httpd_port = ui.readString(useProxy ? "8081" : port_def, //
"Gerrit HTTP listens on port");
String context = "/";
if (useProxy) {
context = ui.readString("/", "Gerrit's subdirectory on proxy server");
if (!context.endsWith("/")) {
context += "/";
}
}
final String httpd_url = (useProxy ? "proxy-" : "") //
+ scheme + "://" + httpd_hostname + ":" + httpd_port + context;
set(cfg, "httpd", "listenUrl", httpd_url);
if (useSSL && useProxy) {
final String port = "443".equals(proxyPort) ? "" : ":" + proxyPort;
set(cfg, "gerrit", "canonicalWebUrl", //
"https://" + proxyName + port + context);
} else if (useSSL && ui.yesno("Create self-signed SSL certificate")) {
final String certName =
ui.readString("*".equals(httpd_hostname) ? hostname()
: httpd_hostname, "Certificate server name");
final String validity =
ui.readString("365", "Certificate expires in (days)");
final String ssl_pass = SignedToken.generateRandomKey();
final String dname =
"CN=" + certName + ",OU=Gerrit Code Review,O=" + domainOf(certName);
final File etc_dir = new File(getSitePath(), "etc");
final File tmpdir = new File(etc_dir, "tmp.sslcertgen");
if (!tmpdir.mkdir()) {
throw die("Cannot create directory " + tmpdir);
}
chmod(0600, tmpdir);
final File tmpstore = new File(tmpdir, "keystore");
Runtime.getRuntime().exec(new String[] {"keytool", //
"-keystore", tmpstore.getAbsolutePath(), //
"-storepass", ssl_pass, //
"-genkeypair", //
"-alias", certName, //
"-keyalg", "RSA", //
"-validity", validity, //
"-dname", dname, //
"-keypass", ssl_pass, //
}).waitFor();
chmod(0600, tmpstore);
final File store = new File(etc_dir, "keystore");
if (!tmpstore.renameTo(store)) {
throw die("Cannot rename " + tmpstore + " to " + store);
}
if (!tmpdir.delete()) {
throw die("Cannot delete " + tmpdir);
}
set(sec, "httpd", "sslKeyPassword", ssl_pass);
set(cfg, "gerrit", "canonicalWebUrl", "https://" + certName + ":"
+ httpd_port + context);
}
}
private void start() {
final String[] argv = {gerrit_sh.getAbsolutePath(), "start"};
final Process proc;
try {
System.err.println("Executing " + argv[0] + " " + argv[1]);
proc = Runtime.getRuntime().exec(argv);
} catch (IOException e) {
System.err.println("error: cannot start Gerrit: " + e.getMessage());
return;
}
try {
proc.getOutputStream().close();
} catch (IOException e) {
}
IoUtil.copyWithThread(proc.getInputStream(), System.err);
IoUtil.copyWithThread(proc.getErrorStream(), System.err);
for (;;) {
try {
final int rc = proc.waitFor();
if (rc != 0) {
System.err.println("error: cannot start Gerrit: exit status " + rc);
}
break;
} catch (InterruptedException e) {
// retry
}
}
}
private void openBrowser() throws IOException, ConfigInvalidException {
if (ui.isBatch()) {
return;
}
final FileBasedConfig cfg = new FileBasedConfig(gerrit_config);
cfg.load();
String url = cfg.getString("httpd", null, "listenUrl");
if (url == null) {
return;
}
if (url.startsWith("proxy-")) {
url = url.substring("proxy-".length());
}
if (!url.endsWith("/")) {
url += "/";
}
url += "#" + PageLinks.ADMIN_PROJECTS;
// If the URL uses * it means all addresses on this system, use the
// current hostname instead so the user can login from any host.
//
final URI uri;
try {
final URI u = new URI(url);
if (u.getHost() == null
&& (u.getAuthority().equals("*") || u.getAuthority().startsWith("*:"))) {
final int s = url.indexOf('*');
url = url.substring(0, s) + hostname() + url.substring(s + 1);
}
uri = new URI(url);
} catch (URISyntaxException e) {
System.err.println("error: invalid httpd.listenUrl: " + url);
return;
}
String hostname = uri.getHost();
int port = uri.getPort();
if (port < 0) {
port = "https".equals(uri.getScheme()) ? 443 : 80;
}
System.err.print("Waiting for server to start ... ");
System.err.flush();
for (;;) {
final Socket s;
try {
s = new Socket(hostname, port);
} catch (IOException e) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
}
continue;
}
s.close();
break;
}
System.err.println("OK");
System.err.println("Opening browser ...");
StartBrowser.openURL(url);
}
private <T extends Enum<?>> void set(Config cfg, String section, String name,
T value, T def) {
if (value != null && value != def) {
cfg.setString(section, null, name, value.toString());
} else {
cfg.unset(section, null, name);
}
}
private void set(Config cfg, String section, String name, String value) {
if (value != null && !value.isEmpty()) {
cfg.setString(section, null, name, value);
} else {
cfg.unset(section, null, name);
}
}
private void inject() {
dbInjector = createDbInjector(SINGLE_USER);
sysInjector = createSysInjector();
sysInjector.injectMembers(this);
}
private Injector createSysInjector() {
final List<Module> modules = new ArrayList<Module>();
modules.add(new AbstractModule() {
@Override
protected void configure() {
bind(GitRepositoryManager.class);
}
});
return dbInjector.createChildInjector(modules);
}
private LibraryDownloader createDownloader() {
return new LibraryDownloader(ui, getSitePath());
}
private static String version() {
return com.google.gerrit.common.Version.getVersion();
}
private static String username() {
return System.getProperty("user.name");
}
private static String hostname() {
return SystemReader.getInstance().getHostname();
}
private static boolean isLocal(final String hostname) {
try {
return InetAddress.getByName(hostname).isLoopbackAddress();
} catch (UnknownHostException e) {
return false;
}
}
private static String dnOf(String name) {
if (name != null) {
int p = name.indexOf("://");
if (0 < p) {
name = name.substring(p + 3);
}
p = name.indexOf(".");
if (0 < p) {
name = name.substring(p + 1);
name = "DC=" + name.replaceAll("\\.", ",DC=");
} else {
name = null;
}
}
return name;
}
private static String domainOf(String name) {
if (name != null) {
int p = name.indexOf("://");
if (0 < p) {
name = name.substring(p + 3);
}
p = name.indexOf(".");
if (0 < p) {
name = name.substring(p + 1);
}
}
return name;
}
private static void recursiveDelete(File path) {
File[] entries = path.listFiles();
if (entries != null) {
for (File e : entries) {
recursiveDelete(e);
}
}
if (!path.delete() && path.exists()) {
System.err.println("warn: Cannot remove " + path);
}
}
private static void extract(final File dst, final String path)
throws IOException {
final URL u = GerritLauncher.class.getClassLoader().getResource(path);
if (u == null) {
System.err.println("warn: Cannot read " + path);
return;
}
copy(dst, u.openStream());
}
private static void copy(final File dst, final InputStream in)
throws FileNotFoundException, IOException {
try {
dst.getParentFile().mkdirs();
final FileOutputStream out = new FileOutputStream(dst);
try {
final byte[] buf = new byte[4096];
int n;
while (0 < (n = in.read(buf))) {
out.write(buf, 0, n);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
}