InitializersExecutor.class, ProjectInitializer.class, UpdateStatusJob.class);
}
- private EventBus eventBus;
- private Phases phases;
- private DecoratorsExecutor decoratorsExecutor;
- private MavenPhaseExecutor mavenPhaseExecutor;
- private MavenPluginsConfigurator mavenPluginsConfigurator;
- private PostJobsExecutor postJobsExecutor;
- private InitializersExecutor initializersExecutor;
- private SensorsExecutor sensorsExecutor;
- private UpdateStatusJob updateStatusJob;
- private PersistenceManager persistenceManager;
- private SensorContext sensorContext;
- private DefaultIndex index;
- private ProjectInitializer pi;
- private ScanPersister[] persisters;
- private FileSystemLogger fsLogger;
+ private final EventBus eventBus;
+ private final Phases phases;
+ private final DecoratorsExecutor decoratorsExecutor;
+ private final MavenPhaseExecutor mavenPhaseExecutor;
+ private final MavenPluginsConfigurator mavenPluginsConfigurator;
+ private final PostJobsExecutor postJobsExecutor;
+ private final InitializersExecutor initializersExecutor;
+ private final SensorsExecutor sensorsExecutor;
+ private final UpdateStatusJob updateStatusJob;
+ private final PersistenceManager persistenceManager;
+ private final SensorContext sensorContext;
+ private final DefaultIndex index;
+ private final ProjectInitializer pi;
+ private final ScanPersister[] persisters;
+ private final FileSystemLogger fsLogger;
private final JsonReport jsonReport;
- private DefaultModuleFileSystem fs;
+ private final DefaultModuleFileSystem fs;
+ private final ProfileLogger profileLogger;
public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
EventBus eventBus, UpdateStatusJob updateStatusJob, ProjectInitializer pi,
- ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, DefaultModuleFileSystem fs) {
+ ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, DefaultModuleFileSystem fs, ProfileLogger profileLogger) {
this.phases = phases;
this.decoratorsExecutor = decoratorsExecutor;
this.mavenPhaseExecutor = mavenPhaseExecutor;
this.fsLogger = fsLogger;
this.jsonReport = jsonReport;
this.fs = fs;
+ this.profileLogger = profileLogger;
}
public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
- EventBus eventBus, ProjectInitializer pi, ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, DefaultModuleFileSystem fs) {
+ EventBus eventBus, ProjectInitializer pi, ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, DefaultModuleFileSystem fs, ProfileLogger profileLogger) {
this(phases, decoratorsExecutor, mavenPhaseExecutor, mavenPluginsConfigurator, initializersExecutor, postJobsExecutor,
- sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, persisters, fsLogger, jsonReport, fs);
+ sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, persisters, fsLogger, jsonReport, fs, profileLogger);
}
/**
// Index and lock the filesystem
fs.index();
+ // Log detected languages and their profiles after FS is indexed and languages detected
+ profileLogger.execute();
+
sensorsExecutor.execute(sensorContext);
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.ModuleLanguages;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Language;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.rule.ModuleQProfiles;
+import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+
+public class ProfileLogger implements BatchComponent {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ProfileLogger.class);
+
+ private final Settings settings;
+ private final ModuleLanguages languages;
+ private final ModuleQProfiles profiles;
+
+ public ProfileLogger(Settings settings, ModuleLanguages languages, ModuleQProfiles profiles) {
+ this.settings = settings;
+ this.languages = languages;
+ this.profiles = profiles;
+ }
+
+ public void execute() {
+ execute(LOG);
+ }
+
+ @VisibleForTesting
+ void execute(Logger logger) {
+ String defaultName = settings.getString(ModuleQProfiles.SONAR_PROFILE_PROP);
+ boolean defaultNameUsed = StringUtils.isBlank(defaultName);
+ for (Language lang : languages.languages()) {
+ QProfile profile = profiles.findByLanguage(lang.getKey());
+ logger.info("Quality profile for {}: {}", lang.getName(), profile.name());
+ if (StringUtils.isNotBlank(defaultName) && defaultName.equals(profile.name())) {
+ defaultNameUsed = true;
+ }
+ }
+ if (!defaultNameUsed) {
+ throw new SonarException("sonar.profile was set to '" + defaultName + "' but didn't match any profile for any language. Please check your configuration.");
+ }
+ }
+
+}
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Language;
*/
public class ModuleQProfiles implements BatchComponent {
- private static final Logger LOG = LoggerFactory.getLogger(ModuleQProfiles.class);
+ public static final String SONAR_PROFILE_PROP = "sonar.profile";
public static class QProfile {
private final String name, language;
public ModuleQProfiles(Settings settings, Languages languages, QualityProfileDao dao) {
ImmutableMap.Builder<String, QProfile> builder = ImmutableMap.builder();
- String defaultName = settings.getString("sonar.profile");
+ String defaultName = settings.getString(SONAR_PROFILE_PROP);
for (Language language : languages.all()) {
- QProfile profile;
+ QProfile profile = null;
if (StringUtils.isNotBlank(defaultName)) {
profile = loadDefaultQProfile(dao, defaultName, language.getKey());
- } else {
+ }
+ if (profile == null) {
profile = loadQProfile(dao, settings, language.getKey());
}
if (profile != null) {
- LOG.info("Quality profile for {}: {}", profile.language(), profile.name());
builder.put(profile.language(), profile);
}
}
private RulesProfile loadSingleLanguageProfile(ModuleQProfiles qProfiles, String language, ProfilesDao dao) {
ModuleQProfiles.QProfile qProfile = qProfiles.findByLanguage(language);
- return new RulesProfileWrapper(select(qProfile, dao));
+ if (qProfile != null) {
+ return new RulesProfileWrapper(select(qProfile, dao));
+ }
+ return new RulesProfileWrapper(Lists.<RulesProfile>newArrayList());
}
private RulesProfile loadProfiles(ModuleQProfiles qProfiles, ProfilesDao dao) {
import org.sonar.batch.issue.ModuleIssues;
import org.sonar.batch.phases.PhaseExecutor;
import org.sonar.batch.phases.PhasesTimeProfiler;
+import org.sonar.batch.phases.ProfileLogger;
import org.sonar.batch.rule.ActiveRulesProvider;
import org.sonar.batch.rule.ModuleQProfiles;
import org.sonar.batch.rule.QProfileSensor;
DefaultModuleFileSystem.class,
ModuleFileSystemInitializer.class,
ProjectFileSystemAdapter.class,
+ ProfileLogger.class,
// the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
getComponentByType(ResourcePersister.class).getSnapshot(module),
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.slf4j.Logger;
+import org.sonar.api.batch.ModuleLanguages;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.AbstractLanguage;
+import org.sonar.api.resources.Language;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.rule.ModuleQProfiles;
+import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+
+import java.util.List;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ProfileLoggerTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private ModuleLanguages languages;
+ private ModuleQProfiles profiles;
+ private Settings settings;
+
+ @Before
+ public void prepare() {
+ languages = mock(ModuleLanguages.class);
+ List<Language> languageList = Lists.newArrayList();
+ languageList.add(new AbstractLanguage("java", "Java") {
+
+ @Override
+ public String[] getFileSuffixes() {
+ return null;
+ }
+ });
+ languageList.add(new AbstractLanguage("cobol", "Cobol") {
+
+ @Override
+ public String[] getFileSuffixes() {
+ return null;
+ }
+ });
+ when(languages.languages()).thenReturn(languageList);
+
+ profiles = mock(ModuleQProfiles.class);
+ QProfile javaProfile = mock(QProfile.class);
+ when(javaProfile.name()).thenReturn("My Java profile");
+ when(profiles.findByLanguage("java")).thenReturn(javaProfile);
+ QProfile cobolProfile = mock(QProfile.class);
+ when(cobolProfile.name()).thenReturn("My Cobol profile");
+ when(profiles.findByLanguage("cobol")).thenReturn(cobolProfile);
+
+ settings = new Settings();
+ }
+
+ @Test
+ public void should_log_all_used_profiles() {
+
+ ProfileLogger profileLogger = new ProfileLogger(settings, languages, profiles);
+ Logger logger = mock(Logger.class);
+ profileLogger.execute(logger);
+
+ verify(logger).info("Quality profile for {}: {}", "Java", "My Java profile");
+ verify(logger).info("Quality profile for {}: {}", "Cobol", "My Cobol profile");
+ }
+
+ @Test
+ public void should_fail_if_default_profile_not_used() {
+ settings.setProperty("sonar.profile", "Unknow");
+
+ ProfileLogger profileLogger = new ProfileLogger(settings, languages, profiles);
+
+ thrown.expect(SonarException.class);
+ thrown.expectMessage("sonar.profile was set to 'Unknow' but didn't match any profile for any language. Please check your configuration.");
+
+ profileLogger.execute();
+
+ }
+
+ @Test
+ public void should_not_fail_if_default_profile_used_at_least_once() {
+ settings.setProperty("sonar.profile", "My Java profile");
+
+ ProfileLogger profileLogger = new ProfileLogger(settings, languages, profiles);
+
+ profileLogger.execute();
+ }
+}
}
@Test
- public void use_deprecated_property() throws Exception {
+ public void use_sonar_profile_property() throws Exception {
setupData("shared");
QualityProfileDao dao = new QualityProfileDao(getMyBatis());
ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, dao);
List<ModuleQProfiles.QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
- assertThat(qProfiles).hasSize(1);
+ assertThat(qProfiles).hasSize(2);
ModuleQProfiles.QProfile javaProfile = qProfiles.get(0);
assertThat(javaProfile.id()).isEqualTo(2);
assertThat(javaProfile.name()).isEqualTo("Java Two");
assertThat(javaProfile.language()).isEqualTo("java");
assertThat(javaProfile.version()).isEqualTo(20);
- // the php profile is not found as sonar.profile overrides all other properties.
+ // Fallback to sonar.profile.php if no match for sonar.profile
+ ModuleQProfiles.QProfile phpProfile = qProfiles.get(1);
+ assertThat(phpProfile.id()).isEqualTo(3);
+ assertThat(phpProfile.name()).isEqualTo("Php One");
+ assertThat(phpProfile.language()).isEqualTo("php");
+ assertThat(phpProfile.version()).isEqualTo(30);
+
}
@Test