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;
|
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) {
|
String url = dbs.optional("url");
|
||||||
case H2: {
|
if (Strings.isNullOrEmpty(url)) {
|
||||||
String database = optional(cfg, "database");
|
url = dst.getUrl();
|
||||||
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: {
|
String username = dbs.optional("username");
|
||||||
final StringBuilder b = new StringBuilder();
|
String password = dbs.optional("password");
|
||||||
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()) {
|
|
||||||
if (url.startsWith("jdbc:h2:")) {
|
|
||||||
driver = "org.h2.Driver";
|
|
||||||
|
|
||||||
} 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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