Abstract out concepts of DataSourceType and DatabaseConfigInitializer.
Encapsulate data source specific logic into subclasses of DataSourceType and DatabaseConfigInitializer. DataSourceType and DatabaseConfigInitializer are separated because we need them at different stages (init vs runtime) and they also need to exist in different projects with different dependencies. This is a first step toward providing support for different database platforms as plugins. Change-Id: I01ea666ef7f682d6137f0e64005d979dd706f67b Signed-off-by: Edwin Kempin <edwin.kempin@sap.com> Signed-off-by: Sasa Zivkov <sasa.zivkov@sap.com>
This commit is contained in:

committed by
Edwin Kempin

parent
05acbe4c0a
commit
b53bffe1b9
@@ -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;
|
package com.google.gerrit.pgm.init;
|
||||||
|
|
||||||
import static com.google.gerrit.pgm.init.InitUtil.die;
|
import static com.google.inject.Stage.PRODUCTION;
|
||||||
import static com.google.gerrit.pgm.init.InitUtil.username;
|
|
||||||
import static com.google.gerrit.server.schema.DataSourceProvider.Type.H2;
|
|
||||||
|
|
||||||
import com.google.gerrit.pgm.util.ConsoleUI;
|
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
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.Inject;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Key;
|
||||||
import com.google.inject.Singleton;
|
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. */
|
/** Initialize the {@code database} configuration section. */
|
||||||
@Singleton
|
@Singleton
|
||||||
@@ -46,59 +53,28 @@ class InitDatabase implements InitStep {
|
|||||||
public void run() {
|
public void run() {
|
||||||
ui.header("SQL Database");
|
ui.header("SQL Database");
|
||||||
|
|
||||||
final DataSourceProvider.Type db_type =
|
Set<String> allowedValues = new TreeSet<String>();
|
||||||
database.select("Database server type", "type", H2);
|
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) {
|
String dbType =
|
||||||
case MYSQL:
|
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();
|
libraries.mysqlDriver.downloadRequired();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean userPassAuth;
|
dci.initConfig(database);
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/** Helper to edit a section of the configuration files. */
|
/** Helper to edit a section of the configuration files. */
|
||||||
class Section {
|
class Section {
|
||||||
@@ -125,6 +126,16 @@ class Section {
|
|||||||
return newValue;
|
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) {
|
String password(final String username, final String password) {
|
||||||
final String ov = getSecure(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) {
|
private static boolean eq(final String a, final String b) {
|
||||||
if (a == null && b == null) {
|
if (a == null && b == null) {
|
||||||
return true;
|
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.pgm.util.ConsoleUI;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.server.schema.DataSourceProvider;
|
|
||||||
import com.google.gerrit.server.util.SocketUtil;
|
import com.google.gerrit.server.util.SocketUtil;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
@@ -122,7 +121,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
|||||||
|
|
||||||
String url = oldprop.getProperty("url");
|
String url = oldprop.getProperty("url");
|
||||||
if (url != null && !convertUrl(database, 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("driver", oldprop.getProperty("driver"));
|
||||||
database.set("url", url);
|
database.set("url", url);
|
||||||
}
|
}
|
||||||
@@ -189,7 +188,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
|||||||
|
|
||||||
if (url.startsWith("jdbc:h2:file:")) {
|
if (url.startsWith("jdbc:h2:file:")) {
|
||||||
url = url.substring("jdbc:h2:file:".length());
|
url = url.substring("jdbc:h2:file:".length());
|
||||||
database.set("type", DataSourceProvider.Type.H2);
|
database.set("type", "h2");
|
||||||
database.set("database", url);
|
database.set("database", url);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -202,7 +201,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final InetSocketAddress addr = SocketUtil.parse(url.substring(0, sl), 0);
|
final InetSocketAddress addr = SocketUtil.parse(url.substring(0, sl), 0);
|
||||||
database.set("type", DataSourceProvider.Type.POSTGRESQL);
|
database.set("type", "postgresql");
|
||||||
sethost(database, addr);
|
sethost(database, addr);
|
||||||
database.set("database", url.substring(sl + 1));
|
database.set("database", url.substring(sl + 1));
|
||||||
setuser(database, username, password);
|
setuser(database, username, password);
|
||||||
@@ -211,7 +210,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
|||||||
|
|
||||||
if (url.startsWith("jdbc:postgresql:")) {
|
if (url.startsWith("jdbc:postgresql:")) {
|
||||||
url = url.substring("jdbc:postgresql:".length());
|
url = url.substring("jdbc:postgresql:".length());
|
||||||
database.set("type", DataSourceProvider.Type.POSTGRESQL);
|
database.set("type", "postgresql");
|
||||||
database.set("hostname", "localhost");
|
database.set("hostname", "localhost");
|
||||||
database.set("database", url);
|
database.set("database", url);
|
||||||
setuser(database, username, password);
|
setuser(database, username, password);
|
||||||
@@ -226,7 +225,7 @@ class UpgradeFrom2_0_x implements InitStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final InetSocketAddress addr = SocketUtil.parse(url.substring(0, sl), 0);
|
final InetSocketAddress addr = SocketUtil.parse(url.substring(0, sl), 0);
|
||||||
database.set("type", DataSourceProvider.Type.MYSQL);
|
database.set("type", "mysql");
|
||||||
sethost(database, addr);
|
sethost(database, addr);
|
||||||
database.set("database", url.substring(sl + 1));
|
database.set("database", url.substring(sl + 1));
|
||||||
setuser(database, username, password);
|
setuser(database, username, password);
|
||||||
|
@@ -18,6 +18,7 @@ import static org.eclipse.jgit.util.StringUtils.equalsIgnoreCase;
|
|||||||
|
|
||||||
import java.io.Console;
|
import java.io.Console;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/** Console based interaction with the invoking user. */
|
/** Console based interaction with the invoking user. */
|
||||||
public abstract class ConsoleUI {
|
public abstract class ConsoleUI {
|
||||||
@@ -73,6 +74,10 @@ public abstract class ConsoleUI {
|
|||||||
/** Prompt the user for a string, suggesting a default, and returning choice. */
|
/** Prompt the user for a string, suggesting a default, and returning choice. */
|
||||||
public abstract String readString(String def, String fmt, Object... args);
|
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. */
|
/** Prompt the user for an integer value, suggesting a default. */
|
||||||
public int readInt(int def, String fmt, Object... args) {
|
public int readInt(int def, String fmt, Object... args) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -161,6 +166,24 @@ public abstract class ConsoleUI {
|
|||||||
return r;
|
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
|
@Override
|
||||||
public String password(String fmt, Object... args) {
|
public String password(String fmt, Object... args) {
|
||||||
final String prompt = String.format(fmt, args);
|
final String prompt = String.format(fmt, args);
|
||||||
@@ -241,6 +264,12 @@ public abstract class ConsoleUI {
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readString(String def, Set<String> allowedValues, String fmt,
|
||||||
|
Object... args) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void waitForUser() {
|
public void waitForUser() {
|
||||||
}
|
}
|
||||||
|
@@ -18,10 +18,13 @@ import static com.google.inject.Scopes.SINGLETON;
|
|||||||
import static com.google.inject.Stage.PRODUCTION;
|
import static com.google.inject.Stage.PRODUCTION;
|
||||||
|
|
||||||
import com.google.gerrit.lifecycle.LifecycleModule;
|
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.GerritServerConfigModule;
|
||||||
import com.google.gerrit.server.config.SitePath;
|
import com.google.gerrit.server.config.SitePath;
|
||||||
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
|
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.DataSourceProvider;
|
||||||
|
import com.google.gerrit.server.schema.DataSourceType;
|
||||||
import com.google.gerrit.server.schema.DatabaseModule;
|
import com.google.gerrit.server.schema.DatabaseModule;
|
||||||
import com.google.gerrit.server.schema.SchemaModule;
|
import com.google.gerrit.server.schema.SchemaModule;
|
||||||
import com.google.gwtorm.server.OrmException;
|
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.name.Names;
|
||||||
import com.google.inject.spi.Message;
|
import com.google.inject.spi.Message;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -147,12 +151,15 @@ public abstract class SiteProgram extends AbstractProgram {
|
|||||||
|
|
||||||
final File sitePath = getSitePath();
|
final File sitePath = getSitePath();
|
||||||
final List<Module> modules = new ArrayList<Module>();
|
final List<Module> modules = new ArrayList<Module>();
|
||||||
modules.add(new AbstractModule() {
|
|
||||||
|
Module sitePathModule = new AbstractModule() {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath);
|
bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
modules.add(sitePathModule);
|
||||||
|
|
||||||
modules.add(new LifecycleModule() {
|
modules.add(new LifecycleModule() {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
@@ -162,7 +169,21 @@ public abstract class SiteProgram extends AbstractProgram {
|
|||||||
listener().to(DataSourceProvider.class);
|
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 DatabaseModule());
|
||||||
modules.add(new SchemaModule());
|
modules.add(new SchemaModule());
|
||||||
modules.add(new LocalDiskRepositoryManager.Module());
|
modules.add(new LocalDiskRepositoryManager.Module());
|
||||||
|
@@ -0,0 +1,37 @@
|
|||||||
|
// 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.server.config;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
|
/** Provides access to one section from {@link Config} */
|
||||||
|
public class ConfigSection {
|
||||||
|
|
||||||
|
private final Config cfg;
|
||||||
|
private final String section;
|
||||||
|
|
||||||
|
public ConfigSection(Config cfg, String section) {
|
||||||
|
this.cfg = cfg;
|
||||||
|
this.section = section;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String optional(String name) {
|
||||||
|
return cfg.getString(section, null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String required(String name) {
|
||||||
|
return ConfigUtil.getRequired(cfg, null, name);
|
||||||
|
}
|
||||||
|
}
|
@@ -286,6 +286,15 @@ public class ConfigUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getRequired(Config cfg, String section, String name) {
|
||||||
|
final String v = cfg.getString(section, null, name);
|
||||||
|
if (v == null || "".equals(v)) {
|
||||||
|
throw new IllegalArgumentException("No " + section + "." + name
|
||||||
|
+ " configured");
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean match(final String a, final String... cases) {
|
private static boolean match(final String a, final String... cases) {
|
||||||
for (final String b : cases) {
|
for (final String b : cases) {
|
||||||
if (equalsIgnoreCase(a, b)) {
|
if (equalsIgnoreCase(a, b)) {
|
||||||
|
@@ -0,0 +1,66 @@
|
|||||||
|
// 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.server.schema;
|
||||||
|
|
||||||
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public abstract class BaseDataSourceType implements DataSourceType {
|
||||||
|
|
||||||
|
private final String driver;
|
||||||
|
|
||||||
|
protected BaseDataSourceType(String driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String getDriver() {
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean usePool() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScriptRunner getIndexScript() throws IOException {
|
||||||
|
return getScriptRunner("index_generic.sql");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScriptRunner getNextValScript() throws IOException {
|
||||||
|
return ScriptRunner.NOOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static final ScriptRunner getScriptRunner(String path) throws IOException {
|
||||||
|
if (path == null) {
|
||||||
|
return ScriptRunner.NOOP;
|
||||||
|
}
|
||||||
|
InputStream in = ReviewDb.class.getResourceAsStream(path);
|
||||||
|
if (in == null) {
|
||||||
|
throw new IllegalStateException("SQL script " + path + " not found");
|
||||||
|
}
|
||||||
|
ScriptRunner runner;
|
||||||
|
try {
|
||||||
|
runner = new ScriptRunner(path, in);
|
||||||
|
} finally {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
return runner;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
// 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.server.schema;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.name.Names;
|
||||||
|
|
||||||
|
public class DataSourceModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(DataSourceType.class).annotatedWith(Names.named("h2")).to(H2.class);
|
||||||
|
bind(DataSourceType.class).annotatedWith(Names.named("jdbc")).to(JDBC.class);
|
||||||
|
bind(DataSourceType.class).annotatedWith(Names.named("mysql")).to(MySql.class);
|
||||||
|
bind(DataSourceType.class).annotatedWith(Names.named("postgresql")).to(PostgreSQL.class);
|
||||||
|
}
|
||||||
|
}
|
@@ -14,11 +14,12 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.schema;
|
package com.google.gerrit.server.schema;
|
||||||
|
|
||||||
import static com.google.gerrit.server.config.ConfigUtil.getEnum;
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.gerrit.extensions.events.LifecycleListener;
|
import com.google.gerrit.extensions.events.LifecycleListener;
|
||||||
|
import com.google.gerrit.server.config.ConfigSection;
|
||||||
import com.google.gerrit.server.config.ConfigUtil;
|
import com.google.gerrit.server.config.ConfigUtil;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
@@ -31,8 +32,6 @@ import com.google.inject.Singleton;
|
|||||||
import org.apache.commons.dbcp.BasicDataSource;
|
import org.apache.commons.dbcp.BasicDataSource;
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
@@ -46,8 +45,8 @@ public final class DataSourceProvider implements Provider<DataSource>,
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
DataSourceProvider(final SitePaths site,
|
DataSourceProvider(final SitePaths site,
|
||||||
@GerritServerConfig final Config cfg, Context ctx) {
|
@GerritServerConfig final Config cfg, Context ctx, DataSourceType dst) {
|
||||||
ds = open(site, cfg, ctx);
|
ds = open(site, cfg, ctx, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -74,100 +73,27 @@ public final class DataSourceProvider implements Provider<DataSource>,
|
|||||||
SINGLE_USER, MULTI_USER;
|
SINGLE_USER, MULTI_USER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum Type {
|
|
||||||
H2, POSTGRESQL, MYSQL, JDBC;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataSource open(final SitePaths site, final Config cfg,
|
private DataSource open(final SitePaths site, final Config cfg,
|
||||||
final Context context) {
|
final Context context, final DataSourceType dst) {
|
||||||
Type type = getEnum(cfg, "database", null, "type", Type.values(), null);
|
ConfigSection dbs = new ConfigSection(cfg, "database");
|
||||||
String driver = optional(cfg, "driver");
|
String driver = dbs.optional("driver");
|
||||||
String url = optional(cfg, "url");
|
if (Strings.isNullOrEmpty(driver)) {
|
||||||
String username = optional(cfg, "username");
|
driver = dst.getDriver();
|
||||||
String password = optional(cfg, "password");
|
|
||||||
|
|
||||||
if (url == null || url.isEmpty()) {
|
|
||||||
if (type == null) {
|
|
||||||
type = Type.H2;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case H2: {
|
|
||||||
String database = optional(cfg, "database");
|
|
||||||
if (database == null || database.isEmpty()) {
|
|
||||||
database = "db/ReviewDB";
|
|
||||||
}
|
|
||||||
File db = site.resolve(database);
|
|
||||||
try {
|
|
||||||
db = db.getCanonicalFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
db = db.getAbsoluteFile();
|
|
||||||
}
|
|
||||||
url = "jdbc:h2:" + db.toURI().toString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case POSTGRESQL: {
|
|
||||||
final StringBuilder b = new StringBuilder();
|
|
||||||
b.append("jdbc:postgresql://");
|
|
||||||
b.append(hostname(optional(cfg, "hostname")));
|
|
||||||
b.append(port(optional(cfg, "port")));
|
|
||||||
b.append("/");
|
|
||||||
b.append(required(cfg, "database"));
|
|
||||||
url = b.toString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MYSQL: {
|
|
||||||
final StringBuilder b = new StringBuilder();
|
|
||||||
b.append("jdbc:mysql://");
|
|
||||||
b.append(hostname(optional(cfg, "hostname")));
|
|
||||||
b.append(port(optional(cfg, "port")));
|
|
||||||
b.append("/");
|
|
||||||
b.append(required(cfg, "database"));
|
|
||||||
url = b.toString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case JDBC:
|
|
||||||
driver = required(cfg, "driver");
|
|
||||||
url = required(cfg, "url");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException(type + " not supported");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (driver == null || driver.isEmpty()) {
|
String url = dbs.optional("url");
|
||||||
if (url.startsWith("jdbc:h2:")) {
|
if (Strings.isNullOrEmpty(url)) {
|
||||||
driver = "org.h2.Driver";
|
url = dst.getUrl();
|
||||||
|
|
||||||
} else if (url.startsWith("jdbc:postgresql:")) {
|
|
||||||
driver = "org.postgresql.Driver";
|
|
||||||
|
|
||||||
} else if (url.startsWith("jdbc:mysql:")) {
|
|
||||||
driver = "com.mysql.jdbc.Driver";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("database.driver must be set");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String username = dbs.optional("username");
|
||||||
|
String password = dbs.optional("password");
|
||||||
|
|
||||||
boolean usePool;
|
boolean usePool;
|
||||||
if (url.startsWith("jdbc:mysql:")) {
|
|
||||||
// MySQL has given us trouble with the connection pool,
|
|
||||||
// sometimes the backend disconnects and the pool winds
|
|
||||||
// up with a stale connection. Fortunately opening up
|
|
||||||
// a new MySQL connection is usually very fast.
|
|
||||||
//
|
|
||||||
usePool = false;
|
|
||||||
} else {
|
|
||||||
usePool = true;
|
|
||||||
}
|
|
||||||
usePool = cfg.getBoolean("database", "connectionpool", usePool);
|
|
||||||
if (context == Context.SINGLE_USER) {
|
if (context == Context.SINGLE_USER) {
|
||||||
usePool = false;
|
usePool = false;
|
||||||
|
} else {
|
||||||
|
usePool = cfg.getBoolean("database", "connectionpool", dst.usePool());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usePool) {
|
if (usePool) {
|
||||||
@@ -207,33 +133,4 @@ public final class DataSourceProvider implements Provider<DataSource>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String hostname(String hostname) {
|
|
||||||
if (hostname == null || hostname.isEmpty()) {
|
|
||||||
hostname = "localhost";
|
|
||||||
|
|
||||||
} else if (hostname.contains(":") && !hostname.startsWith("[")) {
|
|
||||||
hostname = "[" + hostname + "]";
|
|
||||||
}
|
|
||||||
return hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String port(String port) {
|
|
||||||
if (port != null && !port.isEmpty()) {
|
|
||||||
return ":" + port;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String optional(final Config config, final String name) {
|
|
||||||
return config.getString("database", null, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String required(final Config config, final String name) {
|
|
||||||
final String v = optional(config, name);
|
|
||||||
if (v == null || "".equals(v)) {
|
|
||||||
throw new IllegalArgumentException("No database." + name + " configured");
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,44 @@
|
|||||||
|
// 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.server.schema;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
/** Abstraction of a supported database platform */
|
||||||
|
public interface DataSourceType {
|
||||||
|
|
||||||
|
public String getDriver();
|
||||||
|
|
||||||
|
public String getUrl();
|
||||||
|
|
||||||
|
public boolean usePool();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a ScriptRunner that runs the index script. Must not return
|
||||||
|
* <code>null</code>, but may return a ScriptRunner that does nothing.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public ScriptRunner getIndexScript() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a ScriptRunner that runs the nextVal script. Must not return
|
||||||
|
* <code>null</code>, but may return a ScriptRunner that does nothing.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public ScriptRunner getNextValScript() throws IOException;
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
// 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.server.schema;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
class H2 extends BaseDataSourceType {
|
||||||
|
|
||||||
|
protected final Config cfg;
|
||||||
|
private final SitePaths site;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
H2(final SitePaths site, @GerritServerConfig final Config cfg) {
|
||||||
|
super("org.h2.Driver");
|
||||||
|
this.cfg = cfg;
|
||||||
|
this.site = site;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() {
|
||||||
|
String database = cfg.getString("database", null, "database");
|
||||||
|
if (database == null || database.isEmpty()) {
|
||||||
|
database = "db/ReviewDB";
|
||||||
|
}
|
||||||
|
File db = site.resolve(database);
|
||||||
|
try {
|
||||||
|
db = db.getCanonicalFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
db = db.getAbsoluteFile();
|
||||||
|
}
|
||||||
|
return "jdbc:h2:" + db.toURI().toString();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
// 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.server.schema;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.config.ConfigUtil;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
|
class JDBC extends BaseDataSourceType {
|
||||||
|
|
||||||
|
protected final Config cfg;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
JDBC(@GerritServerConfig final Config cfg) {
|
||||||
|
super(ConfigUtil.getRequired(cfg, "database", "driver"));
|
||||||
|
this.cfg = cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() {
|
||||||
|
return ConfigUtil.getRequired(cfg, "database", "url");
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,35 @@
|
|||||||
|
// 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.server.schema;
|
||||||
|
|
||||||
|
public class JdbcUtil {
|
||||||
|
|
||||||
|
public static String hostname(String hostname) {
|
||||||
|
if (hostname == null || hostname.isEmpty()) {
|
||||||
|
hostname = "localhost";
|
||||||
|
|
||||||
|
} else if (hostname.contains(":") && !hostname.startsWith("[")) {
|
||||||
|
hostname = "[" + hostname + "]";
|
||||||
|
}
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String port(String port) {
|
||||||
|
if (port != null && !port.isEmpty()) {
|
||||||
|
return ":" + port;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,59 @@
|
|||||||
|
// 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.server.schema;
|
||||||
|
|
||||||
|
import static com.google.gerrit.server.schema.JdbcUtil.hostname;
|
||||||
|
import static com.google.gerrit.server.schema.JdbcUtil.port;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.config.ConfigSection;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
class MySql extends BaseDataSourceType {
|
||||||
|
|
||||||
|
private Config cfg;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public MySql(@GerritServerConfig final Config cfg) {
|
||||||
|
super("com.mysql.jdbc.Driver");
|
||||||
|
this.cfg = cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() {
|
||||||
|
final StringBuilder b = new StringBuilder();
|
||||||
|
final ConfigSection dbs = new ConfigSection(cfg, "database");
|
||||||
|
b.append("jdbc:mysql://");
|
||||||
|
b.append(hostname(dbs.optional("hostname")));
|
||||||
|
b.append(port(dbs.optional("port")));
|
||||||
|
b.append("/");
|
||||||
|
b.append(dbs.required("database"));
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean usePool() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScriptRunner getNextValScript() throws IOException {
|
||||||
|
return getScriptRunner("mysql_nextval.sql");
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
// 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.server.schema;
|
||||||
|
|
||||||
|
import static com.google.gerrit.server.schema.JdbcUtil.hostname;
|
||||||
|
import static com.google.gerrit.server.schema.JdbcUtil.port;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.config.ConfigSection;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
class PostgreSQL extends BaseDataSourceType {
|
||||||
|
|
||||||
|
private Config cfg;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PostgreSQL(@GerritServerConfig final Config cfg) {
|
||||||
|
super("org.postgresql.Driver");
|
||||||
|
this.cfg = cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() {
|
||||||
|
final StringBuilder b = new StringBuilder();
|
||||||
|
final ConfigSection dbc = new ConfigSection(cfg, "database");
|
||||||
|
b.append("jdbc:postgresql://");
|
||||||
|
b.append(hostname(dbc.optional("hostname")));
|
||||||
|
b.append(port(dbc.optional("port")));
|
||||||
|
b.append("/");
|
||||||
|
b.append(dbc.required("database"));
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScriptRunner getIndexScript() throws IOException {
|
||||||
|
return getScriptRunner("index_postgres.sql");
|
||||||
|
}
|
||||||
|
}
|
@@ -38,10 +38,6 @@ import com.google.gerrit.server.git.MetaDataUpdate;
|
|||||||
import com.google.gerrit.server.git.ProjectConfig;
|
import com.google.gerrit.server.git.ProjectConfig;
|
||||||
import com.google.gwtorm.jdbc.JdbcExecutor;
|
import com.google.gwtorm.jdbc.JdbcExecutor;
|
||||||
import com.google.gwtorm.jdbc.JdbcSchema;
|
import com.google.gwtorm.jdbc.JdbcSchema;
|
||||||
import com.google.gwtorm.schema.sql.DialectH2;
|
|
||||||
import com.google.gwtorm.schema.sql.DialectMySQL;
|
|
||||||
import com.google.gwtorm.schema.sql.DialectPostgreSQL;
|
|
||||||
import com.google.gwtorm.schema.sql.SqlDialect;
|
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
@@ -65,11 +61,9 @@ public class SchemaCreator {
|
|||||||
private final GitRepositoryManager mgr;
|
private final GitRepositoryManager mgr;
|
||||||
private final AllProjectsName allProjectsName;
|
private final AllProjectsName allProjectsName;
|
||||||
private final PersonIdent serverUser;
|
private final PersonIdent serverUser;
|
||||||
|
private final DataSourceType dataSourceType;
|
||||||
|
|
||||||
private final int versionNbr;
|
private final int versionNbr;
|
||||||
private final ScriptRunner index_generic;
|
|
||||||
private final ScriptRunner index_postgres;
|
|
||||||
private final ScriptRunner mysql_nextval;
|
|
||||||
|
|
||||||
private AccountGroup admin;
|
private AccountGroup admin;
|
||||||
private AccountGroup anonymous;
|
private AccountGroup anonymous;
|
||||||
@@ -81,23 +75,23 @@ public class SchemaCreator {
|
|||||||
@Current SchemaVersion version,
|
@Current SchemaVersion version,
|
||||||
GitRepositoryManager mgr,
|
GitRepositoryManager mgr,
|
||||||
AllProjectsName allProjectsName,
|
AllProjectsName allProjectsName,
|
||||||
@GerritPersonIdent PersonIdent au) {
|
@GerritPersonIdent PersonIdent au,
|
||||||
this(site.site_path, version, mgr, allProjectsName, au);
|
DataSourceType dst) {
|
||||||
|
this(site.site_path, version, mgr, allProjectsName, au, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SchemaCreator(@SitePath File site,
|
public SchemaCreator(@SitePath File site,
|
||||||
@Current SchemaVersion version,
|
@Current SchemaVersion version,
|
||||||
GitRepositoryManager gitMgr,
|
GitRepositoryManager gitMgr,
|
||||||
AllProjectsName ap,
|
AllProjectsName ap,
|
||||||
@GerritPersonIdent PersonIdent au) {
|
@GerritPersonIdent PersonIdent au,
|
||||||
|
DataSourceType dst) {
|
||||||
site_path = site;
|
site_path = site;
|
||||||
mgr = gitMgr;
|
mgr = gitMgr;
|
||||||
allProjectsName = ap;
|
allProjectsName = ap;
|
||||||
serverUser = au;
|
serverUser = au;
|
||||||
|
dataSourceType = dst;
|
||||||
versionNbr = version.getVersionNbr();
|
versionNbr = version.getVersionNbr();
|
||||||
index_generic = new ScriptRunner("index_generic.sql");
|
|
||||||
index_postgres = new ScriptRunner("index_postgres.sql");
|
|
||||||
mysql_nextval = new ScriptRunner("mysql_nextval.sql");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create(final ReviewDb db) throws OrmException, IOException,
|
public void create(final ReviewDb db) throws OrmException, IOException,
|
||||||
@@ -123,20 +117,8 @@ public class SchemaCreator {
|
|||||||
initWildCardProject();
|
initWildCardProject();
|
||||||
}
|
}
|
||||||
|
|
||||||
final SqlDialect d = jdbc.getDialect();
|
dataSourceType.getIndexScript().run(db);
|
||||||
if (d instanceof DialectH2) {
|
dataSourceType.getNextValScript().run(db);
|
||||||
index_generic.run(db);
|
|
||||||
|
|
||||||
} else if (d instanceof DialectMySQL) {
|
|
||||||
index_generic.run(db);
|
|
||||||
mysql_nextval.run(db);
|
|
||||||
|
|
||||||
} else if (d instanceof DialectPostgreSQL) {
|
|
||||||
index_postgres.run(db);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new OrmException("Unsupported database " + d.getClass().getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccountGroup newGroup(ReviewDb c, String name, AccountGroup.UUID uuid)
|
private AccountGroup newGroup(ReviewDb c, String name, AccountGroup.UUID uuid)
|
||||||
|
@@ -19,7 +19,6 @@ import com.google.gwtorm.jdbc.JdbcSchema;
|
|||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@@ -34,10 +33,15 @@ class ScriptRunner {
|
|||||||
private final String name;
|
private final String name;
|
||||||
private final List<String> commands;
|
private final List<String> commands;
|
||||||
|
|
||||||
ScriptRunner(final String name) {
|
static final ScriptRunner NOOP = new ScriptRunner(null, null) {
|
||||||
|
void run(final ReviewDb db) {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ScriptRunner(final String scriptName, final InputStream script) {
|
||||||
|
this.name = scriptName;
|
||||||
try {
|
try {
|
||||||
this.name = name;
|
this.commands = script != null ? parse(script) : null;
|
||||||
this.commands = parse(name);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IllegalStateException("Cannot parse " + name, e);
|
throw new IllegalStateException("Cannot parse " + name, e);
|
||||||
}
|
}
|
||||||
@@ -63,12 +67,7 @@ class ScriptRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> parse(final String name) throws IOException {
|
private List<String> parse(final InputStream in) throws IOException {
|
||||||
InputStream in = ReviewDb.class.getResourceAsStream(name);
|
|
||||||
if (in == null) {
|
|
||||||
throw new FileNotFoundException("SQL script " + name + " not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
|
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
|
||||||
try {
|
try {
|
||||||
String delimiter = ";";
|
String delimiter = ";";
|
||||||
|
@@ -27,6 +27,7 @@ import com.google.gerrit.server.config.SitePaths;
|
|||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
|
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
|
||||||
import com.google.gerrit.testutil.InMemoryDatabase;
|
import com.google.gerrit.testutil.InMemoryDatabase;
|
||||||
|
import com.google.gerrit.testutil.InMemoryH2Type;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.gwtorm.server.SchemaFactory;
|
import com.google.gwtorm.server.SchemaFactory;
|
||||||
import com.google.gwtorm.server.StatementExecutor;
|
import com.google.gwtorm.server.StatementExecutor;
|
||||||
@@ -94,6 +95,8 @@ public class SchemaUpdaterTest extends TestCase {
|
|||||||
bind(String.class) //
|
bind(String.class) //
|
||||||
.annotatedWith(AnonymousCowardName.class) //
|
.annotatedWith(AnonymousCowardName.class) //
|
||||||
.toProvider(AnonymousCowardNameProvider.class);
|
.toProvider(AnonymousCowardNameProvider.class);
|
||||||
|
|
||||||
|
bind(DataSourceType.class).to(InMemoryH2Type.class);
|
||||||
}
|
}
|
||||||
}).getInstance(SchemaUpdater.class);
|
}).getInstance(SchemaUpdater.class);
|
||||||
|
|
||||||
|
@@ -157,7 +157,8 @@ public class InMemoryDatabase implements SchemaFactory<ReviewDb> {
|
|||||||
schemaVersion,
|
schemaVersion,
|
||||||
null,
|
null,
|
||||||
new AllProjectsName("Test-Projects"),
|
new AllProjectsName("Test-Projects"),
|
||||||
new PersonIdent("name", "email@site")).create(c);
|
new PersonIdent("name", "email@site"),
|
||||||
|
new InMemoryH2Type()).create(c);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new OrmException("Cannot create in-memory database", e);
|
throw new OrmException("Cannot create in-memory database", e);
|
||||||
} catch (ConfigInvalidException e) {
|
} catch (ConfigInvalidException e) {
|
||||||
|
@@ -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.testutil;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.schema.BaseDataSourceType;
|
||||||
|
|
||||||
|
public class InMemoryH2Type extends BaseDataSourceType {
|
||||||
|
|
||||||
|
protected InMemoryH2Type() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() {
|
||||||
|
// not used
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user