From: Julien HENRY Date: Mon, 14 Oct 2013 16:20:07 +0000 (+0200) Subject: SONAR-3677 Rename dryRun -> preview and introduce sonar.analysis.mode X-Git-Tag: 4.0~109 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=9e5187e9431abe59c832be81a230e8b957e85573;p=sonarqube.git SONAR-3677 Rename dryRun -> preview and introduce sonar.analysis.mode --- diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 2f89e01c7d2..cc9bed17fcc 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -20,7 +20,11 @@ package org.sonar.plugins.core; import com.google.common.collect.ImmutableList; -import org.sonar.api.*; +import org.sonar.api.CoreProperties; +import org.sonar.api.Properties; +import org.sonar.api.Property; +import org.sonar.api.PropertyType; +import org.sonar.api.SonarPlugin; import org.sonar.api.checks.NoSonarFilter; import org.sonar.api.config.PropertyDefinition; import org.sonar.api.resources.Java; @@ -32,21 +36,90 @@ import org.sonar.plugins.core.charts.DistributionAreaChart; import org.sonar.plugins.core.charts.DistributionBarChart; import org.sonar.plugins.core.charts.XradarChart; import org.sonar.plugins.core.colorizers.JavaColorizerFormat; -import org.sonar.plugins.core.dashboards.*; -import org.sonar.plugins.core.issue.*; +import org.sonar.plugins.core.dashboards.GlobalDefaultDashboard; +import org.sonar.plugins.core.dashboards.ProjectDefaultDashboard; +import org.sonar.plugins.core.dashboards.ProjectHotspotDashboard; +import org.sonar.plugins.core.dashboards.ProjectIssuesDashboard; +import org.sonar.plugins.core.dashboards.ProjectTimeMachineDashboard; +import org.sonar.plugins.core.issue.CountFalsePositivesDecorator; +import org.sonar.plugins.core.issue.CountUnresolvedIssuesDecorator; +import org.sonar.plugins.core.issue.InitialOpenIssuesSensor; +import org.sonar.plugins.core.issue.InitialOpenIssuesStack; +import org.sonar.plugins.core.issue.IssueHandlers; +import org.sonar.plugins.core.issue.IssueTracking; +import org.sonar.plugins.core.issue.IssueTrackingDecorator; +import org.sonar.plugins.core.issue.IssuesDensityDecorator; +import org.sonar.plugins.core.issue.WeightedIssuesDecorator; import org.sonar.plugins.core.issue.ignore.IgnoreIssuesPlugin; -import org.sonar.plugins.core.issue.notification.*; +import org.sonar.plugins.core.issue.notification.ChangesOnMyIssueNotificationDispatcher; +import org.sonar.plugins.core.issue.notification.IssueChangesEmailTemplate; +import org.sonar.plugins.core.issue.notification.NewFalsePositiveNotificationDispatcher; +import org.sonar.plugins.core.issue.notification.NewIssuesEmailTemplate; +import org.sonar.plugins.core.issue.notification.NewIssuesNotificationDispatcher; +import org.sonar.plugins.core.issue.notification.SendIssueNotificationsPostJob; import org.sonar.plugins.core.measurefilters.MyFavouritesFilter; import org.sonar.plugins.core.measurefilters.ProjectFilter; import org.sonar.plugins.core.notifications.alerts.NewAlerts; import org.sonar.plugins.core.security.ApplyProjectRolesDecorator; -import org.sonar.plugins.core.sensors.*; +import org.sonar.plugins.core.sensors.BranchCoverageDecorator; +import org.sonar.plugins.core.sensors.CheckAlertThresholds; +import org.sonar.plugins.core.sensors.CommentDensityDecorator; +import org.sonar.plugins.core.sensors.CoverageDecorator; +import org.sonar.plugins.core.sensors.CoverageMeasurementFilter; +import org.sonar.plugins.core.sensors.DirectoriesDecorator; +import org.sonar.plugins.core.sensors.FileHashSensor; +import org.sonar.plugins.core.sensors.FilesDecorator; +import org.sonar.plugins.core.sensors.GenerateAlertEvents; +import org.sonar.plugins.core.sensors.ItBranchCoverageDecorator; +import org.sonar.plugins.core.sensors.ItCoverageDecorator; +import org.sonar.plugins.core.sensors.ItLineCoverageDecorator; +import org.sonar.plugins.core.sensors.LineCoverageDecorator; +import org.sonar.plugins.core.sensors.ManualMeasureDecorator; +import org.sonar.plugins.core.sensors.OverallBranchCoverageDecorator; +import org.sonar.plugins.core.sensors.OverallCoverageDecorator; +import org.sonar.plugins.core.sensors.OverallLineCoverageDecorator; +import org.sonar.plugins.core.sensors.ProfileEventsSensor; +import org.sonar.plugins.core.sensors.ProfileSensor; +import org.sonar.plugins.core.sensors.ProjectLinksSensor; +import org.sonar.plugins.core.sensors.UnitTestDecorator; +import org.sonar.plugins.core.sensors.VersionEventsSensor; import org.sonar.plugins.core.technicaldebt.TechnicalDebtDecorator; -import org.sonar.plugins.core.timemachine.*; +import org.sonar.plugins.core.timemachine.NewCoverageAggregator; +import org.sonar.plugins.core.timemachine.NewCoverageFileAnalyzer; +import org.sonar.plugins.core.timemachine.NewItCoverageFileAnalyzer; +import org.sonar.plugins.core.timemachine.NewOverallCoverageFileAnalyzer; +import org.sonar.plugins.core.timemachine.TendencyDecorator; +import org.sonar.plugins.core.timemachine.TimeMachineConfigurationPersister; +import org.sonar.plugins.core.timemachine.VariationDecorator; import org.sonar.plugins.core.web.Lcom4Viewer; import org.sonar.plugins.core.web.TestsViewer; -import org.sonar.plugins.core.widgets.*; -import org.sonar.plugins.core.widgets.issues.*; +import org.sonar.plugins.core.widgets.AlertsWidget; +import org.sonar.plugins.core.widgets.ComplexityWidget; +import org.sonar.plugins.core.widgets.CoverageWidget; +import org.sonar.plugins.core.widgets.CustomMeasuresWidget; +import org.sonar.plugins.core.widgets.DescriptionWidget; +import org.sonar.plugins.core.widgets.DocumentationCommentsWidget; +import org.sonar.plugins.core.widgets.DuplicationsWidget; +import org.sonar.plugins.core.widgets.EventsWidget; +import org.sonar.plugins.core.widgets.HotspotMetricWidget; +import org.sonar.plugins.core.widgets.HotspotMostViolatedResourcesWidget; +import org.sonar.plugins.core.widgets.HotspotMostViolatedRulesWidget; +import org.sonar.plugins.core.widgets.ItCoverageWidget; +import org.sonar.plugins.core.widgets.MeasureFilterListWidget; +import org.sonar.plugins.core.widgets.MeasureFilterTreemapWidget; +import org.sonar.plugins.core.widgets.SizeWidget; +import org.sonar.plugins.core.widgets.TechnicalDebtPyramidWidget; +import org.sonar.plugins.core.widgets.TimeMachineWidget; +import org.sonar.plugins.core.widgets.TimelineWidget; +import org.sonar.plugins.core.widgets.TreemapWidget; +import org.sonar.plugins.core.widgets.WelcomeWidget; +import org.sonar.plugins.core.widgets.issues.ActionPlansWidget; +import org.sonar.plugins.core.widgets.issues.FalsePositiveIssuesWidget; +import org.sonar.plugins.core.widgets.issues.IssueFilterWidget; +import org.sonar.plugins.core.widgets.issues.IssuesWidget; +import org.sonar.plugins.core.widgets.issues.MyUnresolvedIssuesWidget; +import org.sonar.plugins.core.widgets.issues.UnresolvedIssuesPerAssigneeWidget; +import org.sonar.plugins.core.widgets.issues.UnresolvedIssuesStatusesWidget; import java.util.Arrays; import java.util.List; @@ -116,23 +189,26 @@ import java.util.List; global = true, category = CoreProperties.CATEGORY_GENERAL), @Property( - key = CoreProperties.DRY_RUN, - defaultValue = "false", - name = "Preview", - type = PropertyType.BOOLEAN, + key = CoreProperties.ANALYSIS_MODE, + defaultValue = CoreProperties.ANALYSIS_MODE_ANALYSIS, + name = "Analysis mode", + type = PropertyType.SINGLE_SELECT_LIST, + options = {CoreProperties.ANALYSIS_MODE_ANALYSIS, CoreProperties.ANALYSIS_MODE_PREVIEW, CoreProperties.ANALYSIS_MODE_INCREMENTAL}, global = false, project = false, category = CoreProperties.CATEGORY_GENERAL), @Property( - key = CoreProperties.DRY_RUN_INCLUDE_PLUGINS, + key = CoreProperties.PREVIEW_INCLUDE_PLUGINS, + deprecatedKey = CoreProperties.DRY_RUN_INCLUDE_PLUGINS, name = "Plugins accepted for Preview", - defaultValue = CoreProperties.DRY_RUN_INCLUDE_PLUGINS_DEFAULT_VALUE, + defaultValue = CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE, global = true, project = false, category = CoreProperties.CATEGORY_GENERAL), @Property( - key = CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, + key = CoreProperties.PREVIEW_EXCLUDE_PLUGINS, + deprecatedKey = CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, name = "Plugins excluded for Preview", global = true, project = false, - defaultValue = CoreProperties.DRY_RUN_EXCLUDE_PLUGINS_DEFAULT_VALUE, + defaultValue = CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE, category = CoreProperties.CATEGORY_GENERAL), @Property( key = "sonar.report.export.path", diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java new file mode 100644 index 00000000000..f0872de55b2 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java @@ -0,0 +1,71 @@ +/* + * 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.bootstrap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.BatchComponent; +import org.sonar.api.CoreProperties; + +import java.text.MessageFormat; + +/** + * @since 4.0 + */ +public class AnalysisMode implements BatchComponent { + + private static final Logger LOG = LoggerFactory.getLogger(AnalysisMode.class); + + private boolean preview; + private boolean incremental; + + public AnalysisMode(BootstrapSettings bootstrapSettings) { + init(bootstrapSettings); + } + + public boolean isPreview() { + return preview || incremental; + } + + public boolean isIncremental() { + return incremental; + } + + private void init(BootstrapSettings bootstrapSettings) { + if (bootstrapSettings.properties().containsKey(CoreProperties.DRY_RUN)) { + LOG.warn(MessageFormat.format("Property {0} is deprecated. Please use {1} instead", CoreProperties.DRY_RUN, CoreProperties.ANALYSIS_MODE)); + preview = "true".equals(bootstrapSettings.property(CoreProperties.DRY_RUN)); + incremental = false; + } else { + String mode = bootstrapSettings.property(CoreProperties.ANALYSIS_MODE); + preview = CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode); + incremental = CoreProperties.ANALYSIS_MODE_INCREMENTAL.equals(mode); + } + if (incremental) { + LOG.info("Incremental mode"); + } else if (preview) { + LOG.info("Preview mode"); + } + // To stay compatible with plugins that use the old property to check mode + if (incremental || preview) { + bootstrapSettings.properties().put(CoreProperties.DRY_RUN, "true"); + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java index 8f58a39a4d9..0282d43e178 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java @@ -29,22 +29,28 @@ import java.util.Properties; */ public class BatchDatabase extends DefaultDatabase { + private final AnalysisMode analysisMode; + public BatchDatabase(Settings settings, - // The dependency on JdbcDriverHolder is required to be sure that the JDBC driver - // has been downloaded and injected into classloader - JdbcDriverHolder jdbcDriverHolder, + AnalysisMode analysisMode, + // The dependency on JdbcDriverHolder is required to be sure that the JDBC driver + // has been downloaded and injected into classloader + JdbcDriverHolder jdbcDriverHolder, - // The dependency on DryRunDatabase is required to be sure that the dryRun mode - // changed settings - DryRunDatabase dryRun) { + // The dependency on DryRunDatabase is required to be sure that the dryRun mode + // changed settings + PreviewDatabase dryRun) { super(settings); + this.analysisMode = analysisMode; } public BatchDatabase(Settings settings, - // The dependency on JdbcDriverHolder is required to be sure that the JDBC driver - // has been downloaded and injected into classloader - JdbcDriverHolder jdbcDriverHolder) { + AnalysisMode analysisMode, + // The dependency on JdbcDriverHolder is required to be sure that the JDBC driver + // has been downloaded and injected into classloader + JdbcDriverHolder jdbcDriverHolder) { super(settings); + this.analysisMode = analysisMode; } @Override @@ -57,4 +63,11 @@ public class BatchDatabase extends DefaultDatabase { // SONAR-2965 properties.setProperty("sonar.jdbc.defaultAutoCommit", "false"); } + + @Override + protected void checkH2Database() { + if (!analysisMode.isPreview()) { + super.checkH2Database(); + } + } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java index 755d2a46b97..49603d683d7 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java @@ -35,6 +35,7 @@ import org.sonar.core.plugins.PluginInstaller; import org.sonar.core.plugins.RemotePlugin; import java.io.File; +import java.text.MessageFormat; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -53,11 +54,13 @@ public class BatchPluginRepository implements PluginRepository { private Settings settings; private PluginClassloaders classLoaders; private TempDirectories workingDirectories; + private final AnalysisMode analysisMode; - public BatchPluginRepository(PluginDownloader pluginDownloader, TempDirectories workingDirectories, Settings settings) { + public BatchPluginRepository(PluginDownloader pluginDownloader, TempDirectories workingDirectories, Settings settings, AnalysisMode analysisMode) { this.pluginDownloader = pluginDownloader; this.workingDirectories = workingDirectories; this.settings = settings; + this.analysisMode = analysisMode; } public void start() { @@ -66,7 +69,7 @@ public class BatchPluginRepository implements PluginRepository { } void doStart(List remotePlugins) { - PluginFilter filter = new PluginFilter(settings); + PluginFilter filter = new PluginFilter(settings, analysisMode); PluginInstaller extractor = new PluginInstaller(); metadataByKey = Maps.newHashMap(); for (RemotePlugin remote : remotePlugins) { @@ -119,20 +122,32 @@ public class BatchPluginRepository implements PluginRepository { static class PluginFilter { Set whites = Sets.newHashSet(), blacks = Sets.newHashSet(); - PluginFilter(Settings settings) { + PluginFilter(Settings settings, AnalysisMode mode) { if (settings.hasKey(CoreProperties.BATCH_INCLUDE_PLUGINS)) { whites.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS))); } if (settings.hasKey(CoreProperties.BATCH_EXCLUDE_PLUGINS)) { blacks.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS))); } - if (settings.getBoolean(CoreProperties.DRY_RUN)) { + if (mode.isPreview()) { // These default values are not supported by Settings because the class CorePlugin // is not loaded yet. - whites.addAll(propertyValues(settings, - CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.DRY_RUN_INCLUDE_PLUGINS_DEFAULT_VALUE)); - blacks.addAll(propertyValues(settings, - CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.DRY_RUN_EXCLUDE_PLUGINS_DEFAULT_VALUE)); + if (settings.hasKey(CoreProperties.DRY_RUN_INCLUDE_PLUGINS)) { + LOG.warn(MessageFormat.format("Property {0} is deprecated. Please use {1} instead", CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS)); + whites.addAll(propertyValues(settings, + CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE)); + } else { + whites.addAll(propertyValues(settings, + CoreProperties.PREVIEW_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE)); + } + if (settings.hasKey(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS)) { + LOG.warn(MessageFormat.format("Property {0} is deprecated. Please use {1} instead", CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS)); + blacks.addAll(propertyValues(settings, + CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE)); + } else { + blacks.addAll(propertyValues(settings, + CoreProperties.PREVIEW_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE)); + } } if (!whites.isEmpty()) { LOG.info("Include plugins: " + Joiner.on(", ").join(whites)); diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchSettings.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchSettings.java index 163f9dc232c..e06c8c9c433 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchSettings.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchSettings.java @@ -37,15 +37,17 @@ import java.util.Map; public class BatchSettings extends Settings { public static final String BATCH_BOOTSTRAP_PROPERTIES_URL = "/batch_bootstrap/properties"; private Configuration deprecatedConfiguration; - private boolean dryRun; + private boolean preview; private final BootstrapSettings bootstrapSettings; private final ServerClient client; + private final AnalysisMode mode; private Map savedProperties; public BatchSettings(BootstrapSettings bootstrapSettings, PropertyDefinitions propertyDefinitions, - ServerClient client, Configuration deprecatedConfiguration) { + ServerClient client, Configuration deprecatedConfiguration, AnalysisMode mode) { super(propertyDefinitions); + this.mode = mode; getEncryption().setPathToSecretKey(bootstrapSettings.property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH)); this.bootstrapSettings = bootstrapSettings; this.client = client; @@ -56,8 +58,7 @@ public class BatchSettings extends Settings { public void init(@Nullable ProjectReactor reactor) { savedProperties = this.getProperties(); - // Do not use getBoolean to avoid recursion - this.dryRun = "true".equals(bootstrapSettings.property(CoreProperties.DRY_RUN)); + this.preview = mode.isPreview(); if (reactor != null) { LoggerFactory.getLogger(BatchSettings.class).info("Load project settings"); String branch = bootstrapSettings.property(CoreProperties.PROJECT_BRANCH_PROPERTY); @@ -89,9 +90,9 @@ public class BatchSettings extends Settings { private void downloadSettings(@Nullable String projectKey) { String url; if (StringUtils.isNotBlank(projectKey)) { - url = BATCH_BOOTSTRAP_PROPERTIES_URL + "?project=" + projectKey + "&dryRun=" + dryRun; + url = BATCH_BOOTSTRAP_PROPERTIES_URL + "?project=" + projectKey + "&dryRun=" + preview; } else { - url = BATCH_BOOTSTRAP_PROPERTIES_URL + "?dryRun=" + dryRun; + url = BATCH_BOOTSTRAP_PROPERTIES_URL + "?dryRun=" + preview; } String jsonText = client.request(url); List> json = (List>) JSONValue.parse(jsonText); @@ -119,9 +120,9 @@ public class BatchSettings extends Settings { @Override protected void doOnGetProperties(String key) { - if (dryRun && key.endsWith(".secured") && !key.contains(".license")) { + if (preview && key.endsWith(".secured") && !key.contains(".license")) { throw new SonarException("Access to the secured property '" + key - + "' is not possible in local (dry run) SonarQube analysis. The SonarQube plugin which requires this property must be deactivated in dry run mode."); + + "' is not possible in preview mode. The SonarQube plugin which requires this property must be deactivated in preview mode."); } } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java index 2913aad74d8..6aa2b6b31b5 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java @@ -19,8 +19,6 @@ */ package org.sonar.batch.bootstrap; -import org.sonar.core.purge.PurgeProfiler; - import org.apache.commons.configuration.PropertiesConfiguration; import org.sonar.api.Plugin; import org.sonar.api.config.EmailSettings; @@ -44,6 +42,7 @@ import org.sonar.core.persistence.DatabaseVersion; import org.sonar.core.persistence.MyBatis; import org.sonar.core.persistence.SemaphoreUpdater; import org.sonar.core.persistence.SemaphoresImpl; +import org.sonar.core.purge.PurgeProfiler; import org.sonar.core.qualitymodel.DefaultModelFinder; import org.sonar.core.rule.CacheRuleFinder; import org.sonar.core.user.HibernateUserFinder; @@ -79,6 +78,7 @@ public class BootstrapContainer extends ComponentContainer { add( new PropertiesConfiguration(), BootstrapSettings.class, + AnalysisMode.class, PluginDownloader.class, BatchPluginRepository.class, BatchSettings.class, @@ -90,25 +90,23 @@ public class BootstrapContainer extends ComponentContainer { TempDirectories.class, HttpDownloader.class, UriReader.class, - new FileCacheProvider() - ); + new FileCacheProvider()); } private void addDatabaseComponents() { add( - DryRunDatabase.class, + PreviewDatabase.class, JdbcDriverHolder.class, BatchDatabase.class, MyBatis.class, DatabaseVersion.class, - //TODO check that it still works (see @Freddy) + // TODO check that it still works (see @Freddy) DatabaseCompatibility.class, DefaultDatabaseConnector.class, JpaDatabaseSession.class, BatchDatabaseSessionFactory.class, DaoUtils.getDaoClasses(), - PurgeProfiler.class - ); + PurgeProfiler.class); } /** @@ -134,8 +132,7 @@ public class BootstrapContainer extends ComponentContainer { PastSnapshotFinderByPreviousVersion.class, PastMeasuresLoader.class, PastSnapshotFinder.class, - DefaultModelFinder.class - ); + DefaultModelFinder.class); } @Override diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseCompatibility.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseCompatibility.java index 6fe7394e040..965ce42ae7f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseCompatibility.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseCompatibility.java @@ -34,15 +34,17 @@ public class DatabaseCompatibility implements BatchComponent { private DatabaseVersion version; private Settings settings; private ServerMetadata server; + private AnalysisMode analysisMode; - public DatabaseCompatibility(DatabaseVersion version, ServerMetadata server, Settings settings) { + public DatabaseCompatibility(DatabaseVersion version, ServerMetadata server, Settings settings, AnalysisMode mode) { this.version = version; this.server = server; this.settings = settings; + this.analysisMode = mode; } public void start() { - if (!settings.getBoolean(CoreProperties.DRY_RUN)) { + if (!analysisMode.isPreview()) { checkCorrectServerId(); checkDatabaseStatus(); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRunDatabase.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRunDatabase.java deleted file mode 100644 index f4847877247..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRunDatabase.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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.bootstrap; - -import com.google.common.base.Throwables; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.BatchComponent; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; -import org.sonar.api.database.DatabaseProperties; -import org.sonar.api.utils.HttpDownloader.HttpException; -import org.sonar.api.utils.SonarException; - -import java.io.File; -import java.net.SocketTimeoutException; - -/** - * @since 3.4 - */ -public class DryRunDatabase implements BatchComponent { - private static final Logger LOG = LoggerFactory.getLogger(DryRunDatabase.class); - - private static final String DIALECT = "h2"; - private static final String DRIVER = "org.h2.Driver"; - private static final String URL = "jdbc:h2:"; - private static final String USER = "sonar"; - private static final String PASSWORD = USER; - - private static final int DEFAULT_DRY_RUN_READ_TIMEOUT_SEC = 60; - - private final Settings settings; - private final ServerClient server; - private final TempDirectories tempDirectories; - - public DryRunDatabase(Settings settings, ServerClient server, TempDirectories tempDirectories) { - this.settings = settings; - this.server = server; - this.tempDirectories = tempDirectories; - } - - public void start() { - if (settings.getBoolean(CoreProperties.DRY_RUN)) { - LOG.info("Preview"); - File databaseFile = tempDirectories.getFile("", "dryrun.h2.db"); - - // SONAR-4488 Allow to increase dryRun timeout - int readTimeoutSec = settings.getInt(CoreProperties.DRY_RUN_READ_TIMEOUT_SEC); - readTimeoutSec = (readTimeoutSec == 0) ? DEFAULT_DRY_RUN_READ_TIMEOUT_SEC : readTimeoutSec; - - downloadDatabase(databaseFile, readTimeoutSec * 1000); - - String databasePath = StringUtils.removeEnd(databaseFile.getAbsolutePath(), ".h2.db"); - replaceSettings(databasePath); - } - } - - private void downloadDatabase(File toFile, int readTimeout) { - String projectKey = null; - try { - projectKey = settings.getString(CoreProperties.PROJECT_KEY_PROPERTY); - String branch = settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY); - if (StringUtils.isNotBlank(branch)) { - projectKey = String.format("%s:%s", projectKey, branch); - } - if (StringUtils.isBlank(projectKey)) { - server.download("/batch_bootstrap/db", toFile, readTimeout); - } else { - server.download("/batch_bootstrap/db?project=" + projectKey, toFile, readTimeout); - } - LOG.debug("Dry Run database size: {}", FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(toFile))); - } catch (SonarException e) { - handleException(readTimeout, projectKey, e); - throw e; - } - } - - private void handleException(int readTimeout, String projectKey, SonarException e) { - Throwable rootCause = Throwables.getRootCause(e); - if (rootCause instanceof SocketTimeoutException) { - // Pico will unwrap the first runtime exception - throw new SonarException(new SonarException(String.format("DryRun database read timed out after %s ms. You can try to increase read timeout with property -D" - + CoreProperties.DRY_RUN_READ_TIMEOUT_SEC + " (in seconds)", - readTimeout), e)); - } - if (projectKey != null && (rootCause instanceof HttpException) && (((HttpException) rootCause).getResponseCode() == 401)) { - // Pico will unwrap the first runtime exception - throw new SonarException(new SonarException(String.format("You don't have access rights to project [%s]", projectKey), e)); - } - } - - private void replaceSettings(String databasePath) { - settings - .removeProperty("sonar.jdbc.schema") - .setProperty(DatabaseProperties.PROP_DIALECT, DIALECT) - .setProperty(DatabaseProperties.PROP_DRIVER, DRIVER) - .setProperty(DatabaseProperties.PROP_USER, USER) - .setProperty(DatabaseProperties.PROP_PASSWORD, PASSWORD) - .setProperty(DatabaseProperties.PROP_URL, URL + databasePath); - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java index 8c396056f76..d51421d084c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java @@ -19,10 +19,8 @@ */ package org.sonar.batch.bootstrap; -import org.sonar.api.CoreProperties; import org.sonar.api.ExtensionProvider; import org.sonar.api.Plugin; -import org.sonar.api.config.Settings; import org.sonar.api.platform.ComponentContainer; import org.sonar.api.platform.PluginMetadata; import org.sonar.batch.bootstrapper.EnvironmentInformation; @@ -36,21 +34,21 @@ public class ExtensionInstaller { private final BatchPluginRepository pluginRepository; private final EnvironmentInformation env; - private final Settings settings; + private final AnalysisMode analysisMode; - public ExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation env, Settings settings) { + public ExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation env, AnalysisMode analysisMode) { this.pluginRepository = pluginRepository; this.env = env; - this.settings = settings; + this.analysisMode = analysisMode; } public ExtensionInstaller install(ComponentContainer container, ExtensionMatcher matcher) { - boolean dryRun = isDryRun(); + boolean preview = analysisMode.isPreview(); for (Map.Entry entry : pluginRepository.getPluginsByMetadata().entrySet()) { PluginMetadata metadata = entry.getKey(); Plugin plugin = entry.getValue(); for (Object extension : plugin.getExtensions()) { - doInstall(container, matcher, metadata, dryRun, extension); + doInstall(container, matcher, metadata, preview, extension); } } List providers = container.getComponentsByType(ExtensionProvider.class); @@ -58,10 +56,10 @@ public class ExtensionInstaller { Object object = provider.provide(); if (object instanceof Iterable) { for (Object extension : (Iterable) object) { - doInstall(container, matcher, null, dryRun, extension); + doInstall(container, matcher, null, preview, extension); } } else { - doInstall(container, matcher, null, dryRun, object); + doInstall(container, matcher, null, preview, object); } } return this; @@ -69,7 +67,7 @@ public class ExtensionInstaller { private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginMetadata metadata, boolean dryRun, Object extension) { if (ExtensionUtils.supportsEnvironment(extension, env) - && (!dryRun || ExtensionUtils.supportsDryRun(extension)) + && (!dryRun || ExtensionUtils.supportsPreview(extension)) && matcher.accept(extension)) { container.addExtension(metadata, extension); } else { @@ -77,7 +75,4 @@ public class ExtensionInstaller { } } - private boolean isDryRun() { - return settings.getBoolean(CoreProperties.DRY_RUN); - } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionUtils.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionUtils.java index 1111e7fbfd2..89cdaa59845 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionUtils.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionUtils.java @@ -58,7 +58,7 @@ public class ExtensionUtils { return false; } - public static boolean supportsDryRun(Object extension) { + public static boolean supportsPreview(Object extension) { return AnnotationUtils.getAnnotation(extension, DryRunIncompatible.class) == null; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcDriverHolder.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcDriverHolder.java index 0ebd74fee9f..85777901b5c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcDriverHolder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcDriverHolder.java @@ -22,8 +22,6 @@ package org.sonar.batch.bootstrap; import com.google.common.annotations.VisibleForTesting; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; import org.sonar.api.utils.SonarException; import org.sonar.home.cache.FileCache; @@ -43,20 +41,20 @@ public class JdbcDriverHolder { private static final Logger LOG = LoggerFactory.getLogger(JdbcDriverHolder.class); private ServerClient serverClient; - private Settings settings; + private AnalysisMode analysisMode; private FileCache fileCache; // initialized in start() private JdbcDriverClassLoader classLoader = null; - public JdbcDriverHolder(FileCache fileCache, Settings settings, ServerClient serverClient) { + public JdbcDriverHolder(FileCache fileCache, AnalysisMode analysisMode, ServerClient serverClient) { this.serverClient = serverClient; - this.settings = settings; + this.analysisMode = analysisMode; this.fileCache = fileCache; } public void start() { - if (!settings.getBoolean(CoreProperties.DRY_RUN)) { + if (!analysisMode.isPreview()) { try { LOG.info("Install JDBC driver"); String[] nameAndHash = downloadJdbcDriverIndex(); @@ -150,7 +148,7 @@ public class JdbcDriverHolder { static class JdbcDriverClassLoader extends URLClassLoader { public JdbcDriverClassLoader(URL jdbcDriver, ClassLoader parent) { - super(new URL[]{jdbcDriver}, parent); + super(new URL[] {jdbcDriver}, parent); } public void clearReferencesJdbc() { diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PreviewDatabase.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PreviewDatabase.java new file mode 100644 index 00000000000..222a40fad01 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PreviewDatabase.java @@ -0,0 +1,132 @@ +/* + * 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.bootstrap; + +import com.google.common.base.Throwables; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.BatchComponent; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.api.database.DatabaseProperties; +import org.sonar.api.utils.HttpDownloader.HttpException; +import org.sonar.api.utils.SonarException; + +import java.io.File; +import java.net.SocketTimeoutException; + +/** + * @since 3.4 + */ +public class PreviewDatabase implements BatchComponent { + private static final Logger LOG = LoggerFactory.getLogger(PreviewDatabase.class); + + private static final String DIALECT = "h2"; + private static final String DRIVER = "org.h2.Driver"; + private static final String URL = "jdbc:h2:"; + private static final String USER = "sonar"; + private static final String PASSWORD = USER; + + private static final int DEFAULT_PREVIEW_READ_TIMEOUT_SEC = 60; + + private final Settings settings; + private final ServerClient server; + private final TempDirectories tempDirectories; + private final AnalysisMode mode; + + public PreviewDatabase(Settings settings, ServerClient server, TempDirectories tempDirectories, AnalysisMode mode) { + this.settings = settings; + this.server = server; + this.tempDirectories = tempDirectories; + this.mode = mode; + } + + public void start() { + if (mode.isPreview()) { + File databaseFile = tempDirectories.getFile("", "preview.h2.db"); + + int readTimeoutSec = getReadTimeout(); + downloadDatabase(databaseFile, readTimeoutSec * 1000); + + String databasePath = StringUtils.removeEnd(databaseFile.getAbsolutePath(), ".h2.db"); + replaceSettings(databasePath); + } + } + + // SONAR-4488 Allow to increase dryRun timeout + private int getReadTimeout() { + int readTimeoutSec; + if (settings.hasKey(CoreProperties.DRY_RUN_READ_TIMEOUT_SEC)) { + LOG.warn(String.format("Property {0} is deprecated. Please use {1} instead.", CoreProperties.DRY_RUN_READ_TIMEOUT_SEC, CoreProperties.PREVIEW_READ_TIMEOUT_SEC)); + readTimeoutSec = settings.getInt(CoreProperties.DRY_RUN_READ_TIMEOUT_SEC); + } else if (settings.hasKey(CoreProperties.PREVIEW_READ_TIMEOUT_SEC)) { + readTimeoutSec = settings.getInt(CoreProperties.PREVIEW_READ_TIMEOUT_SEC); + } else { + readTimeoutSec = DEFAULT_PREVIEW_READ_TIMEOUT_SEC; + } + return readTimeoutSec; + } + + private void downloadDatabase(File toFile, int readTimeout) { + String projectKey = null; + try { + projectKey = settings.getString(CoreProperties.PROJECT_KEY_PROPERTY); + String branch = settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY); + if (StringUtils.isNotBlank(branch)) { + projectKey = String.format("%s:%s", projectKey, branch); + } + if (StringUtils.isBlank(projectKey)) { + server.download("/batch_bootstrap/db", toFile, readTimeout); + } else { + server.download("/batch_bootstrap/db?project=" + projectKey, toFile, readTimeout); + } + LOG.debug("Dry Run database size: {}", FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(toFile))); + } catch (SonarException e) { + handleException(readTimeout, projectKey, e); + throw e; + } + } + + private void handleException(int readTimeout, String projectKey, SonarException e) { + Throwable rootCause = Throwables.getRootCause(e); + if (rootCause instanceof SocketTimeoutException) { + // Pico will unwrap the first runtime exception + throw new SonarException(new SonarException(String.format("Preview database read timed out after %s ms. You can try to increase read timeout with property -D" + + CoreProperties.PREVIEW_READ_TIMEOUT_SEC + " (in seconds)", + readTimeout), e)); + } + if (projectKey != null && (rootCause instanceof HttpException) && (((HttpException) rootCause).getResponseCode() == 401)) { + // Pico will unwrap the first runtime exception + throw new SonarException(new SonarException(String.format("You don't have access rights to project [%s]", projectKey), e)); + } + } + + private void replaceSettings(String databasePath) { + settings + .removeProperty("sonar.jdbc.schema") + .setProperty(DatabaseProperties.PROP_DIALECT, DIALECT) + .setProperty(DatabaseProperties.PROP_DRIVER, DRIVER) + .setProperty(DatabaseProperties.PROP_USER, USER) + .setProperty(DatabaseProperties.PROP_PASSWORD, PASSWORD) + .setProperty(DatabaseProperties.PROP_URL, URL + databasePath); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssuePersister.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssuePersister.java index 6668001f9b7..183bbae1e0c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssuePersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssuePersister.java @@ -21,9 +21,8 @@ package org.sonar.batch.issue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.index.ScanPersister; /** @@ -35,18 +34,18 @@ public class IssuePersister implements ScanPersister { private final IssueCache issueCache; private final ScanIssueStorage storage; - private Settings settings; + private AnalysisMode analysisMode; - public IssuePersister(IssueCache issueCache, ScanIssueStorage storage, Settings settings) { + public IssuePersister(IssueCache issueCache, ScanIssueStorage storage, AnalysisMode analysisMode) { this.issueCache = issueCache; this.storage = storage; - this.settings = settings; + this.analysisMode = analysisMode; } @Override public void persist() { - if (settings.getBoolean(CoreProperties.DRY_RUN)) { - LOG.debug("IssuePersister skipped in dryRun"); + if (analysisMode.isPreview()) { + LOG.debug("IssuePersister skipped in preview mode"); return; } Iterable issues = issueCache.all(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java b/sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java index dc338ddd360..bbc78302893 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java @@ -30,6 +30,7 @@ import org.sonar.api.database.model.Snapshot; import org.sonar.api.resources.Project; import org.sonar.api.resources.Scopes; import org.sonar.api.utils.SonarException; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.ServerClient; import org.sonar.batch.index.ResourcePersister; @@ -48,35 +49,37 @@ public class UpdateStatusJob implements BatchComponent { private ResourcePersister resourcePersister; private Settings settings; private Project project; + private AnalysisMode analysisMode; public UpdateStatusJob(Settings settings, ServerClient server, DatabaseSession session, - ResourcePersister resourcePersister, Project project, Snapshot snapshot) { + ResourcePersister resourcePersister, Project project, Snapshot snapshot, AnalysisMode analysisMode) { this.session = session; this.server = server; this.resourcePersister = resourcePersister; this.project = project; this.snapshot = snapshot; this.settings = settings; + this.analysisMode = analysisMode; } public void execute() { disablePreviousSnapshot(); enableCurrentSnapshot(); - evictDryRunDB(); + evictPreviewDB(); } @VisibleForTesting - void evictDryRunDB() { - if (settings.getBoolean(CoreProperties.DRY_RUN)) { - // If this is a dryRun analysis then we should not evict dryRun database + void evictPreviewDB() { + if (analysisMode.isPreview()) { + // If this is a preview analysis then we should not evict remote preview database return; } String url = "/batch_bootstrap/evict?project=" + project.getId(); try { - LOG.debug("Evict dryRun database"); + LOG.debug("Evict preview database"); server.request(url); } catch (Exception e) { - throw new SonarException("Unable to evict dryRun database: " + url, e); + throw new SonarException("Unable to evict preview database: " + url, e); } } @@ -103,7 +106,7 @@ public class UpdateStatusJob implements BatchComponent { @VisibleForTesting void logSuccess(Logger logger) { - if (settings.getBoolean(CoreProperties.DRY_RUN)) { + if (analysisMode.isPreview()) { logger.info("ANALYSIS SUCCESSFUL"); } else { diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/LastSnapshots.java b/sonar-batch/src/main/java/org/sonar/batch/scan/LastSnapshots.java index eeb39aa6cdb..226a3d6751a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/LastSnapshots.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/LastSnapshots.java @@ -20,8 +20,6 @@ package org.sonar.batch.scan; import org.sonar.api.BatchComponent; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; import org.sonar.api.database.DatabaseSession; import org.sonar.api.database.model.ResourceModel; import org.sonar.api.database.model.Snapshot; @@ -29,18 +27,19 @@ import org.sonar.api.database.model.SnapshotSource; import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; import org.sonar.api.utils.HttpDownloader; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.ServerClient; import javax.persistence.Query; public class LastSnapshots implements BatchComponent { - private final Settings settings; + private final AnalysisMode analysisMode; private final DatabaseSession session; private final ServerClient server; - public LastSnapshots(Settings settings, DatabaseSession session, ServerClient server) { - this.settings = settings; + public LastSnapshots(AnalysisMode analysisMode, DatabaseSession session, ServerClient server) { + this.analysisMode = analysisMode; this.session = session; this.server = server; } @@ -48,7 +47,7 @@ public class LastSnapshots implements BatchComponent { public String getSource(Resource resource) { String source = ""; if (ResourceUtils.isFile(resource)) { - if (settings.getBoolean(CoreProperties.DRY_RUN)) { + if (analysisMode.isPreview()) { source = loadSourceFromWs(resource); } else { source = loadSourceFromDb(resource); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java index 956711a1d70..996fb1e60a7 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java @@ -28,6 +28,7 @@ import org.sonar.api.CoreProperties; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.config.Settings; import org.sonar.api.utils.SonarException; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.BatchSettings; import org.sonar.batch.bootstrap.ServerClient; @@ -44,14 +45,14 @@ import static org.sonar.batch.bootstrap.BatchSettings.BATCH_BOOTSTRAP_PROPERTIES public class ModuleSettings extends Settings { private final Configuration deprecatedCommonsConf; - private boolean dryRun; private final ServerClient client; + private AnalysisMode analysisMode; - public ModuleSettings(BatchSettings batchSettings, ProjectDefinition project, Configuration deprecatedCommonsConf, ServerClient client) { + public ModuleSettings(BatchSettings batchSettings, ProjectDefinition project, Configuration deprecatedCommonsConf, ServerClient client, AnalysisMode analysisMode) { super(batchSettings.getDefinitions()); this.client = client; + this.analysisMode = analysisMode; getEncryption().setPathToSecretKey(batchSettings.getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH)); - this.dryRun = "true".equals(batchSettings.getString(CoreProperties.DRY_RUN)); LoggerFactory.getLogger(ModuleSettings.class).info("Load module settings"); this.deprecatedCommonsConf = deprecatedCommonsConf; @@ -77,7 +78,7 @@ public class ModuleSettings extends Settings { } private void downloadSettings(String moduleKey) { - String url = BATCH_BOOTSTRAP_PROPERTIES_URL + "?project=" + moduleKey + "&dryRun=" + dryRun; + String url = BATCH_BOOTSTRAP_PROPERTIES_URL + "?project=" + moduleKey + "&dryRun=" + analysisMode.isPreview(); String jsonText = client.request(url); List> json = (List>) JSONValue.parse(jsonText); for (Map jsonProperty : json) { @@ -124,9 +125,9 @@ public class ModuleSettings extends Settings { @Override protected void doOnGetProperties(String key) { - if (this.dryRun && key.endsWith(".secured") && !key.contains(".license")) { + if (analysisMode.isPreview() && key.endsWith(".secured") && !key.contains(".license")) { throw new SonarException("Access to the secured property '" + key - + "' is not possible in local (dry run) SonarQube analysis. The SonarQube plugin which requires this property must be deactivated in dry run mode."); + + "' is not possible in preview mode. The SonarQube plugin which requires this property must be deactivated in preview mode."); } } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java index 2f51d525153..a21b1bbd93b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java @@ -22,12 +22,11 @@ package org.sonar.batch.scan; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; import org.sonar.api.utils.Semaphores; import org.sonar.api.utils.SonarException; import org.sonar.batch.ProjectTree; +import org.sonar.batch.bootstrap.AnalysisMode; public class ProjectLock { @@ -35,16 +34,16 @@ public class ProjectLock { private final Semaphores semaphores; private final ProjectTree projectTree; - private final Settings settings; + private final AnalysisMode analysisMode; - public ProjectLock(Semaphores semaphores, ProjectTree projectTree, Settings settings) { + public ProjectLock(Semaphores semaphores, ProjectTree projectTree, AnalysisMode analysisMode) { this.semaphores = semaphores; this.projectTree = projectTree; - this.settings = settings; + this.analysisMode = analysisMode; } public void start() { - if (!isInDryRunMode() && StringUtils.isNotBlank(getProject().getKey())) { + if (!analysisMode.isPreview() && StringUtils.isNotBlank(getProject().getKey())) { Semaphores.Semaphore semaphore = acquire(); if (!semaphore.isLocked()) { LOG.error(getErrorMessage(semaphore)); @@ -62,7 +61,7 @@ public class ProjectLock { } public void stop() { - if (!isInDryRunMode()) { + if (!analysisMode.isPreview()) { release(); } } @@ -84,8 +83,4 @@ public class ProjectLock { private Project getProject() { return projectTree.getRootProject(); } - - private boolean isInDryRunMode() { - return settings.getBoolean(CoreProperties.DRY_RUN); - } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java b/sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java index cce1d037c06..c521f261d9c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java @@ -20,7 +20,6 @@ package org.sonar.batch.scan; import org.sonar.api.BatchComponent; -import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.utils.MessageException; @@ -33,7 +32,6 @@ public class UnsupportedProperties implements BatchComponent { public void start() { verify("sonar.light", "The property 'sonar.light' is no longer supported. Please use 'sonar.dynamicAnalysis'"); - verifyIncrementalPreviewMode(); } private void verify(String key, String message) { @@ -41,10 +39,4 @@ public class UnsupportedProperties implements BatchComponent { throw MessageException.of(message); } } - - private void verifyIncrementalPreviewMode() { - if (settings.getBoolean(CoreProperties.INCREMENTAL_PREVIEW) && !settings.getBoolean(CoreProperties.DRY_RUN)) { - throw MessageException.of("Incremental mode is only supported with preview mode"); - } - } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java index 571088ac7cb..f37c3021b66 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java @@ -32,8 +32,10 @@ import org.sonar.api.scan.filesystem.FileQuery; import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.InputFiles; import org.sonar.api.scan.filesystem.ModuleFileSystem; +import org.sonar.batch.bootstrap.AnalysisMode; import javax.annotation.CheckForNull; + import java.io.File; import java.nio.charset.Charset; import java.util.List; @@ -55,16 +57,18 @@ public class DefaultModuleFileSystem implements ModuleFileSystem, Startable { private List binaryDirs = Lists.newArrayList(); private List sourceFiles = Lists.newArrayList(); private List testFiles = Lists.newArrayList(); + private AnalysisMode analysisMode; - public DefaultModuleFileSystem(ProjectDefinition module, Settings settings, FileIndex index, ModuleFileSystemInitializer initializer) { - this(module.getKey(), settings, index, initializer); + public DefaultModuleFileSystem(ProjectDefinition module, Settings settings, FileIndex index, ModuleFileSystemInitializer initializer, AnalysisMode analysisMode) { + this(module.getKey(), settings, index, initializer, analysisMode); } @VisibleForTesting - DefaultModuleFileSystem(String moduleKey, Settings settings, FileIndex index, ModuleFileSystemInitializer initializer) { + DefaultModuleFileSystem(String moduleKey, Settings settings, FileIndex index, ModuleFileSystemInitializer initializer, AnalysisMode analysisMode) { this.moduleKey = moduleKey; this.settings = settings; this.index = index; + this.analysisMode = analysisMode; this.baseDir = initializer.baseDir(); this.workingDir = initializer.workingDir(); this.buildDir = initializer.buildDir(); @@ -141,7 +145,7 @@ public class DefaultModuleFileSystem implements ModuleFileSystem, Startable { @Override public Iterable inputFiles(FileQuery query) { List result = Lists.newArrayList(); - FileQueryFilter filter = new FileQueryFilter(settings, query); + FileQueryFilter filter = new FileQueryFilter(analysisMode, query); for (InputFile input : index.inputFiles(moduleKey)) { if (filter.accept(input)) { result.add(input); @@ -189,7 +193,6 @@ public class DefaultModuleFileSystem implements ModuleFileSystem, Startable { return builder.build(); } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java index a273903d3cb..82f831eac1f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java @@ -21,11 +21,10 @@ package org.sonar.batch.scan.filesystem; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; import org.sonar.api.scan.filesystem.FileQuery; import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.InputFileFilter; +import org.sonar.batch.bootstrap.AnalysisMode; import java.util.Collection; import java.util.List; @@ -35,7 +34,7 @@ class FileQueryFilter { private final List filters; - FileQueryFilter(Settings settings, FileQuery query) { + FileQueryFilter(AnalysisMode analysisMode, FileQuery query) { filters = Lists.newArrayList(); for (String pattern : query.inclusions()) { filters.add(new InclusionFilter(pattern)); @@ -48,7 +47,7 @@ class FileQueryFilter { } // TODO speed-up the following algorithm. Cache ? - if (settings.getBoolean(CoreProperties.INCREMENTAL_PREVIEW)) { + if (analysisMode.isIncremental()) { Collection status = query.attributes().get(InputFile.ATTRIBUTE_STATUS); if (status == null || status.isEmpty()) { // TODO should be not(SAME) instead of is(ADDED, CHANGED) diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelectorFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelectorFactory.java index 81c9f8d4a1e..b384130468c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelectorFactory.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelectorFactory.java @@ -20,22 +20,21 @@ package org.sonar.batch.scan.report; import org.sonar.api.BatchComponent; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.scan.filesystem.InputFileCache; public class ComponentSelectorFactory implements BatchComponent { private final InputFileCache fileCache; - private final Settings settings; + private final AnalysisMode mode; - public ComponentSelectorFactory(InputFileCache fileCache, Settings settings) { + public ComponentSelectorFactory(InputFileCache fileCache, AnalysisMode mode) { this.fileCache = fileCache; - this.settings = settings; + this.mode = mode; } public ComponentSelector create() { - if (settings.getBoolean(CoreProperties.INCREMENTAL_PREVIEW)) { + if (mode.isIncremental()) { return new IncrementalComponentSelector(fileCache); } return new DefaultComponentSelector(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java index 049cff49360..e43dd40be50 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java @@ -25,7 +25,6 @@ import com.google.gson.stream.JsonWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; -import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.platform.Server; @@ -33,12 +32,17 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.scan.filesystem.ModuleFileSystem; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.SonarException; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.events.BatchStepEvent; import org.sonar.batch.events.EventBus; import org.sonar.batch.issue.IssueCache; import org.sonar.core.i18n.RuleI18nManager; -import java.io.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; import java.util.Locale; import java.util.Set; @@ -58,15 +62,16 @@ public class JsonReport implements BatchComponent { private final IssueCache issueCache; private final EventBus eventBus; private final ComponentSelector componentSelector; + private AnalysisMode analysisMode; public JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache, - EventBus eventBus, ComponentSelectorFactory componentSelectorFactory) { - this(settings, fileSystem, server, ruleI18nManager, issueCache, eventBus, componentSelectorFactory.create()); + EventBus eventBus, ComponentSelectorFactory componentSelectorFactory, AnalysisMode mode) { + this(settings, fileSystem, server, ruleI18nManager, issueCache, eventBus, componentSelectorFactory.create(), mode); } @VisibleForTesting JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache, - EventBus eventBus, ComponentSelector componentSelector) { + EventBus eventBus, ComponentSelector componentSelector, AnalysisMode analysisMode) { this.settings = settings; this.fileSystem = fileSystem; this.server = server; @@ -74,10 +79,11 @@ public class JsonReport implements BatchComponent { this.issueCache = issueCache; this.eventBus = eventBus; this.componentSelector = componentSelector; + this.analysisMode = analysisMode; } public void execute() { - if (settings.getBoolean(CoreProperties.DRY_RUN)) { + if (analysisMode.isPreview()) { eventBus.fireEvent(new BatchStepEvent("JSON report", true)); exportResults(); eventBus.fireEvent(new BatchStepEvent("JSON report", false)); @@ -128,19 +134,19 @@ public class JsonReport implements BatchComponent { for (DefaultIssue issue : getIssues()) { if (issue.resolution() == null && componentSelector.register(issue)) { json - .beginObject() - .name("key").value(issue.key()) - .name("component").value(issue.componentKey()) - .name("line").value(issue.line()) - .name("message").value(issue.message()) - .name("severity").value(issue.severity()) - .name("rule").value(issue.ruleKey().toString()) - .name("status").value(issue.status()) - .name("resolution").value(issue.resolution()) - .name("isNew").value(issue.isNew()) - .name("reporter").value(issue.reporter()) - .name("assignee").value(issue.assignee()) - .name("effortToFix").value(issue.effortToFix()); + .beginObject() + .name("key").value(issue.key()) + .name("component").value(issue.componentKey()) + .name("line").value(issue.line()) + .name("message").value(issue.message()) + .name("severity").value(issue.severity()) + .name("rule").value(issue.ruleKey().toString()) + .name("status").value(issue.status()) + .name("resolution").value(issue.resolution()) + .name("isNew").value(issue.isNew()) + .name("reporter").value(issue.reporter()) + .name("assignee").value(issue.assignee()) + .name("effortToFix").value(issue.effortToFix()); if (issue.creationDate() != null) { json.name("creationDate").value(DateUtils.formatDateTime(issue.creationDate())); } @@ -161,9 +167,9 @@ public class JsonReport implements BatchComponent { json.name("components").beginArray(); for (String componentKey : componentSelector.componentKeys()) { json - .beginObject() - .name("key").value(componentKey) - .endObject(); + .beginObject() + .name("key").value(componentKey) + .endObject(); } json.endArray(); } @@ -172,12 +178,12 @@ public class JsonReport implements BatchComponent { json.name("rules").beginArray(); for (RuleKey ruleKey : ruleKeys) { json - .beginObject() - .name("key").value(ruleKey.toString()) - .name("rule").value(ruleKey.rule()) - .name("repository").value(ruleKey.repository()) - .name("name").value(getRuleName(ruleKey)) - .endObject(); + .beginObject() + .name("key").value(ruleKey.toString()) + .name("rule").value(ruleKey.rule()) + .name("repository").value(ruleKey.repository()) + .name("name").value(getRuleName(ruleKey)) + .endObject(); } json.endArray(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseTest.java index 042c2d98bd6..06e1b72b5e0 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseTest.java @@ -30,7 +30,7 @@ import static org.mockito.Mockito.mock; public class BatchDatabaseTest { @Test public void should_init_at_least_two_connections() { - BatchDatabase db = new BatchDatabase(new Settings(), mock(JdbcDriverHolder.class), mock(DryRunDatabase.class)); + BatchDatabase db = new BatchDatabase(new Settings(), mock(AnalysisMode.class), mock(JdbcDriverHolder.class), mock(PreviewDatabase.class)); Properties props = new Properties(); db.doCompleteProperties(props); diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java index 04ac097df7a..56cdc053f3c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java @@ -22,6 +22,7 @@ package org.sonar.batch.bootstrap; import com.google.common.collect.Lists; import org.codehaus.plexus.util.FileUtils; import org.junit.After; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -46,6 +47,12 @@ public class BatchPluginRepositoryTest { public TemporaryFolder temp = new TemporaryFolder(); private BatchPluginRepository repository; + private AnalysisMode mode; + + @Before + public void before() { + mode = mock(AnalysisMode.class); + } @After public void tearDown() { @@ -64,7 +71,7 @@ public class BatchPluginRepositoryTest { PluginDownloader downloader = mock(PluginDownloader.class); when(downloader.downloadPlugin(checkstyle)).thenReturn(copyFiles("sonar-checkstyle-plugin-2.8.jar")); - repository = new BatchPluginRepository(downloader, tempDirs, new Settings()); + repository = new BatchPluginRepository(downloader, tempDirs, new Settings(), mode); repository.doStart(Arrays.asList(checkstyle)); @@ -88,7 +95,7 @@ public class BatchPluginRepositoryTest { when(downloader.downloadPlugin(checkstyle)).thenReturn(copyFiles("sonar-checkstyle-plugin-2.8.jar")); when(downloader.downloadPlugin(checkstyleExt)).thenReturn(copyFiles("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar")); - repository = new BatchPluginRepository(downloader, tempDirs, new Settings()); + repository = new BatchPluginRepository(downloader, tempDirs, new Settings(), mode); repository.doStart(Arrays.asList(checkstyle, checkstyleExt)); @@ -110,7 +117,7 @@ public class BatchPluginRepositoryTest { PluginDownloader downloader = mock(PluginDownloader.class); when(downloader.downloadPlugin(checkstyle)).thenReturn(copyFiles("sonar-checkstyle-plugin-2.8.jar", "checkstyle-ext.xml")); - repository = new BatchPluginRepository(downloader, tempDirs, new Settings()); + repository = new BatchPluginRepository(downloader, tempDirs, new Settings(), mode); repository.doStart(Arrays.asList(checkstyle)); @@ -137,7 +144,7 @@ public class BatchPluginRepositoryTest { Settings settings = new Settings(); settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle"); - repository = new BatchPluginRepository(downloader, tempDirs, settings); + repository = new BatchPluginRepository(downloader, tempDirs, settings, mode); repository.doStart(Arrays.asList(checkstyle, checkstyleExt)); @@ -158,32 +165,32 @@ public class BatchPluginRepositoryTest { @Test public void shouldAlwaysAcceptIfNoWhiteListAndBlackList() { - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings()); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode); assertThat(filter.accepts("pmd")).isTrue(); } @Test public void whiteListShouldTakePrecedenceOverBlackList() { Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs") - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings); + .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd"); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); assertThat(filter.accepts("pmd")).isTrue(); } @Test public void corePluginShouldAlwaysBeInWhiteList() { Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings); + .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); assertThat(filter.accepts("core")).isTrue(); } @Test public void corePluginShouldNeverBeInBlackList() { Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings); + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs"); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); assertThat(filter.accepts("core")).isTrue(); } @@ -191,16 +198,16 @@ public class BatchPluginRepositoryTest { @Test public void englishPackPluginShouldNeverBeInBlackList() { Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "l10nen,findbugs"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings); + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "l10nen,findbugs"); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); assertThat(filter.accepts("l10nen")).isTrue(); } @Test public void shouldCheckWhitelist() { Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings); + .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); assertThat(filter.accepts("checkstyle")).isTrue(); assertThat(filter.accepts("pmd")).isTrue(); assertThat(filter.accepts("cobertura")).isFalse(); @@ -209,21 +216,33 @@ public class BatchPluginRepositoryTest { @Test public void shouldCheckBlackListIfNoWhiteList() { Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings); + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); assertThat(filter.accepts("checkstyle")).isFalse(); assertThat(filter.accepts("pmd")).isFalse(); assertThat(filter.accepts("cobertura")).isTrue(); } @Test - public void should_concatenate_dry_run_filters() { + public void should_concatenate_preview_filters() { + Settings settings = new Settings() + .setProperty(CoreProperties.PREVIEW_INCLUDE_PLUGINS, "cockpit") + .setProperty(CoreProperties.PREVIEW_EXCLUDE_PLUGINS, "views") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); + when(mode.isPreview()).thenReturn(true); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); + assertThat(filter.whites).containsOnly("cockpit"); + assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd"); + } + + @Test + public void should_concatenate_deprecated_dry_run_filters() { Settings settings = new Settings() - .setProperty(CoreProperties.DRY_RUN, true) - .setProperty(CoreProperties.DRY_RUN_INCLUDE_PLUGINS, "cockpit") - .setProperty(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, "views") - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings); + .setProperty(CoreProperties.DRY_RUN_INCLUDE_PLUGINS, "cockpit") + .setProperty(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, "views") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); + when(mode.isPreview()).thenReturn(true); + BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); assertThat(filter.whites).containsOnly("cockpit"); assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd"); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchSettingsTest.java index 396b2d4be3a..0c67862db73 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchSettingsTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchSettingsTest.java @@ -56,9 +56,12 @@ public class BatchSettingsTest { Configuration deprecatedConf = new BaseConfiguration(); BootstrapSettings bootstrapSettings; + private AnalysisMode mode; + @Before public void prepare() { - bootstrapSettings = new BootstrapSettings(new BootstrapProperties(Collections. emptyMap())); + bootstrapSettings = new BootstrapSettings(new BootstrapProperties(Collections.emptyMap())); + mode = mock(AnalysisMode.class); } @Test @@ -66,9 +69,9 @@ public class BatchSettingsTest { when(client.request("/batch_bootstrap/properties?dryRun=false")).thenReturn(JSON_RESPONSE); System.setProperty("BatchSettingsTest.testSystemProp", "system"); // Reconstruct bootstrap settings to get system property - bootstrapSettings = new BootstrapSettings(new BootstrapProperties(Collections. emptyMap())); + bootstrapSettings = new BootstrapSettings(new BootstrapProperties(Collections.emptyMap())); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); assertThat(batchSettings.getString("BatchSettingsTest.testSystemProp")).isEqualTo("system"); } @@ -79,7 +82,7 @@ public class BatchSettingsTest { when(client.request("/batch_bootstrap/properties?project=struts&dryRun=false")).thenReturn(REACTOR_JSON_RESPONSE); project.setProperty("project.prop", "project"); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); batchSettings.init(new ProjectReactor(project)); assertThat(batchSettings.getString("project.prop")).isEqualTo("project"); @@ -89,7 +92,7 @@ public class BatchSettingsTest { public void should_load_global_settings() { when(client.request("/batch_bootstrap/properties?dryRun=false")).thenReturn(JSON_RESPONSE); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); assertThat(batchSettings.getBoolean("sonar.cpd.cross")).isTrue(); } @@ -99,7 +102,7 @@ public class BatchSettingsTest { when(client.request("/batch_bootstrap/properties?dryRun=false")).thenReturn(JSON_RESPONSE); when(client.request("/batch_bootstrap/properties?project=struts&dryRun=false")).thenReturn(REACTOR_JSON_RESPONSE); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); batchSettings.init(new ProjectReactor(project)); assertThat(batchSettings.getString("sonar.java.coveragePlugin")).isEqualTo("jacoco"); @@ -112,7 +115,7 @@ public class BatchSettingsTest { bootstrapSettings.properties().put(CoreProperties.PROJECT_BRANCH_PROPERTY, "mybranch"); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); batchSettings.init(new ProjectReactor(project)); assertThat(batchSettings.getString("sonar.java.coveragePlugin")).isEqualTo("jacoco"); @@ -123,7 +126,7 @@ public class BatchSettingsTest { when(client.request("/batch_bootstrap/properties?dryRun=false")).thenReturn(JSON_RESPONSE_WITH_SECURED); when(client.request("/batch_bootstrap/properties?project=struts&dryRun=false")).thenReturn(REACTOR_JSON_RESPONSE); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); batchSettings.init(new ProjectReactor(project)); assertThat(batchSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2"); @@ -135,15 +138,15 @@ public class BatchSettingsTest { when(client.request("/batch_bootstrap/properties?dryRun=true")).thenReturn(JSON_RESPONSE_WITH_SECURED); when(client.request("/batch_bootstrap/properties?project=struts&dryRun=true")).thenReturn(REACTOR_JSON_RESPONSE); - bootstrapSettings.properties().put(CoreProperties.DRY_RUN, "true"); + when(mode.isPreview()).thenReturn(true); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); batchSettings.init(new ProjectReactor(project)); assertThat(batchSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2"); thrown.expect(SonarException.class); thrown - .expectMessage("Access to the secured property 'sonar.foo.secured' is not possible in local (dry run) SonarQube analysis. The SonarQube plugin which requires this property must be deactivated in dry run mode."); + .expectMessage("Access to the secured property 'sonar.foo.secured' is not possible in preview mode. The SonarQube plugin which requires this property must be deactivated in preview mode."); batchSettings.getString("sonar.foo.secured"); } @@ -153,7 +156,7 @@ public class BatchSettingsTest { System.setProperty("BatchSettingsTest.testSystemProp", "system"); project.setProperty("BatchSettingsTest.testSystemProp", "build"); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); assertThat(batchSettings.getString("BatchSettingsTest.testSystemProp")).isEqualTo("system"); } @@ -163,7 +166,7 @@ public class BatchSettingsTest { when(client.request("/batch_bootstrap/properties?dryRun=false")).thenReturn(JSON_RESPONSE); when(client.request("/batch_bootstrap/properties?project=struts&dryRun=false")).thenReturn(REACTOR_JSON_RESPONSE); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); batchSettings.init(new ProjectReactor(project)); assertThat(deprecatedConf.getString("sonar.cpd.cross")).isEqualTo("true"); @@ -181,7 +184,7 @@ public class BatchSettingsTest { @Test public void project_should_be_optional() { when(client.request("/batch_bootstrap/properties?dryRun=false")).thenReturn(JSON_RESPONSE); - BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf); + BatchSettings batchSettings = new BatchSettings(bootstrapSettings, new PropertyDefinitions(), client, deprecatedConf, mode); assertThat(batchSettings.getProperties()).isNotEmpty(); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseCompatibilityTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseCompatibilityTest.java index 673d422affe..aa166f78195 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseCompatibilityTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseCompatibilityTest.java @@ -41,6 +41,8 @@ public class DatabaseCompatibilityTest { ServerMetadata server; Settings settings; + private AnalysisMode mode; + @Before public void init() { server = mock(ServerMetadata.class); @@ -51,7 +53,8 @@ public class DatabaseCompatibilityTest { settings.setProperty(DatabaseProperties.PROP_URL, "jdbc:postgresql://localhost/foo"); settings.setProperty(DatabaseProperties.PROP_USER, "bar"); settings.setProperty(CoreProperties.SERVER_ID, "123456"); - settings.setProperty(CoreProperties.DRY_RUN, false); + + mode = mock(AnalysisMode.class); databaseVersion = mock(DatabaseVersion.class); } @@ -63,7 +66,7 @@ public class DatabaseCompatibilityTest { thrown.expect(MessageException.class); thrown.expectMessage("Database relates to a more recent version of SonarQube. Please check your settings (JDBC settings, version of Maven plugin)"); - new DatabaseCompatibility(databaseVersion, server, settings).start(); + new DatabaseCompatibility(databaseVersion, server, settings, mode).start(); } @Test @@ -73,7 +76,7 @@ public class DatabaseCompatibilityTest { thrown.expect(MessageException.class); thrown.expectMessage("Database must be upgraded."); - new DatabaseCompatibility(databaseVersion, server, settings).start(); + new DatabaseCompatibility(databaseVersion, server, settings, mode).start(); } @Test @@ -85,7 +88,7 @@ public class DatabaseCompatibilityTest { thrown.expectMessage("- Batch side: jdbc:postgresql://localhost/foo (bar / *****)"); thrown.expectMessage("- Server side: check the configuration at http://localhost:9000/system"); - new DatabaseCompatibility(databaseVersion, server, settings).start(); + new DatabaseCompatibility(databaseVersion, server, settings, mode).start(); } @Test @@ -97,7 +100,7 @@ public class DatabaseCompatibilityTest { thrown.expect(MessageException.class); thrown.expectMessage("- Batch side: jdbc:postgresql://localhost/foo (sonar / *****)"); - new DatabaseCompatibility(databaseVersion, server, settings).start(); + new DatabaseCompatibility(databaseVersion, server, settings, mode).start(); } @Test @@ -106,22 +109,22 @@ public class DatabaseCompatibilityTest { thrown.expect(IllegalStateException.class); - new DatabaseCompatibility(mock(DatabaseVersion.class), server, settings).start(); + new DatabaseCompatibility(mock(DatabaseVersion.class), server, settings, mode).start(); } @Test public void shouldDoNothingIfUpToDate() { when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE); - new DatabaseCompatibility(databaseVersion, server, settings).start(); + new DatabaseCompatibility(databaseVersion, server, settings, mode).start(); // no error } @Test - public void should_not_verify_compatibility_if_dry_run() { + public void should_not_verify_compatibility_if_preview() { settings.setProperty(CoreProperties.SERVER_ID, "11111111"); - settings.setProperty(CoreProperties.DRY_RUN, true); + when(mode.isPreview()).thenReturn(true); - new DatabaseCompatibility(databaseVersion, server, settings).start(); + new DatabaseCompatibility(databaseVersion, server, settings, mode).start(); // no failure } diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DryRunDatabaseTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DryRunDatabaseTest.java deleted file mode 100644 index 94935e8fa20..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DryRunDatabaseTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.bootstrap; - -import org.apache.commons.lang.StringUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; -import org.sonar.api.database.DatabaseProperties; -import org.sonar.api.utils.HttpDownloader; -import org.sonar.api.utils.SonarException; - -import java.io.File; -import java.net.SocketTimeoutException; - -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class DryRunDatabaseTest { - Settings settings; - ServerClient server = mock(ServerClient.class); - TempDirectories tempDirectories = mock(TempDirectories.class); - File databaseFile; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - @Before - public void setUp() throws Exception { - databaseFile = temp.newFile("dryrun.h2.db"); - when(tempDirectories.getFile("", "dryrun.h2.db")).thenReturn(databaseFile); - settings = new Settings(); - settings.setProperty(CoreProperties.DRY_RUN, true); - settings.setProperty(CoreProperties.PROJECT_KEY_PROPERTY, "group:project"); - } - - @Test - public void should_be_disabled_if_not_dry_run() { - settings.setProperty(CoreProperties.DRY_RUN, false); - new DryRunDatabase(settings, server, tempDirectories).start(); - - verifyZeroInteractions(tempDirectories, server); - } - - @Test - public void should_download_database() { - new DryRunDatabase(settings, server, tempDirectories).start(); - - verify(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); - } - - @Test - public void should_download_database_with_overriden_timeout() { - settings.setProperty(CoreProperties.DRY_RUN_READ_TIMEOUT_SEC, 80); - new DryRunDatabase(settings, server, tempDirectories).start(); - - verify(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 80000); - } - - @Test - public void should_download_database_on_branch() { - settings.setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "mybranch"); - new DryRunDatabase(settings, server, tempDirectories).start(); - - verify(server).download("/batch_bootstrap/db?project=group:project:mybranch", databaseFile, 60000); - } - - @Test - public void should_replace_database_settings() { - new DryRunDatabase(settings, server, tempDirectories).start(); - - assertThat(settings.getString(DatabaseProperties.PROP_DIALECT)).isEqualTo("h2"); - assertThat(settings.getString(DatabaseProperties.PROP_DRIVER)).isEqualTo("org.h2.Driver"); - assertThat(settings.getString(DatabaseProperties.PROP_USER)).isEqualTo("sonar"); - assertThat(settings.getString(DatabaseProperties.PROP_PASSWORD)).isEqualTo("sonar"); - assertThat(settings.getString(DatabaseProperties.PROP_URL)).isEqualTo("jdbc:h2:" + StringUtils.removeEnd(databaseFile.getAbsolutePath(), ".h2.db")); - } - - @Test - public void should_fail_on_invalid_role() { - doThrow(new SonarException(new HttpDownloader.HttpException(null, 401))).when(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); - - thrown.expect(SonarException.class); - thrown.expectMessage("You don't have access rights to project [group:project]"); - - new DryRunDatabase(settings, server, tempDirectories).start(); - } - - @Test - public void should_fail_on_read_timeout() { - doThrow(new SonarException(new SocketTimeoutException())).when(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); - - thrown.expect(SonarException.class); - thrown.expectMessage("DryRun database read timed out after 60000 ms. You can try to increase read timeout with property -Dsonar.dryRun.readTimeout (in seconds)"); - - new DryRunDatabase(settings, server, tempDirectories).start(); - } - - @Test - public void should_fail() { - doThrow(new SonarException("BUG")).when(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); - - thrown.expect(SonarException.class); - thrown.expectMessage("BUG"); - - new DryRunDatabase(settings, server, tempDirectories).start(); - } - - @Test - public void project_should_be_optional() { - // on non-scan tasks - settings.removeProperty(CoreProperties.PROJECT_KEY_PROPERTY); - new DryRunDatabase(settings, server, tempDirectories).start(); - verify(server).download("/batch_bootstrap/db", databaseFile, 60000); - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java index cb02a9657dd..d3c5b7c095d 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java @@ -21,13 +21,13 @@ package org.sonar.batch.bootstrap; import com.google.common.collect.Maps; import org.apache.commons.lang.ClassUtils; +import org.junit.Before; import org.junit.Test; import org.sonar.api.BatchExtension; import org.sonar.api.ExtensionProvider; import org.sonar.api.Plugin; import org.sonar.api.SonarPlugin; import org.sonar.api.batch.SupportedEnvironment; -import org.sonar.api.config.Settings; import org.sonar.api.platform.ComponentContainer; import org.sonar.api.platform.PluginMetadata; import org.sonar.batch.bootstrapper.EnvironmentInformation; @@ -42,26 +42,32 @@ import static org.mockito.Mockito.when; public class ExtensionInstallerTest { + private AnalysisMode mode; PluginMetadata metadata = mock(PluginMetadata.class); Map newPlugin(final Object... extensions) { Map result = Maps.newHashMap(); result.put(metadata, - new SonarPlugin() { - public List getExtensions() { - return Arrays.asList(extensions); - } + new SonarPlugin() { + public List getExtensions() { + return Arrays.asList(extensions); } - ); + } + ); return result; } + @Before + public void setUp() throws Exception { + mode = mock(AnalysisMode.class); + } + @Test public void should_filter_extensions_to_install() { BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(Foo.class, Bar.class)); ComponentContainer container = new ComponentContainer(); - ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new Settings()); + ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode); installer.install(container, new FooMatcher()); assertThat(container.getComponentByType(Foo.class)).isNotNull(); @@ -73,7 +79,7 @@ public class ExtensionInstallerTest { BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(new FooProvider(), new BarProvider())); ComponentContainer container = new ComponentContainer(); - ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new Settings()); + ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode); installer.install(container, new FooMatcher()); @@ -86,7 +92,7 @@ public class ExtensionInstallerTest { BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(new FooBarProvider())); ComponentContainer container = new ComponentContainer(); - ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new Settings()); + ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode); installer.install(container, new TrueMatcher()); @@ -100,7 +106,7 @@ public class ExtensionInstallerTest { when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(Foo.class, MavenExtension.class, AntExtension.class, new BarProvider())); ComponentContainer container = new ComponentContainer(); - ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new Settings()); + ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode); installer.install(container, new TrueMatcher()); diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionUtilsTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionUtilsTest.java index d5809081505..7825e2592d9 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionUtilsTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionUtilsTest.java @@ -81,10 +81,10 @@ public class ExtensionUtilsTest { @Test public void shouldSupportDryRun() { - assertThat(ExtensionUtils.supportsDryRun(BatchService.class)).isTrue(); - assertThat(ExtensionUtils.supportsDryRun(new BatchService())).isTrue(); - assertThat(ExtensionUtils.supportsDryRun(PersistentService.class)).isFalse(); - assertThat(ExtensionUtils.supportsDryRun(new PersistentService())).isFalse(); + assertThat(ExtensionUtils.supportsPreview(BatchService.class)).isTrue(); + assertThat(ExtensionUtils.supportsPreview(new BatchService())).isTrue(); + assertThat(ExtensionUtils.supportsPreview(PersistentService.class)).isFalse(); + assertThat(ExtensionUtils.supportsPreview(new PersistentService())).isFalse(); } @InstantiationStrategy(InstantiationStrategy.PER_BATCH) diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/JdbcDriverHolderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/JdbcDriverHolderTest.java index f54e45b464c..3e36a9b103d 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/JdbcDriverHolderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/JdbcDriverHolderTest.java @@ -25,8 +25,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; import org.sonar.home.cache.FileCache; import java.io.File; @@ -47,10 +45,12 @@ public class JdbcDriverHolderTest { public ExpectedException thrown = ExpectedException.none(); ClassLoader initialThreadClassloader; + private AnalysisMode mode; @Before public void before() { initialThreadClassloader = Thread.currentThread().getContextClassLoader(); + mode = mock(AnalysisMode.class); } @After @@ -72,7 +72,7 @@ public class JdbcDriverHolderTest { when(server.request("/deploy/jdbc-driver.txt")).thenReturn("ojdbc14.jar|fakemd5"); when(server.request("/deploy/ojdbc14.jar")).thenReturn("fakecontent"); - JdbcDriverHolder holder = new JdbcDriverHolder(cache, new Settings(), server); + JdbcDriverHolder holder = new JdbcDriverHolder(cache, mode, server); holder.start(); assertThat(holder.getClassLoader().getResource("foo/foo.txt")).isNotNull(); @@ -85,11 +85,11 @@ public class JdbcDriverHolderTest { } @Test - public void should_be_disabled_if_dry_run() { + public void should_be_disabled_if_preview() { FileCache cache = mock(FileCache.class); - Settings settings = new Settings().setProperty(CoreProperties.DRY_RUN, true); + when(mode.isPreview()).thenReturn(true); ServerClient server = mock(ServerClient.class); - JdbcDriverHolder holder = new JdbcDriverHolder(cache, settings, server); + JdbcDriverHolder holder = new JdbcDriverHolder(cache, mode, server); holder.start(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PreviewDatabaseTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PreviewDatabaseTest.java new file mode 100644 index 00000000000..cd41618236d --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PreviewDatabaseTest.java @@ -0,0 +1,155 @@ +/* + * 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.bootstrap; + +import org.apache.commons.lang.StringUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.api.database.DatabaseProperties; +import org.sonar.api.utils.HttpDownloader; +import org.sonar.api.utils.SonarException; + +import java.io.File; +import java.net.SocketTimeoutException; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class PreviewDatabaseTest { + Settings settings; + ServerClient server = mock(ServerClient.class); + TempDirectories tempDirectories = mock(TempDirectories.class); + File databaseFile; + private AnalysisMode mode; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Before + public void setUp() throws Exception { + databaseFile = temp.newFile("preview.h2.db"); + when(tempDirectories.getFile("", "preview.h2.db")).thenReturn(databaseFile); + settings = new Settings(); + settings.setProperty(CoreProperties.PROJECT_KEY_PROPERTY, "group:project"); + + mode = mock(AnalysisMode.class); + when(mode.isPreview()).thenReturn(true); + } + + @Test + public void should_be_disabled_if_not_preview() { + when(mode.isPreview()).thenReturn(false); + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + + verifyZeroInteractions(tempDirectories, server); + } + + @Test + public void should_download_database() { + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + + verify(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); + } + + @Test + public void should_download_database_with_deprecated_overriden_timeout() { + settings.setProperty(CoreProperties.DRY_RUN_READ_TIMEOUT_SEC, 80); + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + + verify(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 80000); + } + + @Test + public void should_download_database_with_overriden_timeout() { + settings.setProperty(CoreProperties.PREVIEW_READ_TIMEOUT_SEC, 80); + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + + verify(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 80000); + } + + @Test + public void should_download_database_on_branch() { + settings.setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "mybranch"); + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + + verify(server).download("/batch_bootstrap/db?project=group:project:mybranch", databaseFile, 60000); + } + + @Test + public void should_replace_database_settings() { + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + + assertThat(settings.getString(DatabaseProperties.PROP_DIALECT)).isEqualTo("h2"); + assertThat(settings.getString(DatabaseProperties.PROP_DRIVER)).isEqualTo("org.h2.Driver"); + assertThat(settings.getString(DatabaseProperties.PROP_USER)).isEqualTo("sonar"); + assertThat(settings.getString(DatabaseProperties.PROP_PASSWORD)).isEqualTo("sonar"); + assertThat(settings.getString(DatabaseProperties.PROP_URL)).isEqualTo("jdbc:h2:" + StringUtils.removeEnd(databaseFile.getAbsolutePath(), ".h2.db")); + } + + @Test + public void should_fail_on_invalid_role() { + doThrow(new SonarException(new HttpDownloader.HttpException(null, 401))).when(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); + + thrown.expect(SonarException.class); + thrown.expectMessage("You don't have access rights to project [group:project]"); + + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + } + + @Test + public void should_fail_on_read_timeout() { + doThrow(new SonarException(new SocketTimeoutException())).when(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); + + thrown.expect(SonarException.class); + thrown.expectMessage("Preview database read timed out after 60000 ms. You can try to increase read timeout with property -Dsonar.preview.readTimeout (in seconds)"); + + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + } + + @Test + public void should_fail() { + doThrow(new SonarException("BUG")).when(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); + + thrown.expect(SonarException.class); + thrown.expectMessage("BUG"); + + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + } + + @Test + public void project_should_be_optional() { + // on non-scan tasks + settings.removeProperty(CoreProperties.PROJECT_KEY_PROPERTY); + new PreviewDatabase(settings, server, tempDirectories, mode).start(); + verify(server).download("/batch_bootstrap/db", databaseFile, 60000); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/IssuePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/IssuePersisterTest.java index 0a30195aa1f..baa08006d3c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/IssuePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/IssuePersisterTest.java @@ -21,8 +21,8 @@ package org.sonar.batch.issue; import org.junit.Before; import org.junit.Test; -import org.sonar.api.config.Settings; import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.core.persistence.AbstractDaoTestCase; import java.util.Arrays; @@ -39,7 +39,7 @@ public class IssuePersisterTest extends AbstractDaoTestCase { IssuePersister persister; private ScanIssueStorage storage; private List issues; - private Settings settings; + private AnalysisMode mode; @Before public void prepare() { @@ -48,8 +48,8 @@ public class IssuePersisterTest extends AbstractDaoTestCase { when(issueCache.all()).thenReturn(issues); storage = mock(ScanIssueStorage.class); - settings = new Settings(); - persister = new IssuePersister(issueCache, storage, settings); + mode = mock(AnalysisMode.class); + persister = new IssuePersister(issueCache, storage, mode); } @Test @@ -60,8 +60,8 @@ public class IssuePersisterTest extends AbstractDaoTestCase { } @Test - public void should_not_persist_issues_in_dry_run() throws Exception { - settings.setProperty("sonar.dryRun", true); + public void should_not_persist_issues_in_preview_mode() throws Exception { + when(mode.isPreview()).thenReturn(true); persister.persist(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java index fd975e034de..88e21cc4a36 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java @@ -19,6 +19,7 @@ */ package org.sonar.batch.phases; +import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.sonar.api.CoreProperties; @@ -27,6 +28,8 @@ import org.sonar.api.database.DatabaseSession; import org.sonar.api.database.model.Snapshot; import org.sonar.api.resources.Project; import org.sonar.api.security.ResourcePermissions; +import org.sonar.batch.bootstrap.AnalysisMode; +import org.sonar.batch.bootstrap.BootstrapSettings; import org.sonar.batch.bootstrap.ServerClient; import org.sonar.batch.index.DefaultResourcePersister; import org.sonar.batch.index.ResourceCache; @@ -41,9 +44,18 @@ import static org.mockito.Matchers.contains; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class UpdateStatusJobTest extends AbstractDbUnitTestCase { + private AnalysisMode mode; + private BootstrapSettings bootstrapSettings; + + @Before + public void setUp() { + mode = mock(AnalysisMode.class); + } + @Test public void shouldUnflagPenultimateLastSnapshot() { assertAnalysis(11, "shouldUnflagPenultimateLastSnapshot"); @@ -67,7 +79,7 @@ public class UpdateStatusJobTest extends AbstractDbUnitTestCase { project.setId(1); UpdateStatusJob job = new UpdateStatusJob(new Settings().appendProperty(CoreProperties.SERVER_BASE_URL, "http://myserver/"), mock(ServerClient.class), session, new DefaultResourcePersister(session, mock(ResourcePermissions.class), mock(SnapshotCache.class), mock(ResourceCache.class)), - project, loadSnapshot(snapshotId)); + project, loadSnapshot(snapshotId), mode); job.execute(); checkTables(fixture, "snapshots"); @@ -85,7 +97,7 @@ public class UpdateStatusJobTest extends AbstractDbUnitTestCase { settings.setProperty(CoreProperties.SERVER_BASE_URL, "http://myserver/"); Project project = new Project("struts"); UpdateStatusJob job = new UpdateStatusJob(settings, mock(ServerClient.class), mock(DatabaseSession.class), - mock(ResourcePersister.class), project, mock(Snapshot.class)); + mock(ResourcePersister.class), project, mock(Snapshot.class), mode); Logger logger = mock(Logger.class); job.logSuccess(logger); @@ -94,12 +106,12 @@ public class UpdateStatusJobTest extends AbstractDbUnitTestCase { } @Test - public void should_log_successful_dry_run_analysis() throws Exception { + public void should_log_successful_preview_analysis() throws Exception { Settings settings = new Settings(); - settings.setProperty("sonar.dryRun", true); + when(mode.isPreview()).thenReturn(true); Project project = new Project("struts"); UpdateStatusJob job = new UpdateStatusJob(settings, mock(ServerClient.class), mock(DatabaseSession.class), - mock(ResourcePersister.class), project, mock(Snapshot.class)); + mock(ResourcePersister.class), project, mock(Snapshot.class), mode); Logger logger = mock(Logger.class); job.logSuccess(logger); @@ -113,22 +125,22 @@ public class UpdateStatusJobTest extends AbstractDbUnitTestCase { Project project = new Project("struts"); ServerClient serverClient = mock(ServerClient.class); UpdateStatusJob job = new UpdateStatusJob(settings, serverClient, mock(DatabaseSession.class), - mock(ResourcePersister.class), project, mock(Snapshot.class)); + mock(ResourcePersister.class), project, mock(Snapshot.class), mode); - job.evictDryRunDB(); + job.evictPreviewDB(); verify(serverClient).request(contains("/batch_bootstrap/evict")); } @Test - public void should_not_evict_cache_for_dry_run_analysis() throws Exception { + public void should_not_evict_cache_for_preview_analysis() throws Exception { Settings settings = new Settings(); - settings.setProperty("sonar.dryRun", true); + when(mode.isPreview()).thenReturn(true); Project project = new Project("struts"); ServerClient serverClient = mock(ServerClient.class); UpdateStatusJob job = new UpdateStatusJob(settings, serverClient, mock(DatabaseSession.class), - mock(ResourcePersister.class), project, mock(Snapshot.class)); + mock(ResourcePersister.class), project, mock(Snapshot.class), mode); - job.evictDryRunDB(); + job.evictPreviewDB(); verify(serverClient, never()).request(anyString()); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/LastSnapshotsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/LastSnapshotsTest.java index fe2a78750de..d712ee66245 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/LastSnapshotsTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/LastSnapshotsTest.java @@ -19,14 +19,14 @@ */ package org.sonar.batch.scan; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; import org.sonar.api.utils.HttpDownloader; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.ServerClient; import org.sonar.jpa.test.AbstractDbUnitTestCase; @@ -36,19 +36,28 @@ import java.net.URISyntaxException; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; public class LastSnapshotsTest extends AbstractDbUnitTestCase { @Rule public ExpectedException thrown = ExpectedException.none(); + private AnalysisMode mode; + + @Before + public void before() { + mode = mock(AnalysisMode.class); + } @Test public void should_get_source_of_last_snapshot() { setupData("last_snapshot"); ServerClient server = mock(ServerClient.class); - LastSnapshots lastSnapshots = new LastSnapshots(new Settings(), getSession(), server); + LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server); assertThat(lastSnapshots.getSource(newFile())).isEqualTo("this is bar"); verifyZeroInteractions(server); @@ -59,21 +68,20 @@ public class LastSnapshotsTest extends AbstractDbUnitTestCase { setupData("no_last_snapshot"); ServerClient server = mock(ServerClient.class); - LastSnapshots lastSnapshots = new LastSnapshots(new Settings(), getSession(), server); + LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server); assertThat(lastSnapshots.getSource(newFile())).isEqualTo(""); verifyZeroInteractions(server); } @Test - public void should_download_source_from_ws_if_dry_run() { + public void should_download_source_from_ws_if_preview_mode() { setupData("last_snapshot"); ServerClient server = mock(ServerClient.class); when(server.request(anyString(), eq(false))).thenReturn("downloaded source of Bar.c"); - Settings settings = new Settings(); - settings.setProperty(CoreProperties.DRY_RUN, true); - LastSnapshots lastSnapshots = new LastSnapshots(settings, getSession(), server); + when(mode.isPreview()).thenReturn(true); + LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server); String source = lastSnapshots.getSource(newFile()); assertThat(source).isEqualTo("downloaded source of Bar.c"); @@ -86,23 +94,21 @@ public class LastSnapshotsTest extends AbstractDbUnitTestCase { ServerClient server = mock(ServerClient.class); when(server.request(anyString(), eq(false))).thenThrow(new HttpDownloader.HttpException(new URI(""), 500)); - Settings settings = new Settings(); - settings.setProperty(CoreProperties.DRY_RUN, true); - LastSnapshots lastSnapshots = new LastSnapshots(settings, getSession(), server); + when(mode.isPreview()).thenReturn(true); + LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server); thrown.expect(HttpDownloader.HttpException.class); lastSnapshots.getSource(newFile()); } @Test - public void should_return_empty_source_if_dry_run_and_no_last_snapshot() throws URISyntaxException { + public void should_return_empty_source_if_preview_mode_and_no_last_snapshot() throws URISyntaxException { setupData("last_snapshot"); ServerClient server = mock(ServerClient.class); when(server.request(anyString(), eq(false))).thenThrow(new HttpDownloader.HttpException(new URI(""), 404)); - Settings settings = new Settings(); - settings.setProperty(CoreProperties.DRY_RUN, true); - LastSnapshots lastSnapshots = new LastSnapshots(settings, getSession(), server); + when(mode.isPreview()).thenReturn(true); + LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server); String source = lastSnapshots.getSource(newFile()); assertThat(source).isEqualTo(""); @@ -114,7 +120,7 @@ public class LastSnapshotsTest extends AbstractDbUnitTestCase { setupData("last_snapshot"); ServerClient server = mock(ServerClient.class); - LastSnapshots lastSnapshots = new LastSnapshots(new Settings(), getSession(), server); + LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server); String source = lastSnapshots.getSource(new Project("my-project")); assertThat(source).isEqualTo(""); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java index 9df1e2aace3..61f2a5c8043 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java @@ -22,13 +22,14 @@ package org.sonar.batch.scan; import com.google.common.collect.ImmutableMap; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.PropertiesConfiguration; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.CoreProperties; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.utils.SonarException; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.BatchSettings; import org.sonar.batch.bootstrap.ServerClient; @@ -44,6 +45,12 @@ public class ModuleSettingsTest { public ExpectedException thrown = ExpectedException.none(); ServerClient client = mock(ServerClient.class); + private AnalysisMode mode; + + @Before + public void before() { + mode = mock(AnalysisMode.class); + } @Test public void testOrderedProjects() { @@ -74,7 +81,7 @@ public class ModuleSettingsTest { ProjectDefinition module = ProjectDefinition.create().setKey("struts-core"); Configuration deprecatedConf = new PropertiesConfiguration(); - ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, deprecatedConf, client); + ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, deprecatedConf, client, mode); assertThat(moduleSettings.getString("overridding")).isEqualTo("module"); assertThat(moduleSettings.getString("on-batch")).isEqualTo("true"); @@ -98,33 +105,35 @@ public class ModuleSettingsTest { ProjectDefinition module = ProjectDefinition.create().setKey("struts-core"); Configuration deprecatedConf = new PropertiesConfiguration(); - ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, deprecatedConf, client); + ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, deprecatedConf, client, mode); assertThat(moduleSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2"); assertThat(moduleSettings.getString("sonar.foo.secured")).isEqualTo("bar"); } @Test - public void should_fail_when_accessing_secured_properties_in_dryrun() { + public void should_fail_when_accessing_secured_properties_in_preview() { BatchSettings batchSettings = mock(BatchSettings.class); when(batchSettings.getDefinitions()).thenReturn(new PropertyDefinitions()); - when(batchSettings.getString(CoreProperties.DRY_RUN)).thenReturn("true"); when(batchSettings.getProperties()).thenReturn(ImmutableMap.of( "sonar.foo.secured", "bar" )); + + when(mode.isPreview()).thenReturn(true); + when(client.request("/batch_bootstrap/properties?project=struts-core&dryRun=true")) .thenReturn("[{\"k\":\"sonar.foo.license.secured\",\"v\":\"bar2\"}]"); ProjectDefinition module = ProjectDefinition.create().setKey("struts-core"); Configuration deprecatedConf = new PropertiesConfiguration(); - ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, deprecatedConf, client); + ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, deprecatedConf, client, mode); assertThat(moduleSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2"); thrown.expect(SonarException.class); thrown - .expectMessage("Access to the secured property 'sonar.foo.secured' is not possible in local (dry run) SonarQube analysis. The SonarQube plugin which requires this property must be deactivated in dry run mode."); + .expectMessage("Access to the secured property 'sonar.foo.secured' is not possible in preview mode. The SonarQube plugin which requires this property must be deactivated in preview mode."); moduleSettings.getString("sonar.foo.secured"); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectLockTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectLockTest.java index c32829a13fc..30a5c367ef8 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectLockTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectLockTest.java @@ -21,12 +21,12 @@ package org.sonar.batch.scan; import org.junit.Before; import org.junit.Test; -import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; import org.sonar.api.utils.Semaphores; import org.sonar.api.utils.SonarException; import org.sonar.batch.ProjectTree; +import org.sonar.batch.bootstrap.AnalysisMode; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; @@ -42,15 +42,16 @@ public class ProjectLockTest { ProjectTree projectTree = mock(ProjectTree.class); Settings settings; Project project; + private AnalysisMode mode; @Before public void setUp() { - settings = new Settings(); - setDryRunMode(false); + mode = mock(AnalysisMode.class); + project = new Project("my-project-key"); when(projectTree.getRootProject()).thenReturn(project); - projectLock = new ProjectLock(semaphores, projectTree, settings); + projectLock = new ProjectLock(semaphores, projectTree, mode); } @Test @@ -69,8 +70,7 @@ public class ProjectLockTest { @Test public void shouldNotAcquireSemaphoreInDryRunMode() { - setDryRunMode(true); - settings = new Settings().setProperty(CoreProperties.DRY_RUN, true); + when(mode.isPreview()).thenReturn(true); projectLock.start(); verifyZeroInteractions(semaphores); } @@ -82,14 +82,10 @@ public class ProjectLockTest { } @Test - public void shouldNotReleaseSemaphoreInDryRunMode() { - setDryRunMode(true); + public void shouldNotReleaseSemaphoreInPreviewMode() { + when(mode.isPreview()).thenReturn(true); projectLock.stop(); verifyZeroInteractions(semaphores); } - private void setDryRunMode(boolean isInDryRunMode) { - settings.setProperty(CoreProperties.DRY_RUN, isInDryRunMode); - } - } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java index f5246e64099..1e61091991c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java @@ -22,7 +22,6 @@ package org.sonar.batch.scan; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.utils.MessageException; @@ -46,23 +45,4 @@ public class UnsupportedPropertiesTest { Settings settings = new Settings(); new UnsupportedProperties(settings).start(); } - - @Test - public void should_fail_if_incremental_but_not_preview_mode() { - thrown.expect(MessageException.class); - thrown.expectMessage("Incremental mode is only supported with preview mode"); - - Settings settings = new Settings(); - settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true); - settings.setProperty(CoreProperties.DRY_RUN, false); - new UnsupportedProperties(settings).start(); - } - - @Test - public void should_not_fail_if_incremental_preview_mode() { - Settings settings = new Settings(); - settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true); - settings.setProperty(CoreProperties.DRY_RUN, true); - new UnsupportedProperties(settings).start(); - } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java index b7948e7f5bd..eeded167a46 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java @@ -21,6 +21,7 @@ package org.sonar.batch.scan.filesystem; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -31,6 +32,7 @@ import org.sonar.api.config.Settings; import org.sonar.api.scan.filesystem.FileQuery; import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.internal.DefaultInputFile; +import org.sonar.batch.bootstrap.AnalysisMode; import java.io.File; import java.io.IOException; @@ -39,7 +41,10 @@ import java.util.Arrays; import java.util.List; import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; public class DefaultModuleFileSystemTest { @@ -52,12 +57,18 @@ public class DefaultModuleFileSystemTest { Settings settings = new Settings(); FileIndex fileIndex = mock(FileIndex.class); ModuleFileSystemInitializer initializer = mock(ModuleFileSystemInitializer.class, Mockito.RETURNS_DEEP_STUBS); + private AnalysisMode mode; + + @Before + public void before() { + mode = mock(AnalysisMode.class); + } @Test public void test_equals_and_hashCode() throws Exception { - DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer); - DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer); - DefaultModuleFileSystem bar = new DefaultModuleFileSystem("bar", settings, fileIndex, initializer); + DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer, mode); + DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer, mode); + DefaultModuleFileSystem bar = new DefaultModuleFileSystem("bar", settings, fileIndex, initializer, mode); assertThat(foo1.moduleKey()).isEqualTo("foo"); assertThat(foo1.equals(foo1)).isTrue(); @@ -70,7 +81,7 @@ public class DefaultModuleFileSystemTest { @Test public void default_source_encoding() { - DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer, mode); assertThat(fs.sourceCharset()).isEqualTo(Charset.defaultCharset()); assertThat(fs.isDefaultSourceCharset()).isTrue(); @@ -79,7 +90,7 @@ public class DefaultModuleFileSystemTest { @Test public void source_encoding_is_set() { settings.setProperty(CoreProperties.ENCODING_PROPERTY, "Cp1124"); - DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer, mode); assertThat(fs.sourceCharset()).isEqualTo(Charset.forName("Cp1124")); @@ -103,8 +114,7 @@ public class DefaultModuleFileSystemTest { when(initializer.additionalSourceFiles()).thenReturn(Arrays.asList(additionalFile)); when(initializer.additionalTestFiles()).thenReturn(Arrays.asList(additionalTest)); - - DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer, mode); assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath()); assertThat(fs.workingDir().getCanonicalPath()).isEqualTo(workingDir.getCanonicalPath()); @@ -123,7 +133,7 @@ public class DefaultModuleFileSystemTest { when(initializer.workingDir()).thenReturn(basedir); when(initializer.sourceDirs()).thenReturn(Arrays.asList(new File(basedir, "src/main/java"))); - DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer, mode); File existingDir = temp.newFolder("new_folder"); File notExistingDir = new File(existingDir, "not_exist"); @@ -144,7 +154,7 @@ public class DefaultModuleFileSystemTest { @Test public void should_search_input_files() throws Exception { - DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer, mode); File mainFile = temp.newFile(); InputFile mainInput = DefaultInputFile.create(mainFile, "Main.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE)); @@ -161,7 +171,7 @@ public class DefaultModuleFileSystemTest { @Test public void should_index() throws Exception { - DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileIndex, initializer, mode); verifyZeroInteractions(fileIndex); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java index b149bbf4576..49cdd51ba14 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java @@ -19,23 +19,30 @@ */ package org.sonar.batch.scan.filesystem; +import org.junit.Before; import org.junit.Test; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; import org.sonar.api.scan.filesystem.FileQuery; import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.InputFileFilter; +import org.sonar.batch.bootstrap.AnalysisMode; import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class FileQueryFilterTest { - Settings settings = new Settings(); + private AnalysisMode mode; + + @Before + public void before() { + mode = mock(AnalysisMode.class); + } @Test public void wrap_query_on_attributes() throws Exception { FileQuery query = FileQuery.onSource(); - FileQueryFilter filter = new FileQueryFilter(settings, query); + FileQueryFilter filter = new FileQueryFilter(mode, query); assertThat(filter.filters()).hasSize(1); InputFileFilter typeFilter = filter.filters().get(0); @@ -47,7 +54,7 @@ public class FileQueryFilterTest { @Test public void wrap_query_on_inclusions() throws Exception { FileQuery query = FileQuery.on().withInclusions("Foo*.java"); - FileQueryFilter filter = new FileQueryFilter(settings, query); + FileQueryFilter filter = new FileQueryFilter(mode, query); assertThat(filter.filters()).hasSize(1); InputFileFilter inclusionFilter = filter.filters().get(0); @@ -58,7 +65,7 @@ public class FileQueryFilterTest { @Test public void wrap_query_on_exclusions() throws Exception { FileQuery query = FileQuery.on().withExclusions("Foo*.java"); - FileQueryFilter filter = new FileQueryFilter(settings, query); + FileQueryFilter filter = new FileQueryFilter(mode, query); assertThat(filter.filters()).hasSize(1); InputFileFilter exclusionFilter = filter.filters().get(0); @@ -69,16 +76,16 @@ public class FileQueryFilterTest { @Test public void all_files_by_default() throws Exception { FileQuery query = FileQuery.on(); - FileQueryFilter filter = new FileQueryFilter(settings, query); + FileQueryFilter filter = new FileQueryFilter(mode, query); assertThat(filter.filters()).isEmpty(); } @Test public void only_changed_files_by_default_if_incremental_mode() throws Exception { - settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true); + when(mode.isIncremental()).thenReturn(true); FileQuery query = FileQuery.on(); - FileQueryFilter filter = new FileQueryFilter(settings, query); + FileQueryFilter filter = new FileQueryFilter(mode, query); assertThat(filter.filters()).hasSize(1); AttributeFilter statusFilter = (AttributeFilter) filter.filters().get(0); @@ -88,10 +95,10 @@ public class FileQueryFilterTest { @Test public void get_all_files_even_if_incremental_mode() throws Exception { - settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true); + when(mode.isIncremental()).thenReturn(true); FileQuery query = FileQuery.on().on(InputFile.ATTRIBUTE_STATUS, InputFile.STATUS_SAME); - FileQueryFilter filter = new FileQueryFilter(settings, query); + FileQueryFilter filter = new FileQueryFilter(mode, query); assertThat(filter.filters()).hasSize(1); AttributeFilter statusFilter = (AttributeFilter) filter.filters().get(0); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java index 74d6b6ce413..2c8d070c97d 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java @@ -25,7 +25,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.skyscreamer.jsonassert.JSONAssert; -import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; @@ -34,6 +33,7 @@ import org.sonar.api.resources.Resource; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; import org.sonar.api.scan.filesystem.ModuleFileSystem; +import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.events.EventBus; import org.sonar.batch.issue.IssueCache; import org.sonar.core.i18n.RuleI18nManager; @@ -62,6 +62,7 @@ public class JsonReportTest { RuleI18nManager ruleI18nManager = mock(RuleI18nManager.class); Settings settings; IssueCache issueCache = mock(IssueCache.class); + private AnalysisMode mode; @Before public void setUp() { @@ -69,62 +70,63 @@ public class JsonReportTest { when(server.getVersion()).thenReturn("3.6"); settings = new Settings(); - settings.setProperty(CoreProperties.DRY_RUN, true); - jsonReport = new JsonReport(settings, fileSystem, server, ruleI18nManager, issueCache, mock(EventBus.class), new DefaultComponentSelector()); + mode = mock(AnalysisMode.class); + when(mode.isPreview()).thenReturn(true); + jsonReport = new JsonReport(settings, fileSystem, server, ruleI18nManager, issueCache, mock(EventBus.class), new DefaultComponentSelector(), mode); } @Test public void should_write_json() throws Exception { DefaultIssue issue = new DefaultIssue() - .setKey("200") - .setComponentKey("struts:org.apache.struts.Action") - .setRuleKey(RuleKey.of("squid", "AvoidCycles")) - .setMessage("There are 2 cycles") - .setSeverity("MINOR") - .setStatus(Issue.STATUS_OPEN) - .setResolution(null) - .setLine(1) - .setEffortToFix(3.14) - .setReporter("julien") - .setAssignee("simon") - .setCreationDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-24")) - .setUpdateDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-25")) - .setNew(false); + .setKey("200") + .setComponentKey("struts:org.apache.struts.Action") + .setRuleKey(RuleKey.of("squid", "AvoidCycles")) + .setMessage("There are 2 cycles") + .setSeverity("MINOR") + .setStatus(Issue.STATUS_OPEN) + .setResolution(null) + .setLine(1) + .setEffortToFix(3.14) + .setReporter("julien") + .setAssignee("simon") + .setCreationDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-24")) + .setUpdateDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-25")) + .setNew(false); when(ruleI18nManager.getName("squid", "AvoidCycles", Locale.getDefault())).thenReturn("Avoid Cycles"); - when(jsonReport.getIssues()).thenReturn(Lists. newArrayList(issue)); + when(jsonReport.getIssues()).thenReturn(Lists.newArrayList(issue)); StringWriter writer = new StringWriter(); jsonReport.writeJson(writer); JSONAssert.assertEquals(TestUtils.getResourceContent("/org/sonar/batch/scan/report/JsonReportTest/report.json"), - writer.toString(), false); + writer.toString(), false); } @Test public void should_exclude_resolved_issues() throws Exception { DefaultIssue issue = new DefaultIssue() - .setKey("200") - .setComponentKey("struts:org.apache.struts.Action") - .setRuleKey(RuleKey.of("squid", "AvoidCycles")) - .setStatus(Issue.STATUS_CLOSED) - .setResolution(Issue.RESOLUTION_FIXED) - .setCreationDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-24")) - .setUpdateDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-25")) - .setCloseDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-26")) - .setNew(false); + .setKey("200") + .setComponentKey("struts:org.apache.struts.Action") + .setRuleKey(RuleKey.of("squid", "AvoidCycles")) + .setStatus(Issue.STATUS_CLOSED) + .setResolution(Issue.RESOLUTION_FIXED) + .setCreationDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-24")) + .setUpdateDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-25")) + .setCloseDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-26")) + .setNew(false); when(ruleI18nManager.getName("squid", "AvoidCycles", Locale.getDefault())).thenReturn("Avoid Cycles"); - when(jsonReport.getIssues()).thenReturn(Lists. newArrayList(issue)); + when(jsonReport.getIssues()).thenReturn(Lists.newArrayList(issue)); StringWriter writer = new StringWriter(); jsonReport.writeJson(writer); JSONAssert.assertEquals(TestUtils.getResourceContent("/org/sonar/batch/scan/report/JsonReportTest/report-without-resolved-issues.json"), - writer.toString(), false); + writer.toString(), false); } @Test public void should_ignore_components_without_issue() throws JSONException { - when(jsonReport.getIssues()).thenReturn(Collections. emptyList()); + when(jsonReport.getIssues()).thenReturn(Collections.emptyList()); StringWriter writer = new StringWriter(); jsonReport.writeJson(writer); @@ -138,7 +140,7 @@ public class JsonReportTest { Rule rule = Rule.create("squid", "AvoidCycles"); when(ruleI18nManager.getName(rule, Locale.getDefault())).thenReturn("Avoid Cycles"); - when(jsonReport.getIssues()).thenReturn(Collections. emptyList()); + when(jsonReport.getIssues()).thenReturn(Collections.emptyList()); settings.setProperty("sonar.report.export.path", "output.json"); when(fileSystem.workingDir()).thenReturn(sonarDirectory); diff --git a/sonar-core/src/main/java/org/sonar/core/dryrun/DryRunCache.java b/sonar-core/src/main/java/org/sonar/core/dryrun/DryRunCache.java deleted file mode 100644 index d85053d8079..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/dryrun/DryRunCache.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * 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.core.dryrun; - -import com.google.common.io.Files; -import org.apache.commons.io.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.ServerExtension; -import org.sonar.api.platform.ServerFileSystem; -import org.sonar.api.utils.SonarException; -import org.sonar.core.persistence.DryRunDatabaseFactory; -import org.sonar.core.properties.PropertiesDao; -import org.sonar.core.properties.PropertyDto; -import org.sonar.core.resource.ResourceDao; -import org.sonar.core.resource.ResourceDto; - -import javax.annotation.Nullable; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * @since 3.7.1 - */ -public class DryRunCache implements ServerExtension { - - private static final Logger LOG = LoggerFactory.getLogger(DryRunCache.class); - - public static final String SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY = "sonar.dryRun.cache.lastUpdate"; - - private ServerFileSystem serverFileSystem; - private PropertiesDao propertiesDao; - private ResourceDao resourceDao; - - private Map lockPerProject = new HashMap(); - private Map lastTimestampPerProject = new HashMap(); - - private DryRunDatabaseFactory dryRunDatabaseFactory; - - public DryRunCache(ServerFileSystem serverFileSystem, PropertiesDao propertiesDao, ResourceDao resourceDao, DryRunDatabaseFactory dryRunDatabaseFactory) { - this.serverFileSystem = serverFileSystem; - this.propertiesDao = propertiesDao; - this.resourceDao = resourceDao; - this.dryRunDatabaseFactory = dryRunDatabaseFactory; - } - - public byte[] getDatabaseForDryRun(@Nullable Long projectId) { - long notNullProjectId = projectId != null ? projectId.longValue() : 0L; - ReadWriteLock rwl = getLock(notNullProjectId); - try { - rwl.readLock().lock(); - if (!isCacheValid(projectId)) { - // upgrade lock manually - // must unlock first to obtain writelock - rwl.readLock().unlock(); - rwl.writeLock().lock(); - // recheck - if (!isCacheValid(projectId)) { - generateNewDB(projectId); - } - // downgrade lock - // reacquire read without giving up write lock - rwl.readLock().lock(); - // unlock write, still hold read - rwl.writeLock().unlock(); - } - File dbFile = new File(getCacheLocation(projectId), lastTimestampPerProject.get(notNullProjectId) + DryRunDatabaseFactory.H2_FILE_SUFFIX); - return fileToByte(dbFile); - } finally { - rwl.readLock().unlock(); - } - } - - private boolean isCacheValid(@Nullable Long projectId) { - long notNullProjectId = projectId != null ? projectId.longValue() : 0L; - Long lastTimestampInCache = lastTimestampPerProject.get(notNullProjectId); - LOG.debug("Timestamp of last cached DB is {}", lastTimestampInCache); - if (lastTimestampInCache != null && isValid(projectId, lastTimestampInCache.longValue())) { - File dbFile = new File(getCacheLocation(projectId), lastTimestampInCache + DryRunDatabaseFactory.H2_FILE_SUFFIX); - LOG.debug("Look for existence of cached DB at {}", dbFile); - if (dbFile.exists()) { - LOG.debug("Found cached DB at {}", dbFile); - return true; - } - } - return false; - } - - private void generateNewDB(@Nullable Long projectId) { - if (projectId != null) { - LOG.debug("Generate new dryRun database for project [id={}]", projectId); - } else { - LOG.debug("Generate new dryRun database for new project"); - } - long notNullProjectId = projectId != null ? projectId.longValue() : 0L; - long newTimestamp = System.currentTimeMillis(); - File cacheLocation = getCacheLocation(projectId); - FileUtils.deleteQuietly(cacheLocation); - File dbFile = dryRunDatabaseFactory.createNewDatabaseForDryRun(projectId, cacheLocation, String.valueOf(newTimestamp)); - LOG.debug("Cached DB at {}", dbFile); - lastTimestampPerProject.put(notNullProjectId, newTimestamp); - } - - private byte[] fileToByte(File dbFile) { - try { - return Files.toByteArray(dbFile); - } catch (IOException e) { - throw new SonarException("Unable to create h2 database file", e); - } - } - - private synchronized ReadWriteLock getLock(long notNullProjectId) { - if (!lockPerProject.containsKey(notNullProjectId)) { - lockPerProject.put(notNullProjectId, new ReentrantReadWriteLock(true)); - } - return lockPerProject.get(notNullProjectId); - } - - private File getRootCacheLocation() { - return new File(serverFileSystem.getTempDir(), "dryRun"); - } - - public File getCacheLocation(@Nullable Long projectId) { - return new File(getRootCacheLocation(), projectId != null ? projectId.toString() : "default"); - } - - private boolean isValid(@Nullable Long projectId, long lastTimestampInCache) { - long globalTimestamp = getModificationTimestamp(null); - if (globalTimestamp > lastTimestampInCache) { - return false; - } - if (projectId != null) { - long projectTimestamp = getModificationTimestamp(projectId); - if (projectTimestamp > lastTimestampInCache) { - return false; - } - } - return true; - } - - private long getModificationTimestamp(@Nullable Long projectId) { - if (projectId == null) { - PropertyDto dto = propertiesDao.selectGlobalProperty(SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY); - if (dto == null) { - return 0; - } - return Long.valueOf(dto.getValue()); - } - // For modules look for root project last modification timestamp - ResourceDto rootProject = resourceDao.getRootProjectByComponentId(projectId); - if (rootProject == null) { - throw new SonarException("Unable to find root project for project with [id=" + projectId + "]"); - } - PropertyDto dto = propertiesDao.selectProjectProperty(rootProject.getId(), SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY); - if (dto == null) { - return 0; - } - return Long.valueOf(dto.getValue()); - } - - public void cleanAll() { - // Delete folder where dryRun DB are stored - FileUtils.deleteQuietly(getRootCacheLocation()); - // Delete all lastUpdate properties to force generation of new DB - propertiesDao.deleteAllProperties(SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY); - } - - public void reportGlobalModification() { - propertiesDao.setProperty(new PropertyDto().setKey(SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY).setValue(String.valueOf(System.currentTimeMillis()))); - } - - public void reportResourceModification(String resourceKey) { - ResourceDto rootProject = resourceDao.getRootProjectByComponentKey(resourceKey); - if (rootProject == null) { - throw new SonarException("Unable to find root project for component with [key=" + resourceKey + "]"); - } - propertiesDao.setProperty(new PropertyDto().setKey(SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY).setResourceId(rootProject.getId()) - .setValue(String.valueOf(System.currentTimeMillis()))); - } -} diff --git a/sonar-core/src/main/java/org/sonar/core/dryrun/package-info.java b/sonar-core/src/main/java/org/sonar/core/dryrun/package-info.java deleted file mode 100644 index fbdd95cb1bb..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/dryrun/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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. - */ -@ParametersAreNonnullByDefault -package org.sonar.core.dryrun; - -import javax.annotation.ParametersAreNonnullByDefault; - diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java b/sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java index 202deabe441..3e4ab3683ef 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java @@ -27,10 +27,13 @@ import org.apache.commons.lang.StringUtils; import org.hibernate.cfg.Environment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.database.DatabaseProperties; -import org.sonar.core.persistence.dialect.*; +import org.sonar.core.persistence.dialect.Dialect; +import org.sonar.core.persistence.dialect.DialectUtils; +import org.sonar.core.persistence.dialect.H2; +import org.sonar.core.persistence.dialect.Oracle; +import org.sonar.core.persistence.dialect.PostgreSql; import org.sonar.jpa.session.CustomHibernateConnectionProvider; import javax.sql.DataSource; @@ -104,16 +107,20 @@ public class DefaultDatabase implements Database { private void initDialect() { dialect = DialectUtils.find(properties.getProperty(SONAR_JDBC_DIALECT), properties.getProperty(SONAR_JDBC_URL)); if (dialect == null) { - throw new IllegalStateException("Can not guess the JDBC dialect. Please check the property "+ SONAR_JDBC_URL + "."); - } - if (H2.ID.equals(dialect.getId()) && !settings.getBoolean(CoreProperties.DRY_RUN)) { - LoggerFactory.getLogger(DefaultDatabase.class).warn("H2 database should be used for evaluation purpose only"); + throw new IllegalStateException("Can not guess the JDBC dialect. Please check the property " + SONAR_JDBC_URL + "."); } + checkH2Database(); if (!properties.containsKey(SONAR_JDBC_DRIVER_CLASS_NAME)) { properties.setProperty(SONAR_JDBC_DRIVER_CLASS_NAME, dialect.getDefaultDriverClassName()); } } + protected void checkH2Database() { + if (H2.ID.equals(dialect.getId())) { + LoggerFactory.getLogger(DefaultDatabase.class).warn("H2 database should be used for evaluation purpose only"); + } + } + private void initSchema() { String deprecatedSchema = null; if (PostgreSql.ID.equals(dialect.getId())) { diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java b/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java deleted file mode 100644 index 78208132988..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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.core.persistence; - -import org.apache.commons.dbcp.BasicDataSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.ServerComponent; -import org.sonar.api.issue.Issue; -import org.sonar.api.utils.SonarException; -import org.sonar.core.source.SnapshotDataTypes; - -import javax.annotation.Nullable; -import javax.sql.DataSource; - -import java.io.File; -import java.sql.SQLException; - -public class DryRunDatabaseFactory implements ServerComponent { - private static final Logger LOG = LoggerFactory.getLogger(DryRunDatabaseFactory.class); - private static final String DIALECT = "h2"; - private static final String DRIVER = "org.h2.Driver"; - private static final String URL = "jdbc:h2:"; - public static final String H2_FILE_SUFFIX = ".h2.db"; - private static final String SONAR = "sonar"; - private static final String USER = SONAR; - private static final String PASSWORD = SONAR; - - private final Database database; - - public DryRunDatabaseFactory(Database database) { - this.database = database; - } - - public File createNewDatabaseForDryRun(Long projectId, File destFolder, String dbFileName) { - long startup = System.currentTimeMillis(); - - String h2Name = destFolder.getAbsolutePath() + File.separator + dbFileName; - - try { - DataSource source = database.getDataSource(); - BasicDataSource destination = create(DIALECT, DRIVER, USER, PASSWORD, URL + h2Name); - - copy(source, destination, projectId); - close(destination); - - File dbFile = new File(h2Name + H2_FILE_SUFFIX); - if (LOG.isDebugEnabled()) { - long size = dbFile.length(); - long duration = System.currentTimeMillis() - startup; - if (projectId == null) { - LOG.debug("Dry Run Database created in " + duration + " ms, size is " + size + " bytes"); - } else { - LOG.debug("Dry Run Database for project " + projectId + " created in " + duration + " ms, size is " + size + " bytes"); - } - } - return dbFile; - - } catch (SQLException e) { - throw new SonarException("Unable to create database for DryRun", e); - } - - } - - private void copy(DataSource source, DataSource dest, @Nullable Long projectId) { - DbTemplate template = new DbTemplate(); - template - .copyTable(source, dest, "active_rules") - .copyTable(source, dest, "active_rule_parameters") - .copyTable(source, dest, "characteristics") - .copyTable(source, dest, "characteristic_edges") - .copyTable(source, dest, "characteristic_properties") - .copyTable(source, dest, "metrics") - .copyTable(source, dest, "permission_templates") - .copyTable(source, dest, "perm_templates_users") - .copyTable(source, dest, "perm_templates_groups") - .copyTable(source, dest, "quality_models") - .copyTable(source, dest, "rules") - .copyTable(source, dest, "rules_parameters") - .copyTable(source, dest, "rules_profiles") - .copyTable(source, dest, "alerts"); - if (projectId != null) { - template.copyTable(source, dest, "projects", projectQuery(projectId, false)); - - template.copyTable(source, dest, "events", "SELECT * FROM events WHERE resource_id=" + projectId); - - StringBuilder snapshotQuery = new StringBuilder() - // All snapshots of root_project for alerts on differential periods - .append("SELECT * FROM snapshots WHERE project_id=") - .append(projectId) - // Plus all last snapshots of all modules having hash data for partial analysis - .append(" UNION SELECT snap.* FROM snapshots snap") - .append(" INNER JOIN (") - .append(projectQuery(projectId, true)) - .append(") res") - .append(" ON snap.project_id=res.id") - .append(" INNER JOIN snapshot_data data") - .append(" ON snap.id=data.snapshot_id") - .append(" AND data.data_type='").append(SnapshotDataTypes.FILE_HASHES).append("'") - .append(" AND snap.islast=").append(database.getDialect().getTrueSqlValue()); - template.copyTable(source, dest, "snapshots", snapshotQuery.toString()); - - StringBuilder snapshotDataQuery = new StringBuilder() - .append("SELECT data.* FROM snapshot_data data") - .append(" INNER JOIN snapshots s") - .append(" ON s.id=data.snapshot_id") - .append(" AND s.islast=").append(database.getDialect().getTrueSqlValue()) - .append(" INNER JOIN (") - .append(projectQuery(projectId, true)) - .append(") res") - .append(" ON data.resource_id=res.id") - .append(" AND data.data_type='").append(SnapshotDataTypes.FILE_HASHES).append("'"); - template.copyTable(source, dest, "snapshot_data", snapshotDataQuery.toString()); - - // All measures of snapshots of root project for alerts on differential periods - template.copyTable(source, dest, "project_measures", "SELECT m.* FROM project_measures m INNER JOIN snapshots s on m.snapshot_id=s.id " - + "WHERE s.project_id=" + projectId); - - StringBuilder issueQuery = new StringBuilder() - .append("SELECT issues.* FROM issues") - .append(" INNER JOIN (") - .append(projectQuery(projectId, true)) - .append(") resources") - .append(" ON issues.component_id=resources.id") - .append(" AND status <> '").append(Issue.STATUS_CLOSED).append("'"); - template.copyTable(source, dest, "issues", issueQuery.toString()); - } - } - - private String projectQuery(Long projectId, boolean returnOnlyIds) { - return new StringBuilder() - .append("SELECT p.").append(returnOnlyIds ? "id" : "*") - .append(" FROM projects p INNER JOIN snapshots s ON p.id = s.project_id") - .append(" WHERE s.islast=").append(database.getDialect().getTrueSqlValue()) - .append(" AND s.root_project_id=").append(projectId) - .append(" UNION") - .append(" SELECT p.").append(returnOnlyIds ? "id" : "*") - .append(" FROM projects p") - .append(" WHERE p.id=").append(projectId) - .append(" OR p.root_id=").append(projectId).toString(); - } - - private BasicDataSource create(String dialect, String driver, String user, String password, String url) { - BasicDataSource dataSource = new DbTemplate().dataSource(driver, user, password, url); - new DbTemplate().createSchema(dataSource, dialect); - return dataSource; - } - - private void close(BasicDataSource destination) throws SQLException { - destination.close(); - } - -} diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/PreviewDatabaseFactory.java b/sonar-core/src/main/java/org/sonar/core/persistence/PreviewDatabaseFactory.java new file mode 100644 index 00000000000..032a58d3e3b --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/persistence/PreviewDatabaseFactory.java @@ -0,0 +1,170 @@ +/* + * 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.core.persistence; + +import org.apache.commons.dbcp.BasicDataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.ServerComponent; +import org.sonar.api.issue.Issue; +import org.sonar.api.utils.SonarException; +import org.sonar.core.source.SnapshotDataTypes; + +import javax.annotation.Nullable; +import javax.sql.DataSource; + +import java.io.File; +import java.sql.SQLException; + +public class PreviewDatabaseFactory implements ServerComponent { + private static final Logger LOG = LoggerFactory.getLogger(PreviewDatabaseFactory.class); + private static final String DIALECT = "h2"; + private static final String DRIVER = "org.h2.Driver"; + private static final String URL = "jdbc:h2:"; + public static final String H2_FILE_SUFFIX = ".h2.db"; + private static final String SONAR = "sonar"; + private static final String USER = SONAR; + private static final String PASSWORD = SONAR; + + private final Database database; + + public PreviewDatabaseFactory(Database database) { + this.database = database; + } + + public File createNewDatabaseForDryRun(Long projectId, File destFolder, String dbFileName) { + long startup = System.currentTimeMillis(); + + String h2Name = destFolder.getAbsolutePath() + File.separator + dbFileName; + + try { + DataSource source = database.getDataSource(); + BasicDataSource destination = create(DIALECT, DRIVER, USER, PASSWORD, URL + h2Name); + + copy(source, destination, projectId); + close(destination); + + File dbFile = new File(h2Name + H2_FILE_SUFFIX); + if (LOG.isDebugEnabled()) { + long size = dbFile.length(); + long duration = System.currentTimeMillis() - startup; + if (projectId == null) { + LOG.debug("Preview Database created in " + duration + " ms, size is " + size + " bytes"); + } else { + LOG.debug("Preview Database for project " + projectId + " created in " + duration + " ms, size is " + size + " bytes"); + } + } + return dbFile; + + } catch (SQLException e) { + throw new SonarException("Unable to create database for DryRun", e); + } + + } + + private void copy(DataSource source, DataSource dest, @Nullable Long projectId) { + DbTemplate template = new DbTemplate(); + template + .copyTable(source, dest, "active_rules") + .copyTable(source, dest, "active_rule_parameters") + .copyTable(source, dest, "characteristics") + .copyTable(source, dest, "characteristic_edges") + .copyTable(source, dest, "characteristic_properties") + .copyTable(source, dest, "metrics") + .copyTable(source, dest, "permission_templates") + .copyTable(source, dest, "perm_templates_users") + .copyTable(source, dest, "perm_templates_groups") + .copyTable(source, dest, "quality_models") + .copyTable(source, dest, "rules") + .copyTable(source, dest, "rules_parameters") + .copyTable(source, dest, "rules_profiles") + .copyTable(source, dest, "alerts"); + if (projectId != null) { + template.copyTable(source, dest, "projects", projectQuery(projectId, false)); + + template.copyTable(source, dest, "events", "SELECT * FROM events WHERE resource_id=" + projectId); + + StringBuilder snapshotQuery = new StringBuilder() + // All snapshots of root_project for alerts on differential periods + .append("SELECT * FROM snapshots WHERE project_id=") + .append(projectId) + // Plus all last snapshots of all modules having hash data for partial analysis + .append(" UNION SELECT snap.* FROM snapshots snap") + .append(" INNER JOIN (") + .append(projectQuery(projectId, true)) + .append(") res") + .append(" ON snap.project_id=res.id") + .append(" INNER JOIN snapshot_data data") + .append(" ON snap.id=data.snapshot_id") + .append(" AND data.data_type='").append(SnapshotDataTypes.FILE_HASHES).append("'") + .append(" AND snap.islast=").append(database.getDialect().getTrueSqlValue()); + template.copyTable(source, dest, "snapshots", snapshotQuery.toString()); + + StringBuilder snapshotDataQuery = new StringBuilder() + .append("SELECT data.* FROM snapshot_data data") + .append(" INNER JOIN snapshots s") + .append(" ON s.id=data.snapshot_id") + .append(" AND s.islast=").append(database.getDialect().getTrueSqlValue()) + .append(" INNER JOIN (") + .append(projectQuery(projectId, true)) + .append(") res") + .append(" ON data.resource_id=res.id") + .append(" AND data.data_type='").append(SnapshotDataTypes.FILE_HASHES).append("'"); + template.copyTable(source, dest, "snapshot_data", snapshotDataQuery.toString()); + + // All measures of snapshots of root project for alerts on differential periods + template.copyTable(source, dest, "project_measures", "SELECT m.* FROM project_measures m INNER JOIN snapshots s on m.snapshot_id=s.id " + + "WHERE s.project_id=" + projectId); + + StringBuilder issueQuery = new StringBuilder() + .append("SELECT issues.* FROM issues") + .append(" INNER JOIN (") + .append(projectQuery(projectId, true)) + .append(") resources") + .append(" ON issues.component_id=resources.id") + .append(" AND status <> '").append(Issue.STATUS_CLOSED).append("'"); + template.copyTable(source, dest, "issues", issueQuery.toString()); + } + } + + private String projectQuery(Long projectId, boolean returnOnlyIds) { + return new StringBuilder() + .append("SELECT p.").append(returnOnlyIds ? "id" : "*") + .append(" FROM projects p INNER JOIN snapshots s ON p.id = s.project_id") + .append(" WHERE s.islast=").append(database.getDialect().getTrueSqlValue()) + .append(" AND s.root_project_id=").append(projectId) + .append(" UNION") + .append(" SELECT p.").append(returnOnlyIds ? "id" : "*") + .append(" FROM projects p") + .append(" WHERE p.id=").append(projectId) + .append(" OR p.root_id=").append(projectId).toString(); + } + + private BasicDataSource create(String dialect, String driver, String user, String password, String url) { + BasicDataSource dataSource = new DbTemplate().dataSource(driver, user, password, url); + new DbTemplate().createSchema(dataSource, dialect); + return dataSource; + } + + private void close(BasicDataSource destination) throws SQLException { + destination.close(); + } + +} diff --git a/sonar-core/src/main/java/org/sonar/core/preview/PreviewCache.java b/sonar-core/src/main/java/org/sonar/core/preview/PreviewCache.java new file mode 100644 index 00000000000..d12edcc0b6d --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/preview/PreviewCache.java @@ -0,0 +1,202 @@ +/* + * 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.core.preview; + +import com.google.common.io.Files; +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.ServerExtension; +import org.sonar.api.platform.ServerFileSystem; +import org.sonar.api.utils.SonarException; +import org.sonar.core.persistence.PreviewDatabaseFactory; +import org.sonar.core.properties.PropertiesDao; +import org.sonar.core.properties.PropertyDto; +import org.sonar.core.resource.ResourceDao; +import org.sonar.core.resource.ResourceDto; + +import javax.annotation.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * @since 3.7.1 + */ +public class PreviewCache implements ServerExtension { + + private static final Logger LOG = LoggerFactory.getLogger(PreviewCache.class); + + public static final String SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY = "sonar.dryRun.cache.lastUpdate"; + + private ServerFileSystem serverFileSystem; + private PropertiesDao propertiesDao; + private ResourceDao resourceDao; + + private Map lockPerProject = new HashMap(); + private Map lastTimestampPerProject = new HashMap(); + + private PreviewDatabaseFactory previewDatabaseFactory; + + public PreviewCache(ServerFileSystem serverFileSystem, PropertiesDao propertiesDao, ResourceDao resourceDao, PreviewDatabaseFactory previewDatabaseFactory) { + this.serverFileSystem = serverFileSystem; + this.propertiesDao = propertiesDao; + this.resourceDao = resourceDao; + this.previewDatabaseFactory = previewDatabaseFactory; + } + + public byte[] getDatabaseForPreview(@Nullable Long projectId) { + long notNullProjectId = projectId != null ? projectId.longValue() : 0L; + ReadWriteLock rwl = getLock(notNullProjectId); + try { + rwl.readLock().lock(); + if (!isCacheValid(projectId)) { + // upgrade lock manually + // must unlock first to obtain writelock + rwl.readLock().unlock(); + rwl.writeLock().lock(); + // recheck + if (!isCacheValid(projectId)) { + generateNewDB(projectId); + } + // downgrade lock + // reacquire read without giving up write lock + rwl.readLock().lock(); + // unlock write, still hold read + rwl.writeLock().unlock(); + } + File dbFile = new File(getCacheLocation(projectId), lastTimestampPerProject.get(notNullProjectId) + PreviewDatabaseFactory.H2_FILE_SUFFIX); + return fileToByte(dbFile); + } finally { + rwl.readLock().unlock(); + } + } + + private boolean isCacheValid(@Nullable Long projectId) { + long notNullProjectId = projectId != null ? projectId.longValue() : 0L; + Long lastTimestampInCache = lastTimestampPerProject.get(notNullProjectId); + LOG.debug("Timestamp of last cached DB is {}", lastTimestampInCache); + if (lastTimestampInCache != null && isValid(projectId, lastTimestampInCache.longValue())) { + File dbFile = new File(getCacheLocation(projectId), lastTimestampInCache + PreviewDatabaseFactory.H2_FILE_SUFFIX); + LOG.debug("Look for existence of cached DB at {}", dbFile); + if (dbFile.exists()) { + LOG.debug("Found cached DB at {}", dbFile); + return true; + } + } + return false; + } + + private void generateNewDB(@Nullable Long projectId) { + if (projectId != null) { + LOG.debug("Generate new preview database for project [id={}]", projectId); + } else { + LOG.debug("Generate new preview database for new project"); + } + long notNullProjectId = projectId != null ? projectId.longValue() : 0L; + long newTimestamp = System.currentTimeMillis(); + File cacheLocation = getCacheLocation(projectId); + FileUtils.deleteQuietly(cacheLocation); + File dbFile = previewDatabaseFactory.createNewDatabaseForDryRun(projectId, cacheLocation, String.valueOf(newTimestamp)); + LOG.debug("Cached DB at {}", dbFile); + lastTimestampPerProject.put(notNullProjectId, newTimestamp); + } + + private byte[] fileToByte(File dbFile) { + try { + return Files.toByteArray(dbFile); + } catch (IOException e) { + throw new SonarException("Unable to create h2 database file", e); + } + } + + private synchronized ReadWriteLock getLock(long notNullProjectId) { + if (!lockPerProject.containsKey(notNullProjectId)) { + lockPerProject.put(notNullProjectId, new ReentrantReadWriteLock(true)); + } + return lockPerProject.get(notNullProjectId); + } + + private File getRootCacheLocation() { + return new File(serverFileSystem.getTempDir(), "dryRun"); + } + + public File getCacheLocation(@Nullable Long projectId) { + return new File(getRootCacheLocation(), projectId != null ? projectId.toString() : "default"); + } + + private boolean isValid(@Nullable Long projectId, long lastTimestampInCache) { + long globalTimestamp = getModificationTimestamp(null); + if (globalTimestamp > lastTimestampInCache) { + return false; + } + if (projectId != null) { + long projectTimestamp = getModificationTimestamp(projectId); + if (projectTimestamp > lastTimestampInCache) { + return false; + } + } + return true; + } + + private long getModificationTimestamp(@Nullable Long projectId) { + if (projectId == null) { + PropertyDto dto = propertiesDao.selectGlobalProperty(SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY); + if (dto == null) { + return 0; + } + return Long.valueOf(dto.getValue()); + } + // For modules look for root project last modification timestamp + ResourceDto rootProject = resourceDao.getRootProjectByComponentId(projectId); + if (rootProject == null) { + throw new SonarException("Unable to find root project for project with [id=" + projectId + "]"); + } + PropertyDto dto = propertiesDao.selectProjectProperty(rootProject.getId(), SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY); + if (dto == null) { + return 0; + } + return Long.valueOf(dto.getValue()); + } + + public void cleanAll() { + // Delete folder where preview DBs are stored + FileUtils.deleteQuietly(getRootCacheLocation()); + // Delete all lastUpdate properties to force generation of new DB + propertiesDao.deleteAllProperties(SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY); + } + + public void reportGlobalModification() { + propertiesDao.setProperty(new PropertyDto().setKey(SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY).setValue(String.valueOf(System.currentTimeMillis()))); + } + + public void reportResourceModification(String resourceKey) { + ResourceDto rootProject = resourceDao.getRootProjectByComponentKey(resourceKey); + if (rootProject == null) { + throw new SonarException("Unable to find root project for component with [key=" + resourceKey + "]"); + } + propertiesDao.setProperty(new PropertyDto().setKey(SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY).setResourceId(rootProject.getId()) + .setValue(String.valueOf(System.currentTimeMillis()))); + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/preview/package-info.java b/sonar-core/src/main/java/org/sonar/core/preview/package-info.java new file mode 100644 index 00000000000..7dde3244fd7 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/preview/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.core.preview; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-core/src/test/java/org/sonar/core/dryrun/DryRunCacheTest.java b/sonar-core/src/test/java/org/sonar/core/dryrun/DryRunCacheTest.java deleted file mode 100644 index 935cc2a41aa..00000000000 --- a/sonar-core/src/test/java/org/sonar/core/dryrun/DryRunCacheTest.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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.core.dryrun; - -import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.sonar.api.platform.ServerFileSystem; -import org.sonar.core.persistence.DryRunDatabaseFactory; -import org.sonar.core.properties.PropertiesDao; -import org.sonar.core.properties.PropertyDto; -import org.sonar.core.resource.ResourceDao; -import org.sonar.core.resource.ResourceDto; - -import java.io.File; -import java.io.IOException; - -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class DryRunCacheTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - private DryRunCache dryRunCache; - private ServerFileSystem serverFileSystem; - private PropertiesDao propertiesDao; - private ResourceDao resourceDao; - - private DryRunDatabaseFactory dryRunDatabaseFactory; - - private File dryRunCacheLocation; - - @Before - public void prepare() throws IOException { - serverFileSystem = mock(ServerFileSystem.class); - propertiesDao = mock(PropertiesDao.class); - resourceDao = mock(ResourceDao.class); - dryRunDatabaseFactory = mock(DryRunDatabaseFactory.class); - - File tempLocation = temp.newFolder(); - when(serverFileSystem.getTempDir()).thenReturn(tempLocation); - dryRunCacheLocation = new File(tempLocation, "dryRun"); - - dryRunCache = new DryRunCache(serverFileSystem, propertiesDao, resourceDao, dryRunDatabaseFactory); - } - - @Test - public void test_getDatabaseForDryRun_on_new_project() throws Exception { - when(dryRunDatabaseFactory.createNewDatabaseForDryRun(isNull(Long.class), any(File.class), anyString())).thenAnswer(new Answer() { - public File answer(InvocationOnMock invocation) throws IOException { - Object[] args = invocation.getArguments(); - File dbFile = new File(new File(dryRunCacheLocation, "default"), (String) args[2] + ".h2.db"); - FileUtils.write(dbFile, "fake db content"); - return dbFile; - } - }); - byte[] dbContent = dryRunCache.getDatabaseForDryRun(null); - assertThat(new String(dbContent)).isEqualTo("fake db content"); - - dbContent = dryRunCache.getDatabaseForDryRun(null); - assertThat(new String(dbContent)).isEqualTo("fake db content"); - - verify(dryRunDatabaseFactory, times(1)).createNewDatabaseForDryRun(anyLong(), any(File.class), anyString()); - } - - @Test - public void test_getDatabaseForDryRun_on_existing_project() throws Exception { - when(dryRunDatabaseFactory.createNewDatabaseForDryRun(eq(123L), any(File.class), anyString())).thenAnswer(new Answer() { - public File answer(InvocationOnMock invocation) throws IOException { - Object[] args = invocation.getArguments(); - File dbFile = new File(new File(dryRunCacheLocation, "123"), (String) args[2] + ".h2.db"); - FileUtils.write(dbFile, "fake db content"); - return dbFile; - } - }); - when(resourceDao.getRootProjectByComponentId(123L)).thenReturn(new ResourceDto().setId(123L)); - byte[] dbContent = dryRunCache.getDatabaseForDryRun(123L); - assertThat(new String(dbContent)).isEqualTo("fake db content"); - - dbContent = dryRunCache.getDatabaseForDryRun(123L); - assertThat(new String(dbContent)).isEqualTo("fake db content"); - - verify(dryRunDatabaseFactory, times(1)).createNewDatabaseForDryRun(anyLong(), any(File.class), anyString()); - } - - @Test - public void test_getDatabaseForDryRun_global_invalidation() throws Exception { - when(dryRunDatabaseFactory.createNewDatabaseForDryRun(isNull(Long.class), any(File.class), anyString())) - .thenAnswer(new Answer() { - public File answer(InvocationOnMock invocation) throws IOException { - Object[] args = invocation.getArguments(); - File dbFile = new File(new File(dryRunCacheLocation, "default"), (String) args[2] + ".h2.db"); - FileUtils.write(dbFile, "fake db content 1"); - return dbFile; - } - }) - .thenAnswer(new Answer() { - public File answer(InvocationOnMock invocation) throws IOException { - Object[] args = invocation.getArguments(); - File dbFile = new File(new File(dryRunCacheLocation, "default"), (String) args[2] + ".h2.db"); - FileUtils.write(dbFile, "fake db content 2"); - return dbFile; - } - }); - byte[] dbContent = dryRunCache.getDatabaseForDryRun(null); - assertThat(new String(dbContent)).isEqualTo("fake db content 1"); - - // Emulate invalidation of cache - Thread.sleep(100); - when(propertiesDao.selectGlobalProperty(DryRunCache.SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY)).thenReturn(new PropertyDto().setValue("" + System.currentTimeMillis())); - - dbContent = dryRunCache.getDatabaseForDryRun(null); - assertThat(new String(dbContent)).isEqualTo("fake db content 2"); - - verify(dryRunDatabaseFactory, times(2)).createNewDatabaseForDryRun(anyLong(), any(File.class), anyString()); - } - - @Test - public void test_getDatabaseForDryRun_project_invalidation() throws Exception { - when(dryRunDatabaseFactory.createNewDatabaseForDryRun(eq(123L), any(File.class), anyString())) - .thenAnswer(new Answer() { - public File answer(InvocationOnMock invocation) throws IOException { - Object[] args = invocation.getArguments(); - File dbFile = new File(new File(dryRunCacheLocation, "123"), (String) args[2] + ".h2.db"); - FileUtils.write(dbFile, "fake db content 1"); - return dbFile; - } - }) - .thenAnswer(new Answer() { - public File answer(InvocationOnMock invocation) throws IOException { - Object[] args = invocation.getArguments(); - File dbFile = new File(new File(dryRunCacheLocation, "123"), (String) args[2] + ".h2.db"); - FileUtils.write(dbFile, "fake db content 2"); - return dbFile; - } - }); - when(resourceDao.getRootProjectByComponentId(123L)).thenReturn(new ResourceDto().setId(123L)); - - byte[] dbContent = dryRunCache.getDatabaseForDryRun(123L); - assertThat(new String(dbContent)).isEqualTo("fake db content 1"); - - // Emulate invalidation of cache - Thread.sleep(100); - when(propertiesDao.selectProjectProperty(123L, DryRunCache.SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY)).thenReturn(new PropertyDto().setValue("" + System.currentTimeMillis())); - - dbContent = dryRunCache.getDatabaseForDryRun(123L); - assertThat(new String(dbContent)).isEqualTo("fake db content 2"); - - verify(dryRunDatabaseFactory, times(2)).createNewDatabaseForDryRun(anyLong(), any(File.class), anyString()); - } - - @Test - public void test_get_cache_location() throws Exception { - File tempFolder = temp.newFolder(); - when(serverFileSystem.getTempDir()).thenReturn(tempFolder); - - assertThat(dryRunCache.getCacheLocation(null)).isEqualTo(new File(new File(tempFolder, "dryRun"), "default")); - assertThat(dryRunCache.getCacheLocation(123L)).isEqualTo(new File(new File(tempFolder, "dryRun"), "123")); - } - - @Test - public void test_clean_all() throws Exception { - File tempFolder = temp.newFolder(); - when(serverFileSystem.getTempDir()).thenReturn(tempFolder); - File cacheLocation = dryRunCache.getCacheLocation(null); - FileUtils.forceMkdir(cacheLocation); - - dryRunCache.cleanAll(); - verify(propertiesDao).deleteAllProperties(DryRunCache.SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY); - - assertThat(cacheLocation).doesNotExist(); - } - - @Test - public void test_report_global_modification() { - dryRunCache.reportGlobalModification(); - - verify(propertiesDao).setProperty( - new PropertyDto() - .setKey(DryRunCache.SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY) - .setValue(anyString())); - } - - @Test - public void test_report_resource_modification() { - when(resourceDao.getRootProjectByComponentKey("foo")).thenReturn(new ResourceDto().setId(456L)); - - dryRunCache.reportResourceModification("foo"); - - verify(propertiesDao).setProperty( - new PropertyDto() - .setKey(DryRunCache.SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY) - .setValue(anyString()) - .setResourceId(456L)); - } -} diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java deleted file mode 100644 index e5389e96277..00000000000 --- a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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.core.persistence; - -import com.google.common.io.Files; -import org.apache.commons.dbcp.BasicDataSource; -import org.apache.commons.io.FileUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.IOException; -import java.sql.SQLException; - -import static org.fest.assertions.Assertions.assertThat; - -public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase { - DryRunDatabaseFactory localDatabaseFactory; - BasicDataSource dataSource; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Before - public void setUp() throws Exception { - localDatabaseFactory = new DryRunDatabaseFactory(getDatabase()); - } - - @After - public void closeDatabase() throws SQLException { - if (dataSource != null) { - dataSource.close(); - } - } - - @Test - public void should_create_database_without_project() throws Exception { - setupData("should_create_database"); - - byte[] db = createDb(null); - dataSource = createDatabase(db); - - assertThat(rowCount("metrics")).isEqualTo(2); - assertThat(rowCount("projects")).isZero(); - assertThat(rowCount("alerts")).isEqualTo(1); - assertThat(rowCount("events")).isZero(); - } - - private byte[] createDb(Long projectId) throws IOException { - return FileUtils.readFileToByteArray(localDatabaseFactory.createNewDatabaseForDryRun(projectId, temporaryFolder.newFolder(), "foo")); - } - - @Test - public void should_create_database_with_project() throws Exception { - setupData("should_create_database"); - - byte[] database = createDb(123L); - dataSource = createDatabase(database); - - assertThat(rowCount("metrics")).isEqualTo(2); - assertThat(rowCount("projects")).isEqualTo(1); - assertThat(rowCount("snapshots")).isEqualTo(1); - assertThat(rowCount("project_measures")).isEqualTo(1); - assertThat(rowCount("events")).isEqualTo(2); - } - - @Test - public void should_create_database_with_issues() throws Exception { - setupData("should_create_database_with_issues"); - - byte[] database = createDb(399L); - dataSource = createDatabase(database); - - assertThat(rowCount("issues")).isEqualTo(1); - } - - @Test - public void should_export_issues_of_project_tree() throws Exception { - setupData("multi-modules-with-issues"); - - // 300 : root module -> export issues of all modules - byte[] database = createDb(300L); - dataSource = createDatabase(database); - assertThat(rowCount("issues")).isEqualTo(1); - assertThat(rowCount("projects")).isEqualTo(4); - assertThat(rowCount("snapshots")).isEqualTo(4); - assertThat(rowCount("snapshot_data")).isEqualTo(2); - assertThat(rowCount("project_measures")).isEqualTo(4); - } - - @Test - public void should_export_issues_of_sub_module() throws Exception { - setupData("multi-modules-with-issues"); - - // 301 : sub module with 1 closed issue and 1 open issue - byte[] database = createDb(301L); - dataSource = createDatabase(database); - assertThat(rowCount("issues")).isEqualTo(1); - assertThat(rowCount("projects")).isEqualTo(2); - assertThat(rowCount("snapshots")).isEqualTo(2); - assertThat(rowCount("project_measures")).isEqualTo(4); - } - - @Test - public void should_export_issues_of_sub_module_2() throws Exception { - setupData("multi-modules-with-issues"); - - // 302 : sub module without any issues - byte[] database = createDb(302L); - dataSource = createDatabase(database); - assertThat(rowCount("issues")).isEqualTo(0); - } - - @Test - public void should_copy_permission_templates_data() throws Exception { - setupData("should_copy_permission_templates"); - - byte[] database = createDb(null); - dataSource = createDatabase(database); - assertThat(rowCount("permission_templates")).isEqualTo(1); - assertThat(rowCount("perm_templates_users")).isEqualTo(1); - assertThat(rowCount("perm_templates_groups")).isEqualTo(1); - } - - private BasicDataSource createDatabase(byte[] db) throws IOException { - File file = temporaryFolder.newFile("db.h2.db"); - Files.write(db, file); - return new DbTemplate().dataSource("org.h2.Driver", "sonar", "sonar", "jdbc:h2:" + file.getAbsolutePath().replaceAll(".h2.db", "")); - } - - private int rowCount(String table) { - return new DbTemplate().getRowCount(dataSource, table); - } -} diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/PreviewDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/PreviewDatabaseFactoryTest.java new file mode 100644 index 00000000000..d144f940f78 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/persistence/PreviewDatabaseFactoryTest.java @@ -0,0 +1,154 @@ +/* + * 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.core.persistence; + +import com.google.common.io.Files; +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; + +import static org.fest.assertions.Assertions.assertThat; + +public class PreviewDatabaseFactoryTest extends AbstractDaoTestCase { + PreviewDatabaseFactory localDatabaseFactory; + BasicDataSource dataSource; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Before + public void setUp() throws Exception { + localDatabaseFactory = new PreviewDatabaseFactory(getDatabase()); + } + + @After + public void closeDatabase() throws SQLException { + if (dataSource != null) { + dataSource.close(); + } + } + + @Test + public void should_create_database_without_project() throws Exception { + setupData("should_create_database"); + + byte[] db = createDb(null); + dataSource = createDatabase(db); + + assertThat(rowCount("metrics")).isEqualTo(2); + assertThat(rowCount("projects")).isZero(); + assertThat(rowCount("alerts")).isEqualTo(1); + assertThat(rowCount("events")).isZero(); + } + + private byte[] createDb(Long projectId) throws IOException { + return FileUtils.readFileToByteArray(localDatabaseFactory.createNewDatabaseForDryRun(projectId, temporaryFolder.newFolder(), "foo")); + } + + @Test + public void should_create_database_with_project() throws Exception { + setupData("should_create_database"); + + byte[] database = createDb(123L); + dataSource = createDatabase(database); + + assertThat(rowCount("metrics")).isEqualTo(2); + assertThat(rowCount("projects")).isEqualTo(1); + assertThat(rowCount("snapshots")).isEqualTo(1); + assertThat(rowCount("project_measures")).isEqualTo(1); + assertThat(rowCount("events")).isEqualTo(2); + } + + @Test + public void should_create_database_with_issues() throws Exception { + setupData("should_create_database_with_issues"); + + byte[] database = createDb(399L); + dataSource = createDatabase(database); + + assertThat(rowCount("issues")).isEqualTo(1); + } + + @Test + public void should_export_issues_of_project_tree() throws Exception { + setupData("multi-modules-with-issues"); + + // 300 : root module -> export issues of all modules + byte[] database = createDb(300L); + dataSource = createDatabase(database); + assertThat(rowCount("issues")).isEqualTo(1); + assertThat(rowCount("projects")).isEqualTo(4); + assertThat(rowCount("snapshots")).isEqualTo(4); + assertThat(rowCount("snapshot_data")).isEqualTo(2); + assertThat(rowCount("project_measures")).isEqualTo(4); + } + + @Test + public void should_export_issues_of_sub_module() throws Exception { + setupData("multi-modules-with-issues"); + + // 301 : sub module with 1 closed issue and 1 open issue + byte[] database = createDb(301L); + dataSource = createDatabase(database); + assertThat(rowCount("issues")).isEqualTo(1); + assertThat(rowCount("projects")).isEqualTo(2); + assertThat(rowCount("snapshots")).isEqualTo(2); + assertThat(rowCount("project_measures")).isEqualTo(4); + } + + @Test + public void should_export_issues_of_sub_module_2() throws Exception { + setupData("multi-modules-with-issues"); + + // 302 : sub module without any issues + byte[] database = createDb(302L); + dataSource = createDatabase(database); + assertThat(rowCount("issues")).isEqualTo(0); + } + + @Test + public void should_copy_permission_templates_data() throws Exception { + setupData("should_copy_permission_templates"); + + byte[] database = createDb(null); + dataSource = createDatabase(database); + assertThat(rowCount("permission_templates")).isEqualTo(1); + assertThat(rowCount("perm_templates_users")).isEqualTo(1); + assertThat(rowCount("perm_templates_groups")).isEqualTo(1); + } + + private BasicDataSource createDatabase(byte[] db) throws IOException { + File file = temporaryFolder.newFile("db.h2.db"); + Files.write(db, file); + return new DbTemplate().dataSource("org.h2.Driver", "sonar", "sonar", "jdbc:h2:" + file.getAbsolutePath().replaceAll(".h2.db", "")); + } + + private int rowCount(String table) { + return new DbTemplate().getRowCount(dataSource, table); + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/preview/PreviewCacheTest.java b/sonar-core/src/test/java/org/sonar/core/preview/PreviewCacheTest.java new file mode 100644 index 00000000000..b274436e361 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/preview/PreviewCacheTest.java @@ -0,0 +1,229 @@ +/* + * 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.core.preview; + +import org.sonar.core.preview.PreviewCache; + +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.sonar.api.platform.ServerFileSystem; +import org.sonar.core.persistence.PreviewDatabaseFactory; +import org.sonar.core.properties.PropertiesDao; +import org.sonar.core.properties.PropertyDto; +import org.sonar.core.resource.ResourceDao; +import org.sonar.core.resource.ResourceDto; + +import java.io.File; +import java.io.IOException; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class PreviewCacheTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private PreviewCache dryRunCache; + private ServerFileSystem serverFileSystem; + private PropertiesDao propertiesDao; + private ResourceDao resourceDao; + + private PreviewDatabaseFactory dryRunDatabaseFactory; + + private File dryRunCacheLocation; + + @Before + public void prepare() throws IOException { + serverFileSystem = mock(ServerFileSystem.class); + propertiesDao = mock(PropertiesDao.class); + resourceDao = mock(ResourceDao.class); + dryRunDatabaseFactory = mock(PreviewDatabaseFactory.class); + + File tempLocation = temp.newFolder(); + when(serverFileSystem.getTempDir()).thenReturn(tempLocation); + dryRunCacheLocation = new File(tempLocation, "dryRun"); + + dryRunCache = new PreviewCache(serverFileSystem, propertiesDao, resourceDao, dryRunDatabaseFactory); + } + + @Test + public void test_getDatabaseForDryRun_on_new_project() throws Exception { + when(dryRunDatabaseFactory.createNewDatabaseForDryRun(isNull(Long.class), any(File.class), anyString())).thenAnswer(new Answer() { + public File answer(InvocationOnMock invocation) throws IOException { + Object[] args = invocation.getArguments(); + File dbFile = new File(new File(dryRunCacheLocation, "default"), (String) args[2] + ".h2.db"); + FileUtils.write(dbFile, "fake db content"); + return dbFile; + } + }); + byte[] dbContent = dryRunCache.getDatabaseForPreview(null); + assertThat(new String(dbContent)).isEqualTo("fake db content"); + + dbContent = dryRunCache.getDatabaseForPreview(null); + assertThat(new String(dbContent)).isEqualTo("fake db content"); + + verify(dryRunDatabaseFactory, times(1)).createNewDatabaseForDryRun(anyLong(), any(File.class), anyString()); + } + + @Test + public void test_getDatabaseForDryRun_on_existing_project() throws Exception { + when(dryRunDatabaseFactory.createNewDatabaseForDryRun(eq(123L), any(File.class), anyString())).thenAnswer(new Answer() { + public File answer(InvocationOnMock invocation) throws IOException { + Object[] args = invocation.getArguments(); + File dbFile = new File(new File(dryRunCacheLocation, "123"), (String) args[2] + ".h2.db"); + FileUtils.write(dbFile, "fake db content"); + return dbFile; + } + }); + when(resourceDao.getRootProjectByComponentId(123L)).thenReturn(new ResourceDto().setId(123L)); + byte[] dbContent = dryRunCache.getDatabaseForPreview(123L); + assertThat(new String(dbContent)).isEqualTo("fake db content"); + + dbContent = dryRunCache.getDatabaseForPreview(123L); + assertThat(new String(dbContent)).isEqualTo("fake db content"); + + verify(dryRunDatabaseFactory, times(1)).createNewDatabaseForDryRun(anyLong(), any(File.class), anyString()); + } + + @Test + public void test_getDatabaseForDryRun_global_invalidation() throws Exception { + when(dryRunDatabaseFactory.createNewDatabaseForDryRun(isNull(Long.class), any(File.class), anyString())) + .thenAnswer(new Answer() { + public File answer(InvocationOnMock invocation) throws IOException { + Object[] args = invocation.getArguments(); + File dbFile = new File(new File(dryRunCacheLocation, "default"), (String) args[2] + ".h2.db"); + FileUtils.write(dbFile, "fake db content 1"); + return dbFile; + } + }) + .thenAnswer(new Answer() { + public File answer(InvocationOnMock invocation) throws IOException { + Object[] args = invocation.getArguments(); + File dbFile = new File(new File(dryRunCacheLocation, "default"), (String) args[2] + ".h2.db"); + FileUtils.write(dbFile, "fake db content 2"); + return dbFile; + } + }); + byte[] dbContent = dryRunCache.getDatabaseForPreview(null); + assertThat(new String(dbContent)).isEqualTo("fake db content 1"); + + // Emulate invalidation of cache + Thread.sleep(100); + when(propertiesDao.selectGlobalProperty(PreviewCache.SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY)).thenReturn(new PropertyDto().setValue("" + System.currentTimeMillis())); + + dbContent = dryRunCache.getDatabaseForPreview(null); + assertThat(new String(dbContent)).isEqualTo("fake db content 2"); + + verify(dryRunDatabaseFactory, times(2)).createNewDatabaseForDryRun(anyLong(), any(File.class), anyString()); + } + + @Test + public void test_getDatabaseForDryRun_project_invalidation() throws Exception { + when(dryRunDatabaseFactory.createNewDatabaseForDryRun(eq(123L), any(File.class), anyString())) + .thenAnswer(new Answer() { + public File answer(InvocationOnMock invocation) throws IOException { + Object[] args = invocation.getArguments(); + File dbFile = new File(new File(dryRunCacheLocation, "123"), (String) args[2] + ".h2.db"); + FileUtils.write(dbFile, "fake db content 1"); + return dbFile; + } + }) + .thenAnswer(new Answer() { + public File answer(InvocationOnMock invocation) throws IOException { + Object[] args = invocation.getArguments(); + File dbFile = new File(new File(dryRunCacheLocation, "123"), (String) args[2] + ".h2.db"); + FileUtils.write(dbFile, "fake db content 2"); + return dbFile; + } + }); + when(resourceDao.getRootProjectByComponentId(123L)).thenReturn(new ResourceDto().setId(123L)); + + byte[] dbContent = dryRunCache.getDatabaseForPreview(123L); + assertThat(new String(dbContent)).isEqualTo("fake db content 1"); + + // Emulate invalidation of cache + Thread.sleep(100); + when(propertiesDao.selectProjectProperty(123L, PreviewCache.SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY)).thenReturn(new PropertyDto().setValue("" + System.currentTimeMillis())); + + dbContent = dryRunCache.getDatabaseForPreview(123L); + assertThat(new String(dbContent)).isEqualTo("fake db content 2"); + + verify(dryRunDatabaseFactory, times(2)).createNewDatabaseForDryRun(anyLong(), any(File.class), anyString()); + } + + @Test + public void test_get_cache_location() throws Exception { + File tempFolder = temp.newFolder(); + when(serverFileSystem.getTempDir()).thenReturn(tempFolder); + + assertThat(dryRunCache.getCacheLocation(null)).isEqualTo(new File(new File(tempFolder, "dryRun"), "default")); + assertThat(dryRunCache.getCacheLocation(123L)).isEqualTo(new File(new File(tempFolder, "dryRun"), "123")); + } + + @Test + public void test_clean_all() throws Exception { + File tempFolder = temp.newFolder(); + when(serverFileSystem.getTempDir()).thenReturn(tempFolder); + File cacheLocation = dryRunCache.getCacheLocation(null); + FileUtils.forceMkdir(cacheLocation); + + dryRunCache.cleanAll(); + verify(propertiesDao).deleteAllProperties(PreviewCache.SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY); + + assertThat(cacheLocation).doesNotExist(); + } + + @Test + public void test_report_global_modification() { + dryRunCache.reportGlobalModification(); + + verify(propertiesDao).setProperty( + new PropertyDto() + .setKey(PreviewCache.SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY) + .setValue(anyString())); + } + + @Test + public void test_report_resource_modification() { + when(resourceDao.getRootProjectByComponentKey("foo")).thenReturn(new ResourceDto().setId(456L)); + + dryRunCache.reportResourceModification("foo"); + + verify(propertiesDao).setProperty( + new PropertyDto() + .setKey(PreviewCache.SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY) + .setValue(anyString()) + .setResourceId(456L)); + } +} diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/multi-modules-with-issues.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/multi-modules-with-issues.xml deleted file mode 100644 index d5583863884..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/multi-modules-with-issues.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_copy_permission_templates.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_copy_permission_templates.xml deleted file mode 100644 index 6bead9e07e1..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_copy_permission_templates.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml deleted file mode 100644 index 008976fde37..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml +++ /dev/null @@ -1,32 +0,0 @@ - - diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database_with_issues.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database_with_issues.xml deleted file mode 100644 index d25ce652ec8..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database_with_issues.xml +++ /dev/null @@ -1,69 +0,0 @@ - - \ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/multi-modules-with-issues.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/multi-modules-with-issues.xml new file mode 100644 index 00000000000..d5583863884 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/multi-modules-with-issues.xml @@ -0,0 +1,128 @@ + + + diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_copy_permission_templates.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_copy_permission_templates.xml new file mode 100644 index 00000000000..6bead9e07e1 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_copy_permission_templates.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_create_database.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_create_database.xml new file mode 100644 index 00000000000..008976fde37 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_create_database.xml @@ -0,0 +1,32 @@ + + diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_create_database_with_issues.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_create_database_with_issues.xml new file mode 100644 index 00000000000..d25ce652ec8 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/persistence/PreviewDatabaseFactoryTest/should_create_database_with_issues.xml @@ -0,0 +1,69 @@ + + \ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java index 673c18fc7d2..f877ab0c798 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java @@ -255,14 +255,24 @@ public interface CoreProperties { /** * @since 3.4 + * @deprecated in 4.0 replaced by {@link CoreProperties#PREVIEW_INCLUDE_PLUGINS} */ String DRY_RUN_INCLUDE_PLUGINS = "sonar.dryRun.includePlugins"; + /** + * @since 3.4 + * @deprecated in 4.0 replaced by {@link CoreProperties#PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE} + */ String DRY_RUN_INCLUDE_PLUGINS_DEFAULT_VALUE = ""; /** * @since 3.4 + * @deprecated in 4.0 replaced by {@link CoreProperties#PREVIEW_EXCLUDE_PLUGINS} */ String DRY_RUN_EXCLUDE_PLUGINS = "sonar.dryRun.excludePlugins"; + /** + * @since 3.4 + * @deprecated in 4.0 replaced by {@link CoreProperties#PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE} + */ String DRY_RUN_EXCLUDE_PLUGINS_DEFAULT_VALUE = "devcockpit,pdfreport,report,scmactivity,views,jira"; /** @@ -435,6 +445,7 @@ public interface CoreProperties { /** * @since 3.4 + * @deprecated in 4.0 replaced by {@link CoreProperties#ANALYSIS_MODE} */ String DRY_RUN = "sonar.dryRun"; @@ -462,9 +473,15 @@ public interface CoreProperties { /** * @since 3.7 + * @deprecated in 4.0 replaced by {@link CoreProperties#PREVIEW_READ_TIMEOUT_SEC} */ String DRY_RUN_READ_TIMEOUT_SEC = "sonar.dryRun.readTimeout"; + /** + * @since 4.0 + */ + String PREVIEW_READ_TIMEOUT_SEC = "sonar.preview.readTimeout"; + /** * @since 4.0 */ @@ -473,5 +490,32 @@ public interface CoreProperties { /** * @since 4.0 */ - String INCREMENTAL_PREVIEW = "sonar.incrementalPreview"; + String ANALYSIS_MODE = "sonar.analysis.mode"; + + /** + * @since 4.0 + */ + String ANALYSIS_MODE_ANALYSIS = "analysis"; + + /** + * @since 4.0 + */ + String ANALYSIS_MODE_PREVIEW = "preview"; + + /** + * @since 4.0 + */ + String ANALYSIS_MODE_INCREMENTAL = "incremental"; + + /** + * @since 4.0 + */ + String PREVIEW_INCLUDE_PLUGINS = "sonar.preview.includePlugins"; + String PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE = ""; + + /** + * @since 4.0 + */ + String PREVIEW_EXCLUDE_PLUGINS = "sonar.preview.excludePlugins"; + String PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE = "devcockpit,pdfreport,report,scmactivity,views,jira"; } diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/Backup.java b/sonar-server/src/main/java/org/sonar/server/configuration/Backup.java index 1af960ed226..d2f86058b0f 100644 --- a/sonar-server/src/main/java/org/sonar/server/configuration/Backup.java +++ b/sonar-server/src/main/java/org/sonar/server/configuration/Backup.java @@ -19,6 +19,8 @@ */ package org.sonar.server.configuration; +import org.sonar.core.preview.PreviewCache; + import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.converters.basic.DateConverter; import com.thoughtworks.xstream.core.util.QuickWriter; @@ -30,7 +32,6 @@ import org.apache.commons.lang.CharEncoding; import org.apache.commons.lang.StringUtils; import org.slf4j.LoggerFactory; import org.sonar.api.database.DatabaseSession; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.persistence.DatabaseVersion; import org.sonar.server.platform.PersistentSettings; @@ -55,7 +56,7 @@ public class Backup { backupables = new ArrayList(); } - public Backup(DatabaseSession session, PersistentSettings persistentSettings, DryRunCache dryRunCache) { + public Backup(DatabaseSession session, PersistentSettings persistentSettings, PreviewCache dryRunCache) { this(); this.session = session; diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java index 968a88dd4b5..c4291cd73dd 100644 --- a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java +++ b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java @@ -19,6 +19,8 @@ */ package org.sonar.server.configuration; +import org.sonar.core.preview.PreviewCache; + import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; @@ -36,7 +38,6 @@ 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.core.dryrun.DryRunCache; import org.sonar.jpa.dao.RulesDao; import java.util.ArrayList; @@ -62,9 +63,9 @@ public class ProfilesBackup implements Backupable { private Collection profiles; private DatabaseSession session; - private DryRunCache dryRunCache; + private PreviewCache dryRunCache; - public ProfilesBackup(DatabaseSession session, DryRunCache dryRunCache) { + public ProfilesBackup(DatabaseSession session, PreviewCache dryRunCache) { this.session = session; this.dryRunCache = dryRunCache; } diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesManager.java b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesManager.java index 11dde4538e2..ea48a665e2f 100644 --- a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesManager.java +++ b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesManager.java @@ -19,6 +19,8 @@ */ package org.sonar.server.configuration; +import org.sonar.core.preview.PreviewCache; + import com.google.common.collect.Lists; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; @@ -30,7 +32,6 @@ import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleParam; import org.sonar.api.rules.RulePriority; import org.sonar.api.utils.ValidationMessages; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.jpa.dao.BaseDao; import org.sonar.jpa.dao.RulesDao; @@ -39,9 +40,9 @@ import java.util.List; public class ProfilesManager extends BaseDao { private RulesDao rulesDao; - private DryRunCache dryRunCache; + private PreviewCache dryRunCache; - public ProfilesManager(DatabaseSession session, RulesDao rulesDao, DryRunCache dryRunCache) { + public ProfilesManager(DatabaseSession session, RulesDao rulesDao, PreviewCache dryRunCache) { super(session); this.rulesDao = rulesDao; this.dryRunCache = dryRunCache; diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/PropertiesBackup.java b/sonar-server/src/main/java/org/sonar/server/configuration/PropertiesBackup.java index 196af403ecb..bd489b190e4 100644 --- a/sonar-server/src/main/java/org/sonar/server/configuration/PropertiesBackup.java +++ b/sonar-server/src/main/java/org/sonar/server/configuration/PropertiesBackup.java @@ -19,13 +19,14 @@ */ package org.sonar.server.configuration; +import org.sonar.core.preview.PreviewCache; + import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.thoughtworks.xstream.XStream; import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.api.database.configuration.Property; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.properties.PropertyDto; import org.sonar.server.platform.PersistentSettings; @@ -83,7 +84,7 @@ public class PropertiesBackup implements Backupable { // default permissions properties should not be exported as they reference permission_templates entries in the DB return !CoreProperties.SERVER_ID.equals(propertyKey) && !propertyKey.startsWith(PERMISSION_PROPERTIES_PREFIX) - && !DryRunCache.SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY.equals(propertyKey); + && !PreviewCache.SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY.equals(propertyKey); } private boolean shouldNotBeErased(String propertyKey) { diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java index d978d5278c2..887ac4ee8f4 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java @@ -20,6 +20,8 @@ package org.sonar.server.issue; +import org.sonar.core.preview.PreviewCache; + import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import org.slf4j.Logger; @@ -30,7 +32,6 @@ import org.sonar.api.issue.IssueQueryResult; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.IssueChangeContext; import org.sonar.api.web.UserRole; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.db.IssueStorage; import org.sonar.server.exceptions.BadRequestException; @@ -50,10 +51,10 @@ public class IssueBulkChangeService { private final DefaultIssueFinder issueFinder; private final IssueStorage issueStorage; private final IssueNotifications issueNotifications; - private final DryRunCache dryRunCache; + private final PreviewCache dryRunCache; private final List actions; - public IssueBulkChangeService(DefaultIssueFinder issueFinder, IssueStorage issueStorage, IssueNotifications issueNotifications, List actions, DryRunCache dryRunCache) { + public IssueBulkChangeService(DefaultIssueFinder issueFinder, IssueStorage issueStorage, IssueNotifications issueNotifications, List actions, PreviewCache dryRunCache) { this.issueFinder = issueFinder; this.issueStorage = issueStorage; this.issueNotifications = issueNotifications; diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java index 33016fbd782..40bd5885e2b 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java @@ -19,6 +19,8 @@ */ package org.sonar.server.issue; +import org.sonar.core.preview.PreviewCache; + import com.google.common.base.Strings; import org.sonar.api.ServerComponent; import org.sonar.api.issue.ActionPlan; @@ -32,7 +34,6 @@ import org.sonar.api.rules.RuleFinder; import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.api.web.UserRole; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.db.IssueStorage; @@ -66,7 +67,7 @@ public class IssueService implements ServerComponent { private final ResourceDao resourceDao; private final AuthorizationDao authorizationDao; private final UserFinder userFinder; - private final DryRunCache dryRunCache; + private final PreviewCache dryRunCache; public IssueService(DefaultIssueFinder finder, IssueWorkflow workflow, @@ -78,7 +79,7 @@ public class IssueService implements ServerComponent { ResourceDao resourceDao, AuthorizationDao authorizationDao, UserFinder userFinder, - DryRunCache dryRunCache) { + PreviewCache dryRunCache) { this.finder = finder; this.workflow = workflow; this.issueStorage = issueStorage; diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 9658cf0aaa8..6c5f06364c7 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -37,7 +37,6 @@ import org.sonar.api.utils.TimeProfiler; import org.sonar.api.utils.UriReader; import org.sonar.core.component.SnapshotPerspectives; import org.sonar.core.config.Logback; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.i18n.GwtI18n; import org.sonar.core.i18n.I18nManager; import org.sonar.core.i18n.RuleI18nManager; @@ -52,7 +51,14 @@ import org.sonar.core.measure.MeasureFilterFactory; import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.permission.PermissionFacade; -import org.sonar.core.persistence.*; +import org.sonar.core.persistence.DaoUtils; +import org.sonar.core.persistence.DatabaseVersion; +import org.sonar.core.persistence.DefaultDatabase; +import org.sonar.core.persistence.MyBatis; +import org.sonar.core.persistence.PreviewDatabaseFactory; +import org.sonar.core.persistence.SemaphoreUpdater; +import org.sonar.core.persistence.SemaphoresImpl; +import org.sonar.core.preview.PreviewCache; import org.sonar.core.purge.PurgeProfiler; import org.sonar.core.qualitymodel.DefaultModelFinder; import org.sonar.core.resource.DefaultResourcePermissions; @@ -83,19 +89,63 @@ import org.sonar.server.db.EmbeddedDatabaseFactory; import org.sonar.server.db.migrations.DatabaseMigration; import org.sonar.server.db.migrations.DatabaseMigrations; import org.sonar.server.db.migrations.DatabaseMigrator; -import org.sonar.server.issue.*; +import org.sonar.server.issue.ActionPlanService; +import org.sonar.server.issue.ActionService; +import org.sonar.server.issue.AssignAction; +import org.sonar.server.issue.CommentAction; +import org.sonar.server.issue.DefaultIssueFinder; +import org.sonar.server.issue.InternalRubyIssueService; +import org.sonar.server.issue.IssueBulkChangeService; +import org.sonar.server.issue.IssueChangelogService; +import org.sonar.server.issue.IssueCommentService; +import org.sonar.server.issue.IssueFilterService; +import org.sonar.server.issue.IssueService; +import org.sonar.server.issue.IssueStatsFinder; +import org.sonar.server.issue.PlanAction; +import org.sonar.server.issue.PublicRubyIssueService; +import org.sonar.server.issue.ServerIssueStorage; +import org.sonar.server.issue.SetSeverityAction; +import org.sonar.server.issue.TransitionAction; import org.sonar.server.notifications.NotificationCenter; import org.sonar.server.notifications.NotificationService; import org.sonar.server.permission.InternalPermissionService; import org.sonar.server.permission.InternalPermissionTemplateService; -import org.sonar.server.plugins.*; +import org.sonar.server.plugins.ApplicationDeployer; +import org.sonar.server.plugins.DefaultServerPluginRepository; +import org.sonar.server.plugins.InstalledPluginReferentialFactory; +import org.sonar.server.plugins.PluginDeployer; +import org.sonar.server.plugins.PluginDownloader; +import org.sonar.server.plugins.ServerExtensionInstaller; +import org.sonar.server.plugins.UpdateCenterClient; +import org.sonar.server.plugins.UpdateCenterMatrixFactory; import org.sonar.server.rule.RubyRuleService; import org.sonar.server.rules.ProfilesConsole; import org.sonar.server.rules.RulesConsole; -import org.sonar.server.startup.*; +import org.sonar.server.startup.CleanDryRunCache; +import org.sonar.server.startup.DeleteDeprecatedMeasures; +import org.sonar.server.startup.GenerateBootstrapIndex; +import org.sonar.server.startup.GeneratePluginIndex; +import org.sonar.server.startup.GwtPublisher; +import org.sonar.server.startup.JdbcDriverDeployer; +import org.sonar.server.startup.LogServerId; +import org.sonar.server.startup.RegisterMetrics; +import org.sonar.server.startup.RegisterNewDashboards; +import org.sonar.server.startup.RegisterNewMeasureFilters; +import org.sonar.server.startup.RegisterNewProfiles; +import org.sonar.server.startup.RegisterPermissionTemplates; +import org.sonar.server.startup.RegisterRules; +import org.sonar.server.startup.RegisterServletFilters; +import org.sonar.server.startup.RegisterTechnicalDebtModel; +import org.sonar.server.startup.RenameDeprecatedPropertyKeys; +import org.sonar.server.startup.ServerMetadataPersister; +import org.sonar.server.startup.VerifyNoQualityModelsAreDefined; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.text.RubyTextService; -import org.sonar.server.ui.*; +import org.sonar.server.ui.CodeColorizers; +import org.sonar.server.ui.JRubyI18n; +import org.sonar.server.ui.PageDecorations; +import org.sonar.server.ui.SecurityRealmFactory; +import org.sonar.server.ui.Views; import org.sonar.server.user.DefaultUserService; import org.sonar.server.user.NewUserNotifier; @@ -186,7 +236,7 @@ public final class Platform { rootContainer.addSingleton(I18nManager.class); rootContainer.addSingleton(RuleI18nManager.class); rootContainer.addSingleton(GwtI18n.class); - rootContainer.addSingleton(DryRunDatabaseFactory.class); + rootContainer.addSingleton(PreviewDatabaseFactory.class); rootContainer.addSingleton(SemaphoreUpdater.class); rootContainer.addSingleton(SemaphoresImpl.class); rootContainer.startComponents(); @@ -249,8 +299,7 @@ public final class Platform { servicesContainer.addSingleton(MeasureFilterFactory.class); servicesContainer.addSingleton(MeasureFilterExecutor.class); servicesContainer.addSingleton(MeasureFilterEngine.class); - servicesContainer.addSingleton(DryRunDatabaseFactory.class); - servicesContainer.addSingleton(DryRunCache.class); + servicesContainer.addSingleton(PreviewCache.class); servicesContainer.addSingleton(DefaultResourcePermissions.class); servicesContainer.addSingleton(Periods.class); diff --git a/sonar-server/src/main/java/org/sonar/server/rules/ProfilesConsole.java b/sonar-server/src/main/java/org/sonar/server/rules/ProfilesConsole.java index b662f2bff3c..c52ed7ccaf2 100644 --- a/sonar-server/src/main/java/org/sonar/server/rules/ProfilesConsole.java +++ b/sonar-server/src/main/java/org/sonar/server/rules/ProfilesConsole.java @@ -20,6 +20,8 @@ package org.sonar.server.rules; +import org.sonar.core.preview.PreviewCache; + import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.sonar.api.ServerComponent; @@ -32,7 +34,6 @@ import org.sonar.api.profiles.XMLProfileSerializer; import org.sonar.api.rules.ActiveRule; import org.sonar.api.rules.ActiveRuleParam; import org.sonar.api.utils.ValidationMessages; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.jpa.session.DatabaseSessionFactory; import java.io.StringReader; @@ -51,9 +52,9 @@ public final class ProfilesConsole implements ServerComponent { private XMLProfileSerializer xmlProfileSerializer; private List exporters = newArrayList(); private List importers = newArrayList(); - private DryRunCache dryRunCache; + private PreviewCache dryRunCache; - public ProfilesConsole(DatabaseSessionFactory sessionFactory, XMLProfileParser xmlProfileParser, XMLProfileSerializer xmlProfileSerializer, DryRunCache dryRunCache) { + public ProfilesConsole(DatabaseSessionFactory sessionFactory, XMLProfileParser xmlProfileParser, XMLProfileSerializer xmlProfileSerializer, PreviewCache dryRunCache) { this.sessionFactory = sessionFactory; this.xmlProfileParser = xmlProfileParser; this.xmlProfileSerializer = xmlProfileSerializer; @@ -64,7 +65,7 @@ public final class ProfilesConsole implements ServerComponent { public ProfilesConsole(DatabaseSessionFactory sessionFactory, XMLProfileParser xmlProfileParser, XMLProfileSerializer xmlProfileSerializer, ProfileExporter[] exporters, - ProfileImporter[] importers, DryRunCache dryRunCache) { + ProfileImporter[] importers, PreviewCache dryRunCache) { this(sessionFactory, xmlProfileParser, xmlProfileSerializer, dryRunCache); this.exporters.addAll(Arrays.asList(exporters)); this.importers.addAll(Arrays.asList(importers)); diff --git a/sonar-server/src/main/java/org/sonar/server/startup/CleanDryRunCache.java b/sonar-server/src/main/java/org/sonar/server/startup/CleanDryRunCache.java index d08ccb32e58..d70003ecf7f 100644 --- a/sonar-server/src/main/java/org/sonar/server/startup/CleanDryRunCache.java +++ b/sonar-server/src/main/java/org/sonar/server/startup/CleanDryRunCache.java @@ -19,16 +19,16 @@ */ package org.sonar.server.startup; -import org.sonar.core.dryrun.DryRunCache; +import org.sonar.core.preview.PreviewCache; /** * @since 4.0 */ public class CleanDryRunCache { - private DryRunCache dryRunCache; + private PreviewCache dryRunCache; - public CleanDryRunCache(DryRunCache dryRunCache) { + public CleanDryRunCache(PreviewCache dryRunCache) { this.dryRunCache = dryRunCache; } diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index 807cb564be7..e2333386845 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -19,6 +19,8 @@ */ package org.sonar.server.ui; +import org.sonar.core.preview.PreviewCache; + import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.api.config.License; @@ -46,7 +48,6 @@ import org.sonar.api.web.Page; import org.sonar.api.web.RubyRailsWebservice; import org.sonar.api.web.Widget; import org.sonar.core.component.SnapshotPerspectives; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.measure.MeasureFilterEngine; import org.sonar.core.measure.MeasureFilterResult; @@ -496,8 +497,8 @@ public final class JRubyFacade { } } - public byte[] createDatabaseForDryRun(@Nullable Long projectId) { - return get(DryRunCache.class).getDatabaseForDryRun(projectId); + public byte[] createDatabaseForPreview(@Nullable Long projectId) { + return get(PreviewCache.class).getDatabaseForPreview(projectId); } public String getPeriodLabel(int periodIndex) { diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/alerts_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/alerts_controller.rb index a2b076d8abe..04cc9b61d86 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/alerts_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/alerts_controller.rb @@ -140,7 +140,7 @@ class AlertsController < ApplicationController private def reportGlobalModification - Property.set(Java::OrgSonarCoreDryrun::DryRunCache::SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY, java.lang.System.currentTimeMillis) + Property.set(Java::OrgSonarCorePreview::PreviewCache::SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY, java.lang.System.currentTimeMillis) end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/batch_bootstrap_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/batch_bootstrap_controller.rb index d5ea35bd158..f22ad213923 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/batch_bootstrap_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/batch_bootstrap_controller.rb @@ -30,7 +30,7 @@ class BatchBootstrapController < Api::ApiController return render_unauthorized("You're not authorized to execute a dry run analysis. Please contact your SonarQube administrator.") if !has_dryrun_role project = load_project() return render_unauthorized("You're not authorized to access to project '" + project.name + "', please contact your SonarQube administrator") if project && !has_role?(:user, project) - db_content = java_facade.createDatabaseForDryRun(project && project.id) + db_content = java_facade.createDatabaseForPreview(project && project.id) send_data String.from_java_bytes(db_content) end @@ -44,7 +44,7 @@ class BatchBootstrapController < Api::ApiController return render_unauthorized("You're not authorized to access to project '" + project.name + "', please contact your SonarQube administrator") if project && !has_scan_role && !has_role?(:user, project) if project - Property.set(Java::OrgSonarCoreDryrun::DryRunCache::SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY, java.lang.System.currentTimeMillis, project.root_project.id) + Property.set(Java::OrgSonarCorePreview::PreviewCache::SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY, java.lang.System.currentTimeMillis, project.root_project.id) render_success('dryRun DB evicted') else render_bad_request('missing projectId') diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb index 2da67f5e802..c2f9cca74b2 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb @@ -160,7 +160,7 @@ class IssuesController < ApplicationController # GET /issues/bulk_change_form?[&criteria] def bulk_change_form - issues_query_params = params.clone.merge({'pageSize' => -1}) + issues_query_params = criteria_params.clone.merge({'pageSize' => -1}) # SONAR-4654 pagination parameters should be remove when loading issues for bulk change issues_query_params.delete('pageIndex') if params[:id] diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb index 5fc629a33e4..37d9d6e1164 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb @@ -402,7 +402,7 @@ class ProjectController < ApplicationController end def reportProjectModification(project_id) - Property.set(Java::OrgSonarCoreDryrun::DryRunCache::SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY, java.lang.System.currentTimeMillis, project_id) + Property.set(Java::OrgSonarCorePreview::PreviewCache::SONAR_PREVIEW_CACHE_LAST_UPDATE_KEY, java.lang.System.currentTimeMillis, project_id) end end diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java index 9fadc4494dd..b795678cbdc 100644 --- a/sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java +++ b/sonar-server/src/test/java/org/sonar/server/configuration/BackupTest.java @@ -19,6 +19,8 @@ */ package org.sonar.server.configuration; +import org.sonar.core.preview.PreviewCache; + import com.google.common.collect.Lists; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.CharEncoding; @@ -36,7 +38,6 @@ 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.core.dryrun.DryRunCache; import java.io.IOException; import java.io.InputStream; @@ -56,11 +57,11 @@ import static org.mockito.Mockito.verify; public class BackupTest { - private DryRunCache dryRunCache; + private PreviewCache dryRunCache; @Before public void prepare() { - this.dryRunCache = mock(DryRunCache.class); + this.dryRunCache = mock(PreviewCache.class); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/InheritedProfilesTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/InheritedProfilesTest.java index 63ceb7343c8..b7f44d92b22 100644 --- a/sonar-server/src/test/java/org/sonar/server/configuration/InheritedProfilesTest.java +++ b/sonar-server/src/test/java/org/sonar/server/configuration/InheritedProfilesTest.java @@ -19,12 +19,12 @@ */ package org.sonar.server.configuration; +import org.sonar.core.preview.PreviewCache; + import org.junit.Before; import org.junit.Test; import org.sonar.api.profiles.RulesProfile; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.jpa.test.AbstractDbUnitTestCase; - import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; @@ -35,7 +35,7 @@ public class InheritedProfilesTest extends AbstractDbUnitTestCase { @Before public void setUp() { - profilesManager = new ProfilesManager(getSession(), null, mock(DryRunCache.class)); + profilesManager = new ProfilesManager(getSession(), null, mock(PreviewCache.class)); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/ProfilesManagerTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/ProfilesManagerTest.java index c1231bda910..82aa83f3897 100644 --- a/sonar-server/src/test/java/org/sonar/server/configuration/ProfilesManagerTest.java +++ b/sonar-server/src/test/java/org/sonar/server/configuration/ProfilesManagerTest.java @@ -19,12 +19,12 @@ */ package org.sonar.server.configuration; +import org.sonar.core.preview.PreviewCache; + import org.junit.Before; import org.junit.Test; import org.sonar.api.profiles.RulesProfile; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.jpa.test.AbstractDbUnitTestCase; - import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -34,7 +34,7 @@ public class ProfilesManagerTest extends AbstractDbUnitTestCase { @Before public void before() { - manager = new ProfilesManager(getSession(), null, mock(DryRunCache.class)); + manager = new ProfilesManager(getSession(), null, mock(PreviewCache.class)); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/RuleChangeTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/RuleChangeTest.java index dd10096e767..e95f817d98a 100644 --- a/sonar-server/src/test/java/org/sonar/server/configuration/RuleChangeTest.java +++ b/sonar-server/src/test/java/org/sonar/server/configuration/RuleChangeTest.java @@ -19,15 +19,15 @@ */ package org.sonar.server.configuration; +import org.sonar.core.preview.PreviewCache; + import org.junit.Before; import org.junit.Test; import org.sonar.api.rules.ActiveRuleChange; import org.sonar.api.rules.ActiveRuleParamChange; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RulePriority; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.jpa.test.AbstractDbUnitTestCase; - import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -36,7 +36,7 @@ public class RuleChangeTest extends AbstractDbUnitTestCase { @Before public void setUp() { - profilesManager = new ProfilesManager(getSession(), null, mock(DryRunCache.class)); + profilesManager = new ProfilesManager(getSession(), null, mock(PreviewCache.class)); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java index 9461440a6ff..14e6ec62075 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java @@ -20,6 +20,8 @@ package org.sonar.server.issue; +import org.sonar.core.preview.PreviewCache; + import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -30,7 +32,6 @@ import org.sonar.api.issue.condition.Condition; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.IssueChangeContext; import org.sonar.api.web.UserRole; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.db.IssueStorage; import org.sonar.server.exceptions.BadRequestException; @@ -79,7 +80,7 @@ public class IssueBulkChangeServiceTest { actions = newArrayList(); - service = new IssueBulkChangeService(finder, issueStorage, issueNotifications, actions, mock(DryRunCache.class)); + service = new IssueBulkChangeService(finder, issueStorage, issueNotifications, actions, mock(PreviewCache.class)); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java index dbb42117b2e..8ce062f1af2 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java @@ -20,6 +20,8 @@ package org.sonar.server.issue; +import org.sonar.core.preview.PreviewCache; + import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -35,7 +37,6 @@ import org.sonar.api.rules.RuleFinder; import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.api.web.UserRole; -import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.issue.DefaultActionPlan; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.IssueUpdater; @@ -96,7 +97,7 @@ public class IssueServiceTest { when(issueQueryResult.first()).thenReturn(issue); issueService = new IssueService(finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService, ruleFinder, resourceDao, authorizationDao, userFinder, - mock(DryRunCache.class)); + mock(PreviewCache.class)); } @Test