Merge "Abstract out concepts of DataSourceType and DatabaseConfigInitializer."
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2012 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.init;
|
||||
|
||||
/** Abstraction of initializer for the database section */
|
||||
interface DatabaseConfigInitializer {
|
||||
|
||||
/**
|
||||
* Performs database platform specific configuration steps and writes
|
||||
* configuration parameters into the given database section
|
||||
*/
|
||||
public void initConfig(Section databaseSection);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2012 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.init;
|
||||
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
public class DatabaseConfigModule extends AbstractModule {
|
||||
|
||||
private final SitePaths site;
|
||||
|
||||
public DatabaseConfigModule(final SitePaths site) {
|
||||
this.site = site;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(SitePaths.class).toInstance(site);
|
||||
bind(DatabaseConfigInitializer.class).annotatedWith(
|
||||
Names.named("h2")).to(H2Initializer.class);
|
||||
bind(DatabaseConfigInitializer.class).annotatedWith(
|
||||
Names.named("jdbc")).to(JDBCInitializer.class);
|
||||
bind(DatabaseConfigInitializer.class).annotatedWith(
|
||||
Names.named("mysql")).to(MySqlInitializer.class);
|
||||
bind(DatabaseConfigInitializer.class).annotatedWith(
|
||||
Names.named("postgresql")).to(PostgreSQLInitializer.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2012 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.init;
|
||||
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
class H2Initializer implements DatabaseConfigInitializer {
|
||||
|
||||
private final SitePaths site;
|
||||
|
||||
@Inject
|
||||
H2Initializer(final SitePaths site) {
|
||||
this.site = site;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initConfig(Section databaseSection) {
|
||||
String path = databaseSection.get("database");
|
||||
if (path == null) {
|
||||
path = "db/ReviewDB";
|
||||
databaseSection.set("database", path);
|
||||
}
|
||||
File db = site.resolve(path);
|
||||
if (db == null) {
|
||||
throw InitUtil.die("database.database must be supplied for H2");
|
||||
}
|
||||
db = db.getParentFile();
|
||||
if (!db.exists() && !db.mkdirs()) {
|
||||
throw InitUtil.die("cannot create database.database "
|
||||
+ db.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,17 +14,24 @@
|
||||
|
||||
package com.google.gerrit.pgm.init;
|
||||
|
||||
import static com.google.gerrit.pgm.init.InitUtil.die;
|
||||
import static com.google.gerrit.pgm.init.InitUtil.username;
|
||||
import static com.google.gerrit.server.schema.DataSourceProvider.Type.H2;
|
||||
import static com.google.inject.Stage.PRODUCTION;
|
||||
|
||||
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.gerrit.server.schema.DataSourceProvider;
|
||||
import com.google.inject.Binding;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.name.Named;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/** Initialize the {@code database} configuration section. */
|
||||
@Singleton
|
||||
@@ -46,59 +53,28 @@ class InitDatabase implements InitStep {
|
||||
public void run() {
|
||||
ui.header("SQL Database");
|
||||
|
||||
final DataSourceProvider.Type db_type =
|
||||
database.select("Database server type", "type", H2);
|
||||
Set<String> allowedValues = new TreeSet<String>();
|
||||
Injector i = Guice.createInjector(PRODUCTION, new DatabaseConfigModule(site));
|
||||
List<Binding<DatabaseConfigInitializer>> dbConfigBindings =
|
||||
i.findBindingsByType(new TypeLiteral<DatabaseConfigInitializer>() {});
|
||||
for (Binding<DatabaseConfigInitializer> binding : dbConfigBindings) {
|
||||
Annotation annotation = binding.getKey().getAnnotation();
|
||||
if (annotation instanceof Named) {
|
||||
allowedValues.add(((Named) annotation).value());
|
||||
}
|
||||
}
|
||||
|
||||
switch (db_type) {
|
||||
case MYSQL:
|
||||
String dbType =
|
||||
database.select("Database server type", "type", "h2", allowedValues);
|
||||
|
||||
DatabaseConfigInitializer dci =
|
||||
i.getInstance(Key.get(DatabaseConfigInitializer.class,
|
||||
Names.named(dbType.toLowerCase())));
|
||||
|
||||
if (dci instanceof MySqlInitializer) {
|
||||
libraries.mysqlDriver.downloadRequired();
|
||||
break;
|
||||
}
|
||||
|
||||
final boolean userPassAuth;
|
||||
switch (db_type) {
|
||||
case H2: {
|
||||
userPassAuth = false;
|
||||
String path = database.get("database");
|
||||
if (path == null) {
|
||||
path = "db/ReviewDB";
|
||||
database.set("database", path);
|
||||
}
|
||||
File db = site.resolve(path);
|
||||
if (db == null) {
|
||||
throw die("database.database must be supplied for H2");
|
||||
}
|
||||
db = db.getParentFile();
|
||||
if (!db.exists() && !db.mkdirs()) {
|
||||
throw die("cannot create database.database " + db.getAbsolutePath());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JDBC: {
|
||||
userPassAuth = true;
|
||||
database.string("Driver class name", "driver", null);
|
||||
database.string("URL", "url", null);
|
||||
break;
|
||||
}
|
||||
|
||||
case POSTGRESQL:
|
||||
case MYSQL: {
|
||||
userPassAuth = true;
|
||||
final String defPort = "(" + db_type.toString() + " default)";
|
||||
database.string("Server hostname", "hostname", "localhost");
|
||||
database.string("Server port", "port", defPort, true);
|
||||
database.string("Database name", "database", "reviewdb");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw die("internal bug, database " + db_type + " not supported");
|
||||
}
|
||||
|
||||
if (userPassAuth) {
|
||||
database.string("Database username", "username", username());
|
||||
database.password("username", "password");
|
||||
}
|
||||
dci.initConfig(database);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2012 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.init;
|
||||
|
||||
import static com.google.gerrit.pgm.init.InitUtil.username;
|
||||
|
||||
class JDBCInitializer implements DatabaseConfigInitializer {
|
||||
|
||||
@Override
|
||||
public void initConfig(Section databaseSection) {
|
||||
databaseSection.string("Driver class name", "driver", null);
|
||||
databaseSection.string("URL", "url", null);
|
||||
databaseSection.string("Database username", "username", username());
|
||||
databaseSection.password("username", "password");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2012 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.init;
|
||||
|
||||
import static com.google.gerrit.pgm.init.InitUtil.username;
|
||||
|
||||
class MySqlInitializer implements DatabaseConfigInitializer {
|
||||
|
||||
@Override
|
||||
public void initConfig(Section databaseSection) {
|
||||
final String defPort = "(mysql default)";
|
||||
databaseSection.string("Server hostname", "hostname", "localhost");
|
||||
databaseSection.string("Server port", "port", defPort, true);
|
||||
databaseSection.string("Database name", "database", "reviewdb");
|
||||
databaseSection.string("Database username", "username", username());
|
||||
databaseSection.password("username", "password");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2012 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.init;
|
||||
|
||||
import static com.google.gerrit.pgm.init.InitUtil.username;
|
||||
|
||||
class PostgreSQLInitializer implements DatabaseConfigInitializer {
|
||||
|
||||
@Override
|
||||
public void initConfig(Section databaseSection) {
|
||||
final String defPort = "(postgresql default)";
|
||||
databaseSection.string("Server hostname", "hostname", "localhost");
|
||||
databaseSection.string("Server port", "port", defPort, true);
|
||||
databaseSection.string("Database name", "database", "reviewdb");
|
||||
databaseSection.string("Database username", "username", username());
|
||||
databaseSection.password("username", "password");
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import com.google.inject.assistedinject.Assisted;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
/** Helper to edit a section of the configuration files. */
|
||||
class Section {
|
||||
@@ -125,6 +126,16 @@ class Section {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
String select(final String title, final String name, final String dv,
|
||||
Set<String> allowedValues) {
|
||||
final String ov = get(name);
|
||||
String nv = ui.readString(ov != null ? ov : dv, allowedValues, "%s", title);
|
||||
if (!eq(ov, nv)) {
|
||||
set(name, nv);
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
String password(final String username, final String password) {
|
||||
final String ov = getSecure(password);
|
||||
|
||||
@@ -166,6 +177,10 @@ class Section {
|
||||
}
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return section;
|
||||
}
|
||||
|
||||
private static boolean eq(final String a, final String b) {
|
||||
if (a == null && b == null) {
|
||||
return true;
|
||||
|
||||
@@ -20,7 +20,6 @@ import static com.google.gerrit.pgm.init.InitUtil.saveSecure;
|
||||
|
||||
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.gerrit.server.schema.DataSourceProvider;
|
||||
import com.google.gerrit.server.util.SocketUtil;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
@@ -122,7 +121,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
||||
|
||||
String url = oldprop.getProperty("url");
|
||||
if (url != null && !convertUrl(database, url)) {
|
||||
database.set("type", DataSourceProvider.Type.JDBC);
|
||||
database.set("type", "jdbc");
|
||||
database.set("driver", oldprop.getProperty("driver"));
|
||||
database.set("url", url);
|
||||
}
|
||||
@@ -189,7 +188,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
||||
|
||||
if (url.startsWith("jdbc:h2:file:")) {
|
||||
url = url.substring("jdbc:h2:file:".length());
|
||||
database.set("type", DataSourceProvider.Type.H2);
|
||||
database.set("type", "h2");
|
||||
database.set("database", url);
|
||||
return true;
|
||||
}
|
||||
@@ -202,7 +201,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
||||
}
|
||||
|
||||
final InetSocketAddress addr = SocketUtil.parse(url.substring(0, sl), 0);
|
||||
database.set("type", DataSourceProvider.Type.POSTGRESQL);
|
||||
database.set("type", "postgresql");
|
||||
sethost(database, addr);
|
||||
database.set("database", url.substring(sl + 1));
|
||||
setuser(database, username, password);
|
||||
@@ -211,7 +210,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
||||
|
||||
if (url.startsWith("jdbc:postgresql:")) {
|
||||
url = url.substring("jdbc:postgresql:".length());
|
||||
database.set("type", DataSourceProvider.Type.POSTGRESQL);
|
||||
database.set("type", "postgresql");
|
||||
database.set("hostname", "localhost");
|
||||
database.set("database", url);
|
||||
setuser(database, username, password);
|
||||
@@ -226,7 +225,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
||||
}
|
||||
|
||||
final InetSocketAddress addr = SocketUtil.parse(url.substring(0, sl), 0);
|
||||
database.set("type", DataSourceProvider.Type.MYSQL);
|
||||
database.set("type", "mysql");
|
||||
sethost(database, addr);
|
||||
database.set("database", url.substring(sl + 1));
|
||||
setuser(database, username, password);
|
||||
|
||||
@@ -18,6 +18,7 @@ import static org.eclipse.jgit.util.StringUtils.equalsIgnoreCase;
|
||||
|
||||
import java.io.Console;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Set;
|
||||
|
||||
/** Console based interaction with the invoking user. */
|
||||
public abstract class ConsoleUI {
|
||||
@@ -73,6 +74,10 @@ public abstract class ConsoleUI {
|
||||
/** Prompt the user for a string, suggesting a default, and returning choice. */
|
||||
public abstract String readString(String def, String fmt, Object... args);
|
||||
|
||||
/** Prompt the user to make a choice from an allowed list of values. */
|
||||
public abstract String readString(String def, Set<String> allowedValues,
|
||||
String fmt, Object... args);
|
||||
|
||||
/** Prompt the user for an integer value, suggesting a default. */
|
||||
public int readInt(int def, String fmt, Object... args) {
|
||||
for (;;) {
|
||||
@@ -161,6 +166,24 @@ public abstract class ConsoleUI {
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString(String def, Set<String> allowedValues, String fmt,
|
||||
Object... args) {
|
||||
for (;;) {
|
||||
String r = readString(def, fmt, args);
|
||||
if (allowedValues.contains(r.toLowerCase())) {
|
||||
return r.toLowerCase();
|
||||
}
|
||||
if (!"?".equals(r)) {
|
||||
console.printf("error: '%s' is not a valid choice\n", r);
|
||||
}
|
||||
console.printf(" Supported options are:\n");
|
||||
for (final String v : allowedValues) {
|
||||
console.printf(" %s\n", v.toString().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String password(String fmt, Object... args) {
|
||||
final String prompt = String.format(fmt, args);
|
||||
@@ -241,6 +264,12 @@ public abstract class ConsoleUI {
|
||||
return def;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString(String def, Set<String> allowedValues, String fmt,
|
||||
Object... args) {
|
||||
return def;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForUser() {
|
||||
}
|
||||
|
||||
@@ -18,10 +18,13 @@ import static com.google.inject.Scopes.SINGLETON;
|
||||
import static com.google.inject.Stage.PRODUCTION;
|
||||
|
||||
import com.google.gerrit.lifecycle.LifecycleModule;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.config.GerritServerConfigModule;
|
||||
import com.google.gerrit.server.config.SitePath;
|
||||
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
|
||||
import com.google.gerrit.server.schema.DataSourceModule;
|
||||
import com.google.gerrit.server.schema.DataSourceProvider;
|
||||
import com.google.gerrit.server.schema.DataSourceType;
|
||||
import com.google.gerrit.server.schema.DatabaseModule;
|
||||
import com.google.gerrit.server.schema.SchemaModule;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
@@ -34,6 +37,7 @@ import com.google.inject.Module;
|
||||
import com.google.inject.name.Names;
|
||||
import com.google.inject.spi.Message;
|
||||
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.kohsuke.args4j.Option;
|
||||
|
||||
import java.io.File;
|
||||
@@ -147,12 +151,15 @@ public abstract class SiteProgram extends AbstractProgram {
|
||||
|
||||
final File sitePath = getSitePath();
|
||||
final List<Module> modules = new ArrayList<Module>();
|
||||
modules.add(new AbstractModule() {
|
||||
|
||||
Module sitePathModule = new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath);
|
||||
}
|
||||
});
|
||||
};
|
||||
modules.add(sitePathModule);
|
||||
|
||||
modules.add(new LifecycleModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
@@ -162,7 +169,21 @@ public abstract class SiteProgram extends AbstractProgram {
|
||||
listener().to(DataSourceProvider.class);
|
||||
}
|
||||
});
|
||||
modules.add(new GerritServerConfigModule());
|
||||
Module configModule = new GerritServerConfigModule();
|
||||
modules.add(configModule);
|
||||
Injector cfgInjector = Guice.createInjector(sitePathModule, configModule);
|
||||
Config cfg = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
|
||||
String dbType = cfg.getString("database", null, "type");
|
||||
|
||||
final DataSourceType dst = Guice.createInjector(new DataSourceModule(), configModule,
|
||||
sitePathModule).getInstance(
|
||||
Key.get(DataSourceType.class, Names.named(dbType.toLowerCase())));
|
||||
|
||||
modules.add(new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DataSourceType.class).toInstance(dst);
|
||||
}});
|
||||
modules.add(new DatabaseModule());
|
||||
modules.add(new SchemaModule());
|
||||
modules.add(new LocalDiskRepositoryManager.Module());
|
||||
|
||||
Reference in New Issue
Block a user