+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.sonarsource.sonarqube</groupId>
- <artifactId>sonarqube</artifactId>
- <version>6.5-SNAPSHOT</version>
- <relativePath>../..</relativePath>
- </parent>
- <artifactId>foo-plugin-v1</artifactId>
- <name>SonarQube :: Plugins :: Foo (V1)</name>
- <packaging>sonar-plugin</packaging>
- <description>Sample of plugin to document and test available APIs</description>
-
- <properties>
- <sonar.skip>true</sonar.skip>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- </dependency>
- <dependency>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.sonarsource.sonarqube</groupId>
- <artifactId>sonar-plugin-api</artifactId>
- <scope>provided</scope>
- </dependency>
-
- <!-- unit testing -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.assertj</groupId>
- <artifactId>assertj-core</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
- <artifactId>sonar-packaging-maven-plugin</artifactId>
- <configuration>
- <pluginKey>foo</pluginKey>
- <pluginName>Foo</pluginName>
- <pluginClass>org.sonar.foo.FooPlugin</pluginClass>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.foo;
-
-import org.sonar.api.resources.Language;
-
-public class Foo implements Language {
-
- public static final String KEY = "foo";
- public static final String NAME = "Foo";
-
- @Override
- public String getKey() {
- return KEY;
- }
-
- @Override
- public String getName() {
- return NAME;
- }
-
- @Override
- public String[] getFileSuffixes() {
- return new String[0];
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.foo;
-
-import org.sonar.api.Plugin;
-import org.sonar.foo.rule.FooBasicProfile;
-import org.sonar.foo.rule.FooRulesDefinition;
-
-/**
- * Plugin entry-point, as declared in pom.xml.
- */
-public class FooPlugin implements Plugin {
-
- @Override
- public void define(Context context) {
- context.addExtensions(
- Foo.class,
- FooRulesDefinition.class,
- FooBasicProfile.class);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.foo;
-
-import javax.annotation.ParametersAreNonnullByDefault;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.foo.rule;
-
-import org.sonar.api.profiles.ProfileDefinition;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.utils.ValidationMessages;
-
-import static org.sonar.api.rules.RulePriority.MAJOR;
-import static org.sonar.foo.Foo.KEY;
-import static org.sonar.foo.rule.FooRulesDefinition.FOO_REPOSITORY;
-
-public class FooBasicProfile extends ProfileDefinition {
-
- @Override
- public RulesProfile createProfile(ValidationMessages validation) {
- final RulesProfile profile = RulesProfile.create("Basic", KEY);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "UnchangedRule"), MAJOR);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "ChangedRule"), MAJOR);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "RemovedRule"), MAJOR);
- return profile;
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.foo.rule;
-
-import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.foo.Foo;
-
-public class FooRulesDefinition implements RulesDefinition {
-
- public static final String FOO_REPOSITORY = "foo";
-
- @Override
- public void define(Context context) {
- defineRulesXoo(context);
- }
-
- private static void defineRulesXoo(Context context) {
- NewRepository repo = context.createRepository(FOO_REPOSITORY, Foo.KEY).setName("Foo");
- createRule(repo, "UnchangedRule");
- createRule(repo, "ChangedRule");
- createRule(repo, "RemovedRule");
- repo.done();
- }
-
- private static NewRule createRule(NewRepository repo, String key) {
- return repo.createRule(key).setName(key).setHtmlDescription(key);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.foo.rule;
-
-import javax.annotation.ParametersAreNonnullByDefault;
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.sonarsource.sonarqube</groupId>
- <artifactId>sonarqube</artifactId>
- <version>6.5-SNAPSHOT</version>
- <relativePath>../..</relativePath>
- </parent>
- <artifactId>foo-plugin-v2</artifactId>
- <name>SonarQube :: Plugins :: Foo (V2)</name>
- <packaging>sonar-plugin</packaging>
- <description>Sample of plugin to document and test available APIs</description>
-
- <properties>
- <sonar.skip>true</sonar.skip>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- </dependency>
- <dependency>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.sonarsource.sonarqube</groupId>
- <artifactId>sonar-plugin-api</artifactId>
- <scope>provided</scope>
- </dependency>
-
- <!-- unit testing -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.assertj</groupId>
- <artifactId>assertj-core</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
- <artifactId>sonar-packaging-maven-plugin</artifactId>
- <configuration>
- <pluginKey>foo</pluginKey>
- <pluginName>Foo</pluginName>
- <pluginClass>org.sonar.foo.FooPlugin</pluginClass>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.foo;
-
-import org.sonar.api.resources.Language;
-
-public class Foo implements Language {
-
- public static final String KEY = "foo";
- public static final String NAME = "Foo";
-
- @Override
- public String getKey() {
- return KEY;
- }
-
- @Override
- public String getName() {
- return NAME;
- }
-
- @Override
- public String[] getFileSuffixes() {
- return new String[0];
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.foo;
-
-import org.sonar.api.Plugin;
-import org.sonar.foo.rule.FooBasicProfile;
-import org.sonar.foo.rule.FooRulesDefinition;
-
-/**
- * Plugin entry-point, as declared in pom.xml.
- */
-public class FooPlugin implements Plugin {
-
- @Override
- public void define(Context context) {
- context.addExtensions(
- Foo.class,
- FooRulesDefinition.class,
- FooBasicProfile.class);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.foo;
-
-import javax.annotation.ParametersAreNonnullByDefault;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.foo.rule;
-
-import org.sonar.api.profiles.ProfileDefinition;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.utils.ValidationMessages;
-
-import static org.sonar.api.rules.RulePriority.MAJOR;
-import static org.sonar.api.rules.RulePriority.MINOR;
-import static org.sonar.foo.Foo.KEY;
-import static org.sonar.foo.rule.FooRulesDefinition.FOO_REPOSITORY;
-
-public class FooBasicProfile extends ProfileDefinition {
-
- @Override
- public RulesProfile createProfile(ValidationMessages validation) {
- final RulesProfile profile = RulesProfile.create("Basic", KEY);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "UnchangedRule"), MAJOR);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "ChangedRule"), MINOR);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "NewRule"), MAJOR);
- return profile;
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.foo.rule;
-
-import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.foo.Foo;
-
-public class FooRulesDefinition implements RulesDefinition {
-
- public static final String FOO_REPOSITORY = "foo";
-
- @Override
- public void define(Context context) {
- defineRulesXoo(context);
- }
-
- private static void defineRulesXoo(Context context) {
- NewRepository repo = context.createRepository(FOO_REPOSITORY, Foo.KEY).setName("Foo");
- createRule(repo, "UnchangedRule");
- createRule(repo, "ChangedRule");
- createRule(repo, "NewRule");
- repo.done();
- }
-
- private static NewRule createRule(NewRepository repo, String key) {
- return repo.createRule(key).setName(key).setHtmlDescription(key);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.foo.rule;
-
-import javax.annotation.ParametersAreNonnullByDefault;
import org.sonar.api.notifications.Notification;
import static com.google.common.base.Preconditions.checkState;
+import static java.lang.Integer.parseInt;
+import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import static org.sonar.server.qualityprofile.BuiltInQualityProfilesNotificationSender.BUILT_IN_QUALITY_PROFILES;
private static final String NUMBER_OF_PROFILES = "numberOfProfiles";
private static final String PROFILE_NAME = ".profileName";
private static final String LANGUAGE = ".language";
+ private static final String NEW_RULES = ".newRules";
+ private static final String UPDATED_RULES = ".updatedRules";
+ private static final String REMOVED_RULES = ".removedRules";
+
private final List<Profile> profiles = new ArrayList<>();
public BuiltInQualityProfilesNotification addProfile(Profile profile) {
AtomicInteger count = new AtomicInteger();
profiles.forEach(profile -> {
int index = count.getAndIncrement();
- notification.setFieldValue(index + ".profileName", profile.getProfileName());
- notification.setFieldValue(index + ".language", profile.getLanguage());
+ notification.setFieldValue(index + PROFILE_NAME, profile.getProfileName());
+ notification.setFieldValue(index + LANGUAGE, profile.getLanguage());
+ notification.setFieldValue(index + NEW_RULES, String.valueOf(profile.getNewRules()));
+ notification.setFieldValue(index + UPDATED_RULES, String.valueOf(profile.getUpdatedRules()));
+ notification.setFieldValue(index + REMOVED_RULES, String.valueOf(profile.getRemovedRules()));
});
return notification;
}
checkState(numberOfProfilesText != null, "Could not read the built-in quality profile notification");
Integer numberOfProfiles = Integer.valueOf(numberOfProfilesText);
IntStream.rangeClosed(0, numberOfProfiles - 1)
- .mapToObj(index -> new Profile(
- requireNonNull(notification.getFieldValue(index + PROFILE_NAME)),
- requireNonNull(notification.getFieldValue(index + LANGUAGE))))
+ .mapToObj(index -> Profile.newBuilder(
+ getNonNullFieldValue(notification, index + PROFILE_NAME),
+ getNonNullFieldValue(notification, index + LANGUAGE))
+ .setNewRules(parseInt(getNonNullFieldValue(notification, index + NEW_RULES)))
+ .setUpdatedRules(parseInt(getNonNullFieldValue(notification, index + UPDATED_RULES)))
+ .setRemovedRules(parseInt(getNonNullFieldValue(notification, index + REMOVED_RULES)))
+ .build())
.forEach(notif::addProfile);
return notif;
}
+ private static String getNonNullFieldValue(Notification notification, String key) {
+ String value = notification.getFieldValue(key);
+ return requireNonNull(value, format("Notification field '%s' is null", key));
+ }
+
public List<Profile> getProfiles() {
return profiles;
}
public static class Profile {
private final String profileName;
private final String language;
+ private final int newRules;
+ private final int updatedRules;
+ private final int removedRules;
- public Profile(String profileName, String language) {
- this.profileName = profileName;
- this.language = language;
+ public Profile(Builder builder) {
+ this.profileName = builder.profileName;
+ this.language = builder.language;
+ this.newRules = builder.newRules;
+ this.updatedRules = builder.updatedRules;
+ this.removedRules = builder.removedRules;
}
public String getProfileName() {
public String getLanguage() {
return language;
}
+
+ public int getNewRules() {
+ return newRules;
+ }
+
+ public int getUpdatedRules() {
+ return updatedRules;
+ }
+
+ public int getRemovedRules() {
+ return removedRules;
+ }
+
+ public static Builder newBuilder(String profileName, String language) {
+ return new Builder(profileName, language);
+ }
+
+ public static class Builder {
+ private final String profileName;
+ private final String language;
+ private int newRules;
+ private int updatedRules;
+ private int removedRules;
+
+ private Builder(String profileName, String language) {
+ this.profileName = requireNonNull(profileName, "profileName should not be null");
+ this.language = requireNonNull(language, "language should not be null");
+ }
+
+ public Builder setNewRules(int newRules) {
+ checkState(newRules >= 0, "newRules should not be negative");
+ this.newRules = newRules;
+ return this;
+ }
+
+ public Builder setUpdatedRules(int updatedRules) {
+ checkState(updatedRules >= 0, "updatedRules should not be negative");
+ this.updatedRules = updatedRules;
+ return this;
+ }
+
+ public Builder setRemovedRules(int removedRules) {
+ checkState(removedRules >= 0, "removedRules should not be negative");
+ this.removedRules = removedRules;
+ return this;
+ }
+
+ public Profile build() {
+ return new Profile(this);
+ }
+ }
}
}
package org.sonar.server.qualityprofile;
-import java.util.List;
+import com.google.common.collect.Multimap;
+import java.util.Collection;
import org.sonar.api.resources.Languages;
import org.sonar.server.notification.NotificationManager;
import org.sonar.server.qualityprofile.BuiltInQualityProfilesNotification.Profile;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.UPDATED;
+
public class BuiltInQualityProfilesNotificationSender {
static final String BUILT_IN_QUALITY_PROFILES = "built-in-quality-profiles";
this.languages = languages;
}
- void send(List<QProfileName> changedProfiles) {
+ void send(Multimap<QProfileName, ActiveRuleChange> changedProfiles) {
BuiltInQualityProfilesNotification notification = new BuiltInQualityProfilesNotification();
- changedProfiles.stream()
+ changedProfiles.keySet().stream()
.map(changedProfile -> {
String profileName = changedProfile.getName();
String languageName = languages.get(changedProfile.getLanguage()).getName();
- return new Profile(profileName, languageName);
+ Collection<ActiveRuleChange> activeRuleChanges = changedProfiles.get(changedProfile);
+ int newRules = (int) activeRuleChanges.stream().map(ActiveRuleChange::getType).filter(ACTIVATED::equals).count();
+ int updatedRules = (int) activeRuleChanges.stream().map(ActiveRuleChange::getType).filter(UPDATED::equals).count();
+ int removedRules = (int) activeRuleChanges.stream().map(ActiveRuleChange::getType).filter(DEACTIVATED::equals).count();
+ return Profile.newBuilder(profileName, languageName)
+ .setNewRules(newRules)
+ .setUpdatedRules(updatedRules)
+ .setRemovedRules(removedRules)
+ .build();
})
.forEach(notification::addProfile);
notificationManager.scheduleForSending(notification.serialize());
StringBuilder message = new StringBuilder("Built-in quality profiles have been updated:\n");
profilesNotification.getProfiles().stream()
.sorted(Comparator.comparing(Profile::getLanguage).thenComparing(Profile::getProfileName))
- .forEach(profile -> message.append("\"").append(profile.getProfileName()).append("\" - ").append(profile.getLanguage()).append("\n"));
+ .forEach(profile -> {
+ message.append("\"")
+ .append(profile.getProfileName()).append("\" - ")
+ .append(profile.getLanguage()).append("\n");
+ int newRules = profile.getNewRules();
+ if (newRules > 0) {
+ message.append(" ").append(newRules).append(" new rules\n");
+ }
+ int updatedRules = profile.getUpdatedRules();
+ if (updatedRules > 0) {
+ message.append(" ").append(updatedRules).append(" rules have been updated\n");
+ }
+ int removedRules = profile.getRemovedRules();
+ if (removedRules > 0) {
+ message.append(" ").append(removedRules).append(" rules removed\n");
+ }
+ });
message.append(
"This is a good time to review your quality profiles and update them to benefit from the latest evolutions.");
*/
package org.sonar.server.qualityprofile;
-import java.util.ArrayList;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.List;
import java.util.Map;
Map<QProfileName, RulesProfileDto> persistedRuleProfiles = loadPersistedProfiles(dbSession);
- List<QProfileName> changedProfiles = new ArrayList<>();
+ Multimap<QProfileName, ActiveRuleChange> changedProfiles = ArrayListMultimap.create();
builtInQProfiles.forEach(builtIn -> {
RulesProfileDto ruleProfile = persistedRuleProfiles.get(builtIn.getQProfileName());
if (ruleProfile == null) {
register(dbSession, batchDbSession, builtIn);
} else {
List<ActiveRuleChange> changes = update(dbSession, builtIn, ruleProfile);
- if (!changes.isEmpty()) {
- changedProfiles.add(builtIn.getQProfileName());
- }
+ changedProfiles.putAll(builtIn.getQProfileName(), changes);
}
});
if (!changedProfiles.isEmpty()) {
*/
package org.sonar.server.qualityprofile;
-import java.util.List;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import java.util.Random;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.assertj.core.groups.Tuple;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.sonar.api.notifications.Notification;
+import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
-import org.sonar.server.language.LanguageTesting;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.server.notification.NotificationManager;
import org.sonar.server.qualityprofile.BuiltInQualityProfilesNotification.Profile;
-import static java.util.Collections.singletonList;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Java6Assertions.assertThat;
import static org.assertj.core.api.Java6Assertions.tuple;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.sonar.server.language.LanguageTesting.newLanguage;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.UPDATED;
public class BuiltInQualityProfilesNotificationSenderTest {
+ private static final Random RANDOM = new Random();
private NotificationManager notificationManager = mock(NotificationManager.class);
@Test
- public void add_profile_to_notification() throws Exception {
- String profileName = randomLowerCaseText();
- String languageKey = randomLowerCaseText();
- String languageName = randomLowerCaseText();
- List<QProfileName> profileNames = singletonList(new QProfileName(languageKey, profileName));
- Languages languages = new Languages(LanguageTesting.newLanguage(languageKey, languageName));
+ public void add_profile_to_notification_for_added_rules() throws Exception {
+ Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
+ Languages languages = new Languages();
+ Tuple expectedTuple = addProfile(profiles, languages, ACTIVATED);
+
+ BuiltInQualityProfilesNotificationSender underTest = new BuiltInQualityProfilesNotificationSender(notificationManager, languages);
+ underTest.send(profiles);
+
+ ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
+ verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
+ verifyNoMoreInteractions(notificationManager);
+ assertThat(BuiltInQualityProfilesNotification.parse(notificationArgumentCaptor.getValue()).getProfiles())
+ .extracting(Profile::getProfileName, Profile::getLanguage, Profile::getNewRules)
+ .containsExactlyInAnyOrder(expectedTuple);
+ }
+
+ @Test
+ public void add_profile_to_notification_for_updated_rules() throws Exception {
+ Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
+ Languages languages = new Languages();
+ Tuple expectedTuple = addProfile(profiles, languages, UPDATED);
+
+ BuiltInQualityProfilesNotificationSender underTest = new BuiltInQualityProfilesNotificationSender(notificationManager, languages);
+ underTest.send(profiles);
+
+ ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
+ verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
+ verifyNoMoreInteractions(notificationManager);
+ assertThat(BuiltInQualityProfilesNotification.parse(notificationArgumentCaptor.getValue()).getProfiles())
+ .extracting(Profile::getProfileName, Profile::getLanguage, Profile::getUpdatedRules)
+ .containsExactlyInAnyOrder(expectedTuple);
+ }
+
+ @Test
+ public void add_profile_to_notification_for_removed_rules() throws Exception {
+ Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
+ Languages languages = new Languages();
+ Tuple expectedTuple = addProfile(profiles, languages, DEACTIVATED);
BuiltInQualityProfilesNotificationSender underTest = new BuiltInQualityProfilesNotificationSender(notificationManager, languages);
- underTest.send(profileNames);
+ underTest.send(profiles);
ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
verifyNoMoreInteractions(notificationManager);
assertThat(BuiltInQualityProfilesNotification.parse(notificationArgumentCaptor.getValue()).getProfiles())
- .extracting(Profile::getProfileName, Profile::getLanguage)
- .containsExactlyInAnyOrder(tuple(profileName, languageName));
+ .extracting(Profile::getProfileName, Profile::getLanguage, Profile::getRemovedRules)
+ .containsExactlyInAnyOrder(expectedTuple);
+ }
+
+ @Test
+ public void add_multiple_profiles_to_notification() throws Exception {
+ Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
+ Languages languages = new Languages();
+ Tuple expectedTuple1 = addProfile(profiles, languages, ACTIVATED);
+ Tuple expectedTuple2 = addProfile(profiles, languages, ACTIVATED);
+
+ BuiltInQualityProfilesNotificationSender underTest = new BuiltInQualityProfilesNotificationSender(notificationManager, languages);
+ underTest.send(profiles);
+
+ ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
+ verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
+ verifyNoMoreInteractions(notificationManager);
+ assertThat(BuiltInQualityProfilesNotification.parse(notificationArgumentCaptor.getValue()).getProfiles())
+ .extracting(Profile::getProfileName, Profile::getLanguage, Profile::getNewRules)
+ .containsExactlyInAnyOrder(expectedTuple1, expectedTuple2);
+ }
+
+ private Tuple addProfile(Multimap<QProfileName, ActiveRuleChange> profiles, Languages languages, ActiveRuleChange.Type type) {
+ String profileName = randomLowerCaseText();
+ Language language = newLanguage(randomLowerCaseText(), randomLowerCaseText());
+ languages.add(language);
+ int numberOfChanges = RANDOM.nextInt(1000);
+ profiles.putAll(
+ new QProfileName(language.getKey(), profileName),
+ IntStream.range(0, numberOfChanges).mapToObj(i -> new ActiveRuleChange(type, ActiveRuleKey.parse("qp:repo:rule" + i))).collect(Collectors.toSet()));
+ return tuple(profileName, language.getName(), numberOfChanges);
}
private static String randomLowerCaseText() {
return randomAlphanumeric(20).toLowerCase();
}
-}
\ No newline at end of file
+}
private BuiltInQualityProfilesNotificationTemplate underTest = new BuiltInQualityProfilesNotificationTemplate();
@Test
- public void notification_contains_list_of_quality_profiles() {
+ public void notification_contains_list_of_new_rules() {
String profileName = randomAlphanumeric(20);
String language = randomAlphanumeric(20);
BuiltInQualityProfilesNotification notification = new BuiltInQualityProfilesNotification()
- .addProfile(new Profile(profileName, language));
+ .addProfile(Profile.newBuilder(profileName, language)
+ .setNewRules(2)
+ .build());
EmailMessage emailMessage = underTest.format(notification.serialize());
assertThat(emailMessage.getMessage()).isEqualTo("Built-in quality profiles have been updated:\n" +
"\"" + profileName + "\" - " + language + "\n" +
+ " 2 new rules\n" +
"This is a good time to review your quality profiles and update them to benefit from the latest evolutions.");
}
+
+ @Test
+ public void notification_contains_list_of_updated_rules() {
+ String profileName = randomAlphanumeric(20);
+ String language = randomAlphanumeric(20);
+ BuiltInQualityProfilesNotification notification = new BuiltInQualityProfilesNotification()
+ .addProfile(Profile.newBuilder(profileName, language)
+ .setUpdatedRules(2)
+ .build());
+
+ EmailMessage emailMessage = underTest.format(notification.serialize());
+
+ assertThat(emailMessage.getMessage()).isEqualTo("Built-in quality profiles have been updated:\n" +
+ "\"" + profileName + "\" - " + language + "\n" +
+ " 2 rules have been updated\n" +
+ "This is a good time to review your quality profiles and update them to benefit from the latest evolutions.");
+ }
+
+ @Test
+ public void notification_contains_list_of_removed_rules() {
+ String profileName = randomAlphanumeric(20);
+ String language = randomAlphanumeric(20);
+ BuiltInQualityProfilesNotification notification = new BuiltInQualityProfilesNotification()
+ .addProfile(Profile.newBuilder(profileName, language)
+ .setRemovedRules(2)
+ .build());
+
+ EmailMessage emailMessage = underTest.format(notification.serialize());
+
+ assertThat(emailMessage.getMessage()).isEqualTo("Built-in quality profiles have been updated:\n" +
+ "\"" + profileName + "\" - " + language + "\n" +
+ " 2 rules removed\n" +
+ "This is a good time to review your quality profiles and update them to benefit from the latest evolutions.");
+ }
+
+ @Test
+ public void notification_contains_list_of_new_updated_and_removed_rules() {
+ String profileName = randomAlphanumeric(20);
+ String language = randomAlphanumeric(20);
+ BuiltInQualityProfilesNotification notification = new BuiltInQualityProfilesNotification()
+ .addProfile(Profile.newBuilder(profileName, language)
+ .setNewRules(2)
+ .setUpdatedRules(3)
+ .setRemovedRules(4)
+ .build());
+
+ EmailMessage emailMessage = underTest.format(notification.serialize());
+
+ assertThat(emailMessage.getMessage()).isEqualTo("Built-in quality profiles have been updated:\n" +
+ "\"" + profileName + "\" - " + language + "\n" +
+ " 2 new rules\n" +
+ " 3 rules have been updated\n" +
+ " 4 rules removed\n" +
+ "This is a good time to review your quality profiles and update them to benefit from the latest evolutions.");
+ }
+
+ @Test
+ public void notification_contains_many_profiles() {
+ String profileName1 = "profile1_" + randomAlphanumeric(20);
+ String language1 = "lang1_" + randomAlphanumeric(20);
+ String profileName2 = "profile1_" + randomAlphanumeric(20);
+ String language2 = "lang2_" + randomAlphanumeric(20);
+ BuiltInQualityProfilesNotification notification = new BuiltInQualityProfilesNotification()
+ .addProfile(Profile.newBuilder(profileName1, language1)
+ .setNewRules(2)
+ .build())
+ .addProfile(Profile.newBuilder(profileName2, language2)
+ .setNewRules(13)
+ .build());
+
+ EmailMessage emailMessage = underTest.format(notification.serialize());
+
+ assertThat(emailMessage.getMessage()).isEqualTo("Built-in quality profiles have been updated:\n" +
+ "\"" + profileName1 + "\" - " + language1 + "\n" +
+ " 2 new rules\n" +
+ "\"" + profileName2 + "\" - " + language2 + "\n" +
+ " 13 new rules\n" +
+ "This is a good time to review your quality profiles and update them to benefit from the latest evolutions.");
+ }
+
+ @Test
+ public void notification_contains_profiles_sorted_by_language_then_by_profile_name() {
+ String language1 = "lang1_" + randomAlphanumeric(20);
+ String language2 = "lang2_" + randomAlphanumeric(20);
+ String profileName1 = "profile1_" + randomAlphanumeric(20);
+ String profileName2 = "profile2_" + randomAlphanumeric(20);
+ String profileName3 = "profile3_" + randomAlphanumeric(20);
+ BuiltInQualityProfilesNotification notification = new BuiltInQualityProfilesNotification()
+ .addProfile(Profile.newBuilder(profileName3, language2).build())
+ .addProfile(Profile.newBuilder(profileName2, language1).build())
+ .addProfile(Profile.newBuilder(profileName1, language2).build());
+
+ EmailMessage emailMessage = underTest.format(notification.serialize());
+
+ assertThat(emailMessage.getMessage()).containsSequence(
+ "\"" + profileName2 + "\" - " + language1,
+ "\"" + profileName1 + "\" - " + language2,
+ "\"" + profileName3 + "\" - " + language2);
+ }
}
String profileName = randomAlphanumeric(20);
String language = randomAlphanumeric(20);
- Notification notification = new BuiltInQualityProfilesNotification().addProfile(new Profile(profileName, language)).serialize();
+ Notification notification = new BuiltInQualityProfilesNotification()
+ .addProfile(Profile.newBuilder(profileName, language)
+ .setNewRules(3)
+ .setUpdatedRules(5)
+ .setRemovedRules(7)
+ .build())
+ .serialize();
BuiltInQualityProfilesNotification result = BuiltInQualityProfilesNotification.parse(notification);
- assertThat(result.getProfiles()).extracting(Profile::getProfileName, Profile::getLanguage)
- .containsExactlyInAnyOrder(tuple(profileName, language));
+ assertThat(result.getProfiles()).extracting(Profile::getProfileName, Profile::getLanguage, Profile::getNewRules, Profile::getUpdatedRules, Profile::getRemovedRules)
+ .containsExactlyInAnyOrder(tuple(profileName, language, 3, 5, 7));
}
@Test
String language2 = randomAlphanumeric(20);
Notification notification = new BuiltInQualityProfilesNotification()
- .addProfile(new Profile(profileName1, language1))
- .addProfile(new Profile(profileName2, language2))
+ .addProfile(Profile.newBuilder(profileName1, language1).build())
+ .addProfile(Profile.newBuilder(profileName2, language2).build())
.serialize();
BuiltInQualityProfilesNotification result = BuiltInQualityProfilesNotification.parse(notification);
*/
package org.sonar.server.qualityprofile;
+import com.google.common.collect.Multimap;
import java.util.Arrays;
-import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.sonar.api.rules.RulePriority.MAJOR;
import static org.sonar.db.qualityprofile.QualityProfileTesting.newRuleProfileDto;
import static org.sonar.server.language.LanguageTesting.newLanguage;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
public class RegisterQualityProfilesNotificationTest {
underTest.start();
- ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+ ArgumentCaptor<Multimap> captor = ArgumentCaptor.forClass(Multimap.class);
verify(builtInQualityProfilesNotification).send(captor.capture());
- List<QProfileName> updatedProfiles = captor.<List<QProfileName>>getValue();
- assertThat(updatedProfiles)
+ Multimap<QProfileName, ActiveRuleChange> updatedProfiles = captor.<Multimap<QProfileName, ActiveRuleChange>>getValue();
+ assertThat(updatedProfiles.keySet())
.extracting(QProfileName::getName, QProfileName::getLanguage)
.containsExactlyInAnyOrder(tuple(dbProfile.getName(), dbProfile.getLanguage()));
+ assertThat(updatedProfiles.values())
+ .extracting(value -> value.getActiveRule().getRuleId(), ActiveRuleChange::getType)
+ .containsExactlyInAnyOrder(tuple(newRule.getId(), ACTIVATED));
}
@Test
- public void only_send_one_notification_when_several_built_in_profiles_contain_new_rules() {
+ public void send_notification_when_built_in_profile_contains_deactivated_rule() {
String language = newLanguageKey();
RuleDefinitionDto existingRule = db.rules().insert(r -> r.setLanguage(language));
- RuleDefinitionDto newRule = db.rules().insert(r -> r.setLanguage(language));
+ RulesProfileDto dbProfile = insertBuiltInProfile(language);
+ activateRuleInDb(dbProfile, existingRule, MAJOR);
+ addPluginProfile(dbProfile);
+ builtInQProfileRepositoryRule.initialize();
+
+ underTest.start();
+
+ ArgumentCaptor<Multimap> captor = ArgumentCaptor.forClass(Multimap.class);
+ verify(builtInQualityProfilesNotification).send(captor.capture());
+ Multimap<QProfileName, ActiveRuleChange> updatedProfiles = captor.<Multimap<QProfileName, ActiveRuleChange>>getValue();
+ assertThat(updatedProfiles.keySet())
+ .extracting(QProfileName::getName, QProfileName::getLanguage)
+ .containsExactlyInAnyOrder(tuple(dbProfile.getName(), dbProfile.getLanguage()));
+ assertThat(updatedProfiles.values())
+ .extracting(value -> value.getActiveRule().getRuleId(), ActiveRuleChange::getType)
+ .containsExactlyInAnyOrder(tuple(existingRule.getId(), DEACTIVATED));
+ }
+ @Test
+ public void only_send_one_notification_when_several_built_in_profiles_contain_new_rules() {
+ String language = newLanguageKey();
+
+ RuleDefinitionDto existingRule1 = db.rules().insert(r -> r.setLanguage(language));
+ RuleDefinitionDto newRule1 = db.rules().insert(r -> r.setLanguage(language));
RulesProfileDto dbProfile1 = insertBuiltInProfile(language);
- activateRuleInDb(dbProfile1, existingRule, MAJOR);
- addPluginProfile(dbProfile1, existingRule, newRule);
+ activateRuleInDb(dbProfile1, existingRule1, MAJOR);
+ addPluginProfile(dbProfile1, existingRule1, newRule1);
+ RuleDefinitionDto existingRule2 = db.rules().insert(r -> r.setLanguage(language));
+ RuleDefinitionDto newRule2 = db.rules().insert(r -> r.setLanguage(language));
RulesProfileDto dbProfile2 = insertBuiltInProfile(language);
- activateRuleInDb(dbProfile2, existingRule, MAJOR);
- addPluginProfile(dbProfile2, existingRule, newRule);
+ activateRuleInDb(dbProfile2, existingRule2, MAJOR);
+ addPluginProfile(dbProfile2, existingRule2, newRule2);
builtInQProfileRepositoryRule.initialize();
underTest.start();
- ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+ ArgumentCaptor<Multimap> captor = ArgumentCaptor.forClass(Multimap.class);
verify(builtInQualityProfilesNotification).send(captor.capture());
- List<QProfileName> updatedProfiles = captor.<List<QProfileName>>getValue();
- assertThat(updatedProfiles)
+ Multimap<QProfileName, ActiveRuleChange> updatedProfiles = captor.<Multimap<QProfileName, ActiveRuleChange>>getValue();
+ assertThat(updatedProfiles.keySet())
.extracting(QProfileName::getName, QProfileName::getLanguage)
.containsExactlyInAnyOrder(
tuple(dbProfile1.getName(), dbProfile1.getLanguage()),
tuple(dbProfile2.getName(), dbProfile2.getLanguage())
);
+ assertThat(updatedProfiles.values())
+ .extracting(value -> value.getActiveRule().getRuleId(), ActiveRuleChange::getType)
+ .containsExactlyInAnyOrder(
+ tuple(newRule1.getId(), ACTIVATED),
+ tuple(newRule2.getId(), ACTIVATED)
+ );
}
private void addPluginProfile(RulesProfileDto dbProfile, RuleDefinitionDto... dbRules) {
import org.sonar.api.profiles.ProfileDefinition;
import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.RulePriority;
import org.sonar.api.utils.ValidationMessages;
import static org.sonar.api.rules.RulePriority.MAJOR;
public class FooBasicProfile extends ProfileDefinition {
+ private final RuleFinder ruleFinder;
+
+ public FooBasicProfile(RuleFinder ruleFinder) {
+ this.ruleFinder = ruleFinder;
+ }
+
@Override
public RulesProfile createProfile(ValidationMessages validation) {
final RulesProfile profile = RulesProfile.create("Basic", KEY);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "UnchangedRule"), MAJOR);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "ChangedRule"), MAJOR);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "RemovedRule"), MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "UnchangedRule", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "ChangedRule", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "ToBeDeactivatedRule", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "ToBeRemovedRule", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "RuleWithUnchangedParameter", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "RuleWithChangedParameter", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "RuleWithRemovedParameter", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "RuleWithAddedParameter", MAJOR);
return profile;
}
+
+ private ActiveRule activateRule(RulesProfile profile, String repo, String key, RulePriority severity) {
+ return profile.activateRule(ruleFinder.findByKey(repo, key), severity);
+ }
+
}
NewRepository repo = context.createRepository(FOO_REPOSITORY, Foo.KEY).setName("Foo");
createRule(repo, "UnchangedRule");
createRule(repo, "ChangedRule");
- createRule(repo, "RemovedRule");
+ createRule(repo, "ToBeDeactivatedRule");
+ createRule(repo, "ToBeRemovedRule");
+ createRule(repo, "RuleWithUnchangedParameter").createParam("unchanged").setDefaultValue("10");
+ createRule(repo, "RuleWithChangedParameter").createParam("toBeChanged").setDefaultValue("10");
+ createRule(repo, "RuleWithRemovedParameter").createParam("toBeRemoved").setDefaultValue("10");
+ createRule(repo, "RuleWithAddedParameter").createParam("added");
repo.done();
}
import org.sonar.api.profiles.ProfileDefinition;
import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.RulePriority;
import org.sonar.api.utils.ValidationMessages;
import static org.sonar.api.rules.RulePriority.MAJOR;
public class FooBasicProfile extends ProfileDefinition {
+ private final RuleFinder ruleFinder;
+
+ public FooBasicProfile(RuleFinder ruleFinder) {
+ this.ruleFinder = ruleFinder;
+ }
+
@Override
public RulesProfile createProfile(ValidationMessages validation) {
final RulesProfile profile = RulesProfile.create("Basic", KEY);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "UnchangedRule"), MAJOR);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "ChangedRule"), MINOR);
- profile.activateRule(Rule.create(FOO_REPOSITORY, "NewRule"), MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "UnchangedRule", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "ChangedRule", MINOR);
+ activateRule(profile, FOO_REPOSITORY, "NewRule", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "RuleWithUnchangedParameter", MAJOR);
+ // Update of the default value of a parameter is not taken into account in quality profile as long as it's not also explicitly set in the quality profile
+ // TODO Remove the parameter value when SONAR_9475 will be fixed
+ activateRule(profile, FOO_REPOSITORY, "RuleWithChangedParameter", MAJOR).setParameter("toBeChanged", "20");
+ activateRule(profile, FOO_REPOSITORY, "RuleWithRemovedParameter", MAJOR);
+ activateRule(profile, FOO_REPOSITORY, "RuleWithAddedParameter", MAJOR);
return profile;
}
+
+ private ActiveRule activateRule(RulesProfile profile, String repo, String key, RulePriority severity) {
+ return profile.activateRule(ruleFinder.findByKey(repo, key), severity);
+ }
+
}
createRule(repo, "UnchangedRule");
createRule(repo, "ChangedRule");
createRule(repo, "NewRule");
+ createRule(repo, "ToBeDeactivatedRule");
+ createRule(repo, "RuleWithUnchangedParameter").createParam("unchanged").setDefaultValue("10");
+ // Update of the default value of a parameter is not taken into account in quality profile as long as it's not also explicitly set in the quality profile
+ createRule(repo, "RuleWithChangedParameter").createParam("toBeChanged").setDefaultValue("20");
+ createRule(repo, "RuleWithRemovedParameter");
+ createRule(repo, "RuleWithAddedParameter").createParam("added").setDefaultValue("10");
repo.done();
}
.addPlugin(pluginArtifact("foo-plugin-v1"))
.setServerProperty("email.smtp_host.secured", "localhost")
.setServerProperty("email.smtp_port.secured", Integer.toString(smtpServer.getServer().getPort()))
- // .setServerProperty("sonar.web.javaAdditionalOpts", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")// FIXME
- // remove web debugging
+ //.setServerProperty("sonar.web.javaAdditionalOpts", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")// FIXME remove web debugging
.build();
orchestrator.start();
.addPlugin(pluginArtifact("foo-plugin-v1"))
.setServerProperty("email.smtp_host.secured", "localhost")
.setServerProperty("email.smtp_port.secured", Integer.toString(smtpServer.getServer().getPort()))
- // .setServerProperty("sonar.web.javaAdditionalOpts", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")// FIXME
- // remove web debugging
+ //.setServerProperty("sonar.web.javaAdditionalOpts", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")// FIXME remove web debugging
.build();
orchestrator.start();
.containsSequence(
"Built-in quality profiles have been updated:",
"\"Basic\" - Foo",
+ " 1 new rules",
+ " 3 rules have been updated",
+ " 1 rules removed",
"This is a good time to review your quality profiles and update them to benefit from the latest evolutions.")
.isEqualTo(messages.get(1).getMimeMessage().getContent().toString());
}
}
}
- private String getContent(MimeMessage mimeMessage1) {
- try {
- return mimeMessage1.getContent().toString();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
private String getAllRecipients(MimeMessage mimeMessage) {
try {
return mimeMessage.getHeader("To", null);