@@ -1171,7 +1171,6 @@ quality_profiles.associated_projects=Associated projects | |||
quality_profiles.no_projects_associated_to_profile_x=No projects are explicitly associated to the profile "{0}". | |||
quality_profiles.projects_warning=List of projects explicitly associated to this Quality profile : | |||
quality_profiles.including_x_overriding.suffix=, incl. {0} overriding | |||
quality_profiles.profile_cant_be_edited=This profile can not be edited. | |||
quality_profiles.set_parent=Set parent | |||
quality_profiles.inherit_rules_from_profile=Inherit rules configuration from the profile | |||
quality_profiles.no_changes_done_on_this_profile=No changes has been done on this quality profile. | |||
@@ -1213,7 +1212,6 @@ quality_profiles.copy_new_name=New Name | |||
rules_configuration.tab.new_rule=New rule | |||
rules_configuration.tab.edit_rule=Edit rule | |||
rules_configuration.profile_cant_be_updated_description=This profile can not be updated but it can be used as a template for your own configuration. Just copy it from the profiles page. | |||
rules_configuration.x_found_in_active_rules={0} found in active rules | |||
rules_configuration.x_found_in_inactive_rules={0} found in inactive rules | |||
rules_configuration.expand_collapse=expand/collapse |
@@ -37,27 +37,28 @@ public class DefaultProfileLoader implements ProfileLoader { | |||
} | |||
public RulesProfile load(Project project) { | |||
String profileName = StringUtils.defaultIfBlank(settings.getString("sonar.profile." + project.getLanguageKey()), settings.getString("sonar.profile")); | |||
RulesProfile profile; | |||
String profileName = StringUtils.defaultIfBlank( | |||
settings.getString("sonar.profile"), | |||
settings.getString("sonar.profile." + project.getLanguageKey()) | |||
); | |||
// temporary | |||
if (StringUtils.isBlank(profileName)) { | |||
profile = dao.getDefaultProfile(project.getLanguageKey()); | |||
if (profile == null) { | |||
// This means that the current language is not supported by any installed plugin, otherwise at least a | |||
// "Default <Language Name>" profile would have been created by ActivateDefaultProfiles class. | |||
throw new SonarException("You must install a plugin that supports the language '" + project.getLanguageKey() + "'"); | |||
} | |||
} else { | |||
profile = dao.getProfile(project.getLanguageKey(), profileName); | |||
if (profile == null) { | |||
throw new SonarException("Quality profile not found : " + profileName + ", language " + project.getLanguageKey()); | |||
} | |||
// This means that the current language is not supported by any installed plugin, otherwise at least a | |||
// "Default <Language Name>" profile would have been created by ActivateDefaultProfiles class. | |||
throw new SonarException("You must install a plugin that supports the language '" + project.getLanguageKey() + "'"); | |||
} | |||
RulesProfile profile = dao.getProfile(project.getLanguageKey(), profileName); | |||
if (profile == null) { | |||
throw new SonarException("Quality profile not found : " + profileName + ", language " + project.getLanguageKey()); | |||
} | |||
return hibernateHack(profile); | |||
} | |||
private RulesProfile hibernateHack(RulesProfile profile) { | |||
// hack to lazy initialize the profile collections | |||
profile.getActiveRules().size(); | |||
for (ActiveRule activeRule : profile.getActiveRules()) { | |||
activeRule.getActiveRuleParams().size(); | |||
activeRule.getRule().getParams().size(); |
@@ -58,16 +58,6 @@ public class DefaultProfileLoaderTest { | |||
assertThat(profile.getName()).isEqualTo("legacy profile"); | |||
} | |||
@Test | |||
public void should_get_default_profile() { | |||
Settings settings = new Settings(); | |||
when(dao.getDefaultProfile(Java.KEY)).thenReturn(RulesProfile.create("default profile", "java")); | |||
RulesProfile profile = new DefaultProfileLoader(dao, settings).load(javaProject); | |||
assertThat(profile.getName()).isEqualTo("default profile"); | |||
} | |||
@Test | |||
public void should_fail_if_not_found() { | |||
Settings settings = new Settings(); |
@@ -35,7 +35,7 @@ import java.util.List; | |||
*/ | |||
public class DatabaseVersion implements BatchComponent, ServerComponent { | |||
public static final int LAST_VERSION = 333; | |||
public static final int LAST_VERSION = 335; | |||
public static enum Status { | |||
UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL |
@@ -25,6 +25,7 @@ public final class LoadedTemplateDto { | |||
public static final String DASHBOARD_TYPE = "DASHBOARD"; | |||
public static final String FILTER_TYPE = "FILTER"; | |||
public static final String QUALITY_PROFILE_TYPE = "QUALITY_PROFILE"; | |||
private Long id; | |||
private String key; |
@@ -28,10 +28,6 @@ public class ProfilesDao extends BaseDao { | |||
super(session); | |||
} | |||
public RulesProfile getDefaultProfile(String languageKey) { | |||
return getSession().getSingleResult(RulesProfile.class, "defaultProfile", true, "language", languageKey); | |||
} | |||
public RulesProfile getProfile(String languageKey, String profileName) { | |||
return getSession().getSingleResult(RulesProfile.class, "language", languageKey, "name", profileName); | |||
} |
@@ -175,6 +175,8 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('330'); | |||
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('331'); | |||
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('332'); | |||
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('333'); | |||
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('334'); | |||
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('335'); | |||
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null); | |||
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2; |
@@ -67,8 +67,6 @@ CREATE TABLE "RULES_PARAMETERS" ( | |||
CREATE TABLE "RULES_PROFILES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"NAME" VARCHAR(100) NOT NULL, | |||
"DEFAULT_PROFILE" BOOLEAN DEFAULT FALSE, | |||
"PROVIDED" BOOLEAN NOT NULL DEFAULT FALSE, | |||
"LANGUAGE" VARCHAR(20), | |||
"PARENT_NAME" VARCHAR(100), | |||
"VERSION" INTEGER DEFAULT 1, |
@@ -43,16 +43,4 @@ public class ProfilesDaoTest extends AbstractDbUnitTestCase { | |||
assertThat(profilesDao.getProfile("unknown language", "my profile")).isNull(); | |||
assertThat(profilesDao.getProfile("java", "my profile").getName()).isEqualTo("my profile"); | |||
} | |||
@Test | |||
public void should_get_default_profile() { | |||
RulesProfile defaultProfile = RulesProfile.create("default profile", "java"); | |||
defaultProfile.setDefaultProfile(true); | |||
RulesProfile otherProfile = RulesProfile.create("other profile", "java"); | |||
otherProfile.setDefaultProfile(false); | |||
getSession().save(defaultProfile, otherProfile); | |||
assertThat(profilesDao.getDefaultProfile("java").getName()).isEqualTo("default profile"); | |||
} | |||
} |
@@ -1,18 +0,0 @@ | |||
<dataset> | |||
<!-- plugins --> | |||
<extensions id="1" plugin_key="checkstyle" extension_type="PLUGIN" version="1.0" | |||
name="Checkstyle" filename="sonar-checkstyle-plugin.jar" plugin_class="[null]" | |||
description="Checkstyle Plugin" organization="SonarSource" organization_url="[null]" license="LGPL" installation_date="[null]" | |||
core="true" /> | |||
<extensions id="2" plugin_key="pmd" extension_type="PLUGIN" version="1.1" | |||
name="PMD" filename="sonar-pmd-plugin.jar" installation_date="[null]" plugin_class="[null]" | |||
description="PMD Plugin" organization="SonarSource" organization_url="[null]" license="LGPL" | |||
core="true" /> | |||
<!-- plugin extensions --> | |||
<extensions id="3" plugin_key="checkstyle" extension_type="PLUGIN_EXTENSION" version="[null]" | |||
name="my_checkstyle_rules.jar" filename="my_checkstyle_rules.jar" installation_date="[null]" plugin_class="[null]" | |||
description="[null]" organization="[null]" organization_url="[null]" license="[null]" core="[null]" /> | |||
</dataset> |
@@ -1,7 +1,7 @@ | |||
<dataset> | |||
<rules_profiles id="1" provided="true" name="profile one" default_profile="0" language="java"/> | |||
<rules_profiles id="2" provided="true" name="profile two" default_profile="0" language="java"/> | |||
<rules_profiles id="3" provided="true" name="profile three" default_profile="0" language="plsql"/> | |||
<rules_profiles id="1" name="profile one" language="java"/> | |||
<rules_profiles id="2" name="profile two" language="java"/> | |||
<rules_profiles id="3" name="profile three" language="plsql"/> | |||
</dataset> |
@@ -6,8 +6,8 @@ | |||
<rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="REGULAR_EXPRESSION"/> | |||
<rules_parameters id="2" rule_id="1" name="param2" description="[null]" param_type="REGULAR_EXPRESSION"/> | |||
<rules_profiles id="1" provided="true" name="profile1" default_profile="1" language="java"/> | |||
<rules_profiles id="2" provided="true" name="profile2" default_profile="1" language="OTHER"/> | |||
<rules_profiles id="1" name="profile1" language="java"/> | |||
<rules_profiles id="2" name="profile2" language="OTHER"/> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2"/> | |||
<active_rules id="2" profile_id="2" rule_id="1" failure_level="2"/> |
@@ -6,8 +6,8 @@ | |||
<rules_parameters id="1" rule_id="1" name="param1" description="foo" param_type="REGULAR_EXPRESSION"/> | |||
<rules_parameters id="2" rule_id="1" name="param2" description="foo" param_type="REGULAR_EXPRESSION"/> | |||
<rules_profiles id="1" provided="true" name="profile1" default_profile="1" language="java"/> | |||
<rules_profiles id="2" provided="true" name="profile2" default_profile="1" language="OTHER"/> | |||
<rules_profiles id="1" name="profile1" language="java"/> | |||
<rules_profiles id="2" name="profile2" language="OTHER"/> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2"/> | |||
<active_rules id="2" profile_id="2" rule_id="1" failure_level="2"/> |
@@ -1,7 +1,7 @@ | |||
<dataset> | |||
<rules_profiles id="1" provided="true" name="profile one" default_profile="1" language="java"/> | |||
<rules_profiles id="2" provided="true" name="profile two" default_profile="0" language="java"/> | |||
<rules_profiles id="1" name="profile one" language="java"/> | |||
<rules_profiles id="2" name="profile two" language="java"/> | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> |
@@ -1,7 +1,7 @@ | |||
<dataset> | |||
<rules_profiles id="1" provided="true" name="profile one" default_profile="1" language="java" /> | |||
<rules_profiles id="2" provided="true" name="profile two" default_profile="0" language="java" /> | |||
<rules_profiles id="1" name="profile one" language="java" /> | |||
<rules_profiles id="2" name="profile two" language="java" /> | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> |
@@ -1,7 +1,7 @@ | |||
<dataset> | |||
<rules_profiles id="1" provided="true" name="profile one" default_profile="1" language="java" /> | |||
<rules_profiles id="2" provided="true" name="profile two" default_profile="0" language="java" /> | |||
<rules_profiles id="1" name="profile one" language="java" /> | |||
<rules_profiles id="2" name="profile two" language="java" /> | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> |
@@ -29,14 +29,7 @@ import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RulePriority; | |||
import javax.persistence.CascadeType; | |||
import javax.persistence.Column; | |||
import javax.persistence.Entity; | |||
import javax.persistence.FetchType; | |||
import javax.persistence.GeneratedValue; | |||
import javax.persistence.Id; | |||
import javax.persistence.OneToMany; | |||
import javax.persistence.Table; | |||
import javax.persistence.*; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
@@ -74,12 +67,9 @@ public class RulesProfile implements Cloneable { | |||
@Column(name = "version", updatable = true, nullable = false) | |||
private int version = 1; | |||
@Column(name = "default_profile", updatable = true, nullable = false) | |||
@Transient | |||
private Boolean defaultProfile = Boolean.FALSE; | |||
@Column(name = "provided", updatable = true, nullable = false) | |||
private Boolean provided = Boolean.FALSE; | |||
@Column(name = "used_profile", updatable = true, nullable = false) | |||
private Boolean used = Boolean.FALSE; | |||
@@ -113,16 +103,6 @@ public class RulesProfile implements Cloneable { | |||
this.alerts = Lists.newArrayList(); | |||
} | |||
/** | |||
* @deprecated since 2.3. Use the factory method create() | |||
*/ | |||
@Deprecated | |||
public RulesProfile(String name, String language, boolean defaultProfile, boolean provided) { | |||
this(name, language); | |||
this.defaultProfile = defaultProfile; | |||
this.provided = provided; | |||
} | |||
public Integer getId() { | |||
return id; | |||
} | |||
@@ -216,18 +196,18 @@ public class RulesProfile implements Cloneable { | |||
} | |||
/** | |||
* @return whether the profile is defined in a plugin. Provided profiles are automatically restored during server startup and can not be | |||
* updated by end users. | |||
* @deprecated since 3.3 not replaced | |||
*/ | |||
@Deprecated | |||
public Boolean getProvided() { | |||
return provided; | |||
return false; | |||
} | |||
/** | |||
* Set whether the profile is provided by a plugin | |||
* @deprecated since 3.3 not replaced | |||
*/ | |||
@Deprecated | |||
public void setProvided(Boolean b) { | |||
this.provided = b; | |||
} | |||
/** |
@@ -60,6 +60,8 @@ public class ProfilesBackup implements Backupable { | |||
xStream.aliasField("default-profile", RulesProfile.class, "defaultProfile"); | |||
xStream.omitField(RulesProfile.class, "id"); | |||
xStream.omitField(RulesProfile.class, "projects"); | |||
xStream.omitField(RulesProfile.class, "provided"); | |||
xStream.omitField(RulesProfile.class, "defaultProfile"); | |||
xStream.omitField(RulesProfile.class, "enabled"); | |||
xStream.registerConverter(getActiveRuleConverter()); | |||
xStream.registerConverter(getAlertsConverter()); |
@@ -43,8 +43,6 @@ public class ProfilesManager extends BaseDao { | |||
RulesProfile profile = getSession().getSingleResult(RulesProfile.class, "id", profileId); | |||
RulesProfile toImport = (RulesProfile) profile.clone(); | |||
toImport.setName(newProfileName); | |||
toImport.setDefaultProfile(false); | |||
toImport.setProvided(false); | |||
ProfilesBackup pb = new ProfilesBackup(getSession()); | |||
pb.importProfile(rulesDao, toImport); | |||
getSession().commit(); | |||
@@ -68,7 +66,7 @@ public class ProfilesManager extends BaseDao { | |||
public ValidationMessages changeParentProfile(Integer profileId, String parentName, String userName) { | |||
ValidationMessages messages = ValidationMessages.create(); | |||
RulesProfile profile = getSession().getEntity(RulesProfile.class, profileId); | |||
if (profile != null && !profile.getProvided()) { | |||
if (profile != null) { | |||
RulesProfile oldParent = getParentProfile(profile); | |||
RulesProfile newParent = getProfile(profile.getLanguage(), parentName); | |||
if (isCycle(profile, newParent)) { | |||
@@ -344,8 +342,7 @@ public class ProfilesManager extends BaseDao { | |||
private List<RulesProfile> getChildren(RulesProfile parent) { | |||
return getSession().getResults(RulesProfile.class, | |||
"language", parent.getLanguage(), | |||
"parentName", parent.getName(), | |||
"provided", false); | |||
"parentName", parent.getName()); | |||
} | |||
private void removeActiveRule(RulesProfile profile, ActiveRule activeRule) { |
@@ -78,18 +78,7 @@ import org.sonar.server.plugins.UpdateCenterMatrixFactory; | |||
import org.sonar.server.qualitymodel.DefaultModelManager; | |||
import org.sonar.server.rules.ProfilesConsole; | |||
import org.sonar.server.rules.RulesConsole; | |||
import org.sonar.server.startup.ActivateDefaultProfiles; | |||
import org.sonar.server.startup.DeleteDeprecatedMeasures; | |||
import org.sonar.server.startup.GeneratePluginIndex; | |||
import org.sonar.server.startup.GwtPublisher; | |||
import org.sonar.server.startup.JdbcDriverDeployer; | |||
import org.sonar.server.startup.RegisterMetrics; | |||
import org.sonar.server.startup.RegisterNewDashboards; | |||
import org.sonar.server.startup.RegisterNewFilters; | |||
import org.sonar.server.startup.RegisterProvidedProfiles; | |||
import org.sonar.server.startup.RegisterQualityModels; | |||
import org.sonar.server.startup.RegisterRules; | |||
import org.sonar.server.startup.ServerMetadataPersister; | |||
import org.sonar.server.startup.*; | |||
import org.sonar.server.ui.CodeColorizers; | |||
import org.sonar.server.ui.JRubyI18n; | |||
import org.sonar.server.ui.PageDecorations; | |||
@@ -259,8 +248,7 @@ public final class Platform { | |||
startupContainer.addSingleton(GwtPublisher.class); | |||
startupContainer.addSingleton(RegisterMetrics.class); | |||
startupContainer.addSingleton(RegisterRules.class); | |||
startupContainer.addSingleton(RegisterProvidedProfiles.class); | |||
startupContainer.addSingleton(ActivateDefaultProfiles.class); | |||
startupContainer.addSingleton(RegisterNewProfiles.class); | |||
startupContainer.addSingleton(JdbcDriverDeployer.class); | |||
startupContainer.addSingleton(ServerMetadataPersister.class); | |||
startupContainer.addSingleton(RegisterQualityModels.class); |
@@ -1,91 +0,0 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2008-2012 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.server.startup; | |||
import org.sonar.api.database.DatabaseSession; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Language; | |||
import org.sonar.api.utils.Logs; | |||
import org.sonar.jpa.session.DatabaseSessionFactory; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
public final class ActivateDefaultProfiles { | |||
private final DatabaseSessionFactory sessionFactory; | |||
private final Language[] languages; | |||
public ActivateDefaultProfiles(DatabaseSessionFactory sessionFactory, Language[] languages, RegisterProvidedProfiles registerProfilesBefore) {// NOSONAR the parameter registerProfilesBefore is used to define the execution order of startup components | |||
this.sessionFactory = sessionFactory; | |||
this.languages = languages; | |||
} | |||
public void start() { | |||
DatabaseSession session = sessionFactory.getSession(); | |||
for (Language language : languages) { | |||
Logs.INFO.info("Activate default profile for " + language.getKey()); | |||
activateDefaultProfile(language, session); | |||
} | |||
session.commit(); | |||
} | |||
public void activateDefaultProfile(Language language, DatabaseSession session) { | |||
List<RulesProfile> profiles = session.getResults(RulesProfile.class, "language", language.getKey()); | |||
RulesProfile profileToActivate = null; | |||
boolean oneProfileIsActivated = false; | |||
if (profiles.isEmpty()) { | |||
profileToActivate = RulesProfile.create("Default " + language.getName(), language.getKey()); | |||
profileToActivate.setDefaultProfile(true); | |||
profileToActivate.setProvided(false); | |||
} else if (profiles.size() == 1) { | |||
profileToActivate = profiles.get(0); | |||
} else if (!activeProfileFoundInDB(profiles)) { | |||
Iterator<RulesProfile> iterator = profiles.iterator(); | |||
while (iterator.hasNext() && !oneProfileIsActivated) { | |||
RulesProfile profile = iterator.next(); | |||
oneProfileIsActivated = profile.getDefaultProfile(); | |||
if (RulesProfile.SONAR_WAY_NAME.equals(profile.getName())) { | |||
profileToActivate = profile; | |||
} | |||
} | |||
if (!oneProfileIsActivated && profileToActivate == null) { | |||
profileToActivate = profiles.get(0); | |||
} | |||
} | |||
activateProfileIfNeeded(session, profileToActivate, oneProfileIsActivated); | |||
} | |||
private void activateProfileIfNeeded(DatabaseSession session, RulesProfile profileToActivate, boolean oneProfileIsActivated) { | |||
if (!oneProfileIsActivated && profileToActivate != null) { | |||
profileToActivate.setDefaultProfile(true); | |||
session.saveWithoutFlush(profileToActivate); | |||
} | |||
} | |||
private boolean activeProfileFoundInDB(List<RulesProfile> profiles) { | |||
for (RulesProfile rulesProfile : profiles) { | |||
if (rulesProfile.getDefaultProfile()) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,228 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2008-2012 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.server.startup; | |||
import com.google.common.base.Function; | |||
import com.google.common.collect.ArrayListMultimap; | |||
import com.google.common.collect.ListMultimap; | |||
import com.google.common.collect.Multimaps; | |||
import com.google.common.collect.Sets; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.sonar.api.database.DatabaseSession; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.*; | |||
import org.sonar.api.utils.SonarException; | |||
import org.sonar.api.utils.TimeProfiler; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.core.template.LoadedTemplateDao; | |||
import org.sonar.core.template.LoadedTemplateDto; | |||
import org.sonar.jpa.session.DatabaseSessionFactory; | |||
import org.sonar.server.platform.PersistentSettings; | |||
import java.util.*; | |||
public class RegisterNewProfiles { | |||
private static final Logger LOGGER = LoggerFactory.getLogger(RegisterNewProfiles.class); | |||
private static final String DEFAULT_PROFILE_NAME = "Sonar way"; | |||
private final List<ProfileDefinition> definitions; | |||
private final LoadedTemplateDao loadedTemplateDao; | |||
private final RuleFinder ruleFinder; | |||
private final DatabaseSessionFactory sessionFactory; | |||
private final PersistentSettings settings; | |||
private DatabaseSession session = null; | |||
public RegisterNewProfiles(List<ProfileDefinition> definitions, | |||
PersistentSettings settings, | |||
RuleFinder ruleFinder, | |||
LoadedTemplateDao loadedTemplateDao, | |||
DatabaseSessionFactory sessionFactory, | |||
RegisterRules registerRulesBefore) { | |||
this.settings = settings; | |||
this.ruleFinder = ruleFinder; | |||
this.definitions = definitions; | |||
this.loadedTemplateDao = loadedTemplateDao; | |||
this.sessionFactory = sessionFactory; | |||
} | |||
public RegisterNewProfiles(PersistentSettings settings, | |||
RuleFinder ruleFinder, | |||
LoadedTemplateDao loadedTemplateDao, | |||
DatabaseSessionFactory sessionFactory, | |||
RegisterRules registerRulesBefore) { | |||
this(Collections.<ProfileDefinition>emptyList(), settings, ruleFinder, loadedTemplateDao, sessionFactory, registerRulesBefore); | |||
} | |||
public void start() { | |||
TimeProfiler profiler = new TimeProfiler().start("Register Quality Profiles"); | |||
session = sessionFactory.getSession(); | |||
ListMultimap<String, RulesProfile> profilesByLanguage = loadDefinitions(); | |||
for (String language : profilesByLanguage.keySet()) { | |||
List<RulesProfile> profiles = profilesByLanguage.get(language); | |||
verifyLanguage(language, profiles); | |||
for (Map.Entry<String, Collection<RulesProfile>> entry : groupByName(profiles).entrySet()) { | |||
String name = entry.getKey(); | |||
if (shouldRegister(language, name)) { | |||
register(language, name, entry.getValue()); | |||
} | |||
} | |||
setDefault(language, profiles); | |||
} | |||
session.commit(); | |||
profiler.stop(); | |||
} | |||
private void setDefault(String language, List<RulesProfile> profiles) { | |||
String propertyKey = "sonar.profile." + language; | |||
if (settings.getString(propertyKey) == null) { | |||
String defaultProfileName = defaultProfileName(profiles); | |||
LOGGER.info("Set default profile for " + language + ": " + defaultProfileName); | |||
settings.saveProperty(propertyKey, defaultProfileName); | |||
} | |||
} | |||
private Map<String, Collection<RulesProfile>> groupByName(List<RulesProfile> profiles) { | |||
return Multimaps.index(profiles, | |||
new Function<RulesProfile, String>() { | |||
public String apply(RulesProfile profile) { | |||
return profile.getName(); | |||
} | |||
}).asMap(); | |||
} | |||
private boolean shouldRegister(String language, String profileName) { | |||
return loadedTemplateDao.countByTypeAndKey(LoadedTemplateDto.QUALITY_PROFILE_TYPE, templateKey(language, profileName)) == 0; | |||
} | |||
private static String templateKey(String language, String profileName) { | |||
return StringUtils.lowerCase(language) + ":" + profileName; | |||
} | |||
private void register(String language, String name, Collection<RulesProfile> profiles) { | |||
clean(language, name); | |||
insert(language, name, profiles); | |||
loadedTemplateDao.insert(new LoadedTemplateDto(templateKey(language, name), LoadedTemplateDto.QUALITY_PROFILE_TYPE)); | |||
} | |||
private void verifyLanguage(String language, List<RulesProfile> profiles) { | |||
if (profiles.isEmpty()) { | |||
LOGGER.warn("No Quality Profile defined for language: " + language); | |||
} | |||
Set<String> defaultProfileNames = defaultProfileNames(profiles); | |||
if (defaultProfileNames.size() > 1) { | |||
throw new SonarException("Several Quality Profiles are flagged as default for the language " + language + ": " + | |||
defaultProfileNames); | |||
} | |||
} | |||
/** | |||
* @return profiles by language | |||
*/ | |||
private ListMultimap<String, RulesProfile> loadDefinitions() { | |||
ListMultimap<String, RulesProfile> byLang = ArrayListMultimap.create(); | |||
for (ProfileDefinition definition : definitions) { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = definition.createProfile(validation); | |||
validation.log(LOGGER); | |||
if (profile != null && !validation.hasErrors()) { | |||
byLang.put(StringUtils.lowerCase(profile.getLanguage()), profile); | |||
} | |||
} | |||
return byLang; | |||
} | |||
private static String defaultProfileName(List<RulesProfile> profiles) { | |||
String defaultName = null; | |||
boolean hasSonarWay = false; | |||
for (RulesProfile profile : profiles) { | |||
if (profile.getDefaultProfile()) { | |||
defaultName = profile.getName(); | |||
} else if (DEFAULT_PROFILE_NAME.equals(profile.getName())) { | |||
hasSonarWay = true; | |||
} | |||
} | |||
if (StringUtils.isBlank(defaultName) && !hasSonarWay && !profiles.isEmpty()) { | |||
defaultName = profiles.get(0).getName(); | |||
} | |||
return StringUtils.defaultIfBlank(defaultName, DEFAULT_PROFILE_NAME); | |||
} | |||
private static Set<String> defaultProfileNames(Collection<RulesProfile> profiles) { | |||
Set<String> names = Sets.newHashSet(); | |||
for (RulesProfile profile : profiles) { | |||
if (profile.getDefaultProfile()) { | |||
names.add(profile.getName()); | |||
} | |||
} | |||
return names; | |||
} | |||
// | |||
// PERSISTENCE | |||
// | |||
private void insert(String language, String name, Collection<RulesProfile> profiles) { | |||
RulesProfile persisted = RulesProfile.create(name, language); | |||
for (RulesProfile profile : profiles) { | |||
for (ActiveRule activeRule : profile.getActiveRules()) { | |||
Rule rule = persistedRule(activeRule); | |||
ActiveRule persistedActiveRule = persisted.activateRule(rule, activeRule.getSeverity()); | |||
for (RuleParam param : rule.getParams()) { | |||
String value = StringUtils.defaultString(activeRule.getParameter(param.getKey()), param.getDefaultValue()); | |||
if (value != null) { | |||
persistedActiveRule.setParameter(param.getKey(), value); | |||
} | |||
} | |||
} | |||
} | |||
session.saveWithoutFlush(persisted); | |||
} | |||
private Rule persistedRule(ActiveRule activeRule) { | |||
Rule rule = activeRule.getRule(); | |||
if (rule != null && rule.getId() == null) { | |||
if (rule.getKey() != null) { | |||
rule = ruleFinder.findByKey(rule.getRepositoryKey(), rule.getKey()); | |||
} else if (rule.getConfigKey() != null) { | |||
rule = ruleFinder.find(RuleQuery.create().withRepositoryKey(rule.getRepositoryKey()).withConfigKey(rule.getConfigKey())); | |||
} | |||
} | |||
return rule; | |||
} | |||
private void clean(String language, String name) { | |||
List<RulesProfile> existingProfiles = session.getResults(RulesProfile.class, "language", language, "name", name); | |||
for (RulesProfile profile : existingProfiles) { | |||
session.removeWithoutFlush(profile); | |||
} | |||
} | |||
} |
@@ -1,190 +0,0 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2008-2012 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.server.startup; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.sonar.api.database.DatabaseSession; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RuleParam; | |||
import org.sonar.api.rules.RuleQuery; | |||
import org.sonar.api.utils.SonarException; | |||
import org.sonar.api.utils.TimeProfiler; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.jpa.session.DatabaseSessionFactory; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.Maps; | |||
import com.google.common.collect.Sets; | |||
public final class RegisterProvidedProfiles { | |||
private static final Logger LOGGER = LoggerFactory.getLogger(RegisterProvidedProfiles.class); | |||
private DatabaseSessionFactory sessionFactory; | |||
private List<ProfileDefinition> definitions = Lists.newArrayList(); | |||
private RuleFinder ruleFinder; | |||
public RegisterProvidedProfiles(RuleFinder ruleFinder, DatabaseSessionFactory sessionFactory,// NOSONAR the parameter registerRulesBefore is unused must be declared for execution order of tasks | |||
RegisterRules registerRulesBefore, | |||
ProfileDefinition[] definitions) { | |||
this.ruleFinder = ruleFinder; | |||
this.sessionFactory = sessionFactory; | |||
this.definitions.addAll(Arrays.asList(definitions)); | |||
} | |||
public RegisterProvidedProfiles(RuleFinder ruleFinder, DatabaseSessionFactory sessionFactory,// NOSONAR the parameter registerRulesBefore is unused must be declared for execution order of tasks | |||
RegisterRules registerRulesBefore) { | |||
this.ruleFinder = ruleFinder; | |||
this.sessionFactory = sessionFactory; | |||
} | |||
public void start() { | |||
TimeProfiler profiler = new TimeProfiler().start("Load provided profiles"); | |||
List<RulesProfile> profiles = createProfiles(); | |||
DatabaseSession session = sessionFactory.getSession(); | |||
cleanProvidedProfiles(profiles, session); | |||
saveProvidedProfiles(profiles, session); | |||
session.commit(); | |||
profiler.stop(); | |||
} | |||
private List<RulesProfile> createProfiles() { | |||
List<RulesProfile> result = Lists.newArrayList(); | |||
Map<String, RulesProfile> defaultProfilesByLanguage = Maps.newHashMap(); | |||
for (ProfileDefinition definition : definitions) { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = definition.createProfile(validation); | |||
validation.log(LOGGER); | |||
if (profile != null && !validation.hasErrors()) { | |||
result.add(profile); | |||
checkIfNoMoreThanOneDefaultProfile(defaultProfilesByLanguage, profile); | |||
} | |||
} | |||
return result; | |||
} | |||
private void checkIfNoMoreThanOneDefaultProfile(Map<String, RulesProfile> defaultProfilesByLanguage, RulesProfile profile) { | |||
if (profile.getDefaultProfile()) { | |||
RulesProfile defaultProfileForLanguage = defaultProfilesByLanguage.get(profile.getLanguage()); | |||
if (defaultProfileForLanguage == null) { | |||
defaultProfilesByLanguage.put(profile.getLanguage(), profile); | |||
} else { | |||
throw new SonarException("Language " + profile.getLanguage() + " can't have 2 default provided profiles: " | |||
+ profile.getName() + " and " | |||
+ defaultProfileForLanguage.getName()); | |||
} | |||
} | |||
} | |||
private void cleanProvidedProfiles(List<RulesProfile> profiles, DatabaseSession session) { | |||
TimeProfiler profiler = new TimeProfiler().start("Clean provided profiles"); | |||
List<RulesProfile> existingProfiles = session.getResults(RulesProfile.class, "provided", true); | |||
for (RulesProfile existingProfile : existingProfiles) { | |||
boolean isDeprecated = true; | |||
for (RulesProfile profile : profiles) { | |||
if (StringUtils.equals(existingProfile.getName(), profile.getName()) && StringUtils.equals(existingProfile.getLanguage(), profile.getLanguage())) { | |||
isDeprecated = false; | |||
break; | |||
} | |||
} | |||
if (isDeprecated) { | |||
session.removeWithoutFlush(existingProfile); | |||
} else { | |||
for (ActiveRule activeRule : existingProfile.getActiveRules()) { | |||
session.removeWithoutFlush(activeRule); | |||
} | |||
existingProfile.setActiveRules(new ArrayList<ActiveRule>()); | |||
session.saveWithoutFlush(existingProfile); | |||
} | |||
} | |||
profiler.stop(); | |||
} | |||
private void saveProvidedProfiles(List<RulesProfile> profiles, DatabaseSession session) { | |||
Collection<String> languagesWithDefaultProfile = findLanguagesWithDefaultProfile(session); | |||
for (RulesProfile profile : profiles) { | |||
TimeProfiler profiler = new TimeProfiler().start("Save profile " + profile); | |||
RulesProfile persistedProfile = findOrCreate(profile, session, languagesWithDefaultProfile.contains(profile.getLanguage())); | |||
for (ActiveRule activeRule : profile.getActiveRules()) { | |||
Rule rule = getPersistedRule(activeRule); | |||
ActiveRule persistedRule = persistedProfile.activateRule(rule, activeRule.getSeverity()); | |||
for (RuleParam param : rule.getParams()) { | |||
String value = StringUtils.defaultString(activeRule.getParameter(param.getKey()), param.getDefaultValue()); | |||
if (value != null) { | |||
persistedRule.setParameter(param.getKey(), value); | |||
} | |||
} | |||
} | |||
session.saveWithoutFlush(persistedProfile); | |||
profiler.stop(); | |||
} | |||
} | |||
private Collection<String> findLanguagesWithDefaultProfile(DatabaseSession session) { | |||
Set<String> languagesWithDefaultProfile = Sets.newHashSet(); | |||
List<RulesProfile> defaultProfiles = session.getResults(RulesProfile.class, "defaultProfile", true); | |||
for (RulesProfile defaultProfile : defaultProfiles) { | |||
languagesWithDefaultProfile.add(defaultProfile.getLanguage()); | |||
} | |||
return languagesWithDefaultProfile; | |||
} | |||
private Rule getPersistedRule(ActiveRule activeRule) { | |||
Rule rule = activeRule.getRule(); | |||
if (rule != null && rule.getId() == null) { | |||
if (rule.getKey() != null) { | |||
rule = ruleFinder.findByKey(rule.getRepositoryKey(), rule.getKey()); | |||
} else if (rule.getConfigKey() != null) { | |||
rule = ruleFinder.find(RuleQuery.create().withRepositoryKey(rule.getRepositoryKey()).withConfigKey(rule.getConfigKey())); | |||
} | |||
} | |||
return rule; | |||
} | |||
private RulesProfile findOrCreate(RulesProfile profile, DatabaseSession session, boolean defaultProfileAlreadyExist) { | |||
RulesProfile persistedProfile = session.getSingleResult(RulesProfile.class, "name", profile.getName(), "language", profile.getLanguage()); | |||
if (persistedProfile == null) { | |||
persistedProfile = RulesProfile.create(profile.getName(), profile.getLanguage()); | |||
persistedProfile.setProvided(true); | |||
if (!defaultProfileAlreadyExist) { | |||
persistedProfile.setDefaultProfile(profile.getDefaultProfile()); | |||
} | |||
} | |||
return persistedProfile; | |||
} | |||
} |
@@ -30,9 +30,9 @@ class Api::ProfilesController < Api::ApiController | |||
name=params[:name] | |||
if name.blank? | |||
@profile=Profile.find(:first, :conditions => ['language=? and default_profile=?', language, true]) | |||
@profile=Profile.by_default(language) | |||
else | |||
@profile=Profile.find(:first, :conditions => ['language=? and name=?', language, name]) | |||
@profile=Profile.find_by_name_and_language(name, language) | |||
end | |||
raise ApiException.new(404, "Profile not found") if @profile.nil? | |||
@@ -60,9 +60,9 @@ class Api::ProfilesController < Api::ApiController | |||
bad_request('Missing parameter: language') if params[:language].blank? | |||
if params[:name].blank? | |||
profile=Profile.find(:first, :conditions => ['language=? and default_profile=?', params[:language], true]) | |||
profile=Profile.by_default(params[:language]) | |||
else | |||
profile=Profile.find(:first, :conditions => ['language=? and name=?', params[:language], params[:name]]) | |||
profile=Profile.find_by_name_and_language(params[:name], params[:language]) | |||
end | |||
not_found('Profile not found') unless profile | |||
@@ -124,8 +124,7 @@ class Api::ProfilesController < Api::ApiController | |||
result[:name]=@profile.name | |||
result[:language]=@profile.language | |||
result[:parent]=@profile.parent_name if @profile.parent_name.present? | |||
result[:default]=@profile.default_profile | |||
result[:provided]=@profile.provided | |||
result[:default]=@profile.default_profile? | |||
rules=[] | |||
@active_rules.each do |active_rule| | |||
@@ -162,8 +161,7 @@ class Api::ProfilesController < Api::ApiController | |||
xml.name(@profile.name) | |||
xml.language(@profile.language) | |||
xml.parent(@profile.parent_name) if @profile.parent_name.present? | |||
xml.default(@profile.default_profile) | |||
xml.provided(@profile.provided) | |||
xml.default(@profile.default_profile?) | |||
@active_rules.each do |active_rule| | |||
xml.rule do |
@@ -25,7 +25,8 @@ class ProfilesController < ApplicationController | |||
# GET /profiles/index | |||
def index | |||
@profiles = Profile.find(:all, :order => 'name') | |||
@profiles = Profile.find(:all) | |||
Api::Utils.insensitive_sort!(@profiles){|profile| profile.name} | |||
end | |||
@@ -50,7 +51,7 @@ class ProfilesController < ApplicationController | |||
profile_name=params[:name] | |||
language=params[:language] | |||
profile = Profile.create(:name => profile_name, :language => language, :default_profile => false) | |||
profile = Profile.create(:name => profile_name, :language => language) | |||
ok = profile.errors.empty? | |||
if ok && params[:backup] | |||
params[:backup].each_pair do |importer_key, file| | |||
@@ -92,7 +93,6 @@ class ProfilesController < ApplicationController | |||
profile = Profile.find(params[:id]) | |||
profile.set_as_default | |||
#TODO remove l10n key: flash[:notice]=message('quality_profiles.default_profile_is_x', :params => profile.name) | |||
redirect_to :action => 'index' | |||
end | |||
@@ -113,7 +113,7 @@ class ProfilesController < ApplicationController | |||
@profile = Profile.find(params[:id]) | |||
name = params['name'] | |||
target_profile=Profile.new(:name => name, :language => @profile.language, :provided => false, :default_profile => false) | |||
target_profile=Profile.new(:name => name, :language => @profile.language) | |||
if target_profile.valid? | |||
java_facade.copyProfile(@profile.id, name) | |||
flash[:notice]= message('quality_profiles.profile_x_not_activated', :params => name) | |||
@@ -257,31 +257,33 @@ class ProfilesController < ApplicationController | |||
end | |||
# POST /profiles/add_project?id=<profile id>&project_id=<project id> | |||
# POST /profiles/add_project?id=<profile id>&project=<project id or key> | |||
def add_project | |||
verify_post_request | |||
require_parameters 'id', 'project_id' | |||
require_parameters 'id', 'project' | |||
admin_required | |||
profile=Profile.find(params[:id]) | |||
bad_request('Unknown profile') unless profile | |||
project=Project.find(params[:project_id]) | |||
project=Project.by_key(params[:project]) | |||
bad_request('Unknown project') unless project | |||
profile.add_project_id(project.id) | |||
redirect_to :action => 'projects', :id => profile.id | |||
end | |||
# POST /profiles/remove_project?id=<profile id>&project_id=<project id> | |||
# POST /profiles/remove_project?id=<profile id>&project=<project id or key> | |||
def remove_project | |||
verify_post_request | |||
require_parameters 'id', 'project_id' | |||
require_parameters 'id', 'project' | |||
admin_required | |||
profile=Profile.find(params[:id]) | |||
bad_request('Unknown profile') unless profile | |||
project=Project.by_key(params[:project]) | |||
bad_request('Unknown project') unless project | |||
Profile.reset_default_profile_for_project_id(profile.language, params[:project_id]) | |||
Profile.reset_default_profile_for_project_id(profile.language, project.id) | |||
redirect_to :action => 'projects', :id => profile.id | |||
end | |||
@@ -22,18 +22,18 @@ require 'cgi' | |||
class RulesConfigurationController < ApplicationController | |||
SECTION=Navigation::SECTION_CONFIGURATION | |||
STATUS_ACTIVE = "ACTIVE" | |||
STATUS_INACTIVE = "INACTIVE" | |||
ANY_SELECTION = [["Any", '']] | |||
RULE_PRIORITIES = Sonar::RulePriority.as_options.reverse | |||
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) | |||
verify :method => :post, | |||
:only => ['activate_rule', 'update_param', 'bulk_edit', 'create', 'update', 'delete', 'revert_rule', 'update_rule_note', 'update_active_rule_note', 'delete_active_rule_note'], | |||
:redirect_to => { :action => 'index' } | |||
verify :method => :post, | |||
:only => ['activate_rule', 'update_param', 'bulk_edit', 'create', 'update', 'delete', 'revert_rule', 'update_rule_note', 'update_active_rule_note', 'delete_active_rule_note'], | |||
:redirect_to => {:action => 'index'} | |||
before_filter :admin_required, :except => [ 'index', 'export' ] | |||
before_filter :admin_required, :except => ['index', 'export'] | |||
def index | |||
unless params[:id].blank? | |||
@@ -50,28 +50,28 @@ class RulesConfigurationController < ApplicationController | |||
else | |||
@profile = Profile.default_profile | |||
end | |||
init_params() | |||
@select_plugins = ANY_SELECTION + java_facade.getRuleRepositoriesByLanguage(@profile.language).collect { |repo| [repo.getName(true), repo.getKey()]}.sort | |||
@select_plugins = ANY_SELECTION + java_facade.getRuleRepositoriesByLanguage(@profile.language).collect { |repo| [repo.getName(true), repo.getKey()] }.sort | |||
@select_priority = ANY_SELECTION + RULE_PRIORITIES | |||
@select_status = [[message('any'),''], [message('active'), STATUS_ACTIVE], [message('inactive'), STATUS_INACTIVE]] | |||
@select_inheritance = [[message('any'),''], [message('rules_configuration.not_inherited'), 'NOT'], [message('rules_configuration.inherited'), 'INHERITED'], [message('rules_configuration.overrides'), 'OVERRIDES']] | |||
@select_status = [[message('any'), ''], [message('active'), STATUS_ACTIVE], [message('inactive'), STATUS_INACTIVE]] | |||
@select_inheritance = [[message('any'), ''], [message('rules_configuration.not_inherited'), 'NOT'], [message('rules_configuration.inherited'), 'INHERITED'], [message('rules_configuration.overrides'), 'OVERRIDES']] | |||
@rules = Rule.search(java_facade, { | |||
:profile => @profile, :status => @status, :priorities => @priorities, :inheritance => @inheritance, | |||
:plugins => @plugins, :searchtext => @searchtext, :include_parameters_and_notes => true, :language => @profile.language}) | |||
:plugins => @plugins, :searchtext => @searchtext, :include_parameters_and_notes => true, :language => @profile.language}) | |||
unless @searchtext.blank? | |||
if @status==STATUS_ACTIVE | |||
@hidden_inactives=Rule.search(java_facade, { | |||
:profile => @profile, :status => STATUS_INACTIVE, :priorities => @priorities, | |||
:plugins => @plugins, :language => @profile.language, :searchtext => @searchtext, :include_parameters_and_notes => false}).size | |||
:plugins => @plugins, :language => @profile.language, :searchtext => @searchtext, :include_parameters_and_notes => false}).size | |||
elsif @status==STATUS_INACTIVE | |||
@hidden_actives=Rule.search(java_facade, { | |||
:profile => @profile, :status => STATUS_ACTIVE, :priorities => @priorities, | |||
:plugins => @plugins, :language => @profile.language, :searchtext => @searchtext, :include_parameters_and_notes => false}).size | |||
:plugins => @plugins, :language => @profile.language, :searchtext => @searchtext, :include_parameters_and_notes => false}).size | |||
end | |||
end | |||
@@ -100,7 +100,7 @@ class RulesConfigurationController < ApplicationController | |||
# | |||
def activate_rule | |||
profile = Profile.find(params[:id].to_i) | |||
if profile && !profile.provided? | |||
if profile | |||
rule=Rule.find(:first, :conditions => {:id => params[:rule_id].to_i, :enabled => true}) | |||
priority=params[:level] | |||
@@ -117,7 +117,7 @@ class RulesConfigurationController < ApplicationController | |||
activated = false | |||
if active_rule.nil? | |||
active_rule = ActiveRule.new(:profile_id => profile.id, :rule => rule) | |||
rule.parameters.select{|p| p.default_value.present?}.each do |p| | |||
rule.parameters.select { |p| p.default_value.present? }.each do |p| | |||
active_rule.active_rule_parameters.build(:rules_parameter => p, :value => p.default_value) | |||
end | |||
activated = true | |||
@@ -126,9 +126,9 @@ class RulesConfigurationController < ApplicationController | |||
active_rule.failure_level=Sonar::RulePriority.id(priority) | |||
active_rule.save! | |||
if activated | |||
java_facade.ruleActivated(profile.id, active_rule.id, current_user.name) | |||
java_facade.ruleActivated(profile.id, active_rule.id, current_user.name) | |||
else | |||
java_facade.ruleSeverityChanged(profile.id, active_rule.id, old_severity, active_rule.failure_level, current_user.name) | |||
java_facade.ruleSeverityChanged(profile.id, active_rule.id, old_severity, active_rule.failure_level, current_user.name) | |||
end | |||
end | |||
if active_rule | |||
@@ -163,33 +163,33 @@ class RulesConfigurationController < ApplicationController | |||
def create | |||
template=Rule.find(params[:rule_id]) | |||
rule=Rule.create(params[:rule].merge( | |||
{ | |||
:priority => Sonar::RulePriority.id(params[:rule][:priority]), | |||
:parent_id => template.id, | |||
:plugin_name => template.plugin_name, | |||
:cardinality => 'SINGLE', | |||
:plugin_rule_key => "#{template.plugin_rule_key}_#{Time.now.to_i}", | |||
:plugin_config_key => template.plugin_config_key, | |||
:enabled => true})) | |||
{ | |||
:priority => Sonar::RulePriority.id(params[:rule][:priority]), | |||
:parent_id => template.id, | |||
:plugin_name => template.plugin_name, | |||
:cardinality => 'SINGLE', | |||
:plugin_rule_key => "#{template.plugin_rule_key}_#{Time.now.to_i}", | |||
:plugin_config_key => template.plugin_config_key, | |||
:enabled => true})) | |||
template.parameters.each do |template_parameter| | |||
rule.rules_parameters.build(:name => template_parameter.name, :param_type => template_parameter.param_type, :description => template_parameter.description, | |||
:default_value => params[:rule_param][template_parameter.name]) | |||
:default_value => params[:rule_param][template_parameter.name]) | |||
end | |||
if rule.save | |||
redirect_to :action => 'index', :id => params[:id], :searchtext => rule.name, :rule_status => 'INACTIVE', "plugins[]" => rule.plugin_name | |||
else | |||
flash[:error]=message('rules_configuration.rule_not_valid_message_x', :params => rule.errors.full_messages.join('<br/>')) | |||
redirect_to :action => 'new', :id => params[:id], :rule_id => params[:rule_id] | |||
end | |||
end | |||
end | |||
# deprecated since 2.3 | |||
def export | |||
redirect_to request.query_parameters.merge({:controller => 'profiles', :action => 'export'}) | |||
redirect_to request.query_parameters.merge({:controller => 'profiles', :action => 'export'}) | |||
end | |||
# | |||
@@ -266,19 +266,19 @@ class RulesConfigurationController < ApplicationController | |||
# | |||
def bulk_edit | |||
profile = Profile.find(params[:id].to_i) | |||
rule_ids = params[:bulk_rule_ids].split(',').map{|id| id.to_i} | |||
rule_ids = params[:bulk_rule_ids].split(',').map { |id| id.to_i } | |||
status=params[:rule_status] | |||
case params[:bulk_action] | |||
when 'activate' | |||
count=activate_rules(profile, rule_ids) | |||
flash[:notice]=message('rules_configuration.x_rules_have_been_activated', :params => count) | |||
status=STATUS_ACTIVE if status==STATUS_INACTIVE | |||
when 'deactivate' | |||
count=deactivate_rules(profile, rule_ids) | |||
flash[:notice]=message('rules_configuration.x_rules_have_been_deactivated', :params => count) | |||
status=STATUS_INACTIVE if status==STATUS_ACTIVE | |||
when 'activate' | |||
count=activate_rules(profile, rule_ids) | |||
flash[:notice]=message('rules_configuration.x_rules_have_been_activated', :params => count) | |||
status=STATUS_ACTIVE if status==STATUS_INACTIVE | |||
when 'deactivate' | |||
count=deactivate_rules(profile, rule_ids) | |||
flash[:notice]=message('rules_configuration.x_rules_have_been_deactivated', :params => count) | |||
status=STATUS_INACTIVE if status==STATUS_ACTIVE | |||
end | |||
url_parameters=request.query_parameters.merge({:action => 'index', :bulk_action => nil, :bulk_rule_ids => nil, :id => profile.id, :rule_status => status}) | |||
@@ -286,7 +286,6 @@ class RulesConfigurationController < ApplicationController | |||
end | |||
def update_param | |||
is_admin=true # security has already been checked by controller filters | |||
profile = Profile.find(params[:profile_id].to_i) | |||
@@ -294,25 +293,23 @@ class RulesConfigurationController < ApplicationController | |||
active_rule = ActiveRule.find(params[:active_rule_id].to_i) | |||
active_param = ActiveRuleParameter.find(params[:id].to_i) if params[:id].to_i > 0 | |||
value = params[:value] | |||
if !profile.provided? | |||
if value != "" | |||
active_param = ActiveRuleParameter.new(:rules_parameter => rule_param, :active_rule => active_rule ) if active_param.nil? | |||
old_value = active_param.value | |||
active_param.value = value | |||
if active_param.save! && active_param.valid? | |||
active_param.reload | |||
java_facade.ruleParamChanged(profile.id, active_rule.id, rule_param.name, old_value, value, current_user.name) | |||
end | |||
elsif !active_param.nil? | |||
old_value = active_param.value | |||
active_param.destroy | |||
active_param = nil | |||
java_facade.ruleParamChanged(profile.id, active_rule.id, rule_param.name, old_value, nil, current_user.name) | |||
if value != "" | |||
active_param = ActiveRuleParameter.new(:rules_parameter => rule_param, :active_rule => active_rule) if active_param.nil? | |||
old_value = active_param.value | |||
active_param.value = value | |||
if active_param.save! && active_param.valid? | |||
active_param.reload | |||
java_facade.ruleParamChanged(profile.id, active_rule.id, rule_param.name, old_value, value, current_user.name) | |||
end | |||
elsif !active_param.nil? | |||
old_value = active_param.value | |||
active_param.destroy | |||
active_param = nil | |||
java_facade.ruleParamChanged(profile.id, active_rule.id, rule_param.name, old_value, nil, current_user.name) | |||
end | |||
# let's reload the active rule | |||
# let's reload the active rule | |||
active_rule = ActiveRule.find(active_rule.id) | |||
render :partial => 'rule', :locals => {:profile => profile, :rule => active_rule.rule, :active_rule => active_rule, :is_admin => is_admin } | |||
render :partial => 'rule', :locals => {:profile => profile, :rule => active_rule.rule, :active_rule => active_rule, :is_admin => is_admin} | |||
end | |||
@@ -327,7 +324,7 @@ class RulesConfigurationController < ApplicationController | |||
note.text = params[:text] | |||
note.user_login = current_user.login | |||
note.save! | |||
render :partial => 'rule_note', :locals => {:rule => rule, :is_admin => true } | |||
render :partial => 'rule_note', :locals => {:rule => rule, :is_admin => true} | |||
end | |||
@@ -342,27 +339,26 @@ class RulesConfigurationController < ApplicationController | |||
note.text = params[:note] | |||
note.user_login = current_user.login | |||
note.save! | |||
render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :is_admin => true, :profile => active_rule.rules_profile } | |||
render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :is_admin => true, :profile => active_rule.rules_profile} | |||
end | |||
def delete_active_rule_note | |||
active_rule = ActiveRule.find(params[:active_rule_id]) | |||
active_rule.note.destroy if active_rule.note | |||
active_rule.note = nil | |||
render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :is_admin => true, :profile => active_rule.rules_profile } | |||
render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :is_admin => true, :profile => active_rule.rules_profile} | |||
end | |||
private | |||
# return the number of newly activated rules | |||
def activate_rules(profile, rule_ids) | |||
count=0 | |||
rule_ids_to_activate=(rule_ids - profile.active_rules.map{|ar| ar.rule_id}) | |||
rule_ids_to_activate=(rule_ids - profile.active_rules.map { |ar| ar.rule_id }) | |||
unless rule_ids_to_activate.empty? | |||
rules_to_activate=Rule.find(:all, :conditions => {:enabled=>true, :id => rule_ids_to_activate}) | |||
rules_to_activate=Rule.find(:all, :conditions => {:enabled => true, :id => rule_ids_to_activate}) | |||
count = rules_to_activate.size | |||
rules_to_activate.each do |rule| | |||
active_rule = profile.active_rules.create(:rule => rule, :failure_level => rule.priority) | |||
@@ -395,7 +391,7 @@ class RulesConfigurationController < ApplicationController | |||
def filter_any(array) | |||
if array && array.size>1 && array.include?('') | |||
array=[''] #keep only 'any' | |||
array=[''] #keep only 'any' | |||
end | |||
array | |||
end |
@@ -60,21 +60,12 @@ class Profile < ActiveRecord::Base | |||
"#{language}_#{name}" | |||
end | |||
def provided? | |||
provided | |||
def default_profile? | |||
Property.value("sonar.profile.#{language}")==name | |||
end | |||
def set_as_default | |||
Profile.transaction do | |||
Profile.find(:all, :conditions => {:language => language}).each do |profile| | |||
if profile.id==id | |||
profile.default_profile=true | |||
else | |||
profile.default_profile=false | |||
end | |||
profile.save | |||
end | |||
end | |||
Property.set("sonar.profile.#{language}", name) | |||
self | |||
end | |||
@@ -105,14 +96,14 @@ class Profile < ActiveRecord::Base | |||
end | |||
def deletable? | |||
!provided? && !default_profile? && children.empty? | |||
!default_profile? && children.empty? | |||
end | |||
def count_overriding_rules | |||
@count_overriding_rules||= | |||
begin | |||
active_rules.count(:conditions => ['inheritance=?', 'OVERRIDES']) | |||
end | |||
begin | |||
active_rules.count(:conditions => ['inheritance=?', 'OVERRIDES']) | |||
end | |||
end | |||
def inherited? | |||
@@ -121,13 +112,13 @@ class Profile < ActiveRecord::Base | |||
def parent | |||
@parent||= | |||
begin | |||
if parent_name.present? | |||
Profile.find(:first, :conditions => ['language=? and name=?', language, parent_name]) | |||
else | |||
nil | |||
begin | |||
if parent_name.present? | |||
Profile.find(:first, :conditions => ['language=? and name=?', language, parent_name]) | |||
else | |||
nil | |||
end | |||
end | |||
end | |||
end | |||
def count_active_rules | |||
@@ -136,14 +127,14 @@ class Profile < ActiveRecord::Base | |||
def ancestors | |||
@ancestors ||= | |||
begin | |||
array=[] | |||
if parent | |||
array<<parent | |||
array.concat(parent.ancestors) | |||
begin | |||
array=[] | |||
if parent | |||
array<<parent | |||
array.concat(parent.ancestors) | |||
end | |||
array | |||
end | |||
array | |||
end | |||
end | |||
def import_configuration(importer_key, file) | |||
@@ -160,8 +151,8 @@ class Profile < ActiveRecord::Base | |||
end | |||
def before_destroy | |||
raise 'This profile can not be deleted' unless deletable? | |||
Property.clear_for_resources("sonar.profile.#{language}", name) | |||
#TODO clear global property sonar.profile.#{language} with value #{name} | |||
end | |||
def rename(new_name) | |||
@@ -186,14 +177,14 @@ class Profile < ActiveRecord::Base | |||
def projects | |||
@projects ||= | |||
begin | |||
Project.find(:all, | |||
:conditions => ['id in (select prop.resource_id from properties prop where prop.resource_id is not null and prop.prop_key=? and prop.text_value like ?)', "sonar.profile.#{language}", name]) | |||
end | |||
begin | |||
Project.find(:all, | |||
:conditions => ['id in (select prop.resource_id from properties prop where prop.resource_id is not null and prop.prop_key=? and prop.text_value like ?)', "sonar.profile.#{language}", name]) | |||
end | |||
end | |||
def sorted_projects | |||
Api::Utils.insensitive_sort(projects){|p| p.name} | |||
Api::Utils.insensitive_sort(projects) { |p| p.name } | |||
end | |||
def add_project_id(project_id) | |||
@@ -221,7 +212,8 @@ class Profile < ActiveRecord::Base | |||
end | |||
def self.by_default(language) | |||
Profile.find(:first, :conditions => {:default_profile => true, :language => language}) | |||
default_name = Property.value("sonar.profile.#{language}") | |||
default_name.present? ? Profile.find(:first, :conditions => {:name => default_name, :language => language}) : nil | |||
end | |||
# Results are NOT sorted |
@@ -2,17 +2,9 @@ | |||
<%= render :partial => 'profiles/tabs', :locals => {:selected_tab=>'Alerts'} %> | |||
<% if is_admin? %> | |||
<% if @profile.provided? %> | |||
<div class="tabs-panel marginbottom10 background-gray"> | |||
<div class="line-info note"> | |||
<%= message('rules_configuration.profile_cant_be_updated_description') -%> | |||
</div> | |||
</div> | |||
<% else %> | |||
<div class="tabs-panel marginbottom10 admin" id="new_alert_form"> | |||
<%= render :partial => 'new' %> | |||
</div> | |||
<% end %> | |||
<div class="tabs-panel marginbottom10 admin" id="new_alert_form"> | |||
<%= render :partial => 'new' %> | |||
</div> | |||
<% else %> | |||
<div class="break10"> </div> | |||
<% end %> | |||
@@ -28,10 +20,8 @@ | |||
<% for alert in @alerts %> | |||
<tr class="<%= cycle('even','odd') -%>"> | |||
<td id="row_alert_<%= alert.id -%>"> | |||
<% if is_admin? && !@profile.provided? %> | |||
<% if is_admin? %> | |||
<%= render :partial => 'edit', :locals => {:alert => alert} %> | |||
<% else %> | |||
<%= render :partial => 'show', :locals => {:alert => alert} %> | |||
<% end %> | |||
</td> | |||
</tr> |
@@ -79,17 +79,13 @@ | |||
<% if administrator? %> | |||
<td align="right"> | |||
<% if !profile.provided? %> | |||
<form method="post" action="/dev/profiles/backup/<%= profile.id -%>" id="backup-<%= profile.key.parameterize -%>-form"> | |||
<a href="#" class="link-action" name="button_backup" id="backup_<%= u profile.key %>" onclick="$j('#backup-<%= profile.key.parameterize -%>-form').submit();return false;"><%= message('backup_verb') -%></a> | |||
</form> | |||
<% end %> | |||
<form method="post" action="/dev/profiles/backup/<%= profile.id -%>" id="backup-<%= profile.key.parameterize -%>-form"> | |||
<a href="#" class="link-action" name="button_backup" id="backup_<%= u profile.key %>" onclick="$j('#backup-<%= profile.key.parameterize -%>-form').submit();return false;"><%= message('backup_verb') -%></a> | |||
</form> | |||
</td> | |||
<td align="right"> | |||
<% if !profile.provided? %> | |||
<a id="rename-<%= profile.key.parameterize -%>" href="profiles/rename_form/<%= profile.id -%>" class="link-action open-modal"><%= message('rename') -%></a> | |||
<% end %> | |||
<a id="rename-<%= profile.key.parameterize -%>" href="profiles/rename_form/<%= profile.id -%>" class="link-action open-modal"><%= message('rename') -%></a> | |||
</td> | |||
<td align="right"> |
@@ -30,10 +30,6 @@ | |||
<% if is_admin? %> | |||
<td valign="top" width="300"> | |||
<div class="admin"> | |||
<% if @profile.provided? %> | |||
<p><%= message('quality_profiles.profile_cant_be_edited') -%></p> | |||
<% else %> | |||
<h3><%= message('quality_profiles.set_parent') -%>:</h3> | |||
<p><%= message('quality_profiles.inherit_rules_from_profile') -%>:</p> | |||
<% form_tag({:action => 'change_parent'}, {:method => 'post'}) do %> | |||
@@ -41,7 +37,6 @@ | |||
<%= select_tag "parent_name", options_for_select(@select_parent, @profile.parent_name) %> | |||
<%= submit_tag message('change_verb'), :id => 'submit_parent'%> | |||
<% end %> | |||
<% end %> | |||
</div> | |||
</td> | |||
<% end %> |
@@ -8,7 +8,7 @@ | |||
<form method="POST" action="<%= ApplicationController.root_context -%>/profiles/add_project" id="add_project_form"> | |||
<input type="hidden" name="id" value="<%= @profile.id -%>"/> | |||
Add project: <%= resource_select_tag 'project_id', { | |||
Add project: <%= resource_select_tag 'project', { | |||
:qualifiers => ['TRK'], | |||
:width => '400px', | |||
:html_id => "select-project", | |||
@@ -32,7 +32,7 @@ | |||
<tr class="<%= cycle('even', 'odd') -%>"> | |||
<td class="thin"> | |||
<%= link_to_action message('quality_profiles.remove_project_action'), | |||
"#{ApplicationController.root_context}/profiles/remove_project?id=#{@profile.id}&project_id=#{project.id}", | |||
"#{ApplicationController.root_context}/profiles/remove_project?id=#{@profile.id}&project=#{project.id}", | |||
:class => 'link-action', | |||
:id => "link-remove-#{project.key.parameterize}", | |||
:confirm_title => 'quality_profiles.remove_project_confirm_title', |
@@ -28,7 +28,7 @@ | |||
</cite> | |||
<p><%= note.html_text -%></p> | |||
</blockquote> | |||
<% elsif is_admin && !profile.provided? %> | |||
<% elsif is_admin %> | |||
<a href="#" onclick="$('<%= active_note_form_div_id -%>').show();$('<%= active_note_detail_div_id -%>').hide();$('<%= active_note_textarea_id -%>').focus(); return false;" | |||
class="link-action spacer-right" id="<%= add_active_note_button_id -%>"><%= message('rules_configuration.add_note') -%></a> | |||
<% end %> |
@@ -1,6 +1,6 @@ | |||
<td nowrap valign="top" class="left" x="<%= active_rule.failure_level if active_rule -%>" width="1%"> | |||
<form id="levels_<%= rule.id -%>" action=""> | |||
<% enable_modification = is_admin && !profile.provided? | |||
<% enable_modification = is_admin | |||
select_box_id = "levels_select_#{rule.id}" | |||
check_box_id = "levels_check_#{rule.id}" | |||
rule_select_box = "$('#{select_box_id}')" |
@@ -2,7 +2,7 @@ | |||
param_value = active_parameter.value if active_parameter | |||
active_param_id = active_parameter.id if active_parameter | |||
active_rule_id = active_rule.id if active_rule | |||
read_only = !active_rule || !is_admin || profile.provided? | |||
read_only = !active_rule || !is_admin | |||
%> | |||
<td class="form-key-cell"><%= parameter.name -%></td> |
@@ -30,15 +30,9 @@ | |||
<%= render :partial => 'profiles/tabs', :locals => {:selected_tab=>'Coding rules'} %> | |||
<% enable_modification = is_admin? && !@profile.provided? %> | |||
<% enable_modification = is_admin? %> | |||
<div class="tabs-panel marginbottom10 background-gray"> | |||
<% if is_admin? && @profile.provided? %> | |||
<div class="line-info note marginbottom10"> | |||
<%= message('rules_configuration.profile_cant_be_updated_description') -%> | |||
</div> | |||
<% end %> | |||
<% form_tag({:action => 'index'}, {:method => 'get'}) do %> | |||
<% hidden_field_tag "id", @id %> | |||
<table class="table" id="search_table"> |
@@ -0,0 +1,41 @@ | |||
# | |||
# Sonar, entreprise quality control tool. | |||
# Copyright (C) 2008-2012 SonarSource | |||
# mailto:contact AT sonarsource DOT com | |||
# | |||
# Sonar 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. | |||
# | |||
# Sonar 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 Sonar; if not, write to the Free Software | |||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
# | |||
# | |||
# Sonar 3.3 | |||
# | |||
class RemoveProfilesDefaultColumn < ActiveRecord::Migration | |||
class Profile < ActiveRecord::Base | |||
set_table_name 'rules_profiles' | |||
end | |||
class Property < ActiveRecord::Base | |||
end | |||
def self.up | |||
Profile.find(:all, :conditions => ['default_profile=true']).each do |profile| | |||
Property.create :prop_key => "sonar.profile.#{profile.language}", :text_value => profile.name | |||
end | |||
remove_column('rules_profiles', 'default_profile') | |||
end | |||
end |
@@ -0,0 +1,30 @@ | |||
# | |||
# Sonar, entreprise quality control tool. | |||
# Copyright (C) 2008-2012 SonarSource | |||
# mailto:contact AT sonarsource DOT com | |||
# | |||
# Sonar 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. | |||
# | |||
# Sonar 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 Sonar; if not, write to the Free Software | |||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
# | |||
# | |||
# Sonar 3.3 | |||
# | |||
class RemoveProfilesProvidedColumn < ActiveRecord::Migration | |||
def self.up | |||
remove_column('rules_profiles', 'provided') | |||
end | |||
end |
@@ -21,24 +21,13 @@ package org.sonar.server.configuration; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.sonar.api.measures.Metric; | |||
import org.sonar.api.profiles.Alert; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.ActiveRuleParam; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleParam; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.jpa.test.AbstractDbUnitTestCase; | |||
import java.util.Arrays; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
import static org.hamcrest.Matchers.equalTo; | |||
import static org.hamcrest.collection.IsCollectionContaining.hasItem; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertNull; | |||
import static org.junit.Assert.assertThat; | |||
public class ProfilesBackupTest extends AbstractDbUnitTestCase { | |||
@@ -85,65 +74,8 @@ public class ProfilesBackupTest extends AbstractDbUnitTestCase { | |||
assertThat(sonarConfig.getProfiles(), hasItem(profileProvided)); | |||
} | |||
@Test | |||
public void shouldImportProvidedProfiles() { | |||
RulesProfile profileProvided = new RulesProfile("test provided", "lang", false, true); | |||
RulesProfile profileNotProvided = new RulesProfile("test not provided", "lang", false, false); | |||
getSession().save(profileProvided, profileNotProvided); | |||
assertThat(getHQLCount(RulesProfile.class), equalTo(2l)); | |||
ProfilesBackup profilesBackup = new ProfilesBackup(getSession()); | |||
assertNull(sonarConfig.getProfiles()); | |||
profilesBackup.importXml(sonarConfig); | |||
assertThat(getHQLCount(RulesProfile.class), equalTo(2l)); | |||
RulesProfile profileProvidedRemains = getSession().getSingleResult(RulesProfile.class, "name", "test provided", "provided", true); | |||
assertNotNull(profileProvidedRemains); | |||
assertEquals(profileProvided, profileProvidedRemains); | |||
} | |||
@Test | |||
public void shouldImportProfiles() { | |||
RulesProfile profileProvided = new RulesProfile("test provided", "lang", false, true); | |||
RulesProfile profileNotProvided = new RulesProfile("test not provided", "lang", false, false); | |||
getSession().save(profileProvided, profileNotProvided); | |||
Rule rule1 = new Rule("testPlugin", "testKey"); | |||
Rule rule2 = new Rule("testPlugin", "testKey2"); | |||
getSession().save(rule1, rule2); | |||
RuleParam ruleParam1 = new RuleParam(rule1, "paramKey", "test", "int"); | |||
getSession().save(ruleParam1); | |||
Metric metric1 = new Metric("testKey"); | |||
Metric metric2 = new Metric("testKey2"); | |||
getSession().save(metric1, metric2); | |||
RulesProfile testProfile = new RulesProfile("testProfile", "lang", false, false); | |||
ActiveRule ar = new ActiveRule(null, new Rule("testPlugin", "testKey"), RulePriority.MAJOR); | |||
ar.getActiveRuleParams().add(new ActiveRuleParam(null, new RuleParam(null, "paramKey", null, null), "testValue")); | |||
testProfile.addActiveRule(ar); | |||
testProfile.addActiveRule(new ActiveRule(null, new Rule("testPlugin", "testKey2"), RulePriority.MINOR)); | |||
testProfile.getAlerts().add(new Alert(null, new Metric("testKey"), Alert.OPERATOR_EQUALS, "10", "22")); | |||
testProfile.getAlerts().add(new Alert(null, new Metric("testKey2"), Alert.OPERATOR_GREATER, "10", "22")); | |||
sonarConfig.setProfiles(Arrays.asList(testProfile)); | |||
ProfilesBackup profilesBackupTest = new ProfilesBackup(getSession()); | |||
profilesBackupTest.importXml(sonarConfig); | |||
assertThat(getHQLCount(RulesProfile.class), equalTo(1l)); | |||
RulesProfile profileProvidedRemains = getSession().getSingleResult(RulesProfile.class, "name", "test provided", "provided", true); | |||
RulesProfile newProfile = getSession().getSingleResult(RulesProfile.class, "name", "testProfile"); | |||
assertNull(profileProvidedRemains); | |||
assertNotNull(newProfile); | |||
assertEquals(2, newProfile.getActiveRules().size()); | |||
assertEquals(1, newProfile.getActiveRules(RulePriority.MAJOR).get(0).getActiveRuleParams().size()); | |||
assertEquals(2, newProfile.getAlerts().size()); | |||
} | |||
} |
@@ -37,8 +37,6 @@ | |||
<profile> | |||
<name><![CDATA[test name]]></name> | |||
<version><![CDATA[1]]></version> | |||
<default-profile><![CDATA[true]]></default-profile> | |||
<provided><![CDATA[true]]></provided> | |||
<used><![CDATA[false]]></used> | |||
<language><![CDATA[test language]]></language> | |||
<active-rules> | |||
@@ -66,8 +64,6 @@ | |||
<profile> | |||
<name><![CDATA[test2 name]]></name> | |||
<version><![CDATA[1]]></version> | |||
<default-profile><![CDATA[false]]></default-profile> | |||
<provided><![CDATA[false]]></provided> | |||
<language><![CDATA[test language]]></language> | |||
<used><![CDATA[false]]></used> | |||
<parentName><![CDATA[test name]]></parentName> |
@@ -5,9 +5,9 @@ | |||
<rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="REGULAR_EXPRESSION"/> | |||
<rules_profiles id="1" version="2" used_profile="false" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="2" used_profile="false" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="2" used_profile="false" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="30"/> |
@@ -5,9 +5,9 @@ | |||
<rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="REGULAR_EXPRESSION"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="30"/> |
@@ -6,11 +6,11 @@ | |||
<rules id="2" name="bar" description="test" plugin_config_key="checker/bar" | |||
plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="new_parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="new_parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="3" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="new_parent" /> | |||
<rules_profiles id="3" version="2" used_profile="false" name="child" language="java" parent_name="new_parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -6,11 +6,11 @@ | |||
<rules id="2" name="bar" description="test" plugin_config_key="checker/bar" | |||
plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="new_parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="new_parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="3" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="3" version="1" used_profile="true" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -3,10 +3,10 @@ | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="level1" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="level1" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="level2" default_profile="0" language="java" parent_name="level1" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="level2" language="java" parent_name="level1" /> | |||
<rules_profiles id="3" version="1" used_profile="true" provided="false" name="level3" default_profile="0" language="java" parent_name="level2" /> | |||
<rules_profiles id="3" version="1" used_profile="true" name="level3" language="java" parent_name="level2" /> | |||
</dataset> |
@@ -3,9 +3,9 @@ | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="2" used_profile="false" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]"/> | |||
<rules_profiles id="1" version="2" used_profile="false" name="parent" language="java" parent_name="[null]"/> | |||
<rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="2" used_profile="false" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -3,9 +3,9 @@ | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -3,9 +3,9 @@ | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="2" used_profile="false" name="child" language="java" parent_name="[null]" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -3,9 +3,9 @@ | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -3,9 +3,9 @@ | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="2" used_profile="false" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -3,9 +3,9 @@ | |||
<rules id="1" name="foo" description="test" plugin_config_key="checker/foo" | |||
plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="child" language="java" parent_name="[null]" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -7,9 +7,9 @@ | |||
plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_parameters id="13" rule_id="2" name="param1" description="[null]" param_type="REGULAR_EXPRESSION"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="child" language="java" parent_name="[null]" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -7,9 +7,9 @@ | |||
plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> | |||
<rules_parameters id="13" rule_id="2" name="param1" description="[null]" param_type="REGULAR_EXPRESSION"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> | |||
@@ -5,9 +5,9 @@ | |||
<rules_parameters id="13" rule_id="2" name="param1" description="[null]" param_type="REGULAR_EXPRESSION"/> | |||
<rules_parameters id="14" rule_id="2" name="param2" description="[null]" param_type="REGULAR_EXPRESSION"/> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="child" language="java" parent_name="parent" /> | |||
<active_rules id="2" profile_id="1" rule_id="2" failure_level="2" inheritance="[null]"/> | |||
<active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="14" value="50"/> |
@@ -1,7 +1,7 @@ | |||
<dataset> | |||
<rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="2" used_profile="false" name="child" language="java" parent_name="parent" /> | |||
</dataset> |
@@ -1,7 +1,7 @@ | |||
<dataset> | |||
<rules_profiles id="1" version="2" used_profile="false" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" /> | |||
<rules_profiles id="1" version="2" used_profile="false" name="parent" language="java" parent_name="[null]" /> | |||
<rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" /> | |||
<rules_profiles id="2" version="2" used_profile="false" name="child" language="java" parent_name="parent" /> | |||
</dataset> |
@@ -6,8 +6,8 @@ | |||
<metrics delete_historical_data="[null]" id="2" name="disabledkey2" val_type="INT" description="description" domain="domain" | |||
short_name="name2" qualitative="false" user_managed="false" enabled="false" origin="JAV" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="1" hidden="false"/> | |||
<rules_profiles id="1" version="1" used_profile="true" name="profile1" default_profile="true" provided="true" language="JAV" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="profile2" default_profile="false" provided="false" language="JAV" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="profile1" language="JAV" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="profile2" language="JAV" /> | |||
<!-- ok --> | |||
<alerts id="1" profile_id="1" metric_id="1" operator=">" value_error="30" value_warning="[null]"/> |
@@ -7,8 +7,8 @@ | |||
short_name="name2" qualitative="false" user_managed="false" enabled="false" origin="JAV" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="1" hidden="false"/> | |||
<rules_profiles id="1" version="1" used_profile="true" name="profile1" default_profile="true" provided="true" language="JAV" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="profile2" default_profile="false" provided="false" language="JAV" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="profile1" language="JAV" /> | |||
<rules_profiles id="2" version="1" used_profile="true" name="profile2" language="JAV" /> | |||
<!-- ok --> | |||
<alerts id="1" profile_id="1" metric_id="1" operator=">" value_error="30" value_warning="[null]"/> |
@@ -10,7 +10,7 @@ | |||
<rules_parameters id="3" rule_id="1" name="param3" description="[null]" param_type="STRING"/> | |||
<rules_profiles id="1" version="1" used_profile="true" name="profile name" language="java" default_profile="false" provided="false" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="profile name" language="java" /> | |||
<active_rules id="1" rule_id="1" profile_id="1" failure_level="4" /> | |||
<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="one" /> | |||
<active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" value="two" /> |
@@ -8,7 +8,7 @@ | |||
<rules_parameters id="1" rule_id="1" name="deprecated-prop" description="[null]" param_type="STRING"/> | |||
<rules_profiles id="1" version="1" used_profile="true" name="sonar way" language="java" default_profile="false" provided="true" /> | |||
<rules_profiles id="1" version="1" used_profile="true" name="sonar way" language="java" /> | |||
<active_rules id="1" rule_id="1" profile_id="1" failure_level="4" /> | |||
<active_rules id="2" rule_id="2" profile_id="1" failure_level="0" /> | |||
@@ -30,7 +30,6 @@ public class Profile extends Model { | |||
private String language; | |||
private String name; | |||
private boolean defaultProfile; | |||
private boolean provided; | |||
private String parentName; | |||
private List<Rule> rules = new ArrayList<Rule>(); | |||
@@ -61,15 +60,6 @@ public class Profile extends Model { | |||
return this; | |||
} | |||
public boolean isProvided() { | |||
return provided; | |||
} | |||
public Profile setProvided(boolean b) { | |||
this.provided = b; | |||
return this; | |||
} | |||
public String getParentName() { | |||
return parentName; | |||
} |
@@ -32,8 +32,7 @@ public class ProfileUnmarshaller extends AbstractUnmarshaller<Profile> { | |||
.setLanguage(utils.getString(json, "language")) | |||
.setName(utils.getString(json, "name")) | |||
.setDefaultProfile(utils.getBoolean(json, "default")) | |||
.setParentName(utils.getString(json, "parent")) | |||
.setProvided(utils.getBoolean(json, "provided")); | |||
.setParentName(utils.getString(json, "parent")); | |||
parseRules(utils, profile, json); | |||
return profile; |
@@ -42,7 +42,6 @@ public class ProfileUnmarshallerTest extends UnmarshallerTestCase { | |||
assertThat(profile.getName(), is("Sonar way")); | |||
assertThat(profile.getParentName(), nullValue()); | |||
assertThat(profile.isDefaultProfile(), is(true)); | |||
assertThat(profile.isProvided(), is(true)); | |||
assertThat(profile.getRules().size(), is(116)); | |||
Profile.Rule rule1 = profile.getRules().get(0); |