aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2018-12-03 11:24:13 +0100
committerSonarTech <sonartech@sonarsource.com>2018-12-21 20:21:02 +0100
commitd4baa0caf3fe490cbc72c445a17aa82f649d8faa (patch)
treee65a1212f5c6c2d2e0af3aa44dd08fc417cfd6af /server
parentc314c417d0ffefcb23e731767744ee6ab3cd80e1 (diff)
downloadsonarqube-d4baa0caf3fe490cbc72c445a17aa82f649d8faa.tar.gz
sonarqube-d4baa0caf3fe490cbc72c445a17aa82f649d8faa.zip
SONARCLOUD-192 core extension can now declare MyBatis mapper and alias
Diffstat (limited to 'server')
-rw-r--r--server/sonar-db-core/src/test/java/org/sonar/db/AbstractDbTester.java4
-rw-r--r--server/sonar-db-core/src/test/java/org/sonar/db/CoreTestDb.java41
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java15
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfExtension.java36
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java51
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/TestDb.java44
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionTest.java2
7 files changed, 158 insertions, 35 deletions
diff --git a/server/sonar-db-core/src/test/java/org/sonar/db/AbstractDbTester.java b/server/sonar-db-core/src/test/java/org/sonar/db/AbstractDbTester.java
index 703bf316975..33229b0a43f 100644
--- a/server/sonar-db-core/src/test/java/org/sonar/db/AbstractDbTester.java
+++ b/server/sonar-db-core/src/test/java/org/sonar/db/AbstractDbTester.java
@@ -84,6 +84,10 @@ public class AbstractDbTester<T extends CoreTestDb> extends ExternalResource {
this.db = db;
}
+ public T getDb() {
+ return db;
+ }
+
public void executeUpdateSql(String sql, Object... params) {
try (Connection connection = getConnection()) {
new QueryRunner().update(connection, sql, params);
diff --git a/server/sonar-db-core/src/test/java/org/sonar/db/CoreTestDb.java b/server/sonar-db-core/src/test/java/org/sonar/db/CoreTestDb.java
index 6b963d27e31..fe7852f5a65 100644
--- a/server/sonar-db-core/src/test/java/org/sonar/db/CoreTestDb.java
+++ b/server/sonar-db-core/src/test/java/org/sonar/db/CoreTestDb.java
@@ -26,6 +26,7 @@ import java.net.URI;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
+import java.util.function.BiConsumer;
import javax.annotation.Nullable;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
@@ -61,17 +62,18 @@ class CoreTestDb {
private IDatabaseTester tester;
private boolean isDefault;
- static CoreTestDb create(@Nullable String schemaPath) {
- if (schemaPath == null) {
- if (DEFAULT == null) {
- DEFAULT = new CoreTestDb(null);
- }
- return DEFAULT;
- }
- return new CoreTestDb(schemaPath);
+ protected CoreTestDb() {
+ // use static factory method
+ }
+
+ protected CoreTestDb(CoreTestDb base) {
+ this.db = base.db;
+ this.isDefault = base.isDefault;
+ this.commands = base.commands;
+ this.tester = base.tester;
}
- CoreTestDb(@Nullable String schemaPath) {
+ CoreTestDb init(@Nullable String schemaPath, BiConsumer<Database, Boolean> extendedStart) {
if (db == null) {
Settings settings = new MapSettings().addProperties(System.getProperties());
if (isNotEmpty(settings.getString("orchestrator.configUrl"))) {
@@ -102,16 +104,23 @@ class CoreTestDb {
commands = DatabaseCommands.forDialect(db.getDialect());
tester = new DataSourceDatabaseTester(db.getDataSource(), commands.useLoginAsSchema() ? login : null);
- extendStart(db);
+ extendedStart.accept(db, true);
+ } else {
+ extendedStart.accept(db, false);
}
+ return this;
}
- /**
- * to be overridden by subclasses to extend what's done when db is created
- * @param db
- */
- protected void extendStart(Database db) {
- // nothing done here
+ static CoreTestDb create(@Nullable String schemaPath) {
+ if (schemaPath == null) {
+ if (DEFAULT == null) {
+ DEFAULT = new CoreTestDb().init(null, (db, created) -> {
+ });
+ }
+ return DEFAULT;
+ }
+ return new CoreTestDb().init(schemaPath, (db, created) -> {
+ });
}
public void start() {
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
index 1172e62b86d..8316c4f74b9 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
@@ -23,6 +23,10 @@ import com.google.common.annotations.VisibleForTesting;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nullable;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
@@ -139,11 +143,16 @@ import org.sonar.db.webhook.WebhookDeliveryMapper;
import org.sonar.db.webhook.WebhookMapper;
public class MyBatis implements Startable {
-
+ private final List<MyBatisConfExtension> confExtensions;
private final Database database;
private SqlSessionFactory sessionFactory;
public MyBatis(Database database) {
+ this(database, null);
+ }
+
+ public MyBatis(Database database, @Nullable MyBatisConfExtension[] confExtensions) {
+ this.confExtensions = confExtensions == null ? Collections.emptyList() : Arrays.asList(confExtensions);
this.database = database;
}
@@ -202,6 +211,7 @@ public class MyBatis implements Startable {
confBuilder.loadAlias("User", UserDto.class);
confBuilder.loadAlias("UuidWithProjectUuid", UuidWithProjectUuidDto.class);
confBuilder.loadAlias("ViewsSnapshot", ViewsSnapshotDto.class);
+ confExtensions.forEach(ext -> ext.loadAliases(confBuilder::loadAlias));
// keep them sorted alphabetically
Class<?>[] mappers = {
@@ -268,6 +278,9 @@ public class MyBatis implements Startable {
WebhookDeliveryMapper.class
};
confBuilder.loadMappers(mappers);
+ confExtensions.stream()
+ .flatMap(MyBatisConfExtension::getMapperClasses)
+ .forEach(confBuilder::loadMapper);
sessionFactory = new SqlSessionFactoryBuilder().build(confBuilder.build());
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfExtension.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfExtension.java
new file mode 100644
index 00000000000..3d755724284
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfExtension.java
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db;
+
+import java.util.stream.Stream;
+import org.sonar.core.extension.PlatformLevel;
+
+@PlatformLevel(1)
+public interface MyBatisConfExtension {
+ default void loadAliases(LoadAliasContext context) {
+ // no alias to load
+ }
+
+ interface LoadAliasContext {
+ void loadAlias(String alias, Class<?> dtoClass);
+ }
+
+ Stream<Class<?>> getMapperClasses();
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
index 82194a971a4..41a7d21036b 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
@@ -21,8 +21,11 @@ package org.sonar.db;
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang.StringUtils;
@@ -90,8 +93,8 @@ public class DbTester extends AbstractDbTester<TestDb> {
private final WebhookDeliveryDbTester webhookDeliveryDbTester;
private final AlmDbTester almDbTester;
- public DbTester(System2 system2, @Nullable String schemaPath) {
- super(TestDb.create(schemaPath));
+ private DbTester(System2 system2, @Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
+ super(TestDb.create(schemaPath, confExtensions));
this.system2 = system2;
initDbClient();
@@ -125,6 +128,14 @@ public class DbTester extends AbstractDbTester<TestDb> {
return new DbTester(system2, null);
}
+ public static DbTester createWithExtensionMappers(Class<?> firstMapperClass, Class<?>... otherMapperClasses) {
+ return new DbTester(System2.INSTANCE, null, new DbTesterMyBatisConfExtension(firstMapperClass, otherMapperClasses));
+ }
+
+ public static DbTester createWithExtensionMappers(System2 system2, Class<?> firstMapperClass, Class<?>... otherMapperClasses) {
+ return new DbTester(system2, null, new DbTesterMyBatisConfExtension(firstMapperClass, otherMapperClasses));
+ }
+
public static DbTester createForSchema(System2 system2, Class testClass, String filename) {
String path = StringUtils.replaceChars(testClass.getCanonicalName(), '.', '/');
String schemaPath = path + "/" + filename;
@@ -257,7 +268,7 @@ public class DbTester extends AbstractDbTester<TestDb> {
return pluginDbTester;
}
- public WebhookDbTester webhooks(){
+ public WebhookDbTester webhooks() {
return webhookDbTester;
}
@@ -355,4 +366,38 @@ public class DbTester extends AbstractDbTester<TestDb> {
}
}
+ private static class DbTesterMyBatisConfExtension implements MyBatisConfExtension {
+ // do not replace with a lambda to allow cache of MyBatis instances in TestDb to work
+ private final Class<?>[] mapperClasses;
+
+ public DbTesterMyBatisConfExtension(Class<?> firstMapperClass, Class<?>... otherMapperClasses) {
+ this.mapperClasses = Stream.concat(
+ Stream.of(firstMapperClass),
+ Arrays.stream(otherMapperClasses))
+ .sorted(Comparator.comparing(Class::getName))
+ .toArray(Class<?>[]::new);
+ }
+
+ @Override
+ public Stream<Class<?>> getMapperClasses() {
+ return Arrays.stream(mapperClasses);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DbTesterMyBatisConfExtension that = (DbTesterMyBatisConfExtension) o;
+ return Arrays.equals(mapperClasses, that.mapperClasses);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(mapperClasses);
+ }
+ }
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/TestDb.java b/server/sonar-db-dao/src/test/java/org/sonar/db/TestDb.java
index d8c4f250205..cd877df8bee 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/TestDb.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/TestDb.java
@@ -19,32 +19,48 @@
*/
package org.sonar.db;
+import java.util.HashMap;
+import java.util.Map;
import javax.annotation.Nullable;
class TestDb extends CoreTestDb {
- private static TestDb SINGLETON;
+ private static TestDb defaultSchemaBaseTestDb;
+ // instantiating MyBatis objects is costly => we cache them for default schema
+ private static final Map<MyBatisConfExtension[], TestDb> defaultSchemaTestDbsWithExtensions = new HashMap<>();
private MyBatis myBatis;
- private TestDb(@Nullable String schemaPath) {
- super(schemaPath);
+ private TestDb(@Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
+ super();
+ init(schemaPath, (db, created) -> myBatis = newMyBatis(db, confExtensions));
}
- static TestDb create(@Nullable String schemaPath) {
+ private TestDb(TestDb base, MyBatis myBatis) {
+ super(base);
+ this.myBatis = myBatis;
+ }
+
+ private static MyBatis newMyBatis(Database db, MyBatisConfExtension[] extensions) {
+ MyBatis newMyBatis = new MyBatis(db, extensions);
+ newMyBatis.start();
+ return newMyBatis;
+ }
+
+ static TestDb create(@Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
+ MyBatisConfExtension[] extensionArray = confExtensions == null || confExtensions.length == 0 ? null : confExtensions;
if (schemaPath == null) {
- if (SINGLETON == null) {
- SINGLETON = new TestDb(null);
+ if (defaultSchemaBaseTestDb == null) {
+ defaultSchemaBaseTestDb = new TestDb((String) null);
}
- return SINGLETON;
+ if (extensionArray != null) {
+ return defaultSchemaTestDbsWithExtensions.computeIfAbsent(
+ extensionArray,
+ extensions -> new TestDb(defaultSchemaBaseTestDb, newMyBatis(defaultSchemaBaseTestDb.getDatabase(), extensions)));
+ }
+ return defaultSchemaBaseTestDb;
}
- return new TestDb(schemaPath);
- }
-
- @Override
- protected void extendStart(Database db) {
- myBatis = new MyBatis(db);
- myBatis.start();
+ return new TestDb(schemaPath, confExtensions);
}
MyBatis getMyBatis() {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionTest.java
index 707212e283a..d637737c8da 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionTest.java
@@ -78,7 +78,7 @@ import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.
public class ChangeParentActionTest {
@Rule
- public DbTester db = new DbTester(System2.INSTANCE, null);
+ public DbTester db = DbTester.create(System2.INSTANCE);
@Rule
public EsTester es = EsTester.create();
@Rule