diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java index ecb019282440..f5e458a27771 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java @@ -20,19 +20,23 @@ package org.sonar.server.qualityprofile; import com.google.common.collect.Lists; +import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.annotation.CheckForNull; import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.StringUtils; import org.sonar.core.util.Slug; +import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.qualityprofile.ActiveRuleDto; import org.sonar.db.qualityprofile.QualityProfileDto; -import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.Verifications; +import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED; + /** * Create, delete, rename and set as default profile. */ @@ -84,21 +88,11 @@ private QualityProfileDto doCreate(DbSession dbSession, QProfileName name) { // ------------- DELETION - void delete(String key) { - DbSession session = db.openSession(false); - try { - delete(session, key, false); - session.commit(); - } finally { - session.close(); - } - } - /** * Session is NOT committed. Profiles marked as "default" for a language can't be deleted, * except if the parameter force is true. */ - public void delete(DbSession session, String key, boolean force) { + public List delete(DbSession session, String key, boolean force) { QualityProfileDto profile = db.qualityProfileDao().selectOrFailByKey(session, key); List descendants = db.qualityProfileDao().selectDescendants(session, key); if (!force) { @@ -108,16 +102,23 @@ public void delete(DbSession session, String key, boolean force) { } } // delete bottom-up + List changes = new ArrayList<>(); for (QualityProfileDto descendant : Lists.reverse(descendants)) { - doDelete(session, descendant); + changes.addAll(doDelete(session, descendant)); } - doDelete(session, profile); + changes.addAll(doDelete(session, profile)); + return changes; } - private void doDelete(DbSession session, QualityProfileDto profile) { + private List doDelete(DbSession session, QualityProfileDto profile) { db.qualityProfileDao().deleteAllProjectProfileAssociation(profile.getKey(), session); - db.activeRuleDao().deleteByProfileKey(session, profile.getKey()); + List changes = new ArrayList<>(); + for (ActiveRuleDto activeRule : db.activeRuleDao().selectByProfileKey(session, profile.getKey())) { + db.activeRuleDao().delete(session, activeRule.getKey()); + changes.add(ActiveRuleChange.createFor(DEACTIVATED, activeRule.getKey())); + } db.qualityProfileDao().delete(session, profile); + return changes; } // ------------- DEFAULT PROFILE diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java index d94a6bd6abaf..7567c3b52309 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java @@ -19,6 +19,7 @@ */ package org.sonar.server.qualityprofile; +import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -27,6 +28,7 @@ import org.junit.rules.ExpectedException; import org.sonar.api.server.rule.RuleParamType; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.RowNotFoundException; import org.sonar.db.component.ComponentDto; @@ -34,11 +36,11 @@ import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.db.rule.RuleTesting; -import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.qualityprofile.index.ActiveRuleIndex; -import org.sonar.server.search.IndexClient; +import org.sonar.server.qualityprofile.index.ActiveRuleIndex2; +import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; +import org.sonar.server.rule.index.RuleIndexer; import org.sonar.server.tester.MockUserSession; import org.sonar.server.tester.ServerTester; import org.sonar.server.tester.UserSessionRule; @@ -52,7 +54,7 @@ public class QProfileFactoryMediumTest { @ClassRule - public static ServerTester tester = new ServerTester(); + public static ServerTester tester = new ServerTester().withEsIndexes(); @Rule public ExpectedException thrown = ExpectedException.none(); @Rule @@ -60,7 +62,9 @@ public class QProfileFactoryMediumTest { DbClient db; DbSession dbSession; - IndexClient index; + ActiveRuleIndex2 activeRuleIndex; + ActiveRuleIndexer activeRuleIndexer; + RuleIndexer ruleIndexer; QProfileFactory factory; @Before @@ -68,8 +72,12 @@ public void before() { tester.clearDbAndIndexes(); db = tester.get(DbClient.class); dbSession = db.openSession(false); - index = tester.get(IndexClient.class); factory = tester.get(QProfileFactory.class); + activeRuleIndex = tester.get(ActiveRuleIndex2.class); + activeRuleIndexer = tester.get(ActiveRuleIndexer.class); + activeRuleIndexer.setEnabled(true); + ruleIndexer = tester.get(RuleIndexer.class); + ruleIndexer.setEnabled(true); } @After @@ -208,13 +216,15 @@ public void delete() { dbSession.commit(); dbSession.clearCache(); - factory.delete(XOO_P1_KEY); + List changes = factory.delete(dbSession, XOO_P1_KEY, false); + dbSession.commit(); + activeRuleIndexer.index(changes); dbSession.clearCache(); assertThat(db.qualityProfileDao().selectAll(dbSession)).isEmpty(); - assertThat(db.deprecatedActiveRuleDao().selectAll(dbSession)).isEmpty(); - assertThat(db.deprecatedActiveRuleDao().selectAllParams(dbSession)).isEmpty(); - assertThat(index.get(ActiveRuleIndex.class).findByProfile(XOO_P1_KEY)).isEmpty(); + assertThat(db.activeRuleDao().selectAll(dbSession)).isEmpty(); + assertThat(db.activeRuleDao().selectAllParams(dbSession)).isEmpty(); + assertThat(activeRuleIndex.findByProfile(XOO_P1_KEY)).isEmpty(); } @Test @@ -223,23 +233,27 @@ public void delete_descendants() { // create parent and child profiles db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1(), QProfileTesting.newXooP2(), QProfileTesting.newXooP3()); - tester.get(RuleActivator.class).setParent(dbSession, XOO_P2_KEY, XOO_P1_KEY); - tester.get(RuleActivator.class).setParent(dbSession, XOO_P3_KEY, XOO_P1_KEY); - tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(RuleTesting.XOO_X1), XOO_P1_KEY); + List changes = tester.get(RuleActivator.class).setParent(dbSession, XOO_P2_KEY, XOO_P1_KEY); + changes.addAll(tester.get(RuleActivator.class).setParent(dbSession, XOO_P3_KEY, XOO_P1_KEY)); + changes.addAll(tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(RuleTesting.XOO_X1), XOO_P1_KEY)); dbSession.commit(); dbSession.clearCache(); + activeRuleIndexer.index(changes); + assertThat(db.qualityProfileDao().selectAll(dbSession)).hasSize(3); - assertThat(db.deprecatedActiveRuleDao().selectAll(dbSession)).hasSize(3); + assertThat(db.activeRuleDao().selectAll(dbSession)).hasSize(3); - factory.delete(XOO_P1_KEY); + changes = factory.delete(dbSession, XOO_P1_KEY, false); + dbSession.commit(); + activeRuleIndexer.index(changes); dbSession.clearCache(); assertThat(db.qualityProfileDao().selectAll(dbSession)).isEmpty(); - assertThat(db.deprecatedActiveRuleDao().selectAll(dbSession)).isEmpty(); - assertThat(db.deprecatedActiveRuleDao().selectAllParams(dbSession)).isEmpty(); - assertThat(index.get(ActiveRuleIndex.class).findByProfile(XOO_P1_KEY)).isEmpty(); - assertThat(index.get(ActiveRuleIndex.class).findByProfile(XOO_P2_KEY)).isEmpty(); - assertThat(index.get(ActiveRuleIndex.class).findByProfile(XOO_P3_KEY)).isEmpty(); + assertThat(db.activeRuleDao().selectAll(dbSession)).isEmpty(); + assertThat(db.activeRuleDao().selectAllParams(dbSession)).isEmpty(); + assertThat(activeRuleIndex.findByProfile(XOO_P1_KEY)).isEmpty(); + assertThat(activeRuleIndex.findByProfile(XOO_P2_KEY)).isEmpty(); + assertThat(activeRuleIndex.findByProfile(XOO_P3_KEY)).isEmpty(); } @Test @@ -250,7 +264,9 @@ public void do_not_delete_default_profile() { dbSession.clearCache(); try { - factory.delete(XOO_P1_KEY); + List changes = factory.delete(dbSession, XOO_P1_KEY, false); + dbSession.commit(); + activeRuleIndexer.index(changes); fail(); } catch (BadRequestException e) { assertThat(e).hasMessage("The profile marked as default can not be deleted: XOO_P1"); @@ -261,14 +277,18 @@ public void do_not_delete_default_profile() { @Test public void do_not_delete_if_default_descendant() { db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1(), QProfileTesting.newXooP2(), QProfileTesting.newXooP3()); - tester.get(RuleActivator.class).setParent(dbSession, XOO_P2_KEY, XOO_P1_KEY); - tester.get(RuleActivator.class).setParent(dbSession, XOO_P3_KEY, XOO_P1_KEY); + + List changes = tester.get(RuleActivator.class).setParent(dbSession, XOO_P2_KEY, XOO_P1_KEY); + changes.addAll(tester.get(RuleActivator.class).setParent(dbSession, XOO_P3_KEY, XOO_P1_KEY)); factory.setDefault(dbSession, XOO_P3_KEY); dbSession.commit(); dbSession.clearCache(); + activeRuleIndexer.index(changes); try { - factory.delete(XOO_P1_KEY); + changes = factory.delete(dbSession, XOO_P1_KEY, false); + dbSession.commit(); + activeRuleIndexer.index(changes); fail(); } catch (BadRequestException e) { assertThat(e).hasMessage("The profile marked as default can not be deleted: XOO_P3"); @@ -281,7 +301,9 @@ public void fail_if_unknown_profile_to_be_deleted() { thrown.expect(RowNotFoundException.class); thrown.expectMessage("Quality profile not found: XOO_P1"); - factory.delete(XOO_P1_KEY); + List changes = factory.delete(dbSession, XOO_P1_KEY, false); + dbSession.commit(); + activeRuleIndexer.index(changes); } @Test @@ -348,10 +370,12 @@ private void initRules() { // create pre-defined rules RuleDto xooRule1 = RuleTesting.newXooX1(); RuleDto xooRule2 = RuleTesting.newXooX2(); - db.deprecatedRuleDao().insert(dbSession, xooRule1, xooRule2); - db.deprecatedRuleDao().insertRuleParam(dbSession, xooRule1, RuleParamDto.createFor(xooRule1) + db.ruleDao().insert(dbSession, xooRule1); + db.ruleDao().insert(dbSession, xooRule2); + db.ruleDao().insertRuleParam(dbSession, xooRule1, RuleParamDto.createFor(xooRule1) .setName("max").setDefaultValue("10").setType(RuleParamType.INTEGER.type())); dbSession.commit(); dbSession.clearCache(); + ruleIndexer.index(); } } 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 index 808b85f593ed..d85a54b7a41f 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java @@ -57,6 +57,11 @@ public List selectByRule(DbSession dbSession, RuleDto rule) { return mapper(dbSession).selectByRuleId(rule.getId()); } + // TODO As it's only used by MediumTest, it should be replaced by DbTester.countRowsOfTable() + public List selectAll(DbSession dbSession) { + return mapper(dbSession).selectAll(); + } + public List selectAllParams(DbSession dbSession) { return mapper(dbSession).selectAllParams(); } @@ -122,13 +127,6 @@ public void deleteParam(DbSession session, ActiveRuleDto activeRule, ActiveRuleP mapper(session).deleteParameter(activeRuleParam.getId()); } - public void deleteByProfileKey(DbSession session, String profileKey) { - /** Functional cascade for params */ - for (ActiveRuleDto activeRule : selectByProfileKey(session, profileKey)) { - delete(session, activeRule.getKey()); - } - } - public List selectByProfileKey(DbSession session, String profileKey) { return mapper(session).selectByProfileKey(profileKey); }