return actions;
}
- /**
- * Deactivate all active rules from profiles using a rule, then remove then.
- */
- public void removeActivatedRules(int ruleId) {
- List<ActiveRule> activeRules = getSession().createQuery("FROM " + ActiveRule.class.getSimpleName() + " WHERE rule.id=:ruleId").setParameter("ruleId", ruleId).getResultList();
- List<ActiveRule> activeRulesToRemove = Lists.newArrayList();
-
- for (ActiveRule activeRule : activeRules) {
- if (!activeRule.isInherited()) {
- RulesProfile profile = activeRule.getRulesProfile();
- incrementProfileVersionIfNeeded(profile);
- ruleDisabled(profile, activeRule, null);
- for (RulesProfile child : getChildren(profile.getId())) {
- deactivate(child, activeRule.getRule(), null);
- }
- activeRulesToRemove.add(activeRule);
- }
- }
-
- for (ActiveRule activeRule : activeRulesToRemove) {
- // Do not use getSingleResult as it can generate an EntityNotFoundException
- ActiveRule activeRuleToRemove = getSession().getEntity(ActiveRule.class, activeRule.getId());
- removeActiveRule(activeRuleToRemove);
- }
- getSession().commit();
- dryRunCache.reportGlobalModification();
- }
-
-
/**
* Rule was activated
*/
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import org.sonar.api.ServerComponent;
-import org.sonar.api.database.DatabaseSession;
import org.sonar.api.profiles.ProfileDefinition;
import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.profiles.XMLProfileParser;
-import org.sonar.api.profiles.XMLProfileSerializer;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleParam;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.qualityprofile.db.QualityProfileKey;
import org.sonar.core.rule.RuleDto;
-import org.sonar.jpa.session.DatabaseSessionFactory;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.user.UserSession;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class QProfileBackup implements ServerComponent {
- private final DatabaseSessionFactory sessionFactory;
- private final XMLProfileParser xmlProfileParser;
- private final XMLProfileSerializer xmlProfileSerializer;
-
private final MyBatis myBatis;
- private final QProfileLookup qProfileLookup;
private final QProfileOperations qProfileOperations;
private final QProfileActiveRuleOperations qProfileActiveRuleOperations;
private final RuleDao ruleDao;
private final DefaultProfilesCache defaultProfilesCache;
private final PreviewCache dryRunCache;
- public QProfileBackup(DatabaseSessionFactory sessionFactory, XMLProfileParser xmlProfileParser, XMLProfileSerializer xmlProfileSerializer, MyBatis myBatis,
- QProfileLookup qProfileLookup, QProfileOperations qProfileOperations, QProfileActiveRuleOperations qProfileActiveRuleOperations, RuleDao ruleDao,
+ public QProfileBackup(MyBatis myBatis,
+ QProfileOperations qProfileOperations, QProfileActiveRuleOperations qProfileActiveRuleOperations, RuleDao ruleDao,
DefaultProfilesCache defaultProfilesCache, PreviewCache dryRunCache) {
- this(sessionFactory, xmlProfileParser, xmlProfileSerializer, myBatis, qProfileLookup, qProfileOperations, qProfileActiveRuleOperations, ruleDao,
+ this(myBatis, qProfileOperations, qProfileActiveRuleOperations, ruleDao,
Collections.<ProfileDefinition>emptyList(), defaultProfilesCache, dryRunCache);
}
- public QProfileBackup(DatabaseSessionFactory sessionFactory, XMLProfileParser xmlProfileParser, XMLProfileSerializer xmlProfileSerializer, MyBatis myBatis,
- QProfileLookup qProfileLookup, QProfileOperations qProfileOperations, QProfileActiveRuleOperations qProfileActiveRuleOperations, RuleDao ruleDao,
+ public QProfileBackup(MyBatis myBatis,
+ QProfileOperations qProfileOperations, QProfileActiveRuleOperations qProfileActiveRuleOperations, RuleDao ruleDao,
List<ProfileDefinition> definitions, DefaultProfilesCache defaultProfilesCache, PreviewCache dryRunCache) {
- this.sessionFactory = sessionFactory;
- this.xmlProfileParser = xmlProfileParser;
- this.xmlProfileSerializer = xmlProfileSerializer;
this.myBatis = myBatis;
- this.qProfileLookup = qProfileLookup;
this.qProfileOperations = qProfileOperations;
this.qProfileActiveRuleOperations = qProfileActiveRuleOperations;
this.ruleDao = ruleDao;
this.dryRunCache = dryRunCache;
}
- public String backupProfile(QProfile profile) {
- DatabaseSession session = sessionFactory.getSession();
- RulesProfile rulesProfile = session.getSingleResult(RulesProfile.class, "id", profile.id());
- Writer writer = new StringWriter();
- xmlProfileSerializer.write(rulesProfile, writer);
- return writer.toString();
- }
-
- /**
- * @param deleteExisting is used to not fail if profile exist but to delete it first. It's only used by WS, and it should be soon removed.
- */
- public QProfileResult restore(String xmlBackup, boolean deleteExisting) {
- checkPermission(UserSession.get());
-
- DbSession session = myBatis.openSession(false);
- QProfileResult result = new QProfileResult();
- try {
- ValidationMessages messages = ValidationMessages.create();
- RulesProfile importedProfile = xmlProfileParser.parse(new StringReader(xmlBackup), messages);
- processValidationMessages(messages, result);
- if (importedProfile != null) {
- DatabaseSession hibernateSession = sessionFactory.getSession();
- checkProfileDoesNotExists(importedProfile, deleteExisting, hibernateSession);
- hibernateSession.saveWithoutFlush(importedProfile);
- hibernateSession.commit();
-
- QProfile newProfile = qProfileLookup.profile(importedProfile.getId(), session);
- if (newProfile == null) {
- throw new BadRequestException("Restore of the profile has failed.");
- }
- //esActiveRule.bulkIndexProfile(newProfile.id(), session);
- dryRunCache.reportGlobalModification(session);
- session.commit();
- result.setProfile(newProfile);
- }
- } finally {
- MyBatis.closeQuietly(session);
- }
- return result;
- }
-
/**
* Recreate built-in profile for a given language.
* If a profile with same name than default profile already exists, an exception will be thrown.
return defaultProfilesCache.byLanguage(language);
}
- private void checkProfileDoesNotExists(RulesProfile importedProfile, boolean deleteExisting, DatabaseSession hibernateSession) {
- RulesProfile existingProfile = hibernateSession.getSingleResult(RulesProfile.class, "name", importedProfile.getName(), "language", importedProfile.getLanguage());
- if (existingProfile != null && !deleteExisting) {
- throw BadRequestException.of("The profile " + existingProfile + " already exists. Please delete it before restoring.");
- }
- if (existingProfile != null) {
- // Warning, profile with children can be deleted as no check is done!
- hibernateSession.removeWithoutFlush(existingProfile);
- hibernateSession.commit();
- //esActiveRule.deleteActiveRulesFromProfile(existingProfile.getId());
- }
- }
-
private void processValidationMessages(ValidationMessages messages, QProfileResult result) {
if (!messages.getErrors().isEmpty()) {
List<BadRequestException.Message> errors = newArrayList();
--- /dev/null
+/*
+ * 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.server.qualityprofile;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
+import org.codehaus.staxmate.SMInputFactory;
+import org.codehaus.staxmate.in.SMHierarchicCursor;
+import org.codehaus.staxmate.in.SMInputCursor;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.text.XmlWriter;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.ActiveRuleKey;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.qualityprofile.db.QualityProfileKey;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
+import org.sonar.server.search.IndexClient;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class QProfileBackuper implements ServerComponent {
+
+ private final RuleActivator activator;
+ private final DbClient db;
+ private final IndexClient index;
+
+ public QProfileBackuper(RuleActivator activator, DbClient db, IndexClient index) {
+ this.activator = activator;
+ this.db = db;
+ this.index = index;
+ }
+
+ public void backup(QualityProfileKey key, Writer writer) {
+ // TODO check permission
+ DbSession dbSession = db.openSession(false);
+ try {
+ QualityProfileDto profile = db.qualityProfileDao().getByKey(key, dbSession);
+ if (profile == null) {
+ throw new IllegalArgumentException("Quality profile does not exist: " + key);
+ }
+ List<ActiveRule> activeRules = index.get(ActiveRuleIndex.class).findByProfile(key);
+ writeXml(writer, profile, activeRules);
+
+ } finally {
+ dbSession.close();
+ }
+ }
+
+ private void writeXml(Writer writer, QualityProfileDto profile, List<ActiveRule> activeRules) {
+ XmlWriter xml = XmlWriter.of(writer).declaration();
+ xml.begin("profile");
+ xml.prop("name", profile.getName());
+ xml.prop("language", profile.getLanguage());
+ xml.begin("rules");
+ for (ActiveRule activeRule : activeRules) {
+ xml.begin("rule");
+ xml.prop("repositoryKey", activeRule.key().ruleKey().repository());
+ xml.prop("key", activeRule.key().ruleKey().rule());
+ xml.prop("priority", activeRule.severity());
+ xml.begin("parameters");
+ for (Map.Entry<String, String> param : activeRule.params().entrySet()) {
+ xml
+ .begin("parameter")
+ .prop("key", param.getKey())
+ .prop("value", param.getValue())
+ .end();
+ }
+ xml.end("parameters");
+ xml.end("rule");
+ }
+ xml.end("rules");
+ xml.end("profile").close();
+ }
+
+ public void restore(Reader reader) {
+ try {
+ String profileLang = null, profileName = null;
+ SMInputFactory inputFactory = initStax();
+ SMHierarchicCursor rootC = inputFactory.rootElementCursor(reader);
+ rootC.advance(); // <profile>
+ SMInputCursor cursor = rootC.childElementCursor();
+ while (cursor.getNext() != null) {
+ String nodeName = cursor.getLocalName();
+ if (StringUtils.equals("name", nodeName)) {
+ profileName = StringUtils.trim(cursor.collectDescendantText(false));
+
+ } else if (StringUtils.equals("language", nodeName)) {
+ profileLang = StringUtils.trim(cursor.collectDescendantText(false));
+
+ } else if (StringUtils.equals("rules", nodeName)) {
+ QualityProfileKey profileKey = QualityProfileKey.of(profileName, profileLang);
+ SMInputCursor rulesCursor = cursor.childElementCursor("rule");
+ doRestore(rulesCursor, profileKey);
+ }
+ }
+ } catch (XMLStreamException e) {
+ throw new IllegalStateException("Fail to restore Quality profile backup", e);
+ }
+ }
+
+ private void doRestore(SMInputCursor rulesCursor, QualityProfileKey profileKey) throws XMLStreamException {
+ Set<RuleKey> rulesToDeactivate = Sets.newHashSet();
+ DbSession dbSession = db.openSession(false);
+ try {
+ // find or create profile
+ if (db.qualityProfileDao().getByKey(profileKey, dbSession) == null) {
+ // create new profile
+ db.qualityProfileDao().insert(dbSession, QualityProfileDto.createFor(profileKey));
+ } else {
+ // already exists. Keep reference to all the activated rules before backup restore
+ for (ActiveRuleDto activeRuleDto : db.activeRuleDao().findByProfileKey(dbSession, profileKey)) {
+ rulesToDeactivate.add(activeRuleDto.getKey().ruleKey());
+ }
+ }
+
+ while (rulesCursor.getNext() != null) {
+ SMInputCursor ruleCursor = rulesCursor.childElementCursor();
+ String repositoryKey = null, key = null, severity = null;
+ Map<String, String> parameters = Maps.newHashMap();
+ while (ruleCursor.getNext() != null) {
+ String nodeName = ruleCursor.getLocalName();
+ if (StringUtils.equals("repositoryKey", nodeName)) {
+ repositoryKey = StringUtils.trim(ruleCursor.collectDescendantText(false));
+
+ } else if (StringUtils.equals("key", nodeName)) {
+ key = StringUtils.trim(ruleCursor.collectDescendantText(false));
+
+ } else if (StringUtils.equals("priority", nodeName)) {
+ severity = StringUtils.trim(ruleCursor.collectDescendantText(false));
+
+ } else if (StringUtils.equals("parameters", nodeName)) {
+ SMInputCursor propsCursor = ruleCursor.childElementCursor("parameter");
+ readParameters(propsCursor, parameters);
+ }
+ }
+ RuleKey ruleKey = RuleKey.of(repositoryKey, key);
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(profileKey, ruleKey));
+ activation.setSeverity(severity);
+ activation.setParameters(parameters);
+ activator.activate(dbSession, activation);
+ rulesToDeactivate.remove(ruleKey);
+ }
+ for (RuleKey ruleKey : rulesToDeactivate) {
+ // Will fail to deactivate a rule which is activated in a parent profile
+ activator.deactivate(ActiveRuleKey.of(profileKey, ruleKey), dbSession);
+ }
+ dbSession.commit();
+
+ } finally {
+ dbSession.close();
+ }
+ }
+
+ private void readParameters(SMInputCursor propsCursor, Map<String, String> parameters) throws XMLStreamException {
+ while (propsCursor.getNext() != null) {
+ SMInputCursor propCursor = propsCursor.childElementCursor();
+ String key = null;
+ String value = null;
+ while (propCursor.getNext() != null) {
+ String nodeName = propCursor.getLocalName();
+ if (StringUtils.equals("key", nodeName)) {
+ key = StringUtils.trim(propCursor.collectDescendantText(false));
+
+ } else if (StringUtils.equals("value", nodeName)) {
+ value = StringUtils.trim(propCursor.collectDescendantText(false));
+ }
+ }
+ if (key != null) {
+ parameters.put(key, value);
+ }
+ }
+ }
+
+ private SMInputFactory initStax() {
+ XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
+ xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
+ xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);
+ // just so it won't try to load DTD in if there's DOCTYPE
+ xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
+ xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
+ return new SMInputFactory(xmlFactory);
+ }
+
+ public void resetForLang(String language) {
+ // TODO
+ }
+}
import com.google.common.collect.Multimap;
import org.sonar.api.ServerComponent;
import org.sonar.api.rule.RuleKey;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.qualityprofile.db.ActiveRuleKey;
import org.sonar.core.qualityprofile.db.QualityProfileKey;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.rule.index.RuleQuery;
import org.sonar.server.search.IndexClient;
+import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
import java.util.List;
public class QProfileService implements ServerComponent {
private final IndexClient index;
private final RuleActivator ruleActivator;
+ private final QProfileBackuper backuper;
- public QProfileService(IndexClient index, RuleActivator ruleActivator) {
+ public QProfileService(IndexClient index, RuleActivator ruleActivator, QProfileBackuper backuper) {
this.index = index;
this.ruleActivator = ruleActivator;
+ this.backuper = backuper;
}
@CheckForNull
* activated.
*/
public List<ActiveRuleChange> activate(RuleActivation activation) {
+ verifyAdminPermission();
return ruleActivator.activate(activation);
}
* fails (fast) if the rule or the profile does not exist.
*/
public List<ActiveRuleChange> deactivate(ActiveRuleKey key) {
+ verifyAdminPermission();
return ruleActivator.deactivate(key);
}
public Multimap<String, String> bulkActivate(RuleQuery ruleQuery, QualityProfileKey profile) {
+ verifyAdminPermission();
return ruleActivator.bulkActivate(ruleQuery, profile);
}
public Multimap<String, String> bulkDeactivate(RuleQuery ruleQuery, QualityProfileKey profile) {
+ verifyAdminPermission();
return ruleActivator.bulkDeactivate(ruleQuery, profile);
}
+
+ public void backup(QualityProfileKey key, Writer writer) {
+ // Allowed to non-admin users (see http://jira.codehaus.org/browse/SONAR-2039)
+ backuper.backup(key, writer);
+ }
+
+ /**
+ * @deprecated used only by Ruby on Rails. Use {@link #backup(org.sonar.core.qualityprofile.db.QualityProfileKey, java.io.Writer)}
+ */
+ @Deprecated
+ public String backup(QualityProfileKey key) {
+ StringWriter output = new StringWriter();
+ backup(key, output);
+ return output.toString();
+ }
+
+ public void restore(Reader backup) {
+ verifyAdminPermission();
+ backuper.restore(backup);
+ }
+
+ /**
+ * @deprecated used only by Ruby on Rails. Use {@link #restore(java.io.Reader)}
+ */
+ @Deprecated
+ public void restore(String backup) {
+ restore(new StringReader(backup));
+ }
+
+ public void resetForLang(String lang) {
+ // TODO
+ verifyAdminPermission();
+ }
+
+ public void copy(QualityProfileKey key, String newName) {
+ // TODO
+ verifyAdminPermission();
+ }
+
+ public void delete(QualityProfileKey key) {
+ // TODO
+ verifyAdminPermission();
+ }
+
+ public void rename(QualityProfileKey key, String newName) {
+ // TODO
+ verifyAdminPermission();
+ }
+
+ //public void create(NewQualityProfile newProfile) {
+ // TODO
+ //verifyAdminPermission();
+ //}
+
+ public void setParent(QualityProfileKey key, @Nullable QualityProfileKey parent) {
+ // TODO
+ verifyAdminPermission();
+ }
+
+ /**
+ * Set the given quality profile as default for the related language
+ */
+ public void setDefault(QualityProfileKey key) {
+ // TODO
+ verifyAdminPermission();
+ }
+
+ private void verifyAdminPermission() {
+ UserSession.get().checkLoggedIn();
+ UserSession.get().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ }
}
package org.sonar.server.qualityprofile;
import com.google.common.collect.Maps;
+import org.apache.commons.lang.StringUtils;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
import org.sonar.core.qualityprofile.db.QualityProfileDto;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import java.util.Collection;
-import java.util.HashMap;
import java.util.Map;
class RuleActivationContext {
return this;
}
- @CheckForNull
- ActiveRuleDto parentActiveRule() {
- return parentActiveRule;
- }
-
RuleActivationContext setParentActiveRule(@Nullable ActiveRuleDto a) {
this.parentActiveRule = a;
return this;
return activeRuleParams;
}
- @CheckForNull
Map<String, String> parentActiveRuleParamsAsStringMap() {
- Map<String, String> params = new HashMap<String, String>();
+ Map<String, String> params = Maps.newHashMap();
for (Map.Entry<String, ActiveRuleParamDto> param : parentActiveRuleParams.entrySet()) {
params.put(param.getKey(), param.getValue().getValue());
}
}
return ruleParam.getDefaultValue();
}
+
+ /**
+ * True if trying to override an inherited rule but with exactly the same values
+ */
+ boolean isSameAsParent(RuleActivation activation) {
+ if (parentActiveRule == null) {
+ return false;
+ }
+ if (activation.isReset()) {
+ return true;
+ }
+ if (StringUtils.equals(activation.getSeverity(), parentActiveRule.getSeverityString())) {
+ return Maps.difference(activation.getParameters(), parentActiveRuleParamsAsStringMap()).areEqual();
+ }
+ return false;
+ }
}
import org.sonar.core.qualityprofile.db.QualityProfileKey;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.db.DbClient;
+import org.sonar.server.rule.Rule;
import java.util.Collection;
throw new IllegalArgumentException("Rule was removed: " + ruleKey);
}
if (Cardinality.MULTIPLE.equals(rule.getCardinality())) {
- throw new IllegalArgumentException("A rule template can't be activated on a Quality profile: " + ruleKey);
+ throw new IllegalArgumentException("Rule template can't be activated on a Quality profile: " + ruleKey);
+ }
+ if (Rule.MANUAL_REPOSITORY_KEY.equals(rule.getRepositoryKey())) {
+ throw new IllegalArgumentException("Manual rule can't be activated on a Quality profile: " + ruleKey);
}
context.setRule(rule);
context.setRuleParams(db.ruleDao().findRuleParamsByRuleKey(dbSession, rule.getKey()));
import org.apache.commons.lang.StringUtils;
import org.sonar.api.ServerComponent;
import org.sonar.api.server.rule.RuleParamType;
-import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.preview.PreviewCache;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.server.qualityprofile.db.ActiveRuleDao;
import org.sonar.server.rule.Rule;
import org.sonar.server.rule.index.RuleIndex;
-import org.sonar.server.rule.index.RuleNormalizer;
import org.sonar.server.rule.index.RuleQuery;
import org.sonar.server.rule.index.RuleResult;
import org.sonar.server.search.IndexClient;
import org.sonar.server.search.QueryOptions;
-import org.sonar.server.user.UserSession;
import org.sonar.server.util.TypeValidations;
import javax.annotation.Nullable;
* Activate a rule on a Quality profile. Update configuration (severity/parameters) if the rule is already
* activated.
*/
- public List<ActiveRuleChange> activate(RuleActivation activation) {
- verifyPermission(UserSession.get());
+ List<ActiveRuleChange> activate(RuleActivation activation) {
DbSession dbSession = db.openSession(false);
try {
List<ActiveRuleChange> changes = activate(dbSession, activation);
}
/**
- * Activate the rule WITHOUT committing db session and WITHOUT checking permissions
+ * Activate the rule WITHOUT committing db session
*/
List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation) {
change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, activation.getKey());
//Rules crated by default Inheritance
- if (activation.isCascade()) {
+ if (activation.isCascade() || context.isSameAsParent(activation)) {
change.setInheritance(ActiveRule.Inheritance.INHERITED);
}
} else {
//Updates on rule that exists with a valid parent switch them to OVERRIDE
if (!activation.isCascade() && context.parentProfile() != null) {
- change.setInheritance(activation.isReset() ? ActiveRule.Inheritance.INHERITED : ActiveRule.Inheritance.OVERRIDES);
+ change.setInheritance(context.isSameAsParent(activation) ? ActiveRule.Inheritance.INHERITED : ActiveRule.Inheritance.OVERRIDES);
}
}
* Deactivate a rule on a Quality profile. Does nothing if the rule is not activated, but
* fails (fast) if the rule or the profile does not exist.
*/
- public List<ActiveRuleChange> deactivate(ActiveRuleKey key) {
- verifyPermission(UserSession.get());
+ List<ActiveRuleChange> deactivate(ActiveRuleKey key) {
DbSession dbSession = db.openSession(false);
List<ActiveRuleChange> changes = Lists.newArrayList();
try {
/**
* Deactivate a rule on a Quality profile WITHOUT committing db session and WITHOUT checking permissions
*/
- public List<ActiveRuleChange> deactivate(ActiveRuleKey key, DbSession dbSession) {
+ List<ActiveRuleChange> deactivate(ActiveRuleKey key, DbSession dbSession) {
return cascadeDeactivation(key, dbSession, false);
}
private List<ActiveRuleChange> cascadeDeactivation(ActiveRuleKey key, DbSession dbSession, boolean isCascade) {
List<ActiveRuleChange> changes = Lists.newArrayList();
RuleActivationContext context = contextFactory.create(key, dbSession);
- ActiveRuleChange change = null;
+ ActiveRuleChange change;
if (context.activeRule() == null) {
return changes;
- } else if (!isCascade && (context.activeRule().isInherited() ||
+ }
+ if (!isCascade && (context.activeRule().isInherited() ||
context.activeRule().doesOverride())) {
throw new IllegalStateException("Cannot deactivate inherited rule '" + key.ruleKey() + "'");
}
}
- private void verifyPermission(UserSession userSession) {
- userSession.checkLoggedIn();
- userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
- }
-
private void verifyParam(RuleParamDto ruleParam, @Nullable String value) {
if (value != null) {
RuleParamType ruleParamType = RuleParamType.parse(ruleParam.getType());
}
}
- public Multimap<String, String> bulkActivate(RuleQuery ruleQuery, QualityProfileKey profile) {
- return bulkActivate(ruleQuery, profile, null);
- }
-
- public Multimap<String, String> bulkActivate(RuleQuery ruleQuery, QualityProfileKey profile, @Nullable String severity) {
- verifyPermission(UserSession.get());
+ Multimap<String, String> bulkActivate(RuleQuery ruleQuery, QualityProfileKey profile) {
RuleIndex ruleIndex = index.get(RuleIndex.class);
Multimap<String, String> results = ArrayListMultimap.create();
DbSession dbSession = db.openSession(false);
return results;
}
- public Multimap<String, String> bulkDeactivate(RuleQuery ruleQuery, QualityProfileKey profile) {
- verifyPermission(UserSession.get());
+ Multimap<String, String> bulkDeactivate(RuleQuery ruleQuery, QualityProfileKey profile) {
RuleIndex ruleIndex = index.get(RuleIndex.class);
Multimap<String, String> results = ArrayListMultimap.create();
DbSession dbSession = db.openSession(false);
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.qualityprofile.db.QualityProfileKey;
import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.rule.RuleService;
import org.sonar.server.rule.ws.SearchAction;
writeResponse(results, response);
}
- private void writeResponse(Multimap<String, String> results, Response response){
+ private void writeResponse(Multimap<String, String> results, Response response) {
JsonWriter json = response.newJsonWriter().beginObject();
- for(String action:results.keySet()){
+ for (String action : results.keySet()) {
json.name(action).beginArray();
- for(String key:results.get(action)){
+ for (String key : results.get(action)) {
json.beginObject()
- .prop("key",key)
+ .prop("key", key)
.endObject();
}
json.endArray();
action.createParam("name")
.setDescription("Profile name. If not set, the default profile for the selected language is used")
.setExampleValue("Sonar way");
- RailsHandler.addFormatParam(action);
}
private void defineRestoreAction(NewController controller) {
action.createParam("backup")
.setRequired(true)
.setDescription("Path to the file containing the backup (HTML format)");
- RailsHandler.addJsonOnlyFormatParam(action);
}
private void defineDestroyAction(NewController controller) {
import org.sonar.core.technicaldebt.db.CharacteristicDao;
import org.sonar.core.technicaldebt.db.CharacteristicDto;
import org.sonar.server.db.DbClient;
-import org.sonar.server.qualityprofile.ProfilesManager;
+import org.sonar.server.qualityprofile.ActiveRule;
+import org.sonar.server.qualityprofile.QProfileService;
import org.sonar.server.search.IndexDefinition;
import org.sonar.server.search.action.EmbeddedIndexAction;
import org.sonar.server.search.action.IndexAction;
private static final Logger LOG = LoggerFactory.getLogger(RegisterRules.class);
private final RuleDefinitionsLoader defLoader;
- private final ProfilesManager profilesManager;
+ private final QProfileService profileService;
private final DbClient dbClient;
private final CharacteristicDao characteristicDao;
- public RegisterRules(RuleDefinitionsLoader defLoader, ProfilesManager profilesManager,
+ public RegisterRules(RuleDefinitionsLoader defLoader, QProfileService profileService,
DbClient dbClient) {
- this(defLoader, profilesManager, dbClient, System2.INSTANCE);
+ this(defLoader, profileService, dbClient, System2.INSTANCE);
}
@VisibleForTesting
- RegisterRules(RuleDefinitionsLoader defLoader, ProfilesManager profilesManager,
+ RegisterRules(RuleDefinitionsLoader defLoader, QProfileService profileService,
DbClient dbClient, System2 system) {
this.defLoader = defLoader;
- this.profilesManager = profilesManager;
+ this.profileService = profileService;
this.dbClient = dbClient;
this.characteristicDao = dbClient.debtCharacteristicDao();
}
for (RuleDto rule : removedRules) {
// SONAR-4642 Remove active rules only when repository still exists
if (repositoryKeys.contains(rule.getRepositoryKey())) {
- profilesManager.removeActivatedRules(rule.getId());
+ List<ActiveRule> activeRules = profileService.findActiveRulesByRule(rule.getKey());
+ for (ActiveRule activeRule : activeRules) {
+ profileService.deactivate(activeRule.key());
+ }
}
}
}
else
profile = Internal.quality_profiles.profile(params[:name], params[:language])
end
- not_found('Profile not found') unless profile
- backup = Internal.profile_backup.backupProfile(profile)
+
+ profile_key=Java::OrgSonarCoreQualityprofileDb::QualityProfileKey.of(profile.name, profile.language)
+ backup = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).backup(profile_key)
+
respond_to do |format|
format.xml { render :xml => backup }
format.json { render :json => jsonp({:backup => backup}) }
verify_post_request
require_parameters :backup
- result = Internal.profile_backup.restore(Api::Utils.read_post_request_param(params[:backup]), true)
+ backup = Api::Utils.read_post_request_param(params[:backup])
+ Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).restore(backup)
respond_to do |format|
- format.json { render :json => jsonp(validation_result_to_json(result)), :status => 200 }
+ #TODO format.json { render :json => jsonp(validation_result_to_json(result)), :status => 200 }
+ format.json { render :json => jsonp({}), :status => 200 }
end
end
verify_post_request
require_parameters 'id'
- profile = Internal.quality_profiles.profile(params[:id].to_i)
- not_found('Profile not found') unless profile
- xml = Internal.profile_backup.backupProfile(profile)
- filename = profile.name().gsub(' ', '_')
- send_data(xml, :type => 'text/xml', :disposition => "attachment; filename=#{filename}_#{profile.language()}.xml")
+ profile_key=profile_id_to_key(params[:id].to_i)
+
+ xml = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).backup(profile_key)
+ filename = profile_key.toString().gsub(' ', '_')
+ send_data(xml, :type => 'text/xml', :disposition => "attachment; filename=#{filename}.xml")
end
flash[:warning] = message('quality_profiles.please_upload_backup_file')
else
call_backend do
- result = Internal.profile_backup.restore(Api::Utils.read_post_request_param(params[:backup]), false)
- flash_result(result)
+ xml=Api::Utils.read_post_request_param(params[:backup])
+ Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).restore(xml)
+ #flash_result(result)
end
end
redirect_to :action => 'index'
def set_profile_breadcrumbs
add_breadcrumbs ProfilesController::root_breadcrumb, Api::Utils.language_name(@profile.language), {:name => @profile.name, :url => {:controller => 'rules_configuration', :action => 'index', :id => @profile.id}}
end
+
+ def profile_id_to_key(profile_id)
+ profile = Profile.find(profile_id)
+ not_found('Profile not found') unless profile
+ Java::OrgSonarCoreQualityprofileDb::QualityProfileKey.of(profile.name, profile.language)
+ end
end
component(Java::OrgSonarServerUi::JRubyI18n.java_class)
end
- private
-
def self.component(component_java_class)
Java::OrgSonarServerPlatform::Platform.component(component_java_class)
end
package org.sonar.server.qualityprofile;
import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rules.ActiveRule;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RulePriority;
import org.sonar.core.preview.PreviewCache;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
-import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
public class ProfilesManagerTest extends AbstractDbUnitTestCase {
manager = new ProfilesManager(getSession(), null, mock(PreviewCache.class));
}
- @Test
- public void remove_activated_rules() {
- Rule rule1 = Rule.create("repo", "key");
-
- RulesProfile profile1 = RulesProfile.create("profile1", "xoo");
- ActiveRule activeRule1 = new ActiveRule(profile1, rule1, RulePriority.BLOCKER);
-
- RulesProfile profile2 = RulesProfile.create("profile2", "foo");
- ActiveRule activeRule2 = new ActiveRule(profile2, rule1, RulePriority.BLOCKER);
-
- getSession().save(profile1, rule1, activeRule1, profile2, activeRule2);
-
- manager.removeActivatedRules(rule1.getId());
-
- assertThat(getHQLCount(ActiveRule.class)).isEqualTo(0);
- }
-
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.database.DatabaseSession;
import org.sonar.api.profiles.ProfileDefinition;
import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.profiles.XMLProfileParser;
-import org.sonar.api.profiles.XMLProfileSerializer;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.qualityprofile.db.QualityProfileKey;
import org.sonar.core.rule.RuleDto;
-import org.sonar.jpa.session.DatabaseSessionFactory;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.user.UserSession;
-import java.io.Reader;
-import java.io.Writer;
import java.util.Collection;
import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class QProfileBackupTest {
- @Mock
- DatabaseSessionFactory sessionFactory;
-
- @Mock
- DatabaseSession hibernateSession;
-
@Mock
MyBatis myBatis;
@Mock
DbSession session;
- @Mock
- XMLProfileParser xmlProfileParser;
-
- @Mock
- XMLProfileSerializer xmlProfileSerializer;
-
- @Mock
- QProfileLookup qProfileLookup;
-
@Mock
QProfileOperations qProfileOperations;
@Before
public void setUp() throws Exception {
when(myBatis.openSession(false)).thenReturn(session);
- when(sessionFactory.getSession()).thenReturn(hibernateSession);
definitions = newArrayList();
- backup = new QProfileBackup(sessionFactory, xmlProfileParser, xmlProfileSerializer, myBatis, qProfileLookup, qProfileOperations, qProfileActiveRuleOperations, ruleDao,
+ backup = new QProfileBackup(myBatis, qProfileOperations, qProfileActiveRuleOperations, ruleDao,
definitions, defaultProfilesCache, dryRunCache);
MockUserSession.set().setLogin("nicolas").setName("Nicolas").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
}
- @Test
- public void backup() throws Exception {
- RulesProfile profile = mock(RulesProfile.class);
- when(profile.getId()).thenReturn(1);
- when(hibernateSession.getSingleResult(any(Class.class), eq("id"), eq(1))).thenReturn(profile);
-
- backup.backupProfile(new QProfile().setId(1));
-
- verify(xmlProfileSerializer).write(eq(profile), any(Writer.class));
- }
-
- @Test
- public void restore() throws Exception {
- RulesProfile profile = mock(RulesProfile.class);
- when(profile.getName()).thenReturn("Default");
- when(profile.getLanguage()).thenReturn("java");
- when(profile.getId()).thenReturn(1);
- when(xmlProfileParser.parse(any(Reader.class), any(ValidationMessages.class))).thenReturn(profile);
- when(hibernateSession.getSingleResult(any(Class.class), eq("name"), eq("Default"), eq("language"), eq("java"))).thenReturn(null);
- when(qProfileLookup.profile(anyInt(), eq(session))).thenReturn(new QProfile().setId(1));
-
- QProfileResult result = backup.restore("<xml/>", false);
-
- assertThat(result.profile()).isNotNull();
- verify(hibernateSession).saveWithoutFlush(profile);
- verify(dryRunCache).reportGlobalModification(session);
- verify(session).commit();
- }
-
- @Test
- public void fail_to_restore_without_profile_admin_permission() throws Exception {
- try {
- MockUserSession.set().setLogin("nicolas").setName("Nicolas");
- backup.restore("<xml/>", false);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(ForbiddenException.class);
- }
- verify(hibernateSession, never()).saveWithoutFlush(any(RulesProfile.class));
- verifyZeroInteractions(dryRunCache);
- }
-
- @Test
- public void fail_to_restore_if_profile_already_exist() throws Exception {
- RulesProfile profile = mock(RulesProfile.class);
- when(profile.getName()).thenReturn("Default");
- when(profile.getLanguage()).thenReturn("java");
- when(xmlProfileParser.parse(any(Reader.class), any(ValidationMessages.class))).thenReturn(profile);
- when(hibernateSession.getSingleResult(any(Class.class), eq("name"), eq("Default"), eq("language"), eq("java"))).thenReturn(RulesProfile.create("Default", "java"));
- when(qProfileLookup.profile(anyInt())).thenReturn(new QProfile().setId(1));
-
- try {
- backup.restore("<xml/>", false);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("The profile [name=Default,language=java] already exists. Please delete it before restoring.");
- }
-
- verify(hibernateSession, never()).saveWithoutFlush(any(RulesProfile.class));
- verifyZeroInteractions(dryRunCache);
- }
-
- @Test
- public void restore_should_delete_existing_profile() throws Exception {
- RulesProfile profile = mock(RulesProfile.class);
- when(profile.getName()).thenReturn("Default");
- when(profile.getLanguage()).thenReturn("java");
- when(profile.getId()).thenReturn(1);
- when(xmlProfileParser.parse(any(Reader.class), any(ValidationMessages.class))).thenReturn(profile);
-
- RulesProfile existingProfile = mock(RulesProfile.class);
- when(existingProfile.getId()).thenReturn(1);
- when(hibernateSession.getSingleResult(any(Class.class), eq("name"), eq("Default"), eq("language"), eq("java"))).thenReturn(existingProfile);
- when(qProfileLookup.profile(anyInt(), eq(session))).thenReturn(new QProfile().setId(1));
-
- QProfileResult result = backup.restore("<xml/>", true);
-
- assertThat(result.profile()).isNotNull();
- verify(hibernateSession).removeWithoutFlush(eq(existingProfile));
- verify(dryRunCache).reportGlobalModification(session);
- verify(session).commit();
- }
-
- @Test
- public void restore_should_add_warnings_and_infos_from_xml_parsing() throws Exception {
- final RulesProfile profile = mock(RulesProfile.class);
- when(profile.getName()).thenReturn("Default");
- when(profile.getLanguage()).thenReturn("java");
- when(profile.getId()).thenReturn(1);
- doAnswer(new Answer() {
- public Object answer(InvocationOnMock invocation) {
- Object[] args = invocation.getArguments();
- ValidationMessages validationMessages = (ValidationMessages) args[1];
- validationMessages.addInfoText("an info message");
- validationMessages.addWarningText("a warning message");
- return profile;
- }
- }).when(xmlProfileParser).parse(any(Reader.class), any(ValidationMessages.class));
-
- when(hibernateSession.getSingleResult(any(Class.class), eq("name"), eq("Default"), eq("language"), eq("java"))).thenReturn(null);
- when(qProfileLookup.profile(anyInt(), eq(session))).thenReturn(new QProfile().setId(1));
-
- QProfileResult result = backup.restore("<xml/>", true);
-
- assertThat(result.profile()).isNotNull();
- assertThat(result.warnings()).isNotEmpty();
- assertThat(result.infos()).isNotEmpty();
- }
-
- @Test
- public void restore_should_fail_if_errors_when_parsing_xml() throws Exception {
- final RulesProfile profile = mock(RulesProfile.class);
- when(profile.getName()).thenReturn("Default");
- when(profile.getLanguage()).thenReturn("java");
- when(profile.getId()).thenReturn(1);
- doAnswer(new Answer() {
- public Object answer(InvocationOnMock invocation) {
- Object[] args = invocation.getArguments();
- ValidationMessages validationMessages = (ValidationMessages) args[1];
- validationMessages.addErrorText("error!");
- return profile;
- }
- }).when(xmlProfileParser).parse(any(Reader.class), any(ValidationMessages.class));
-
- when(hibernateSession.getSingleResult(any(Class.class), eq("name"), eq("Default"), eq("language"), eq("java"))).thenReturn(null);
- when(qProfileLookup.profile(anyInt(), eq(session))).thenReturn(new QProfile().setId(1));
-
- try {
- backup.restore("<xml/>", false);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Fail to restore profile");
- BadRequestException badRequestException = (BadRequestException) e;
- assertThat(badRequestException.errors()).hasSize(1);
- assertThat(badRequestException.errors().get(0).text()).isEqualTo("error!");
- }
-
- verify(hibernateSession, never()).saveWithoutFlush(any(RulesProfile.class));
- verifyZeroInteractions(dryRunCache);
- }
-
- @Test
- public void do_not_restore_if_xml_is_empty() throws Exception {
- when(xmlProfileParser.parse(any(Reader.class), any(ValidationMessages.class))).thenReturn(null);
- when(hibernateSession.getSingleResult(any(Class.class), eq("name"), eq("Default"), eq("language"), eq("java"))).thenReturn(null);
- when(qProfileLookup.profile(anyInt(), eq(session))).thenReturn(new QProfile().setId(1));
-
- QProfileResult result = backup.restore("<xml/>", false);
-
- assertThat(result.profile()).isNull();
- verify(hibernateSession, never()).saveWithoutFlush(any(RulesProfile.class));
- verifyZeroInteractions(dryRunCache);
- }
-
- @Test
- public void do_not_restore_if_new_profile_is_null_after_import() throws Exception {
- RulesProfile profile = mock(RulesProfile.class);
- when(profile.getName()).thenReturn("Default");
- when(profile.getLanguage()).thenReturn("java");
- when(profile.getId()).thenReturn(1);
- when(xmlProfileParser.parse(any(Reader.class), any(ValidationMessages.class))).thenReturn(profile);
-
- when(hibernateSession.getSingleResult(any(Class.class), eq("name"), eq("Default"), eq("language"), eq("java"))).thenReturn(null);
- when(qProfileLookup.profile(anyInt(), eq(session))).thenReturn(null);
-
- try {
- backup.restore("<xml/>", false);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Restore of the profile has failed.");
- }
-
- verifyZeroInteractions(dryRunCache);
- }
-
@Test
public void recreate_built_in_profiles_from_language() throws Exception {
String name = "Default";
--- /dev/null
+/*
+ * 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.server.qualityprofile;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.Resources;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.server.rule.RuleParamType;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleKey;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.qualityprofile.db.QualityProfileKey;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.rule.RuleParamDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.tester.ServerTester;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class QProfileBackuperMediumTest {
+
+ static final QualityProfileKey XOO_PROFILE_KEY = QualityProfileKey.of("P1", "xoo");
+ static final QualityProfileKey XOO_CHILD_PROFILE_KEY = QualityProfileKey.of("P2", "xoo");
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester();
+
+ DbClient db;
+ DbSession dbSession;
+
+ @Before
+ public void before() {
+ tester.clearDbAndIndexes();
+ db = tester.get(DbClient.class);
+ dbSession = db.openSession(false);
+
+ // create pre-defined rules
+ RuleDto xooRule1 = RuleTesting.newDto(RuleKey.of("xoo", "x1"))
+ .setSeverity("MINOR").setLanguage("xoo");
+ RuleDto xooRule2 = RuleTesting.newDto(RuleKey.of("xoo", "x2"))
+ .setSeverity("MAJOR").setLanguage("xoo");
+ db.ruleDao().insert(dbSession, xooRule1, xooRule2);
+ db.ruleDao().addRuleParam(dbSession, xooRule1, RuleParamDto.createFor(xooRule1)
+ .setName("max").setDefaultValue("10").setType(RuleParamType.INTEGER.type()));
+ dbSession.commit();
+ dbSession.clearCache();
+ }
+
+ @After
+ public void after() throws Exception {
+ dbSession.close();
+ }
+
+ @Test
+ public void backup() throws Exception {
+ // create profile with rule x1 activated
+ db.qualityProfileDao().insert(dbSession, QualityProfileDto.createFor(XOO_PROFILE_KEY));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation.setSeverity(Severity.BLOCKER);
+ activation.setParameter("max", "7");
+ tester.get(RuleActivator.class).activate(dbSession, activation);
+ dbSession.commit();
+ dbSession.clearCache();
+
+ StringWriter output = new StringWriter();
+ tester.get(QProfileBackuper.class).backup(XOO_PROFILE_KEY, output);
+
+ XMLUnit.setIgnoreWhitespace(true);
+ Diff diff = XMLUnit.compareXML(output.toString(),
+ Resources.toString(getClass().getResource("QProfileBackuperMediumTest/expected-backup.xml"), Charsets.UTF_8));
+
+ assertThat(diff.identical()).as(diff.toString()).isTrue();
+ }
+
+ @Test
+ public void fail_to_backup_unknown_profile() throws Exception {
+ try {
+ tester.get(QProfileBackuper.class).backup(QualityProfileKey.of("unknown", "xoo"), new StringWriter());
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Quality profile does not exist: unknown:xoo");
+ }
+ }
+
+ @Test
+ public void restore_and_create_profile() throws Exception {
+ tester.get(QProfileBackuper.class).restore(new StringReader(
+ Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore.xml"), Charsets.UTF_8)));
+
+ List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(XOO_PROFILE_KEY);
+ assertThat(activeRules).hasSize(1);
+ assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
+ assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
+ assertThat(activeRules.get(0).params().get("max")).isEqualTo("7");
+ }
+
+ @Test
+ public void restore_and_update_profile() throws Exception {
+ // create profile with rules x1 and x2 activated
+ db.qualityProfileDao().insert(dbSession, QualityProfileDto.createFor(XOO_PROFILE_KEY));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation.setSeverity(Severity.INFO);
+ activation.setParameter("max", "10");
+ tester.get(RuleActivator.class).activate(dbSession, activation);
+
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x2")));
+ activation.setSeverity(Severity.INFO);
+ tester.get(RuleActivator.class).activate(dbSession, activation);
+ dbSession.commit();
+ dbSession.clearCache();
+
+ // restore backup, which activates only x1
+ // -> update x1 and deactivate x2
+ tester.get(QProfileBackuper.class).restore(new StringReader(
+ Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore.xml"), Charsets.UTF_8)));
+
+
+ List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(XOO_PROFILE_KEY);
+ assertThat(activeRules).hasSize(1);
+ assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
+ assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
+ assertThat(activeRules.get(0).params().get("max")).isEqualTo("7");
+ }
+
+ @Test
+ public void restore_child_profile() throws Exception {
+ // define two parent/child profiles
+ db.qualityProfileDao().insert(dbSession,
+ QualityProfileDto.createFor(XOO_PROFILE_KEY),
+ QualityProfileDto.createFor(XOO_CHILD_PROFILE_KEY).setParent(XOO_PROFILE_KEY.name()));
+ dbSession.commit();
+
+ // rule x1 is activated on parent profile (so inherited by child profile)
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation.setSeverity(Severity.INFO);
+ activation.setParameter("max", "10");
+ tester.get(RuleActivator.class).activate(dbSession, activation);
+ dbSession.commit();
+ dbSession.clearCache();
+
+ // restore backup of child profile -> overrides x1
+ tester.get(QProfileBackuper.class).restore(new StringReader(
+ Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore-child.xml"), Charsets.UTF_8)));
+
+ // parent profile is unchanged
+ List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(XOO_PROFILE_KEY);
+ assertThat(activeRules).hasSize(1);
+ assertThat(activeRules.get(0).severity()).isEqualTo("INFO");
+ assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
+ assertThat(activeRules.get(0).params().get("max")).isEqualTo("10");
+
+ // child profile overrides parent
+ activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(XOO_CHILD_PROFILE_KEY);
+ assertThat(activeRules).hasSize(1);
+ assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
+ assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.OVERRIDES);
+ assertThat(activeRules.get(0).params().get("max")).isEqualTo("7");
+ }
+
+ @Test
+ public void restore_parent_profile() throws Exception {
+ // define two parent/child profiles
+ db.qualityProfileDao().insert(dbSession,
+ QualityProfileDto.createFor(XOO_PROFILE_KEY),
+ QualityProfileDto.createFor(XOO_CHILD_PROFILE_KEY).setParent(XOO_PROFILE_KEY.name()));
+ dbSession.commit();
+
+ // rule x1 is activated on parent profile (so inherited by child profile)
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation.setSeverity(Severity.INFO);
+ activation.setParameter("max", "10");
+ tester.get(RuleActivator.class).activate(dbSession, activation);
+ dbSession.commit();
+ dbSession.clearCache();
+
+ // restore backup of parent profile -> update x1 and propagates to child
+ tester.get(QProfileBackuper.class).restore(new StringReader(
+ Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore-parent.xml"), Charsets.UTF_8)));
+
+ // parent profile is updated
+ List<ActiveRule> activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(XOO_PROFILE_KEY);
+ assertThat(activeRules).hasSize(1);
+ assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
+ assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
+ assertThat(activeRules.get(0).params().get("max")).isEqualTo("7");
+
+ // child profile is inherited
+ activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(XOO_CHILD_PROFILE_KEY);
+ assertThat(activeRules).hasSize(1);
+ assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER");
+ assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.INHERITED);
+ assertThat(activeRules.get(0).params().get("max")).isEqualTo("7");
+ }
+
+ @Test
+ public void restore_fails_to_deactivate_inherited_rule() throws Exception {
+ // define two parent/child profiles
+ db.qualityProfileDao().insert(dbSession,
+ QualityProfileDto.createFor(XOO_PROFILE_KEY),
+ QualityProfileDto.createFor(XOO_CHILD_PROFILE_KEY).setParent(XOO_PROFILE_KEY.name()));
+ dbSession.commit();
+
+ // rule x1 is activated on parent profile (so inherited by child profile)
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation.setSeverity(Severity.INFO);
+ activation.setParameter("max", "10");
+ tester.get(RuleActivator.class).activate(dbSession, activation);
+ dbSession.commit();
+ dbSession.clearCache();
+
+ // backup of child profile does not contain x1
+ try {
+ tester.get(QProfileBackuper.class).restore(new StringReader(
+ Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore_fails_to_deactivate_inherited_rule.xml"), Charsets.UTF_8)));
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e).hasMessage("Cannot deactivate inherited rule 'xoo:x1'");
+ }
+ }
+
+ @Test
+ public void fail_to_restore_if_not_xml_backup() throws Exception {
+ try {
+ tester.get(QProfileBackuper.class).restore(new StringReader(
+ Resources.toString(getClass().getResource("QProfileBackuperMediumTest/not-xml-backup.txt"), Charsets.UTF_8)));
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e).hasMessage("Fail to restore Quality profile backup");
+ assertThat(e.getCause()).isInstanceOf(XMLStreamException.class);
+ }
+ }
+}
import org.junit.ClassRule;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
import org.sonar.api.server.rule.RuleParamType;
import org.sonar.check.Cardinality;
-import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.qualityprofile.db.ActiveRuleKey;
import org.sonar.core.rule.RuleParamDto;
import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
+import org.sonar.server.rule.Rule;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.tester.ServerTester;
-import org.sonar.server.user.MockUserSession;
import javax.annotation.Nullable;
import java.util.List;
static final QualityProfileKey XOO_PROFILE_KEY = QualityProfileKey.of("P1", "xoo");
static final QualityProfileKey XOO_CHILD_PROFILE_KEY = QualityProfileKey.of("P2", "xoo");
static final QualityProfileKey XOO_GRAND_CHILD_PROFILE_KEY = QualityProfileKey.of("P3", "xoo");
+ static final RuleKey MANUAL_RULE_KEY = RuleKey.of(Rule.MANUAL_REPOSITORY_KEY, "m1");
+ static final RuleKey XOO_RULE_1 = RuleKey.of("xoo", "x1");
@ClassRule
public static ServerTester tester = new ServerTester();
// create pre-defined rules
RuleDto javaRule = RuleTesting.newDto(RuleKey.of("squid", "j1"))
.setSeverity("MAJOR").setLanguage("java");
- RuleDto xooRule1 = RuleTesting.newDto(RuleKey.of("xoo", "x1"))
+ RuleDto xooRule1 = RuleTesting.newDto(XOO_RULE_1)
.setSeverity("MINOR").setLanguage("xoo");
RuleDto xooTemplateRule1 = RuleTesting.newDto(RuleKey.of("xoo", "template1"))
.setSeverity("MINOR").setLanguage("xoo").setCardinality(Cardinality.MULTIPLE);
- db.ruleDao().insert(dbSession, javaRule, xooRule1, xooTemplateRule1);
+ RuleDto manualRule = RuleTesting.newDto(MANUAL_RULE_KEY);
+ db.ruleDao().insert(dbSession, javaRule, xooRule1, xooTemplateRule1, manualRule);
db.ruleDao().addRuleParam(dbSession, xooRule1, RuleParamDto.createFor(xooRule1)
.setName("max").setDefaultValue("10").setType(RuleParamType.INTEGER.type()));
@Test
public void activate() throws Exception {
- grantPermission();
-
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
@Test
public void activate_with_default_severity_and_parameter() throws Exception {
- grantPermission();
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
+ ruleActivator.activate(activation);
+
+ verifyOneActiveRule(XOO_PROFILE_KEY, Severity.MINOR, null, ImmutableMap.of("max", "10"));
+ }
+
+ @Test
+ public void activation_ignores_unsupported_parameters() throws Exception {
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
+ activation.setParameter("xxx", "yyy");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_PROFILE_KEY, Severity.MINOR, null, ImmutableMap.of("max", "10"));
@Test
public void update_activation_severity_and_parameters() throws Exception {
// initial activation
- grantPermission();
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
ruleActivator.activate(activation);
// update
- RuleActivation update = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation update = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
update.setSeverity(Severity.CRITICAL);
update.setParameter("max", "42");
ruleActivator.activate(update);
@Test
public void update_activation_but_new_parameter() throws Exception {
// initial activation
- grantPermission();
- ActiveRuleKey activeRuleKey = ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1"));
+ ActiveRuleKey activeRuleKey = ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1);
RuleActivation activation = new RuleActivation(activeRuleKey);
activation.setSeverity(Severity.BLOCKER);
ruleActivator.activate(activation);
dbSession.clearCache();
// update
- RuleActivation update = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation update = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
update.setSeverity(Severity.CRITICAL);
update.setParameter("max", "42");
// contrary to activerule, the param 'max' is supposed to be inserted but not updated
@Test
public void revert_activation_to_default_severity_and_parameters() throws Exception {
// initial activation
- grantPermission();
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
// update
- RuleActivation update = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation update = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
ruleActivator.activate(update);
verifyOneActiveRule(XOO_PROFILE_KEY, Severity.MINOR, null, ImmutableMap.of("max", "10"));
}
- @Test
- public void fail_to_activate_if_not_granted() throws Exception {
- MockUserSession.set().setLogin("marius");
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
-
- try {
- ruleActivator.activate(activation);
- fail();
- } catch (ForbiddenException e) {
- verifyZeroActiveRules(XOO_PROFILE_KEY);
- }
- }
-
@Test
public void fail_to_activate_if_template() throws Exception {
- grantPermission();
RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "template1")));
try {
ruleActivator.activate(activation);
fail();
} catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("A rule template can't be activated on a Quality profile: xoo:template1");
+ assertThat(e).hasMessage("Rule template can't be activated on a Quality profile: xoo:template1");
verifyZeroActiveRules(XOO_PROFILE_KEY);
}
}
@Test
public void fail_to_activate_if_different_languages() throws Exception {
// profile and rule have different languages
- grantPermission();
RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("squid", "j1")));
try {
@Test
public void fail_to_activate_if_unknown_rule() throws Exception {
// profile and rule have different languages
- grantPermission();
RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x3")));
try {
}
}
+ @Test
+ public void fail_to_activate_if_rule_with_removed_status() throws Exception {
+ RuleDto ruleDto = db.ruleDao().getByKey(dbSession, XOO_RULE_1);
+ ruleDto.setStatus(RuleStatus.REMOVED);
+ db.ruleDao().update(dbSession, ruleDto);
+ dbSession.commit();
+ dbSession.clearCache();
+
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
+
+ try {
+ ruleActivator.activate(activation);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Rule was removed: xoo:x1");
+ verifyZeroActiveRules(XOO_PROFILE_KEY);
+ }
+ }
+
+ @Test
+ public void fail_to_activate_if_manual_rule() throws Exception {
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, MANUAL_RULE_KEY));
+
+ try {
+ ruleActivator.activate(activation);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Manual rule can't be activated on a Quality profile: manual:m1");
+ verifyZeroActiveRules(XOO_PROFILE_KEY);
+ }
+ }
+
@Test
public void fail_to_activate_if_unknown_profile() throws Exception {
// profile and rule have different languages
- grantPermission();
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(QualityProfileKey.of("other", "js"), RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(QualityProfileKey.of("other", "js"), XOO_RULE_1));
try {
ruleActivator.activate(activation);
@Test
public void fail_to_activate_if_invalid_parameter() throws Exception {
- grantPermission();
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setParameter("max", "foo");
try {
@Test
public void deactivate() throws Exception {
// activation
- grantPermission();
- ActiveRuleKey key = ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1"));
+ ActiveRuleKey key = ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1);
RuleActivation activation = new RuleActivation(key);
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
@Test
public void ignore_deactivation_if_rule_not_activated() throws Exception {
- grantPermission();
-
// deactivation
- ActiveRuleKey key = ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1"));
+ ActiveRuleKey key = ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1);
ruleActivator.deactivate(key);
verifyZeroActiveRules(XOO_PROFILE_KEY);
@Test
public void deactivation_fails_if_rule_not_found() throws Exception {
- grantPermission();
ActiveRuleKey key = ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x3"));
try {
ruleActivator.deactivate(key);
@Test
public void deactivation_fails_if_profile_not_found() throws Exception {
- grantPermission();
- ActiveRuleKey key = ActiveRuleKey.of(QualityProfileKey.of("other", "js"), RuleKey.of("xoo", "x1"));
+ ActiveRuleKey key = ActiveRuleKey.of(QualityProfileKey.of("other", "js"), XOO_RULE_1);
try {
ruleActivator.deactivate(key);
fail();
// INHERITANCE OF PROFILES
@Test
public void activate_on_child_profile() throws Exception {
- grantPermission();
createChildProfiles();
// activate on child profile, but not on root
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
@Test
public void propagate_activation_on_child_profiles() throws Exception {
- grantPermission();
createChildProfiles();
// activate on root profile
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
@Test
public void propagate_activation_update_on_child_profiles() throws Exception {
- grantPermission();
createChildProfiles();
// activate on root profile
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.BLOCKER, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "7"));
// update on parent
- activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.INFO);
activation.setParameter("max", "8");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.INFO, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "8"));
// update on child -> propagate on grand child only
- activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.MINOR);
activation.setParameter("max", "9");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.MINOR, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "9"));
// update on grand child
- activation = new RuleActivation(ActiveRuleKey.of(XOO_GRAND_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_GRAND_CHILD_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "10");
ruleActivator.activate(activation);
@Test
public void do_not_propagate_activation_update_on_child_overrides() throws Exception {
- grantPermission();
createChildProfiles();
// activate on root profile
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.INFO);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.INFO, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "7"));
// override on child
- activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "8");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.BLOCKER, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "8"));
// change on parent -> do not propagate on children because they're overriding values
- activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.CRITICAL);
activation.setParameter("max", "10");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.BLOCKER, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "8"));
}
+ @Test
+ public void do_not_override_on_child_if_same_values() throws Exception {
+ createChildProfiles();
+
+ // activate on root profile
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
+ activation.setSeverity(Severity.INFO);
+ activation.setParameter("max", "7");
+ ruleActivator.activate(activation);
+ verifyOneActiveRule(XOO_PROFILE_KEY, Severity.INFO, null, ImmutableMap.of("max", "7"));
+ verifyOneActiveRule(XOO_CHILD_PROFILE_KEY, Severity.INFO, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "7"));
+
+ // override on child with same severity and params -> do nothing (still INHERITED but not OVERRIDDEN)
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
+ activation.setSeverity(Severity.INFO);
+ activation.setParameter("max", "7");
+ ruleActivator.activate(activation);
+ dbSession.clearCache();
+ verifyOneActiveRule(XOO_PROFILE_KEY, Severity.INFO, null, ImmutableMap.of("max", "7"));
+ verifyOneActiveRule(XOO_CHILD_PROFILE_KEY, Severity.INFO, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "7"));
+ }
+
@Test
public void propagate_deactivation_on_child_profiles() throws Exception {
- grantPermission();
createChildProfiles();
// activate on root profile
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
@Test
public void do_not_deactivate_inherited_or_overridden_rule() throws Exception {
- grantPermission();
createChildProfiles();
// activate on root profile
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
// try to deactivate on child
try {
- ruleActivator.deactivate(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ ruleActivator.deactivate(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
fail();
} catch (IllegalStateException e) {
assertThat(e).hasMessage("Cannot deactivate inherited rule 'xoo:x1'");
@Test
public void reset_activation_on_child_profile() throws Exception {
- grantPermission();
createChildProfiles();
// activate on root profile
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.BLOCKER, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "7"));
// override
- activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.INFO);
activation.setParameter("max", "10");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.INFO, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "10"));
// reset -> remove overridden values
- activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
ruleActivator.activate(activation);
dbSession.clearCache();
verifyOneActiveRule(XOO_PROFILE_KEY, Severity.BLOCKER, null, ImmutableMap.of("max", "7"));
@Test
public void activation_reset_does_not_propagate_to_child_overrides() throws Exception {
- grantPermission();
createChildProfiles();
// activate on root profile
- RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ RuleActivation activation = new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.BLOCKER);
activation.setParameter("max", "7");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.BLOCKER, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "7"));
// override on child
- activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.INFO);
activation.setParameter("max", "10");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.INFO, ActiveRuleDto.INHERITED, ImmutableMap.of("max", "10"));
// override on grand child
- activation = new RuleActivation(ActiveRuleKey.of(XOO_GRAND_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_GRAND_CHILD_PROFILE_KEY, XOO_RULE_1));
activation.setSeverity(Severity.MINOR);
activation.setParameter("max", "20");
ruleActivator.activate(activation);
verifyOneActiveRule(XOO_GRAND_CHILD_PROFILE_KEY, Severity.MINOR, ActiveRuleDto.OVERRIDES, ImmutableMap.of("max", "20"));
// reset child -> keep the overridden grand-child
- activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, RuleKey.of("xoo", "x1")));
+ activation = new RuleActivation(ActiveRuleKey.of(XOO_CHILD_PROFILE_KEY, XOO_RULE_1));
ruleActivator.activate(activation);
dbSession.clearCache();
verifyOneActiveRule(XOO_PROFILE_KEY, Severity.BLOCKER, null, ImmutableMap.of("max", "7"));
dbSession.commit();
}
- private void grantPermission() {
- MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("marius");
- }
-
private void verifyZeroActiveRules(QualityProfileKey key) {
// verify db
dbSession.clearCache();
checkTables("changeParentProfile", new String[]{"change_date"}, "active_rule_changes");
}
- @Test
- public void should_track_remove_activated_rules() {
- setupData("initialData");
- Rule rule = getSession().reattach(Rule.class, 1);
- profilesManager.removeActivatedRules(rule.getId());
- checkTables("removeActivatedRules", new String[]{"change_date"}, "active_rule_changes", "active_rules");
- }
-
}
import org.sonar.core.rule.RuleParamDto;
import org.sonar.core.technicaldebt.db.CharacteristicDao;
import org.sonar.server.db.DbClient;
-import org.sonar.server.qualityprofile.ProfilesManager;
+import org.sonar.server.qualityprofile.QProfileService;
import org.sonar.server.qualityprofile.db.ActiveRuleDao;
import org.sonar.server.rule.db.RuleDao;
static final Date DATE2 = DateUtils.parseDateTime("2014-02-01T12:10:03+0100");
static final Date DATE3 = DateUtils.parseDateTime("2014-03-01T12:10:03+0100");
- ProfilesManager profilesManager = mock(ProfilesManager.class);
+ QProfileService profileService = mock(QProfileService.class);
System2 system;
DbClient dbClient;
DbSession dbSession;
private void execute(RulesDefinition... defs) {
RuleDefinitionsLoader loader = new RuleDefinitionsLoader(mock(RuleRepositories.class), defs);
- RegisterRules task = new RegisterRules(loader, profilesManager, dbClient, system);
+ RegisterRules task = new RegisterRules(loader, profileService, dbClient, system);
task.start();
}
@Test
public void should_not_find_removed() {
// insert db
- RuleKey ruleKey = RuleKey.of("javascript", "S001");
- RuleDto ruleDto = newRuleDto(ruleKey).setStatus(RuleStatus.READY);
-
+ RuleKey readyKey = RuleKey.of("javascript", "S001");
+ RuleDto readyDto = RuleTesting.newDto(readyKey).setStatus(RuleStatus.READY);
RuleKey removedKey = RuleKey.of("javascript", "S002");
- RuleDto removedDto = newRuleDto(removedKey).setStatus(RuleStatus.REMOVED);
- dao.insert(dbSession, ruleDto);
- dao.insert(dbSession, removedDto);
+ RuleDto removedDto = RuleTesting.newDto(removedKey).setStatus(RuleStatus.REMOVED);
+ dao.insert(dbSession, readyDto, removedDto);
dbSession.commit();
// 0. Assert rules are in DB
assertThat(index.getByKey(removedKey)).isNotNull();
// 2. assert find does not get REMOVED
- assertThat(index.search(new RuleQuery(), QueryOptions.DEFAULT)
- .getRules()).hasSize(1);
+ List<Rule> rules = index.search(new RuleQuery(), QueryOptions.DEFAULT).getHits();
+ assertThat(rules).hasSize(1);
+ assertThat(rules.get(0).key()).isEqualTo(readyKey);
}
private RuleDto newRuleDto(RuleKey ruleKey) {
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<profile>
+ <name>P1</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>x1</key>
+ <priority>BLOCKER</priority>
+ <parameters>
+ <parameter>
+ <key>max</key>
+ <value>7</value>
+ </parameter>
+ </parameters>
+ </rule>
+ </rules>
+</profile>
--- /dev/null
+invalid backup
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<profile>
+ <name>P2</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>x1</key>
+ <priority>BLOCKER</priority>
+ <parameters>
+ <parameter>
+ <key>max</key>
+ <value>7</value>
+ </parameter>
+ </parameters>
+ </rule>
+ </rules>
+</profile>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<profile>
+ <name>P1</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>x1</key>
+ <priority>BLOCKER</priority>
+ <parameters>
+ <parameter>
+ <key>max</key>
+ <value>7</value>
+ </parameter>
+ </parameters>
+ </rule>
+ </rules>
+</profile>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<profile>
+ <name>P1</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>x1</key>
+ <priority>BLOCKER</priority>
+ <parameters>
+ <parameter>
+ <key>max</key>
+ <value>7</value>
+ </parameter>
+ </parameters>
+ </rule>
+ </rules>
+</profile>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<profile>
+ <name>P2</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>x2</key>
+ <priority>BLOCKER</priority>
+ </rule>
+ </rules>
+</profile>