diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-07-05 10:06:55 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-07-06 09:22:44 +0200 |
commit | 32af292b745b7226bacc3f34d612437664af0ba3 (patch) | |
tree | 538d0b9852eaeb08ad685d426ea61c8170210e40 /sonar-db/src/main/java | |
parent | 1df148803610cd54f182b8636f01c0e6ece92b19 (diff) | |
download | sonarqube-32af292b745b7226bacc3f34d612437664af0ba3.tar.gz sonarqube-32af292b745b7226bacc3f34d612437664af0ba3.zip |
Move some classes from sonar-server to sonar-db
Diffstat (limited to 'sonar-db/src/main/java')
42 files changed, 1509 insertions, 266 deletions
diff --git a/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java b/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java index 2d16c7137d0..9a70977c140 100644 --- a/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java +++ b/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java @@ -30,11 +30,9 @@ import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.database.model.Snapshot; import org.sonar.api.i18n.I18n; -import org.sonar.api.server.ServerSide; import static org.sonar.api.utils.DateUtils.longToDate; -@ServerSide public class Periods { private final Settings settings; diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentIndexMapper.java b/sonar-db/src/main/java/org/sonar/db/AbstractDao.java index 44eafac3a24..245f0e87ec9 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/ComponentIndexMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/AbstractDao.java @@ -17,13 +17,25 @@ * 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; -package org.sonar.db.component; +import org.sonar.api.utils.System2; -import java.util.List; -import org.apache.ibatis.annotations.Param; +public abstract class AbstractDao implements Dao { -public interface ComponentIndexMapper { + private final MyBatis myBatis; + private final System2 system2; - List<Long> selectProjectIdsFromQueryAndViewOrSubViewUuid(@Param("query") String query, @Param("viewUuidQuery") String viewUuidQuery); + public AbstractDao(MyBatis myBatis, System2 system2) { + this.myBatis = myBatis; + this.system2 = system2; + } + + protected MyBatis myBatis() { + return myBatis; + } + + protected long now() { + return system2.now(); + } } diff --git a/sonar-db/src/main/java/org/sonar/db/DaoUtils.java b/sonar-db/src/main/java/org/sonar/db/DaoUtils.java index 5c0d3269e3c..7e3773f2b0d 100644 --- a/sonar-db/src/main/java/org/sonar/db/DaoUtils.java +++ b/sonar-db/src/main/java/org/sonar/db/DaoUtils.java @@ -19,19 +19,22 @@ */ package org.sonar.db; -import com.google.common.base.Function; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import java.util.Collection; -import java.util.Collections; +import java.util.Arrays; import java.util.List; +import org.sonar.db.activity.ActivityDao; +import org.sonar.db.component.ComponentLinkDao; import org.sonar.db.component.ResourceDao; import org.sonar.db.component.ResourceIndexerDao; import org.sonar.db.component.ResourceKeyUpdaterDao; +import org.sonar.db.component.SnapshotDao; +import org.sonar.db.compute.AnalysisReportDao; import org.sonar.db.dashboard.ActiveDashboardDao; import org.sonar.db.dashboard.DashboardDao; +import org.sonar.db.dashboard.WidgetDao; +import org.sonar.db.dashboard.WidgetPropertyDao; import org.sonar.db.debt.CharacteristicDao; import org.sonar.db.duplication.DuplicationDao; +import org.sonar.db.event.EventDao; import org.sonar.db.issue.ActionPlanDao; import org.sonar.db.issue.ActionPlanStatsDao; import org.sonar.db.issue.IssueChangeDao; @@ -39,48 +42,53 @@ import org.sonar.db.issue.IssueDao; import org.sonar.db.issue.IssueFilterDao; import org.sonar.db.issue.IssueFilterFavouriteDao; import org.sonar.db.loadedtemplate.LoadedTemplateDao; +import org.sonar.db.measure.MeasureDao; +import org.sonar.db.measure.MeasureFilterDao; import org.sonar.db.notification.NotificationQueueDao; import org.sonar.db.permission.PermissionDao; import org.sonar.db.permission.PermissionTemplateDao; import org.sonar.db.property.PropertiesDao; import org.sonar.db.purge.PurgeDao; import org.sonar.db.qualitygate.QualityGateConditionDao; -import org.sonar.db.qualityprofile.ActiveRuleDao; import org.sonar.db.qualityprofile.QualityProfileDao; import org.sonar.db.rule.RuleDao; import org.sonar.db.semaphore.SemaphoreDao; +import org.sonar.db.source.FileSourceDao; import org.sonar.db.user.AuthorDao; import org.sonar.db.user.AuthorizationDao; import org.sonar.db.user.GroupMembershipDao; import org.sonar.db.user.RoleDao; import org.sonar.db.user.UserDao; - -import static com.google.common.collect.Lists.newArrayList; +import org.sonar.db.user.UserGroupDao; public final class DaoUtils { - private static final int PARTITION_SIZE_FOR_ORACLE = 1000; - private DaoUtils() { // only static stuff } - public static List<Class> getDaoClasses() { - return ImmutableList.<Class>of( + public static List<Class<? extends Dao>> getDaoClasses() { + return Arrays.asList( ActionPlanDao.class, ActionPlanStatsDao.class, ActiveDashboardDao.class, - ActiveRuleDao.class, + ActivityDao.class, + AnalysisReportDao.class, AuthorDao.class, AuthorizationDao.class, + ComponentLinkDao.class, DashboardDao.class, DuplicationDao.class, + EventDao.class, + FileSourceDao.class, GroupMembershipDao.class, IssueDao.class, IssueChangeDao.class, IssueFilterDao.class, IssueFilterFavouriteDao.class, LoadedTemplateDao.class, + MeasureDao.class, + MeasureFilterDao.class, NotificationQueueDao.class, PermissionDao.class, PermissionTemplateDao.class, @@ -95,55 +103,11 @@ public final class DaoUtils { RoleDao.class, RuleDao.class, SemaphoreDao.class, - UserDao.class + SnapshotDao.class, + UserDao.class, + UserGroupDao.class, + WidgetDao.class, + WidgetPropertyDao.class ); } - - /** - * Partition by 1000 elements a list of input and execute a function on each part. - * - * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)' - * and with MsSQL when there's more than 2000 parameters in a query - */ - public static <OUTPUT, INPUT> List<OUTPUT> executeLargeInputs(Collection<INPUT> input, Function<List<INPUT>, List<OUTPUT>> function) { - if (input.isEmpty()) { - return Collections.emptyList(); - } - List<OUTPUT> results = newArrayList(); - List<List<INPUT>> partitionList = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE); - for (List<INPUT> partition : partitionList) { - List<OUTPUT> subResults = function.apply(partition); - results.addAll(subResults); - } - return results; - } - - /** - * Partition by 1000 elements a list of input and execute a function on each part. - * The function has not output (ex: delete operation) - * - * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)' - * and with MsSQL when there's more than 2000 parameters in a query - */ - public static <INPUT> void executeLargeInputsWithoutOutput(Collection<INPUT> input, Function<List<INPUT>, Void> function) { - if (input.isEmpty()) { - return; - } - - List<List<INPUT>> partitions = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE); - for (List<INPUT> partition : partitions) { - function.apply(partition); - } - } - - public static String repeatCondition(String sql, int count, String separator) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < count; i++) { - sb.append(sql); - if (i < count - 1) { - sb.append(" ").append(separator).append(" "); - } - } - return sb.toString(); - } } diff --git a/sonar-db/src/main/java/org/sonar/db/DatabaseChecker.java b/sonar-db/src/main/java/org/sonar/db/DatabaseChecker.java new file mode 100644 index 00000000000..31dc571008f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/DatabaseChecker.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 com.google.common.base.Throwables; +import java.sql.Connection; +import java.sql.SQLException; +import org.apache.commons.dbutils.DbUtils; +import org.apache.commons.lang.StringUtils; +import org.picocontainer.Startable; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.log.Loggers; +import org.sonar.db.dialect.H2; +import org.sonar.db.dialect.Oracle; + +public class DatabaseChecker implements Startable { + + public static final int ORACLE_MIN_MAJOR_VERSION = 11; + + private final Database db; + + public DatabaseChecker(Database db) { + this.db = db; + } + + @Override + public void start() { + try { + if (H2.ID.equals(db.getDialect().getId())) { + Loggers.get(DatabaseChecker.class).warn("H2 database should be used for evaluation purpose only"); + } else if (Oracle.ID.equals(db.getDialect().getId())) { + checkOracleVersion(); + } + } catch (Exception e) { + Throwables.propagate(e); + } + } + + @Override + public void stop() { + // nothing to do + } + + private void checkOracleVersion() throws SQLException { + Connection connection = db.getDataSource().getConnection(); + try { + // check version of db + // See http://jira.sonarsource.com/browse/SONAR-6434 + int majorVersion = connection.getMetaData().getDatabaseMajorVersion(); + if (majorVersion < ORACLE_MIN_MAJOR_VERSION) { + throw MessageException.of(String.format( + "Unsupported Oracle version: %s. Minimal required version is %d.", connection.getMetaData().getDatabaseProductVersion(), ORACLE_MIN_MAJOR_VERSION)); + } + + // check version of driver + String driverVersion = connection.getMetaData().getDriverVersion(); + String[] parts = StringUtils.split(driverVersion, "."); + int intVersion = Integer.parseInt(parts[0]) * 100 + Integer.parseInt(parts[1]); + if (intVersion < 1102) { + throw MessageException.of(String.format( + "Unsupported Oracle JDBC driver version: %s. Minimal required version is 11.2.", driverVersion)); + } + + } finally { + DbUtils.closeQuietly(connection); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java b/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java index 28ac5923b72..6d74d2474cc 100644 --- a/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java +++ b/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java @@ -19,17 +19,24 @@ */ package org.sonar.db; +import com.google.common.base.Function; +import com.google.common.collect.Lists; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import javax.annotation.Nullable; import org.slf4j.LoggerFactory; -/** - * @since 2.13 - */ +import static com.google.common.collect.Lists.newArrayList; + public final class DatabaseUtils { + + private static final int PARTITION_SIZE_FOR_ORACLE = 1000; + private DatabaseUtils() { // only static methods } @@ -66,4 +73,52 @@ public final class DatabaseUtils { } } } + + /** + * Partition by 1000 elements a list of input and execute a function on each part. + * + * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)' + * and with MsSQL when there's more than 2000 parameters in a query + */ + public static <OUTPUT, INPUT> List<OUTPUT> executeLargeInputs(Collection<INPUT> input, Function<List<INPUT>, List<OUTPUT>> function) { + if (input.isEmpty()) { + return Collections.emptyList(); + } + List<OUTPUT> results = newArrayList(); + List<List<INPUT>> partitionList = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE); + for (List<INPUT> partition : partitionList) { + List<OUTPUT> subResults = function.apply(partition); + results.addAll(subResults); + } + return results; + } + + /** + * Partition by 1000 elements a list of input and execute a function on each part. + * The function has not output (ex: delete operation) + * + * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)' + * and with MsSQL when there's more than 2000 parameters in a query + */ + public static <INPUT> void executeLargeInputsWithoutOutput(Collection<INPUT> input, Function<List<INPUT>, Void> function) { + if (input.isEmpty()) { + return; + } + + List<List<INPUT>> partitions = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE); + for (List<INPUT> partition : partitions) { + function.apply(partition); + } + } + + public static String repeatCondition(String sql, int count, String separator) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < count; i++) { + sb.append(sql); + if (i < count - 1) { + sb.append(" ").append(separator).append(" "); + } + } + return sb.toString(); + } } diff --git a/sonar-db/src/main/java/org/sonar/db/DbClient2.java b/sonar-db/src/main/java/org/sonar/db/DbClient2.java new file mode 100644 index 00000000000..92cbd39c2c5 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/DbClient2.java @@ -0,0 +1,253 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.IdentityHashMap; +import java.util.Map; +import javax.annotation.Nullable; +import org.sonar.db.activity.ActivityDao; +import org.sonar.db.component.ComponentLinkDao; +import org.sonar.db.component.ResourceDao; +import org.sonar.db.component.ResourceIndexerDao; +import org.sonar.db.component.SnapshotDao; +import org.sonar.db.compute.AnalysisReportDao; +import org.sonar.db.dashboard.DashboardDao; +import org.sonar.db.dashboard.WidgetDao; +import org.sonar.db.dashboard.WidgetPropertyDao; +import org.sonar.db.debt.CharacteristicDao; +import org.sonar.db.event.EventDao; +import org.sonar.db.issue.ActionPlanDao; +import org.sonar.db.issue.ActionPlanStatsDao; +import org.sonar.db.issue.IssueChangeDao; +import org.sonar.db.issue.IssueDao; +import org.sonar.db.issue.IssueFilterDao; +import org.sonar.db.loadedtemplate.LoadedTemplateDao; +import org.sonar.db.measure.MeasureDao; +import org.sonar.db.permission.PermissionTemplateDao; +import org.sonar.db.property.PropertiesDao; +import org.sonar.db.purge.PurgeDao; +import org.sonar.db.qualitygate.QualityGateConditionDao; +import org.sonar.db.qualityprofile.QualityProfileDao; +import org.sonar.db.source.FileSourceDao; +import org.sonar.db.user.AuthorDao; +import org.sonar.db.user.AuthorizationDao; +import org.sonar.db.user.GroupMembershipDao; +import org.sonar.db.user.RoleDao; +import org.sonar.db.user.UserGroupDao; + +public class DbClient2 { + + private final MyBatis myBatis; + private final QualityProfileDao qualityProfileDao; + private final CharacteristicDao debtCharacteristicDao; + private final LoadedTemplateDao loadedTemplateDao; + private final PropertiesDao propertiesDao; + private final SnapshotDao snapshotDao; + private final ResourceDao resourceDao; + private final MeasureDao measureDao; + private final ActivityDao activityDao; + private final AuthorizationDao authorizationDao; + private final UserGroupDao userGroupDao; + private final GroupMembershipDao groupMembershipDao; + private final RoleDao roleDao; + private final PermissionTemplateDao permissionTemplateDao; + private final IssueDao issueDao; + private final IssueFilterDao issueFilterDao; + private final IssueChangeDao issueChangeDao; + private final ActionPlanDao actionPlanDao; + private final ActionPlanStatsDao actionPlanStatsDao; + private final AnalysisReportDao analysisReportDao; + private final DashboardDao dashboardDao; + private final WidgetDao widgetDao; + private final WidgetPropertyDao widgetPropertyDao; + private final FileSourceDao fileSourceDao; + private final AuthorDao authorDao; + private final ResourceIndexerDao componentIndexDao; + private final ComponentLinkDao componentLinkDao; + private final EventDao eventDao; + private final PurgeDao purgeDao; + private final QualityGateConditionDao gateConditionDao; + + public DbClient2(MyBatis myBatis, Dao[] daos) { + this.myBatis = myBatis; + + Map<Class, Dao> map = new IdentityHashMap<>(); + for (Dao dao : daos) { + map.put(dao.getClass(), dao); + } + debtCharacteristicDao = getDao(map, CharacteristicDao.class); + qualityProfileDao = getDao(map, QualityProfileDao.class); + loadedTemplateDao = getDao(map, LoadedTemplateDao.class); + propertiesDao = getDao(map, PropertiesDao.class); + snapshotDao = getDao(map, SnapshotDao.class); + resourceDao = getDao(map, ResourceDao.class); + measureDao = getDao(map, MeasureDao.class); + activityDao = getDao(map, ActivityDao.class); + authorizationDao = getDao(map, AuthorizationDao.class); + userGroupDao = getDao(map, UserGroupDao.class); + groupMembershipDao = getDao(map, GroupMembershipDao.class); + roleDao = getDao(map, RoleDao.class); + permissionTemplateDao = getDao(map, PermissionTemplateDao.class); + issueDao = getDao(map, IssueDao.class); + issueFilterDao = getDao(map, IssueFilterDao.class); + issueChangeDao = getDao(map, IssueChangeDao.class); + actionPlanDao = getDao(map, ActionPlanDao.class); + actionPlanStatsDao = getDao(map, ActionPlanStatsDao.class); + analysisReportDao = getDao(map, AnalysisReportDao.class); + dashboardDao = getDao(map, DashboardDao.class); + widgetDao = getDao(map, WidgetDao.class); + widgetPropertyDao = getDao(map, WidgetPropertyDao.class); + fileSourceDao = getDao(map, FileSourceDao.class); + authorDao = getDao(map, AuthorDao.class); + componentIndexDao = getDao(map, ResourceIndexerDao.class); + componentLinkDao = getDao(map, ComponentLinkDao.class); + eventDao = getDao(map, EventDao.class); + purgeDao = getDao(map, PurgeDao.class); + gateConditionDao = getDao(map, QualityGateConditionDao.class); + } + + public DbSession openSession(boolean batch) { + return myBatis.openSession(batch); + } + + public void closeSession(@Nullable DbSession session) { + MyBatis.closeQuietly(session); + } + + public IssueDao issueDao() { + return issueDao; + } + + public IssueFilterDao issueFilterDao() { + return issueFilterDao; + } + + public IssueChangeDao issueChangeDao() { + return issueChangeDao; + } + + public QualityProfileDao qualityProfileDao() { + return qualityProfileDao; + } + + public CharacteristicDao debtCharacteristicDao() { + return debtCharacteristicDao; + } + + public LoadedTemplateDao loadedTemplateDao() { + return loadedTemplateDao; + } + + public PropertiesDao propertiesDao() { + return propertiesDao; + } + + public SnapshotDao snapshotDao() { + return snapshotDao; + } + + public ResourceDao resourceDao() { + return resourceDao; + } + + public MeasureDao measureDao() { + return measureDao; + } + + public ActivityDao activityDao() { + return activityDao; + } + + public AuthorizationDao authorizationDao() { + return authorizationDao; + } + + public UserGroupDao userGroupDao() { + return userGroupDao; + } + + public GroupMembershipDao groupMembershipDao() { + return groupMembershipDao; + } + + public RoleDao roleDao() { + return roleDao; + } + + public PermissionTemplateDao permissionTemplateDao() { + return permissionTemplateDao; + } + + public ActionPlanDao actionPlanDao() { + return actionPlanDao; + } + + public AnalysisReportDao analysisReportDao() { + return analysisReportDao; + } + + public DashboardDao dashboardDao() { + return dashboardDao; + } + + public WidgetDao widgetDao() { + return widgetDao; + } + + public WidgetPropertyDao widgetPropertyDao() { + return widgetPropertyDao; + } + + public FileSourceDao fileSourceDao() { + return fileSourceDao; + } + + public AuthorDao authorDao() { + return authorDao; + } + + public ResourceIndexerDao componentIndexDao() { + return componentIndexDao; + } + + public ComponentLinkDao componentLinkDao() { + return componentLinkDao; + } + + public EventDao eventDao() { + return eventDao; + } + + public PurgeDao purgeDao() { + return purgeDao; + } + + public ActionPlanStatsDao getActionPlanStatsDao() { + return actionPlanStatsDao; + } + + public QualityGateConditionDao gateConditionDao() { + return gateConditionDao; + } + + private <K extends Dao> K getDao(Map<Class, Dao> map, Class<K> clazz) { + return (K) map.get(clazz); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java b/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java index c5e5e1c12b8..47db0259f00 100644 --- a/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java +++ b/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java @@ -30,10 +30,10 @@ import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import org.apache.commons.dbutils.DbUtils; import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.sonar.api.config.Settings; import org.sonar.api.database.DatabaseProperties; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; import org.sonar.db.dialect.Dialect; import org.sonar.db.dialect.DialectUtils; import org.sonar.db.profiling.ProfiledDataSource; @@ -43,7 +43,7 @@ import org.sonar.db.profiling.ProfiledDataSource; */ public class DefaultDatabase implements Database { - private static final Logger LOG = LoggerFactory.getLogger(Database.class); + private static final Logger LOG = Loggers.get(Database.class); private static final String DEFAULT_URL = "jdbc:h2:tcp://localhost/sonar"; private static final String SONAR_JDBC = "sonar.jdbc."; @@ -65,20 +65,12 @@ public class DefaultDatabase implements Database { initSettings(); initDatasource(); checkConnection(); - doAfterStart(); } catch (Exception e) { throw new IllegalStateException("Fail to connect to database", e); } } - /** - * Override to execute post-startup code. - */ - protected void doAfterStart() { - // nothing to do - } - @VisibleForTesting void initSettings() { properties = new Properties(); @@ -104,7 +96,6 @@ public class DefaultDatabase implements Database { private void checkConnection() { Connection connection = null; try { - LOG.debug("Testing JDBC connection"); connection = datasource.getConnection(); } catch (SQLException e) { throw new IllegalStateException("Can not connect to database. Please check connectivity and settings (see the properties prefixed by 'sonar.jdbc.').", e); @@ -176,7 +167,7 @@ public class DefaultDatabase implements Database { } private static void completeDefaultProperty(Properties props, String key, String defaultValue) { - if (props.getProperty(key) == null && defaultValue != null) { + if (props.getProperty(key) == null) { props.setProperty(key, defaultValue); } } diff --git a/sonar-db/src/main/java/org/sonar/db/MyBatis.java b/sonar-db/src/main/java/org/sonar/db/MyBatis.java index a6aa01cbc4f..5926def8753 100644 --- a/sonar-db/src/main/java/org/sonar/db/MyBatis.java +++ b/sonar-db/src/main/java/org/sonar/db/MyBatis.java @@ -23,6 +23,9 @@ package org.sonar.db; import ch.qos.logback.classic.Level; import com.google.common.io.Closeables; import java.io.InputStream; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import javax.annotation.Nullable; import org.apache.ibatis.builder.xml.XMLMapperBuilder; import org.apache.ibatis.logging.LogFactory; @@ -35,10 +38,10 @@ import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; import org.apache.ibatis.type.JdbcType; import org.slf4j.LoggerFactory; +import org.sonar.api.utils.log.Loggers; import org.sonar.db.activity.ActivityDto; import org.sonar.db.activity.ActivityMapper; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentIndexMapper; import org.sonar.db.component.ComponentLinkDto; import org.sonar.db.component.ComponentLinkMapper; import org.sonar.db.component.ComponentMapper; @@ -144,8 +147,6 @@ public class MyBatis { private final Database database; private SqlSessionFactory sessionFactory; - - // TODO this queue should directly be an IndexQueue. Pending move of persistence to sonar-server private WorkQueue<?> queue; public MyBatis(Database database, WorkQueue<?> queue) { @@ -153,12 +154,13 @@ public class MyBatis { this.queue = queue; } + // FIXME should be visible only to DAOs -> to be moved to AbstractDao public static void closeQuietly(@Nullable SqlSession session) { if (session != null) { try { session.close(); } catch (Exception e) { - LoggerFactory.getLogger(MyBatis.class).warn("Fail to close session", e); + Loggers.get(MyBatis.class).warn("Fail to close db session", e); // do not re-throw the exception } } @@ -255,7 +257,7 @@ public class MyBatis { GroupMembershipMapper.class, QualityProfileMapper.class, ActiveRuleMapper.class, MeasureMapper.class, MetricMapper.class, CustomMeasureMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, SnapshotMapper.class, ProjectQgateAssociationMapper.class, EventMapper.class, - AnalysisReportMapper.class, ComponentIndexMapper.class, ComponentLinkMapper.class, + AnalysisReportMapper.class, ComponentLinkMapper.class, Migration45Mapper.class, Migration50Mapper.class }; loadMappers(conf, mappers); @@ -277,14 +279,6 @@ public class MyBatis { } /** - * @deprecated since 4.4. Replaced by <code>openSession(true)</code>. - */ - @Deprecated - public BatchSession openBatchSession() { - return (BatchSession) openSession(true); - } - - /** * @since 4.4 */ public DbSession openSession(boolean batch) { @@ -323,4 +317,31 @@ public class MyBatis { private void loadAlias(Configuration conf, String alias, Class dtoClass) { conf.getTypeAliasRegistry().registerAlias(alias, dtoClass); } + + /** + * Create a PreparedStatement for SELECT requests with scrolling of results + */ + public PreparedStatement newScrollingSelectStatement(DbSession session, String sql) { + int fetchSize = database.getDialect().getScrollDefaultFetchSize(); + return newScrollingSelectStatement(session, sql, fetchSize); + } + + /** + * Create a PreparedStatement for SELECT requests with scrolling of results row by row (only one row + * in memory at a time) + */ + public PreparedStatement newScrollingSingleRowSelectStatement(DbSession session, String sql) { + int fetchSize = database.getDialect().getScrollSingleRowFetchSize(); + return newScrollingSelectStatement(session, sql, fetchSize); + } + + private PreparedStatement newScrollingSelectStatement(DbSession session, String sql, int fetchSize) { + try { + PreparedStatement stmt = session.getConnection().prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + stmt.setFetchSize(fetchSize); + return stmt; + } catch (SQLException e) { + throw new IllegalStateException("Fail to create SQL statement: " + sql, e); + } + } } diff --git a/sonar-db/src/main/java/org/sonar/db/ResultSetIterator.java b/sonar-db/src/main/java/org/sonar/db/ResultSetIterator.java new file mode 100644 index 00000000000..e96a9577141 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/ResultSetIterator.java @@ -0,0 +1,115 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 org.apache.commons.dbutils.DbUtils; + +import java.io.Closeable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Forward-only {@link java.util.Iterator} over a {@link java.sql.ResultSet}. Rows are + * lazily loaded. The underlying ResultSet must be closed by calling the method + * {@link #close()} + * <p/> + * As a safeguard, the ResultSet is automatically closed after the last element has + * been retrieved via {@link #next()} or {@link #hasNext()} is called (which will return false). + * This automagic behavior is not enough to remove explicit calls to {@link #close()} + * from caller methods. Errors raised before end of traversal must still be handled. + */ +public abstract class ResultSetIterator<E> implements Iterator<E>, Closeable { + + private final ResultSet rs; + private final PreparedStatement stmt; + + private volatile boolean didNext = false; + private volatile boolean hasNext = false; + private volatile boolean closed = false; + + public ResultSetIterator(PreparedStatement stmt) throws SQLException { + this.stmt = stmt; + this.rs = stmt.executeQuery(); + } + + protected ResultSetIterator(ResultSet rs) { + this.stmt = null; + this.rs = rs; + } + + @Override + public boolean hasNext() { + if (closed) { + return false; + } + if (!didNext) { + hasNext = doNextQuietly(); + if (hasNext) { + didNext = true; + } else { + close(); + } + } + return hasNext; + } + + @Override + public E next() { + if (!hasNext()) { + close(); + throw new NoSuchElementException(); + } + try { + return read(rs); + } catch (SQLException e) { + throw new IllegalStateException("Fail to read result set row", e); + } finally { + hasNext = doNextQuietly(); + if (!hasNext) { + close(); + } + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public void close() { + closed = true; + DbUtils.closeQuietly(rs); + DbUtils.closeQuietly(stmt); + } + + protected abstract E read(ResultSet rs) throws SQLException; + + private boolean doNextQuietly() { + try { + return rs.next(); + } catch (SQLException e) { + throw new IllegalStateException("Fail to read row of JDBC result set", e); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/activity/ActivityDao.java b/sonar-db/src/main/java/org/sonar/db/activity/ActivityDao.java new file mode 100644 index 00000000000..25b7539beba --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/activity/ActivityDao.java @@ -0,0 +1,49 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.activity; + +import java.util.Date; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class ActivityDao extends AbstractDao { + + public ActivityDao(MyBatis mybatis, System2 system) { + super(mybatis, system); + } + + public void insert(ActivityDto dto) { + DbSession session = myBatis().openSession(false); + try { + insert(session, dto); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(DbSession session, ActivityDto dto) { + dto.setCreatedAt(new Date(now())); + session.getMapper(ActivityMapper.class).insert(dto); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDao.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDao.java new file mode 100644 index 00000000000..9c4f2940936 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDao.java @@ -0,0 +1,45 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.component; + +import java.util.List; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; + +public class ComponentLinkDao implements Dao { + + public List<ComponentLinkDto> selectByComponentUuid(DbSession session, String componentUuid) { + return session.getMapper(ComponentLinkMapper.class).selectByComponentUuid(componentUuid); + } + + public void insert(DbSession session, ComponentLinkDto dto) { + session.getMapper(ComponentLinkMapper.class).insert(dto); + } + + public void update(DbSession session, ComponentLinkDto dto) { + session.getMapper(ComponentLinkMapper.class).update(dto); + } + + public void delete(DbSession session, long id) { + session.getMapper(ComponentLinkMapper.class).delete(id); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java index 2ebd03ec015..80addc6dd54 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java @@ -32,27 +32,24 @@ import org.sonar.api.component.Component; import org.sonar.api.resources.Scopes; import org.sonar.api.utils.System2; import org.sonar.api.utils.internal.Uuids; -import org.sonar.db.Dao; +import org.sonar.db.AbstractDao; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; import static com.google.common.collect.Lists.newArrayList; -public class ResourceDao implements Dao { - private MyBatis mybatis; - private System2 system2; +public class ResourceDao extends AbstractDao { - public ResourceDao(MyBatis mybatis, System2 system2) { - this.mybatis = mybatis; - this.system2 = system2; + public ResourceDao(MyBatis myBatis, System2 system2) { + super(myBatis, system2); } public List<ResourceDto> getResources(ResourceQuery query) { - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return session.getMapper(ResourceMapper.class).selectResources(query); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -66,11 +63,11 @@ public class ResourceDao implements Dao { */ @CheckForNull public ResourceDto getResource(ResourceQuery query) { - DbSession session = mybatis.openSession(false); + DbSession session = myBatis().openSession(false); try { return getResource(query, session); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -84,30 +81,30 @@ public class ResourceDao implements Dao { } public List<Long> getResourceIds(ResourceQuery query) { - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return session.getMapper(ResourceMapper.class).selectResourceIds(query); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } public ResourceDto getResource(long projectId) { - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return getResource(projectId, session); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @CheckForNull public ResourceDto getResource(String componentUuid) { - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return session.getMapper(ResourceMapper.class).selectResourceByUuid(componentUuid); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -126,11 +123,11 @@ public class ResourceDao implements Dao { } public List<ResourceDto> getDescendantProjects(long projectId) { - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return getDescendantProjects(projectId, session); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -153,9 +150,9 @@ public class ResourceDao implements Dao { * Used by the Views Plugin */ public ResourceDao insertOrUpdate(ResourceDto... resources) { - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); ResourceMapper mapper = session.getMapper(ResourceMapper.class); - Date now = new Date(system2.now()); + Date now = new Date(now()); try { for (ResourceDto resource : resources) { if (resource.getId() == null) { @@ -175,7 +172,7 @@ public class ResourceDao implements Dao { } session.commit(); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } return this; } @@ -184,7 +181,7 @@ public class ResourceDao implements Dao { * Should not be called from batch side (used to reindex permission in E/S) */ public void updateAuthorizationDate(Long projectId, SqlSession session) { - session.getMapper(ResourceMapper.class).updateAuthorizationDate(projectId, system2.now()); + session.getMapper(ResourceMapper.class).updateAuthorizationDate(projectId, now()); } @CheckForNull @@ -222,11 +219,11 @@ public class ResourceDao implements Dao { @CheckForNull public ResourceDto getRootProjectByComponentKey(String componentKey) { - DbSession session = mybatis.openSession(false); + DbSession session = myBatis().openSession(false); try { return getRootProjectByComponentKey(session, componentKey); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -253,7 +250,7 @@ public class ResourceDao implements Dao { */ @CheckForNull public ResourceDto getRootProjectByComponentId(long componentId) { - DbSession session = mybatis.openSession(false); + DbSession session = myBatis().openSession(false); try { ResourceDto component = getParentModuleByComponentId(componentId, session); Long rootId = component != null ? component.getRootId() : null; @@ -263,7 +260,7 @@ public class ResourceDao implements Dao { return component; } } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -271,11 +268,11 @@ public class ResourceDao implements Dao { if (qualifiers.isEmpty()) { return Collections.emptyList(); } - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return toComponents(session.getMapper(ResourceMapper.class).selectProjectsByQualifiers(qualifiers)); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -286,11 +283,11 @@ public class ResourceDao implements Dao { if (qualifiers.isEmpty()) { return Collections.emptyList(); } - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return toComponents(session.getMapper(ResourceMapper.class).selectProjectsIncludingNotCompletedOnesByQualifiers(qualifiers)); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -304,11 +301,11 @@ public class ResourceDao implements Dao { if (qualifiers.isEmpty()) { return Collections.emptyList(); } - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return toComponents(session.getMapper(ResourceMapper.class).selectGhostsProjects(qualifiers)); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -319,11 +316,11 @@ public class ResourceDao implements Dao { if (qualifiers.isEmpty()) { return Collections.emptyList(); } - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return session.getMapper(ResourceMapper.class).selectProvisionedProjects(qualifiers); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } @@ -335,11 +332,11 @@ public class ResourceDao implements Dao { } public ResourceDto selectProvisionedProject(String key) { - DbSession session = mybatis.openSession(false); + DbSession session = myBatis().openSession(false); try { return selectProvisionedProject(session, key); } finally { - MyBatis.closeQuietly(session); + myBatis().closeQuietly(session); } } diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java index 6a61ef714e6..827ece8fd1b 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java @@ -19,16 +19,19 @@ */ package org.sonar.db.component; +import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.ibatis.session.ResultContext; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.SqlSession; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDao; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; -public class ResourceIndexerDao { +public class ResourceIndexerDao extends AbstractDao { private static final String SELECT_RESOURCES = "org.sonar.db.component.ResourceIndexerMapper.selectResources"; public static final int MINIMUM_KEY_SIZE = 3; @@ -41,17 +44,19 @@ public class ResourceIndexerDao { private static final String[] NOT_RENAMABLE_QUALIFIERS = {Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE, Qualifiers.CLASS}; private static final String[] NOT_RENAMABLE_SCOPES = {Scopes.FILE}; - private final MyBatis mybatis; + public ResourceIndexerDao(MyBatis myBatis, System2 system2) { + super(myBatis, system2); + } - public ResourceIndexerDao(MyBatis mybatis) { - this.mybatis = mybatis; + public List<Long> selectProjectIdsFromQueryAndViewOrSubViewUuid(DbSession session, String query, String viewOrSubViewUuid) { + return session.getMapper(ResourceIndexerMapper.class).selectProjectIdsFromQueryAndViewOrSubViewUuid(query + "%", "%." + viewOrSubViewUuid + ".%"); } /** * This method is reentrant. It can be executed even if the project is already indexed. */ public ResourceIndexerDao indexProject(final long rootProjectId) { - DbSession session = mybatis.openSession(true); + DbSession session = myBatis().openSession(true); try { indexProject(rootProjectId, session); session.commit(); @@ -71,7 +76,7 @@ public class ResourceIndexerDao { * This method is reentrant. It can be executed even if some projects are already indexed. */ public ResourceIndexerDao indexProjects() { - final DbSession session = mybatis.openSession(true); + final DbSession session = myBatis().openSession(true); try { final ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); session.select("org.sonar.db.component.ResourceIndexerMapper.selectRootProjectIds", /* workaround to get booleans */ResourceIndexerQuery.create(), new ResultHandler() { @@ -132,7 +137,7 @@ public class ResourceIndexerDao { } public boolean indexResource(long id) { - DbSession session = mybatis.openSession(false); + DbSession session = myBatis().openSession(false); try { return indexResource(session, id); } finally { @@ -156,7 +161,7 @@ public class ResourceIndexerDao { public boolean indexResource(int id, String name, String qualifier, int rootId) { boolean indexed = false; - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); try { indexed = indexResource(id, name, qualifier, rootId, session, mapper); diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java index ecbacc7da82..a0cb17b2ccf 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java @@ -19,8 +19,13 @@ */ package org.sonar.db.component; +import java.util.List; +import org.apache.ibatis.annotations.Param; + public interface ResourceIndexerMapper { + List<Long> selectProjectIdsFromQueryAndViewOrSubViewUuid(@Param("query") String query, @Param("viewUuidQuery") String viewUuidQuery); + ResourceIndexDto selectMasterIndexByResourceId(long resourceId); ResourceDto selectResourceToIndex(long resourceId); diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java index 6441c88df37..78217f48edd 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; @@ -36,7 +37,7 @@ import org.sonar.db.MyBatis; * * @since 3.2 */ -public class ResourceKeyUpdaterDao { +public class ResourceKeyUpdaterDao implements Dao { private MyBatis mybatis; public ResourceKeyUpdaterDao(MyBatis mybatis) { diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java new file mode 100644 index 00000000000..d23eeb5a934 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.component; + +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.api.resources.Scopes; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; + +public class SnapshotDao implements Dao { + + @CheckForNull + public SnapshotDto selectNullableById(DbSession session, long id) { + return mapper(session).selectByKey(id); + } + + public SnapshotDto selectById(DbSession session, long id) { + SnapshotDto value = selectNullableById(session, id); + if (value == null) { + throw new IllegalArgumentException(String.format("Snapshot id does not exist: %d", id)); + } + return value; + } + + @CheckForNull + public SnapshotDto selectLastSnapshotByComponentId(DbSession session, long componentId) { + return mapper(session).selectLastSnapshot(componentId); + } + + public List<SnapshotDto> selectSnapshotsByComponentId(DbSession session, long componentId) { + return mapper(session).selectSnapshotsByQuery(new SnapshotQuery().setComponentId(componentId)); + } + + public List<SnapshotDto> selectSnapshotsByQuery(DbSession session, SnapshotQuery query) { + return mapper(session).selectSnapshotsByQuery(query); + } + + public List<SnapshotDto> selectPreviousVersionSnapshots(DbSession session, long componentId, String lastVersion) { + return mapper(session).selectPreviousVersionSnapshots(componentId, lastVersion); + } + + public List<SnapshotDto> selectSnapshotAndChildrenOfProjectScope(DbSession session, long snapshotId) { + return mapper(session).selectSnapshotAndChildrenOfScope(snapshotId, Scopes.PROJECT); + } + + public int updateSnapshotAndChildrenLastFlagAndStatus(DbSession session, SnapshotDto snapshot, boolean isLast, String status) { + Long rootId = snapshot.getId(); + String path = Strings.nullToEmpty(snapshot.getPath()) + snapshot.getId() + ".%"; + Long pathRootId = snapshot.getRootIdOrSelf(); + + return mapper(session).updateSnapshotAndChildrenLastFlagAndStatus(rootId, pathRootId, path, isLast, status); + } + + public int updateSnapshotAndChildrenLastFlag(DbSession session, SnapshotDto snapshot, boolean isLast) { + Long rootId = snapshot.getId(); + String path = Strings.nullToEmpty(snapshot.getPath()) + snapshot.getId() + ".%"; + Long pathRootId = snapshot.getRootIdOrSelf(); + + return mapper(session).updateSnapshotAndChildrenLastFlag(rootId, pathRootId, path, isLast); + } + + public static boolean isLast(SnapshotDto snapshotTested, @Nullable SnapshotDto previousLastSnapshot) { + return previousLastSnapshot == null || previousLastSnapshot.getCreatedAt() < snapshotTested.getCreatedAt(); + } + + public SnapshotDto insert(DbSession session, SnapshotDto item) { + mapper(session).insert(item); + return item; + } + + public void insert(DbSession session, Collection<SnapshotDto> items) { + for (SnapshotDto item : items) { + insert(session, item); + } + } + + public void insert(DbSession session, SnapshotDto item, SnapshotDto... others) { + insert(session, Lists.asList(item, others)); + } + + private SnapshotMapper mapper(DbSession session) { + return session.getMapper(SnapshotMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDao.java b/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDao.java new file mode 100644 index 00000000000..d805044aae6 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDao.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.compute; + +import com.google.common.annotations.VisibleForTesting; +import org.sonar.api.utils.System2; +import org.sonar.db.compute.AnalysisReportDto; +import org.sonar.db.compute.AnalysisReportMapper; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; + +import javax.annotation.CheckForNull; + +import java.util.List; + +import static org.sonar.db.compute.AnalysisReportDto.Status.PENDING; +import static org.sonar.db.compute.AnalysisReportDto.Status.WORKING; + +public class AnalysisReportDao implements Dao { + + private System2 system2; + + public AnalysisReportDao(System2 system2) { + this.system2 = system2; + } + + /** + * Update all rows with: STATUS='PENDING', STARTED_AT=NULL, UPDATED_AT={now} + */ + public void resetAllToPendingStatus(DbSession session) { + mapper(session).resetAllToPendingStatus(system2.now()); + } + + public void truncate(DbSession session) { + mapper(session).truncate(); + } + + public List<AnalysisReportDto> selectByProjectKey(DbSession session, String projectKey) { + return mapper(session).selectByProjectKey(projectKey); + } + + @VisibleForTesting + AnalysisReportDto selectById(DbSession session, long id) { + return mapper(session).selectById(id); + } + + @CheckForNull + public AnalysisReportDto pop(DbSession session) { + List<Long> reportIds = mapper(session).selectAvailables(PENDING, WORKING); + if (reportIds.isEmpty()) { + return null; + } + + long reportId = reportIds.get(0); + return tryToPop(session, reportId); + } + + @VisibleForTesting + AnalysisReportDto tryToPop(DbSession session, long reportId) { + AnalysisReportMapper mapper = mapper(session); + int nbOfReportBooked = mapper.updateWithBookingReport(reportId, system2.now(), PENDING, WORKING); + if (nbOfReportBooked == 0) { + return null; + } + + AnalysisReportDto result = mapper.selectById(reportId); + session.commit(); + return result; + } + + public List<AnalysisReportDto> selectAll(DbSession session) { + return mapper(session).selectAll(); + } + + public AnalysisReportDto insert(DbSession session, AnalysisReportDto report) { + report.setCreatedAt(system2.now()); + report.setUpdatedAt(system2.now()); + mapper(session).insert(report); + return report; + } + + public void delete(DbSession session, long id) { + mapper(session).delete(id); + } + + private AnalysisReportMapper mapper(DbSession session) { + return session.getMapper(AnalysisReportMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java index 8463da58cfa..c29f495047e 100644 --- a/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java @@ -22,11 +22,9 @@ package org.sonar.db.dashboard; import java.util.List; import javax.annotation.Nullable; import org.apache.ibatis.session.SqlSession; -import org.sonar.api.server.ServerSide; import org.sonar.db.Dao; import org.sonar.db.MyBatis; -@ServerSide public class ActiveDashboardDao implements Dao { private MyBatis mybatis; diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java index 40b151e7ec9..4462c1c24c8 100644 --- a/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java @@ -19,8 +19,11 @@ */ package org.sonar.db.dashboard; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import org.apache.ibatis.session.SqlSession; import org.sonar.db.Dao; +import org.sonar.db.DbSession; import org.sonar.db.MyBatis; public class DashboardDao implements Dao { @@ -62,4 +65,21 @@ public class DashboardDao implements Dao { } } + @CheckForNull + public DashboardDto getNullableByKey(DbSession session, Long key) { + return mapper(session).selectById(key); + } + + /** + * Get dashboard if allowed : shared or owned by logged-in user + * @param userId id of logged-in user, null if anonymous + */ + @CheckForNull + public DashboardDto getAllowedByKey(DbSession session, Long key, @Nullable Long userId) { + return mapper(session).selectAllowedById(key, userId != null ? userId : -1L); + } + + private DashboardMapper mapper(DbSession session) { + return session.getMapper(DashboardMapper.class); + } } diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDao.java new file mode 100644 index 00000000000..dec981655e0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDao.java @@ -0,0 +1,76 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.dashboard; + +import java.util.Collection; +import org.sonar.db.dashboard.WidgetDto; +import org.sonar.db.dashboard.WidgetMapper; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class WidgetDao implements Dao { + + private MyBatis myBatis; + + public WidgetDao(MyBatis myBatis) { + this.myBatis = myBatis; + } + + public WidgetDto getNullableByKey(Long widgetId) { + DbSession session = myBatis.openSession(false); + try { + return getNullableByKey(session, widgetId); + } finally { + MyBatis.closeQuietly(session); + } + } + + public WidgetDto getNullableByKey(DbSession session, Long widgetId) { + return mapper(session).selectById(widgetId); + } + + public WidgetDto update(WidgetDto item) { + DbSession session = myBatis.openSession(false); + try { + return update(session, item); + } finally { + MyBatis.closeQuietly(session); + } + } + + public WidgetDto update(DbSession session, WidgetDto item) { + mapper(session).update(item); + return item; + } + + public Collection<WidgetDto> findByDashboard(DbSession session, long dashboardKey) { + return mapper(session).selectByDashboard(dashboardKey); + } + + public Collection<WidgetDto> findAll(DbSession session) { + return mapper(session).selectAll(); + } + + private WidgetMapper mapper(DbSession session) { + return session.getMapper(WidgetMapper.class); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDao.java new file mode 100644 index 00000000000..0102d3338a0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDao.java @@ -0,0 +1,90 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.dashboard; + +import com.google.common.base.Function; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import org.sonar.db.Dao; +import org.sonar.db.DaoUtils; +import org.sonar.db.DatabaseUtils; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class WidgetPropertyDao implements Dao { + + private final MyBatis myBatis; + + public WidgetPropertyDao(MyBatis myBatis) { + this.myBatis = myBatis; + } + + public WidgetPropertyDto insert(WidgetPropertyDto item) { + DbSession session = myBatis.openSession(false); + try { + return insert(session, item); + } finally { + MyBatis.closeQuietly(session); + } + } + + public WidgetPropertyDto insert(DbSession session, WidgetPropertyDto item) { + mapper(session).insert(item); + return item; + } + + public void insert(DbSession session, Collection<WidgetPropertyDto> items) { + for (WidgetPropertyDto item : items) { + insert(session, item); + } + } + + public WidgetPropertyDto getNullableByKey(Long propertyId) { + DbSession session = myBatis.openSession(false); + try { + return getNullableByKey(session, propertyId); + } finally { + MyBatis.closeQuietly(session); + } + } + + public WidgetPropertyDto getNullableByKey(DbSession session, Long propertyId) { + return mapper(session).selectById(propertyId); + } + + public Collection<WidgetPropertyDto> findByDashboard(DbSession session, long dashboardKey) { + return mapper(session).selectByDashboard(dashboardKey); + } + + public void deleteByWidgetIds(final DbSession session, List<Long> widgetIdsWithPropertiesToDelete) { + DatabaseUtils.executeLargeInputs(widgetIdsWithPropertiesToDelete, new Function<List<Long>, List<Void>>() { + @Override + public List<Void> apply(List<Long> input) { + mapper(session).deleteByWidgetIds(input); + return Arrays.asList(); + } + }); + } + + private WidgetPropertyMapper mapper(DbSession session) { + return session.getMapper(WidgetPropertyMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java index 25690f35569..94d7ef81c73 100644 --- a/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java +++ b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java @@ -22,10 +22,11 @@ package org.sonar.db.duplication; import java.util.Collection; import java.util.List; import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; -public class DuplicationDao { +public class DuplicationDao implements Dao { private final MyBatis mybatis; diff --git a/sonar-db/src/main/java/org/sonar/batch/index/ResourceCopy.java b/sonar-db/src/main/java/org/sonar/db/event/EventDao.java index 6a3ccd83029..0f58097ab35 100644 --- a/sonar-db/src/main/java/org/sonar/batch/index/ResourceCopy.java +++ b/sonar-db/src/main/java/org/sonar/db/event/EventDao.java @@ -17,13 +17,25 @@ * 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.batch.index; -/** - * Used by views !! - */ -public interface ResourceCopy { +package org.sonar.db.event; + +import java.util.List; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; + +public class EventDao implements Dao { + + public List<EventDto> selectByComponentUuid(DbSession session, String componentUuid) { + return session.getMapper(EventMapper.class).selectByComponentUuid(componentUuid); + } + + public void insert(DbSession session, EventDto dto) { + session.getMapper(EventMapper.class).insert(dto); + } - int getCopyResourceId(); + public void delete(DbSession session, Long id) { + session.getMapper(EventMapper.class).delete(id); + } } diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java index bb63a3c9b90..5c061ad2407 100644 --- a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java +++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java @@ -25,13 +25,11 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import org.apache.ibatis.session.SqlSession; -import org.sonar.api.server.ServerSide; import org.sonar.db.Dao; import org.sonar.db.MyBatis; import static com.google.common.collect.Lists.newArrayList; -@ServerSide public class ActionPlanDao implements Dao { private final MyBatis mybatis; diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java index dfd4192922b..4d653374b5c 100644 --- a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java +++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java @@ -22,18 +22,18 @@ package org.sonar.db.issue; import java.util.List; import org.apache.ibatis.session.SqlSession; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDao; import org.sonar.db.MyBatis; -public class ActionPlanStatsDao { +public class ActionPlanStatsDao extends AbstractDao { - private final MyBatis mybatis; - - public ActionPlanStatsDao(MyBatis mybatis) { - this.mybatis = mybatis; + public ActionPlanStatsDao(MyBatis myBatis, System2 system2) { + super(myBatis, system2); } public List<ActionPlanStatsDto> findByProjectId(Long projectId) { - SqlSession session = mybatis.openSession(false); + SqlSession session = myBatis().openSession(false); try { return session.getMapper(ActionPlanStatsMapper.class).findByProjectId(projectId); } finally { diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java index edc89f9c267..cecd0fe0f08 100644 --- a/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java @@ -20,12 +20,16 @@ package org.sonar.db.issue; +import java.util.List; +import java.util.Set; +import javax.annotation.CheckForNull; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; -public class IssueDao { +public class IssueDao implements Dao { private final MyBatis mybatis; @@ -43,7 +47,48 @@ public class IssueDao { } } - protected IssueMapper mapper(DbSession session) { + @CheckForNull + public IssueDto selectNullableByKey(DbSession session, String key) { + return mapper(session).selectByKey(key); + } + + public IssueDto selectByKey(DbSession session, String key) { + IssueDto issue = selectNullableByKey(session, key); + if (issue == null) { + throw new IllegalArgumentException(String.format("Issue key '%s' does not exist", key)); + } + return issue; + } + + public List<IssueDto> findByActionPlan(DbSession session, String actionPlan) { + return mapper(session).selectByActionPlan(actionPlan); + } + + public List<IssueDto> selectByKeys(DbSession session, List<String> keys) { + return mapper(session).selectByKeys(keys); + } + + public Set<String> selectComponentUuidsOfOpenIssuesForProjectUuid(DbSession session, String projectUuid) { + return mapper(session).selectComponentUuidsOfOpenIssuesForProjectUuid(projectUuid); + } + + public void insert(DbSession session, IssueDto dto) { + mapper(session).insert(dto); + } + + public void insert(DbSession session, IssueDto dto, IssueDto... others) { + IssueMapper mapper = mapper(session); + mapper.insert(dto); + for (IssueDto other : others) { + mapper.insert(other); + } + } + + public void update(DbSession session, IssueDto dto) { + mapper(session).update(dto); + } + + private IssueMapper mapper(DbSession session) { return session.getMapper(IssueMapper.class); } diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java index f9de1a19963..7f1f06ce324 100644 --- a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java @@ -22,9 +22,10 @@ package org.sonar.db.issue; import java.util.List; import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; import org.sonar.db.MyBatis; -public class IssueFilterFavouriteDao { +public class IssueFilterFavouriteDao implements Dao { private final MyBatis mybatis; diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java new file mode 100644 index 00000000000..ff4b710d9ca --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java @@ -0,0 +1,87 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.measure; + +import com.google.common.base.Function; +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import javax.annotation.CheckForNull; +import org.sonar.db.Dao; +import org.sonar.db.DaoUtils; +import org.sonar.db.DatabaseUtils; +import org.sonar.db.DbSession; +import org.sonar.db.component.SnapshotDto; + +public class MeasureDao implements Dao { + + public boolean existsByKey(DbSession session, String componentKey, String metricKey) { + return mapper(session).countByComponentAndMetric(componentKey, metricKey) > 0; + } + + @CheckForNull + public MeasureDto findByComponentKeyAndMetricKey(DbSession session, String componentKey, String metricKey) { + return mapper(session).selectByComponentAndMetric(componentKey, metricKey); + } + + public List<MeasureDto> findByComponentKeyAndMetricKeys(final DbSession session, final String componentKey, List<String> metricKeys) { + return DatabaseUtils.executeLargeInputs(metricKeys, new Function<List<String>, List<MeasureDto>>() { + @Override + public List<MeasureDto> apply(List<String> keys) { + return mapper(session).selectByComponentAndMetrics(componentKey, keys); + } + }); + } + + public List<PastMeasureDto> selectByComponentUuidAndProjectSnapshotIdAndMetricIds(final DbSession session, final String componentUuid, final long projectSnapshotId, + Set<Integer> metricIds) { + return DatabaseUtils.executeLargeInputs(metricIds, new Function<List<Integer>, List<PastMeasureDto>>() { + @Override + public List<PastMeasureDto> apply(List<Integer> ids) { + return mapper(session).selectByComponentUuidAndProjectSnapshotIdAndStatusAndMetricIds(componentUuid, projectSnapshotId, ids, + SnapshotDto.STATUS_PROCESSED); + } + }); + } + + public void insert(DbSession session, MeasureDto measureDto) { + mapper(session).insert(measureDto); + } + + public void insert(DbSession session, Collection<MeasureDto> items) { + for (MeasureDto item : items) { + insert(session, item); + } + } + + public void insert(DbSession session, MeasureDto item, MeasureDto... others) { + insert(session, Lists.asList(item, others)); + } + + public List<String> selectMetricKeysForSnapshot(DbSession session, long snapshotId) { + return mapper(session).selectMetricKeysForSnapshot(snapshotId); + } + + private MeasureMapper mapper(DbSession session) { + return session.getMapper(MeasureMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java index 50d0bad2f53..8b5981caa45 100644 --- a/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java @@ -20,9 +20,10 @@ package org.sonar.db.measure; import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; import org.sonar.db.MyBatis; -public class MeasureFilterDao { +public class MeasureFilterDao implements Dao { private MyBatis mybatis; public MeasureFilterDao(MyBatis mybatis) { diff --git a/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java index b82ba01dd09..6fc69f7818e 100644 --- a/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java +++ b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java @@ -23,10 +23,11 @@ package org.sonar.db.notification; import java.util.Collections; import java.util.List; import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; -public class NotificationQueueDao { +public class NotificationQueueDao implements Dao { private final MyBatis mybatis; diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java index e6a1508e222..e18bdbbcb57 100644 --- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java @@ -27,13 +27,12 @@ import javax.annotation.Nullable; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; import org.sonar.api.security.DefaultGroups; -import org.sonar.api.server.ServerSide; +import org.sonar.db.Dao; import org.sonar.db.MyBatis; import static com.google.common.collect.Maps.newHashMap; -@ServerSide -public class PermissionDao { +public class PermissionDao implements Dao { private static final String QUERY_PARAMETER = "query"; private static final String COMPONENT_ID_PARAMETER = "componentId"; diff --git a/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java b/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java index cb1a63adbe3..c69532dc8ea 100644 --- a/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java +++ b/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java @@ -36,6 +36,7 @@ import org.apache.ibatis.session.SqlSession; import org.sonar.api.resources.Scopes; import org.sonar.db.Dao; import org.sonar.db.DaoUtils; +import org.sonar.db.DatabaseUtils; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; @@ -83,7 +84,7 @@ public class PropertiesDao implements Dao { String sql = "SELECT count(*) FROM properties pp " + "left outer join projects pj on pp.resource_id = pj.id " + "where pp.user_id is not null and (pp.resource_id is null or pj.uuid=?) " + - "and (" + DaoUtils.repeatCondition("pp.prop_key like ?", dispatcherKeys.size(), "or") + ")"; + "and (" + DatabaseUtils.repeatCondition("pp.prop_key like ?", dispatcherKeys.size(), "or") + ")"; try { pstmt = connection.prepareStatement(sql); pstmt.setString(1, projectUuid); diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java index a06767ab51c..f4ddf2478b6 100644 --- a/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java @@ -48,19 +48,17 @@ public class PurgeDao implements Dao { private final MyBatis mybatis; private final ResourceDao resourceDao; private final System2 system2; - private final PurgeProfiler profiler; - public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, PurgeProfiler profiler, System2 system2) { + public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, System2 system2) { this.mybatis = mybatis; this.resourceDao = resourceDao; - this.profiler = profiler; this.system2 = system2; } - public PurgeDao purge(PurgeConfiguration conf, PurgeListener purgeListener) { + public PurgeDao purge(PurgeConfiguration conf, PurgeListener listener, PurgeProfiler profiler) { DbSession session = mybatis.openSession(true); try { - purge(session, conf, purgeListener); + purge(session, conf, listener, profiler); session.commit(); } finally { MyBatis.closeQuietly(session); @@ -68,7 +66,7 @@ public class PurgeDao implements Dao { return this; } - public void purge(DbSession session, PurgeConfiguration conf, PurgeListener purgeListener) { + public void purge(DbSession session, PurgeConfiguration conf, PurgeListener listener, PurgeProfiler profiler) { PurgeMapper mapper = session.getMapper(PurgeMapper.class); PurgeCommands commands = new PurgeCommands(session, mapper, profiler); List<ResourceDto> projects = getProjects(conf.rootProjectIdUuid().getId(), session); @@ -78,7 +76,7 @@ public class PurgeDao implements Dao { purge(project, conf.scopesWithoutHistoricalData(), commands); } for (ResourceDto project : projects) { - disableOrphanResources(project, session, mapper, purgeListener); + disableOrphanResources(project, session, mapper, listener); } deleteOldClosedIssues(conf, mapper); } @@ -171,16 +169,16 @@ public class PurgeDao implements Dao { return result; } - public PurgeDao deleteResourceTree(IdUuidPair rootIdUuid) { + public PurgeDao deleteResourceTree(IdUuidPair rootIdUuid, PurgeProfiler profiler) { DbSession session = mybatis.openSession(true); try { - return deleteResourceTree(session, rootIdUuid); + return deleteResourceTree(session, rootIdUuid, profiler); } finally { MyBatis.closeQuietly(session); } } - public PurgeDao deleteResourceTree(DbSession session, IdUuidPair rootIdUuid) { + public PurgeDao deleteResourceTree(DbSession session, IdUuidPair rootIdUuid, PurgeProfiler profiler) { deleteProject(rootIdUuid, mapper(session), new PurgeCommands(session, profiler)); deleteFileSources(rootIdUuid.getUuid(), new PurgeCommands(session, profiler)); return this; @@ -209,17 +207,17 @@ public class PurgeDao implements Dao { mapper.resolveResourceIssuesNotAlreadyResolved(componentIdUuid.getUuid(), system2.now()); } - public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) { + public PurgeDao deleteSnapshots(PurgeSnapshotQuery query, PurgeProfiler profiler) { final DbSession session = mybatis.openSession(true); try { - return deleteSnapshots(query, session); + return deleteSnapshots(query, session, profiler); } finally { MyBatis.closeQuietly(session); } } - public PurgeDao deleteSnapshots(PurgeSnapshotQuery query, final DbSession session) { + public PurgeDao deleteSnapshots(PurgeSnapshotQuery query, DbSession session, PurgeProfiler profiler) { new PurgeCommands(session, profiler).deleteSnapshots(query); return this; } diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java b/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java index ac7bad54d1a..35c03578122 100644 --- a/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java +++ b/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java @@ -29,6 +29,7 @@ import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.db.DbSession; import org.sonar.db.purge.PurgeDao; +import org.sonar.db.purge.PurgeProfiler; import org.sonar.db.purge.PurgeSnapshotQuery; import org.sonar.db.purge.PurgeableSnapshotDto; @@ -36,10 +37,12 @@ import org.sonar.db.purge.PurgeableSnapshotDto; public class DefaultPeriodCleaner { private static final Logger LOG = Loggers.get(DefaultPeriodCleaner.class); - private PurgeDao purgeDao; + private final PurgeDao purgeDao; + private final PurgeProfiler profiler; - public DefaultPeriodCleaner(PurgeDao purgeDao) { + public DefaultPeriodCleaner(PurgeDao purgeDao, PurgeProfiler profiler) { this.purgeDao = purgeDao; + this.profiler = profiler; } public void clean(DbSession session, long projectId, Settings settings) { @@ -58,8 +61,8 @@ public class DefaultPeriodCleaner { private void delete(List<PurgeableSnapshotDto> snapshots, DbSession session) { for (PurgeableSnapshotDto snapshot : snapshots) { LOG.debug("<- Delete snapshot: {} [{}]", DateUtils.formatDateTime(snapshot.getDate()), snapshot.getSnapshotId()); - purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()), session); - purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()), session); + purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()), session, profiler); + purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()), session, profiler); } } diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java deleted file mode 100644 index 24efe187dd7..00000000000 --- a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.qualityprofile; - -import java.util.List; -import org.apache.ibatis.session.SqlSession; -import org.sonar.api.server.ServerSide; -import org.sonar.db.DbSession; -import org.sonar.db.MyBatis; - -/** - * @deprecated use the ActiveRuleDao class defined in sonar-server - */ -@Deprecated -@ServerSide -public class ActiveRuleDao { - - private final MyBatis mybatis; - - public ActiveRuleDao(MyBatis mybatis) { - this.mybatis = mybatis; - } - - public void insert(ActiveRuleDto dto, SqlSession session) { - session.getMapper(ActiveRuleMapper.class).insert(dto); - } - - public List<ActiveRuleDto> selectByProfileKey(String profileKey) { - DbSession session = mybatis.openSession(false); - try { - return session.getMapper(ActiveRuleMapper.class).selectByProfileKey(profileKey); - } finally { - session.close(); - } - } - - public void insert(ActiveRuleParamDto dto, SqlSession session) { - session.getMapper(ActiveRuleMapper.class).insertParameter(dto); - } - - public List<ActiveRuleParamDto> selectParamsByProfileKey(String profileKey) { - DbSession session = mybatis.openSession(false); - try { - return session.getMapper(ActiveRuleMapper.class).selectParamsByProfileKey(profileKey); - } finally { - session.close(); - } - } -} diff --git a/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java b/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java index 25236bc2bcb..8991c688db6 100644 --- a/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java +++ b/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java @@ -21,13 +21,14 @@ package org.sonar.db.rule; import java.util.List; import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; import org.sonar.db.MyBatis; /** * @deprecated in 4.4 moved to org.sonar.server.rule.db.RuleDao. */ @Deprecated -public class RuleDao { +public class RuleDao implements Dao { private MyBatis mybatis; diff --git a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java index c34a9b89542..59c89c738b1 100644 --- a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java +++ b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java @@ -24,15 +24,13 @@ import javax.annotation.CheckForNull; import org.apache.ibatis.session.SqlSession; import org.sonar.api.utils.Semaphores; import org.sonar.api.utils.System2; +import org.sonar.db.Dao; import org.sonar.db.MyBatis; import static com.google.common.base.Preconditions.checkArgument; import static org.sonar.api.utils.DateUtils.longToDate; -/** - * @since 3.4 - */ -public class SemaphoreDao { +public class SemaphoreDao implements Dao { private static final String SEMAPHORE_NAME_MUST_NOT_BE_EMPTY = "Semaphore name must not be empty"; private final MyBatis mybatis; diff --git a/sonar-db/src/main/java/org/sonar/db/source/FileSourceDao.java b/sonar-db/src/main/java/org/sonar/db/source/FileSourceDao.java new file mode 100644 index 00000000000..6aeb7d0742b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/source/FileSourceDao.java @@ -0,0 +1,146 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.source; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import java.io.Reader; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.commons.dbutils.DbUtils; +import org.apache.commons.io.IOUtils; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; +import org.sonar.db.source.FileSourceDto.Type; + +public class FileSourceDao implements Dao { + + private static final Splitter END_OF_LINE_SPLITTER = Splitter.on('\n'); + private final MyBatis mybatis; + + public FileSourceDao(MyBatis myBatis) { + this.mybatis = myBatis; + } + + @CheckForNull + public FileSourceDto selectSource(String fileUuid) { + DbSession session = mybatis.openSession(false); + try { + return mapper(session).select(fileUuid, Type.SOURCE); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public FileSourceDto selectTest(String fileUuid) { + DbSession session = mybatis.openSession(false); + try { + return mapper(session).select(fileUuid, Type.TEST); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public List<String> selectLineHashes(DbSession dbSession, String fileUuid) { + Connection connection = dbSession.getConnection(); + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type=?"); + pstmt.setString(1, fileUuid); + pstmt.setString(2, Type.SOURCE); + rs = pstmt.executeQuery(); + if (rs.next()) { + return END_OF_LINE_SPLITTER.splitToList(rs.getString(1)); + } + return null; + } catch (SQLException e) { + throw new IllegalStateException("Fail to read FILE_SOURCES.LINE_HASHES of file " + fileUuid, e); + } finally { + DbUtils.closeQuietly(connection, pstmt, rs); + } + } + + public <T> void readLineHashesStream(DbSession dbSession, String fileUuid, Function<Reader, T> function) { + Connection connection = dbSession.getConnection(); + PreparedStatement pstmt = null; + ResultSet rs = null; + Reader reader = null; + try { + pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type=?"); + pstmt.setString(1, fileUuid); + pstmt.setString(2, Type.SOURCE); + rs = pstmt.executeQuery(); + if (rs.next()) { + reader = rs.getCharacterStream(1); + function.apply(reader); + } + } catch (SQLException e) { + throw new IllegalStateException("Fail to read FILE_SOURCES.LINE_HASHES of file " + fileUuid, e); + } finally { + IOUtils.closeQuietly(reader); + DbUtils.closeQuietly(connection, pstmt, rs); + } + } + + public void insert(FileSourceDto dto) { + DbSession session = mybatis.openSession(false); + try { + insert(session, dto); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(DbSession session, FileSourceDto dto) { + mapper(session).insert(dto); + } + + public void update(FileSourceDto dto) { + DbSession session = mybatis.openSession(false); + try { + update(session, dto); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void update(DbSession session, FileSourceDto dto) { + mapper(session).update(dto); + } + + public void updateDateWhenUpdatedDateIsZero(DbSession session, String projectUuid, long updateDate) { + mapper(session).updateDateWhenUpdatedDateIsZero(projectUuid, updateDate); + } + + private FileSourceMapper mapper(DbSession session) { + return session.getMapper(FileSourceMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java index 5837964ce82..56a4eb312fc 100644 --- a/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java +++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java @@ -27,6 +27,7 @@ import java.util.List; import org.apache.ibatis.session.SqlSession; import org.sonar.db.Dao; import org.sonar.db.DaoUtils; +import org.sonar.db.DatabaseUtils; import org.sonar.db.MyBatis; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ResourceDao; @@ -112,7 +113,7 @@ public class AuthorDao implements Dao { } public List<String> selectScmAccountsByDeveloperUuids(final SqlSession session, Collection<String> developerUuids) { - return DaoUtils.executeLargeInputs(developerUuids, new Function<List<String>, List<String>>() { + return DatabaseUtils.executeLargeInputs(developerUuids, new Function<List<String>, List<String>>() { @Override public List<String> apply(List<String> partition) { return session.getMapper(AuthorMapper.class).selectScmAccountsByDeveloperUuids(partition); diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java index 2a386c1d2b7..c4c8a118dce 100644 --- a/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java +++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java @@ -30,6 +30,7 @@ import org.apache.ibatis.session.SqlSession; import org.sonar.api.server.ServerSide; import org.sonar.db.Dao; import org.sonar.db.DaoUtils; +import org.sonar.db.DatabaseUtils; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; @@ -49,7 +50,7 @@ public class AuthorizationDao implements Dao { if (componentIds.isEmpty()) { return Collections.emptySet(); } - return DaoUtils.executeLargeInputs(componentIds, new Function<List<Long>, List<Long>>() { + return DatabaseUtils.executeLargeInputs(componentIds, new Function<List<Long>, List<Long>>() { @Override public List<Long> apply(List<Long> partition) { if (userId == null) { diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java index a62609259b8..e27e6fe5d98 100644 --- a/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java @@ -34,6 +34,7 @@ import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; import org.sonar.db.Dao; import org.sonar.db.DaoUtils; +import org.sonar.db.DatabaseUtils; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; @@ -77,7 +78,7 @@ public class GroupMembershipDao implements Dao { public Map<String, Integer> countUsersByGroups(final DbSession session, Collection<Long> groupIds) { final Map<String, Integer> result = Maps.newHashMap(); - DaoUtils.executeLargeInputs(groupIds, new Function<List<Long>, List<GroupUserCount>>() { + DatabaseUtils.executeLargeInputs(groupIds, new Function<List<Long>, List<GroupUserCount>>() { @Override public List<GroupUserCount> apply(@Nonnull List<Long> input) { List<GroupUserCount> userCounts = mapper(session).countUsersByGroup(input); @@ -93,7 +94,7 @@ public class GroupMembershipDao implements Dao { public Multimap<String, String> selectGroupsByLogins(final DbSession session, Collection<String> logins) { final Multimap<String, String> result = ArrayListMultimap.create(); - DaoUtils.executeLargeInputs(logins, new Function<List<String>, List<LoginGroup>>() { + DatabaseUtils.executeLargeInputs(logins, new Function<List<String>, List<LoginGroup>>() { @Override public List<LoginGroup> apply(@Nonnull List<String> input) { List<LoginGroup> groupMemberships = mapper(session).selectGroupsByLogins(input); diff --git a/sonar-db/src/main/java/org/sonar/core/issue/db/package-info.java b/sonar-db/src/main/java/org/sonar/db/user/UserGroupDao.java index 55dc4912649..2c5a8665ee6 100644 --- a/sonar-db/src/main/java/org/sonar/core/issue/db/package-info.java +++ b/sonar-db/src/main/java/org/sonar/db/user/UserGroupDao.java @@ -17,8 +17,28 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -@ParametersAreNonnullByDefault -package org.sonar.core.issue.db; -import javax.annotation.ParametersAreNonnullByDefault; +package org.sonar.db.user; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; + +public class UserGroupDao implements Dao { + + public UserGroupDto insert(DbSession session, UserGroupDto dto) { + mapper(session).insert(dto); + return dto; + } + + public void delete(DbSession session, UserGroupDto dto) { + mapper(session).delete(dto); + } + + public void deleteMembersByGroupId(DbSession session, long groupId) { + mapper(session).deleteMembersByGroup(groupId); + } + + protected UserGroupMapper mapper(DbSession session) { + return session.getMapper(UserGroupMapper.class); + } +} |