From 79a6209eaccbc7c92631fcb14752bd149f030b28 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Wed, 27 Jul 2016 14:55:59 +0200 Subject: Add javadoc to org.sonar.api.platform.Server --- .../main/java/org/sonar/api/platform/Server.java | 47 ++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) (limited to 'sonar-plugin-api/src') diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java index 8d52dce62d5..f8aa4bd2a2c 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java @@ -27,24 +27,62 @@ import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; /** + * Runtime information about server + * * @since 2.2 - */ + */ @ScannerSide @ServerSide @ComputeEngineSide public abstract class Server { + /** + * Name is misleading, this is an UUID generated + * at each startup, so it changes if server is restarted. + * @return a non-null UUID. Format can change over versions. + */ public abstract String getId(); + /** + * UUID generated on demand by system administrators. It is + * {@code null} by default on fresh installations. When defined, + * value does not change when server is restarted. + * @since 2.10 + */ + @CheckForNull + public abstract String getPermanentServerId(); + + /** + * Non-null version of SonarQube at runtime + */ public abstract String getVersion(); + /** + * Date when server started + */ public abstract Date getStartedAt(); + /** + * @deprecated in 6.0. Replaced by {@link ServerFileSystem#getHomeDir()} + * @return an existing directory in server and CE environments, {@code null} in scanner. + */ + @Deprecated public abstract File getRootDir(); + /** + * @deprecated always {@code null} since version 6.0. No alternatives, as plugins do not have to touch this directory. + */ + @Deprecated @CheckForNull public abstract File getDeployDir(); + /** + * Context path of web server. Value is blank {@code ""} by default. When defined by + * the property {@code sonar.web.context} of conf/sonar.properties, then value starts but does + * not end with slash {@code '/'}, for instance {@code "/sonarqube"}. + * + * @return non-null but possibly blank path + */ public abstract String getContextPath(); /** @@ -56,7 +94,7 @@ public abstract class Server { public abstract String getPublicRootUrl(); /** - * The dev mode is enabled when the property sonar.web.dev is true. + * The dev mode is enabled when the property {@code sonar.web.dev} is {@code true}. * * @since 5.4 */ @@ -76,9 +114,4 @@ public abstract class Server { * @since since 2.4 on batch side only, since 5.6 on both batch side and server side (WebServer and Compute Engine) */ public abstract String getURL(); - - /** - * @since 2.10 - */ - public abstract String getPermanentServerId(); } -- cgit v1.2.3 From 85bfbe28689b4276a04eeeed91b205ab76e81d06 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Wed, 27 Jul 2016 17:48:35 +0200 Subject: Improve org.sonar.api.SonarRuntime * javadoc was not up-to-date * SensorContext has a single method #runtime() instead of #getRuntimeApiVersion() and #getRuntimeProduct() * deprecated SonarQubeVersion does not extend SonarRuntime * SonarRuntime becomes an interface. Implementation is org.sonar.api.internal.SonarRuntimeImpl for unit tests. --- .../src/main/java/org/sonar/xoo/XooPlugin.java | 7 +- .../src/test/java/org/sonar/xoo/XooPluginTest.java | 17 +- .../sonar/xoo/rule/OneIssuePerLineSensorTest.java | 4 +- .../ce/container/ComputeEngineContainerImpl.java | 932 +++++++++++---------- .../container/ComputeEngineContainerImplTest.java | 2 +- .../platform/platformlevel/PlatformLevel1.java | 10 +- .../src/main/java/org/sonar/api/Plugin.java | 29 +- .../src/main/java/org/sonar/api/SonarQubeSide.java | 5 +- .../main/java/org/sonar/api/SonarQubeVersion.java | 116 +-- .../src/main/java/org/sonar/api/SonarRuntime.java | 150 ++-- .../org/sonar/api/batch/sensor/SensorContext.java | 21 +- .../batch/sensor/internal/SensorContextTester.java | 35 +- .../java/org/sonar/api/internal/ApiVersion.java | 51 ++ .../sonar/api/internal/SonarRuntimeFactory.java | 53 -- .../org/sonar/api/internal/SonarRuntimeImpl.java | 83 ++ .../src/test/java/org/sonar/api/PluginTest.java | 10 +- .../java/org/sonar/api/SonarQubeVersionTest.java | 7 +- .../test/java/org/sonar/api/SonarRuntimeTest.java | 73 -- .../org/sonar/api/internal/ApiVersionTest.java | 56 ++ .../api/internal/SonarRuntimeFactoryTest.java | 58 -- .../sonar/api/internal/SonarRuntimeImplTest.java | 69 ++ .../sonar/scanner/bootstrap/GlobalContainer.java | 11 +- .../sonar/scanner/sensor/DefaultSensorContext.java | 10 +- .../scanner/bootstrap/ExtensionInstallerTest.java | 12 +- .../scanner/sensor/DefaultSensorContextTest.java | 12 +- 25 files changed, 908 insertions(+), 925 deletions(-) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/internal/ApiVersion.java delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeFactory.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java delete mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/SonarRuntimeTest.java create mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/internal/ApiVersionTest.java delete mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeFactoryTest.java create mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java (limited to 'sonar-plugin-api/src') diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java index 7cc594aa958..06925832258 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java @@ -23,6 +23,7 @@ import org.sonar.api.Plugin; import org.sonar.api.SonarProduct; import org.sonar.api.config.PropertyDefinition; import org.sonar.api.resources.Qualifiers; +import org.sonar.api.utils.Version; import org.sonar.xoo.coverage.ItCoverageSensor; import org.sonar.xoo.coverage.OverallCoverageSensor; import org.sonar.xoo.coverage.UtCoverageSensor; @@ -65,8 +66,6 @@ import org.sonar.xoo.scm.XooScmProvider; import org.sonar.xoo.test.CoveragePerTestSensor; import org.sonar.xoo.test.TestExecutionSensor; -import static org.sonar.api.SonarRuntime.V5_5; - /** * Plugin entry-point, as declared in pom.xml. */ @@ -140,12 +139,12 @@ public class XooPlugin implements Plugin { XooProjectBuilder.class, XooPostJob.class); - if (context.getRuntimeProduct() != SonarProduct.SONARLINT) { + if (context.getRuntime().getProduct() != SonarProduct.SONARLINT) { context.addExtensions(MeasureSensor.class, DeprecatedResourceApiSensor.class); } - if (context.getSonarQubeVersion().isGreaterThanOrEqual(V5_5)) { + if (context.getRuntime().getApiVersion().isGreaterThanOrEqual(Version.create(5, 5))) { context.addExtension(CpdTokenizerSensor.class); } } diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java index 3d72a69bd42..03d8f037c4b 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java @@ -21,9 +21,9 @@ package org.sonar.xoo; import org.junit.Test; import org.sonar.api.Plugin; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; import org.sonar.api.SonarRuntime; +import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.utils.Version; import org.sonar.xoo.lang.CpdTokenizerSensor; @@ -32,13 +32,18 @@ import static org.assertj.core.api.Assertions.assertThat; public class XooPluginTest { @Test - public void provide_extensions_for_5_5() { - Plugin.Context context = new Plugin.Context(new SonarRuntime(Version.parse("5.5"), SonarProduct.SONARQUBE, SonarQubeSide.SCANNER)); + public void provide_extensions_for_5_4() { + SonarRuntime runtime = SonarRuntimeImpl.forSonarLint(Version.parse("5.4")); + Plugin.Context context = new Plugin.Context(runtime); new XooPlugin().define(context); - assertThat(context.getExtensions()).hasSize(44).contains(CpdTokenizerSensor.class); + assertThat(context.getExtensions()).hasSize(41).doesNotContain(CpdTokenizerSensor.class); + } - context = new Plugin.Context(new SonarRuntime(Version.parse("5.4"), SonarProduct.SONARLINT, null)); + @Test + public void provide_extensions_for_5_5() { + SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("5.5"), SonarQubeSide.SCANNER); + Plugin.Context context = new Plugin.Context(runtime); new XooPlugin().define(context); - assertThat(context.getExtensions()).hasSize(41).doesNotContain(CpdTokenizerSensor.class); + assertThat(context.getExtensions()).hasSize(44).contains(CpdTokenizerSensor.class); } } diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java index e709e31831f..263eb23f625 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java @@ -23,13 +23,13 @@ import java.io.IOException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.rule.Severity; import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; import org.sonar.api.batch.sensor.internal.SensorContextTester; import org.sonar.api.batch.sensor.issue.Issue; +import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.utils.Version; import org.sonar.xoo.Xoo; @@ -106,7 +106,7 @@ public class OneIssuePerLineSensorTest { SensorContextTester context = SensorContextTester.create(temp.newFolder()); context.fileSystem().add(inputFile); context.settings().setProperty(OneIssuePerLineSensor.EFFORT_TO_FIX_PROPERTY, "1.2"); - context.setRuntime(Version.parse("5.4"), SonarProduct.SONARQUBE, SonarQubeSide.SCANNER); + context.setRuntime(SonarRuntimeImpl.forSonarQube(Version.parse("5.4"), SonarQubeSide.SCANNER)); sensor.execute(context); diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java index ed1873c396b..240bb11e5e0 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java @@ -22,10 +22,11 @@ package org.sonar.ce.container; import com.google.common.annotations.VisibleForTesting; import java.util.List; import javax.annotation.CheckForNull; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; +import org.sonar.api.SonarQubeVersion; import org.sonar.api.config.EmailSettings; -import org.sonar.api.internal.SonarRuntimeFactory; +import org.sonar.api.internal.ApiVersion; +import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.profiles.AnnotationProfileParser; import org.sonar.api.profiles.XMLProfileParser; import org.sonar.api.profiles.XMLProfileSerializer; @@ -37,6 +38,7 @@ import org.sonar.api.server.rule.RulesDefinitionXmlLoader; import org.sonar.api.utils.Durations; import org.sonar.api.utils.System2; import org.sonar.api.utils.UriReader; +import org.sonar.api.utils.Version; import org.sonar.ce.db.ReadOnlyPropertiesDao; import org.sonar.ce.es.EsIndexerEnabler; import org.sonar.ce.platform.ComputeEngineExtensionInstaller; @@ -135,455 +137,6 @@ import org.sonar.server.view.index.ViewIndexer; import org.sonarqube.ws.Rules; public class ComputeEngineContainerImpl implements ComputeEngineContainer { - private static final Object[] LEVEL_1_COMPONENTS = new Object[] { - ComputeEngineSettings.class, - SonarRuntimeFactory.create(System2.INSTANCE, SonarProduct.SONARQUBE, SonarQubeSide.COMPUTE_ENGINE), - ServerImpl.class, - UuidFactoryImpl.INSTANCE, - // no EmbeddedDatabaseFactory.class, creating H2 DB if responsibility of WebServer - DefaultDatabase.class, - DatabaseChecker.class, - // must instantiate deprecated class in 5.2 and only this one (and not its replacement) - // to avoid having two SqlSessionFactory instances - org.sonar.core.persistence.MyBatis.class, - DatabaseServerCompatibility.class, - DatabaseVersion.class, - PurgeProfiler.class, - DefaultServerFileSystem.class, - // no TempFolderCleaner.class, responsibility of Web Server - new TempFolderProvider(), - System2.INSTANCE, - - // user session - CeUserSession.class, - - // DB - DaoModule.class, - // DbClient.class, replaced by CeDbClient to use ReadOnlyPropertiesDao instead of PropertiesDao - ReadOnlyPropertiesDao.class, - DbClient.class, - // MigrationStepModule.class, DB maintenance, responsibility of Web Server - - // Elasticsearch - EsSearchModule.class, - - // rules/qprofiles - RuleIndex.class, - ActiveRuleIndex.class, - - // issues - IssueIndex.class, - - // Classes kept for backward compatibility of plugins/libs (like sonar-license) that are directly calling classes from the core - // org.sonar.core.properties.PropertiesDao.class, replaced by ReadOnlyPropertiesDao (declared above) which is a ReadOnly implementation - }; - private static final Object[] LEVEL_2_COMPONENTS = new Object[] { - // add ReadOnlyPropertiesDao at level2 again so that it shadows PropertiesDao - ReadOnlyPropertiesDao.class, - DefaultServerUpgradeStatus.class, - // no DatabaseMigrator.class, responsibility of Web Server - - // plugins - PluginClassloaderFactory.class, - CePluginJarExploder.class, - PluginLoader.class, - CePluginRepository.class, - InstalledPluginReferentialFactory.class, - ComputeEngineExtensionInstaller.class, - - // depends on plugins - // RailsAppsDeployer.class, - // JRubyI18n.class, - DefaultI18n.class, // used by RuleI18nManager - RuleI18nManager.class, // used by DebtRulesXMLImporter - Durations.class, // used in Web Services and DebtCalculator - }; - private static final Object[] LEVEL_3_COMPONENTS = new Object[] { - PersistentSettings.class, - // ServerMetadataPersister.class, server id is the responsibility of Web Server - // DefaultHttpDownloader.class, does not make sense to use it from Compute Engine - UriReader.class, - // ServerIdGenerator.class, server id is the responsibility of Web Server - }; - private static final Object[] LEVEL_4_COMPONENTS = new Object[] { - // PluginDownloader.class, no use in CE - // Views.class, UI - ResourceTypes.class, - DefaultResourceTypes.get(), - // SettingsChangeNotifier.class, used only by JRuby - // PageDecorations.class, used only by JRuby - Periods.class, // used by JRuby and EvaluationResultTextConverterImpl - // ServerWs.class, no Web Service in CE - // BackendCleanup.class, DB maintenance, responsibility of Web Server - // IndexDefinitions.class, ES maintenance, responsibility of Web Server - // IndexCreator.class, ES maintenance, responsibility of Web Server - - // Activity - ActivityIndexer.class, - ActivityIndex.class, - ActivityService.class, - // ActivityIndexDefinition.class, ES maintenance, responsibility of Web Server - - // batch - // BatchWsModule.class, no Web Service in CE - - // Dashboard, UI - // [...] - - // update center, no Update Center in CE - - // quality profile - ActiveRuleIndexer.class, - XMLProfileParser.class, - XMLProfileSerializer.class, - AnnotationProfileParser.class, - Rules.QProfiles.class, - QProfileLookup.class, - QProfileProjectOperations.class, - QProfileProjectLookup.class, - QProfileComparison.class, - BuiltInProfiles.class, - // RestoreBuiltInAction.class, no Web Service in CE - // org.sonar.server.qualityprofile.ws.SearchAction.class, no Web Service in CE - // SearchDataLoader.class, no Web Service in CE - // SetDefaultAction.class, no Web Service in CE - // ProjectsAction.class, no Web Service in CE - // org.sonar.server.qualityprofile.ws.DeleteAction.class, no Web Service in CE - // RenameAction.class, no Web Service in CE - // CopyAction.class, no Web Service in CE - // BackupAction.class, no Web Service in CE - // RestoreAction.class, no Web Service in CE - // CreateAction.class, no Web Service in CE - // ImportersAction.class, no Web Service in - // InheritanceAction.class, no Web Service in CE - // ChangeParentAction.class, no Web Service in CE - // ChangelogAction.class, no Web Service in CE - // CompareAction.class, no Web Service in CE - // ExportAction.class, no Web Service in CE - // ExportersAction.class, no Web Service in CE - // QProfilesWs.class, no Web Service in CE - // ProfilesWs.class, no Web Service in CE - // OldRestoreAction.class, no Web Service in CE - // RuleActivationActions.class, no Web Service in CE - // BulkRuleActivationActions.class, no Web Service in CE - // ProjectAssociationActions.class, no Web Service in CE - // RuleActivator.class, indirectly only used in Web Services - // QProfileLoader.class, only used in QProfileService - // QProfileExporters.class, only used in Web Service and QProfileService - // QProfileService.class, depends on UserSession - // RuleActivatorContextFactory.class, indirectly only used in Web Services - // QProfileFactory.class, indirectly only used in Web Services - // QProfileCopier.class, indirectly only used in Web Services - // QProfileBackuper.class, indirectly only used in Web Services - // QProfileReset.class, indirectly only used in Web Services - // RubyQProfileActivityService.class, only used by JRuby - - // rule - // RuleIndexDefinition.class, ES maintenance, responsibility of Web Server - RuleIndexer.class, - AnnotationRuleParser.class, - XMLRuleParser.class, - DefaultRuleFinder.class, - // RuleOperations.class, supposed to be dropped in 4.4 - // RubyRuleService.class, used by JRuby - RuleRepositories.class, - DeprecatedRulesDefinitionLoader.class, - CommonRuleDefinitionsImpl.class, - RuleDefinitionsLoader.class, - RulesDefinitionXmlLoader.class, - // RuleUpdater.class, only used in Web Services - // RuleCreator.class, only used from Ruby or Web Service - // RuleDeleter.class, only used from Ruby or Web Service - // RuleService.class, only used from Ruby or Web Service - // org.sonar.server.rule.ws.UpdateAction.class, no Web Service in CE - // RulesWs.class, no Web Service in CE - // org.sonar.server.rule.ws.SearchAction.class, no Web Service in CE - // org.sonar.server.rule.ws.ShowAction.class, no Web Service in CE - // org.sonar.server.rule.ws.CreateAction.class, no Web Service in CE - // org.sonar.server.rule.ws.DeleteAction.class, no Web Service in CE - // org.sonar.server.rule.ws.ListAction.class, no Web Service in CE - // TagsAction.class, no Web Service in CE - // RuleMapper.class, only used in Web Services - // ActiveRuleCompleter.class, only used in Web Services - // RepositoriesAction.class, no Web Service in CE - // org.sonar.server.rule.ws.AppAction.class, no Web Service in CE - - // languages - Languages.class, // used by CommonRuleDefinitionsImpl - // org.sonar.server.language.ws.ListAction.class, no Web Service in CE - // LanguageWs.class, no Web Service in CE - - // activity - // ActivityMapping.class, no Web Service in CE - // org.sonar.server.activity.ws.SearchAction.class, no Web Service in CE - // ActivitiesWs.class, no Web Service in CE - - // measure - // MeasureFilterFactory.class, used only in MeasureFilterEngine - // MeasureFilterExecutor.class, used only in MeasureFilterEngine - // MeasureFilterEngine.class, used only in JRubyFacade - // MetricsWsModule.class, no Web Service in CE - // MeasuresWsModule.class, no Web Service in CE - // CustomMeasuresWsModule.class, no Web Service in CE - // ProjectFilter.class, used only in GlobalDefaultDashboard - // MyFavouritesFilter.class, used only in GlobalDefaultDashboard - CoreCustomMetrics.class, - DefaultMetricFinder.class, - // TimeMachineWs.class, no Web Service in CE - - // quality gates - // QualityGates.class, used only in Web Service and RegisterQualityGates - // QgateProjectFinder.class, used only in Web Service - // org.sonar.server.qualitygate.ws.ListAction.class, no Web Service in CE - // org.sonar.server.qualitygate.ws.SearchAction.class, no Web Service in CE - // org.sonar.server.qualitygate.ws.ShowAction.class, no Web Service in CE - // org.sonar.server.qualitygate.ws.CreateAction.class, no Web Service in CE - // org.sonar.server.qualitygate.ws.RenameAction.class, no Web Service in CE - // org.sonar.server.qualitygate.ws.CopyAction.class, no Web Service in CE - // DestroyAction.class, no Web Service in CE - // SetAsDefaultAction.class, no Web Service in CE - // UnsetDefaultAction.class, no Web Service in CE - // SelectAction.class, no Web Service in CE - // DeselectAction.class, no Web Service in CE - // CreateConditionAction.class, no Web Service in CE - // DeleteConditionAction.class, no Web Service in CE - // UpdateConditionAction.class, no Web Service in CE - // org.sonar.server.qualitygate.ws.AppAction.class, no Web Service in CE - // ProjectStatusAction.class, no Web Service in CE - // QGatesWs.class, no Web Service in CE - - // web services - // WebServiceEngine.class, no Web Service in CE - // WebServicesWs.class, no Web Service in CE - - // localization - // L10nWs.class, no Web Service in CE - - // authentication - // AuthenticationModule.class, only used for Web Server security - - // users - // SecurityRealmFactory.class, only used for Web Server security - DeprecatedUserFinder.class, - // NewUserNotifier.class, only used in UI or UserUpdater - DefaultUserFinder.class, - // DefaultUserService.class, used only by Ruby - // UserJsonWriter.class, used only in Web Service - // UsersWs.class, no Web Service in CE - // org.sonar.server.user.ws.CreateAction.class, no Web Service in CE - // org.sonar.server.user.ws.UpdateAction.class, no Web Service in CE - // org.sonar.server.user.ws.DeactivateAction.class, no Web Service in CE - // org.sonar.server.user.ws.ChangePasswordAction.class, no Web Service in CE - // CurrentAction.class, no Web Service in CE - // org.sonar.server.user.ws.SearchAction.class, no Web Service in CE - // org.sonar.server.user.ws.GroupsAction.class, no Web Service in CE - // FavoritesWs.class, no Web Service in CE - // UserPropertiesWs.class, no Web Service in CE - // UserIndexDefinition.class, ES maintenance, responsibility of Web Server - UserIndexer.class, - UserIndex.class, - // UserUpdater.class, - // UserTokenModule.class, - - // groups - // GroupMembershipFinder.class, // only used byGroupMembershipService - // GroupMembershipService.class, // only used by Ruby - // UserGroupsModule.class, no Web Service in CE - - // permissions - PermissionRepository.class, - // PermissionService.class, // depends on UserSession - // PermissionUpdater.class, // depends on UserSession - // PermissionFinder.class, used only in Web Service - // PermissionsWsModule.class, no Web Service in CE - - // components - // ProjectsWsModule.class, no Web Service in CE - // ComponentsWsModule.class, no Web Service in CE - // DefaultComponentFinder.class, only used in DefaultRubyComponentService - // DefaultRubyComponentService.class, only used by Ruby - ComponentFinder.class, // used in ComponentService - ComponentService.class, // used in ReportSubmitter - NewAlerts.class, - NewAlerts.newMetadata(), - ComponentCleanerService.class, - - // views - // ViewIndexDefinition.class, ES maintenance, responsibility of Web Server - ViewIndexer.class, - ViewIndex.class, - - // issues - // IssueIndexDefinition.class, - IssueIndexer.class, - IssueAuthorizationIndexer.class, - // ServerIssueStorage.class, indirectly used only in Web Services - IssueUpdater.class, // used in Web Services and CE's DebtCalculator - FunctionExecutor.class, // used by IssueWorkflow - IssueWorkflow.class, // used in Web Services and CE's DebtCalculator - // IssueCommentService.class, indirectly used only in Web Services - // InternalRubyIssueService.class, indirectly used only in Web Services - // IssueChangelogService.class, indirectly used only in Web Services - // ActionService.class, indirectly used only in Web Services - // IssueBulkChangeService.class, indirectly used only in Web Services - // WsResponseCommonFormat.class, indirectly used only in Web Services - // IssueWsModule.class, no Web Service in CE - // IssueService.class, indirectly used only in Web Services - // IssueQueryService.class, used only in Web Services and Ruby - NewIssuesEmailTemplate.class, - MyNewIssuesEmailTemplate.class, - IssueChangesEmailTemplate.class, - AlertsEmailTemplate.class, - ChangesOnMyIssueNotificationDispatcher.class, - ChangesOnMyIssueNotificationDispatcher.newMetadata(), - NewIssuesNotificationDispatcher.class, - NewIssuesNotificationDispatcher.newMetadata(), - MyNewIssuesNotificationDispatcher.class, - MyNewIssuesNotificationDispatcher.newMetadata(), - DoNotFixNotificationDispatcher.class, - DoNotFixNotificationDispatcher.newMetadata(), - NewIssuesNotificationFactory.class, // used by SendIssueNotificationsStep - EmailNotificationChannel.class, - - // IssueFilterWsModule.class, no Web Service in CE - - // action plan - // ActionPlanWs.class, no Web Service in CE - // ActionPlanService.class, no Web Service in CE - - // issues actions - // AssignAction.class, no Web Service in CE - // SetTypeAction.class, no Web Service in CE - // PlanAction.class, no Web Service in CE - // SetSeverityAction.class, no Web Service in CE - // CommentAction.class, no Web Service in CE - // TransitionAction.class, no Web Service in CE - // AddTagsAction.class, no Web Service in CE - // RemoveTagsAction.class, no Web Service in CE - - // technical debt - // DebtModelService.class, - // DebtModelBackup.class, - DebtModelPluginRepository.class, - // DebtModelXMLExporter.class, - DebtRulesXMLImporter.class, - - // source - // HtmlSourceDecorator.class, indirectly used only in Web Service - // SourceService.class, indirectly used only in Web Service - // SourcesWs.class, no Web Service in CE - // org.sonar.server.source.ws.ShowAction.class, no Web Service in CE - // LinesAction.class, no Web Service in CE - // HashAction.class, no Web Service in CE - // RawAction.class, no Web Service in CE - // IndexAction.class, no Web Service in CE - // ScmAction.class, no Web Service in CE - - // // Duplications - // DuplicationsParser.class, - // DuplicationsWs.class, no Web Service in CE - // DuplicationsJsonWriter.class, - // org.sonar.server.duplication.ws.ShowAction.class, no Web Service in CE - - // text - // MacroInterpreter.class, only used in Web Services and Ruby - // RubyTextService.class, - - // Notifications - EmailSettings.class, - NotificationService.class, - NotificationCenter.class, - DefaultNotificationManager.class, - - // Tests - // CoverageService.class, - // TestsWs.class, - // CoveredFilesAction.class, - // org.sonar.server.test.ws.ListAction.class, - // TestIndexDefinition.class, - // TestIndex.class, - TestIndexer.class, - - // Properties - // PropertiesWs.class, no Web Service in CE - - // TypeValidationModule.class, indirectly used only in Web Service - - // System - ServerLogging.class, - // RestartAction.class, no Web Service in CE - // InfoAction.class, no Web Service in CE - // UpgradesAction.class, no Web Service in CE - // StatusAction.class, no Web Service in CE - // SystemWs.class, no Web Service in CE - // SystemMonitor.class, no Monitor in CE, responsibility of Web Server - // SonarQubeMonitor.class, no Monitor in CE, responsibility of Web Server - // EsMonitor.class, no Monitor in CE, responsibility of Web Server - // PluginsMonitor.class, no Monitor in CE, responsibility of Web Server - // JvmPropsMonitor.class, no Monitor in CE, responsibility of Web Server - // DatabaseMonitor.class, no Monitor in CE, responsibility of Web Server - // MigrateDbAction.class, no Web Service in CE - // LogsAction.class, no Web Service in CE - // ChangeLogLevelAction.class, no Web Service in CE - // DbMigrationStatusAction.class, no Web Service in CE - - // Plugins WS - // PluginWSCommons.class, no Web Service in CE - // PluginUpdateAggregator.class, no Web Service in CE - // InstalledAction.class, no Web Service in CE - // AvailableAction.class, no Web Service in CE - // UpdatesAction.class, no Web Service in CE - // PendingAction.class, no Web Service in CE - // InstallAction.class, no Web Service in CE - // org.sonar.server.plugins.ws.UpdateAction.class, no Web Service in CE - // UninstallAction.class, no Web Service in CE - // CancelAllAction.class, no Web Service in CE - // PluginsWs.class, no Web Service in CE - - // Views plugin - // ViewsBootstrap.class, Views not supported in 5.5 - // ViewsStopper.class, Views not supported in 5.5 - - // privileged plugins - PrivilegedPluginsBootstraper.class, - PrivilegedPluginsStopper.class, - - // Compute engine (must be after Views and Developer Cockpit) - CeModule.class, - CeQueueModule.class, - ReportProcessingModule.class, - CeTaskProcessorModule.class, - // CeWsModule.class, no Web Service in CE - - ProjectSettingsFactory.class, - - // UI - // GlobalNavigationAction.class, no Web Service in CE - // SettingsNavigationAction.class, no Web Service in CE - // ComponentNavigationAction.class, no Web Service in CE - // NavigationWs.class, no Web Service in CE - }; - private static final Object[] STARTUP_COMPONENTS = new Object[] { - // IndexerStartupTask.class, ES maintenance, responsibility of Web Server - EsIndexerEnabler.class, - // RegisterMetrics.class, DB maintenance, responsibility of Web Server - // RegisterQualityGates.class, DB maintenance, responsibility of Web Server - // RegisterRules.class, DB maintenance, responsibility of Web Server - // RegisterQualityProfiles.class, DB maintenance, responsibility of Web Server - // GeneratePluginIndex.class, ES maintenance, responsibility of Web Server - // RegisterNewMeasureFilters.class, DB maintenance, responsibility of Web Server - // RegisterDashboards.class, UI related, anyway, DB maintenance, responsibility of Web Server - // RegisterPermissionTemplates.class, DB maintenance, responsibility of Web Server - // RenameDeprecatedPropertyKeys.class, DB maintenance, responsibility of Web Server - LogServerId.class, - // RegisterServletFilters.class, Web Server only - // RegisterIssueFilters.class, DB maintenance, responsibility of Web Server - // RenameIssueWidgets.class, UI related, anyway, DB maintenance, responsibility of Web Server - ServerLifecycleNotifier.class, - PurgeCeActivities.class, - // DisplayLogOnDeprecatedProjects.class, responsibility of Web Server - // ClearRulesOverloadedDebt.class, DB maintenance, responsibility of Web Server - }; @CheckForNull private ComponentContainer level1; @@ -595,24 +148,24 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { this.level1 = new ComponentContainer(); this.level1 .add(props.rawProperties()) - .add(LEVEL_1_COMPONENTS) + .add(level1Components()) .add(toArray(CorePropertyDefinitions.all())) .add(toArray(CePropertyDefinitions.all())); configureFromModules(this.level1); this.level1.startComponents(); ComponentContainer level2 = this.level1.createChild(); - level2.add(LEVEL_2_COMPONENTS); + level2.add(level2Components()); configureFromModules(level2); level2.startComponents(); ComponentContainer level3 = level2.createChild(); - level3.add(LEVEL_3_COMPONENTS); + level3.add(level3Components()); configureFromModules(level3); level3.startComponents(); this.level4 = level3.createChild(); - this.level4.add(LEVEL_4_COMPONENTS); + this.level4.add(level4Components()); configureFromModules(this.level4); ServerExtensionInstaller extensionInstaller = this.level4.getComponentByType(ServerExtensionInstaller.class); extensionInstaller.installExtensions(this.level4); @@ -625,7 +178,7 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { private void startupTasks() { ComponentContainer startupLevel = this.level4.createChild(); - startupLevel.add(STARTUP_COMPONENTS); + startupLevel.add(startupComponents()); startupLevel.startComponents(); // done in PlatformLevelStartup ServerLifecycleNotifier serverLifecycleNotifier = startupLevel.getComponentByType(ServerLifecycleNotifier.class); @@ -646,6 +199,473 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { return level4; } + private static Object[] level1Components() { + Version apiVersion = ApiVersion.load(System2.INSTANCE); + return new Object[] { + ComputeEngineSettings.class, + new SonarQubeVersion(apiVersion), + SonarRuntimeImpl.forSonarQube(ApiVersion.load(System2.INSTANCE), SonarQubeSide.COMPUTE_ENGINE), + ServerImpl.class, + UuidFactoryImpl.INSTANCE, + // no EmbeddedDatabaseFactory.class, creating H2 DB if responsibility of WebServer + DefaultDatabase.class, + DatabaseChecker.class, + // must instantiate deprecated class in 5.2 and only this one (and not its replacement) + // to avoid having two SqlSessionFactory instances + org.sonar.core.persistence.MyBatis.class, + DatabaseServerCompatibility.class, + DatabaseVersion.class, + PurgeProfiler.class, + DefaultServerFileSystem.class, + // no TempFolderCleaner.class, responsibility of Web Server + new TempFolderProvider(), + System2.INSTANCE, + + // user session + CeUserSession.class, + + // DB + DaoModule.class, + // DbClient.class, replaced by CeDbClient to use ReadOnlyPropertiesDao instead of PropertiesDao + ReadOnlyPropertiesDao.class, + DbClient.class, + // MigrationStepModule.class, DB maintenance, responsibility of Web Server + + // Elasticsearch + EsSearchModule.class, + + // rules/qprofiles + RuleIndex.class, + ActiveRuleIndex.class, + + // issues + IssueIndex.class, + + // Classes kept for backward compatibility of plugins/libs (like sonar-license) that are directly calling classes from the core + // org.sonar.core.properties.PropertiesDao.class, replaced by ReadOnlyPropertiesDao (declared above) which is a ReadOnly + // implementation + }; + } + + private static Object[] level2Components() { + return new Object[] { + // add ReadOnlyPropertiesDao at level2 again so that it shadows PropertiesDao + ReadOnlyPropertiesDao.class, + DefaultServerUpgradeStatus.class, + // no DatabaseMigrator.class, responsibility of Web Server + + // plugins + PluginClassloaderFactory.class, + CePluginJarExploder.class, + PluginLoader.class, + CePluginRepository.class, + InstalledPluginReferentialFactory.class, + ComputeEngineExtensionInstaller.class, + + // depends on plugins + // RailsAppsDeployer.class, + // JRubyI18n.class, + DefaultI18n.class, // used by RuleI18nManager + RuleI18nManager.class, // used by DebtRulesXMLImporter + Durations.class, // used in Web Services and DebtCalculator + }; + } + + private static Object[] level3Components() { + return new Object[] { + PersistentSettings.class, + // ServerMetadataPersister.class, server id is the responsibility of Web Server + // DefaultHttpDownloader.class, does not make sense to use it from Compute Engine + UriReader.class, + // ServerIdGenerator.class, server id is the responsibility of Web Server + }; + } + + private static Object[] level4Components() { + return new Object[] { + // PluginDownloader.class, no use in CE + // Views.class, UI + ResourceTypes.class, + DefaultResourceTypes.get(), + // SettingsChangeNotifier.class, used only by JRuby + // PageDecorations.class, used only by JRuby + Periods.class, // used by JRuby and EvaluationResultTextConverterImpl + // ServerWs.class, no Web Service in CE + // BackendCleanup.class, DB maintenance, responsibility of Web Server + // IndexDefinitions.class, ES maintenance, responsibility of Web Server + // IndexCreator.class, ES maintenance, responsibility of Web Server + + // Activity + ActivityIndexer.class, + ActivityIndex.class, + ActivityService.class, + // ActivityIndexDefinition.class, ES maintenance, responsibility of Web Server + + // batch + // BatchWsModule.class, no Web Service in CE + + // Dashboard, UI + // [...] + + // update center, no Update Center in CE + + // quality profile + ActiveRuleIndexer.class, + XMLProfileParser.class, + XMLProfileSerializer.class, + AnnotationProfileParser.class, + Rules.QProfiles.class, + QProfileLookup.class, + QProfileProjectOperations.class, + QProfileProjectLookup.class, + QProfileComparison.class, + BuiltInProfiles.class, + // RestoreBuiltInAction.class, no Web Service in CE + // org.sonar.server.qualityprofile.ws.SearchAction.class, no Web Service in CE + // SearchDataLoader.class, no Web Service in CE + // SetDefaultAction.class, no Web Service in CE + // ProjectsAction.class, no Web Service in CE + // org.sonar.server.qualityprofile.ws.DeleteAction.class, no Web Service in CE + // RenameAction.class, no Web Service in CE + // CopyAction.class, no Web Service in CE + // BackupAction.class, no Web Service in CE + // RestoreAction.class, no Web Service in CE + // CreateAction.class, no Web Service in CE + // ImportersAction.class, no Web Service in + // InheritanceAction.class, no Web Service in CE + // ChangeParentAction.class, no Web Service in CE + // ChangelogAction.class, no Web Service in CE + // CompareAction.class, no Web Service in CE + // ExportAction.class, no Web Service in CE + // ExportersAction.class, no Web Service in CE + // QProfilesWs.class, no Web Service in CE + // ProfilesWs.class, no Web Service in CE + // OldRestoreAction.class, no Web Service in CE + // RuleActivationActions.class, no Web Service in CE + // BulkRuleActivationActions.class, no Web Service in CE + // ProjectAssociationActions.class, no Web Service in CE + // RuleActivator.class, indirectly only used in Web Services + // QProfileLoader.class, only used in QProfileService + // QProfileExporters.class, only used in Web Service and QProfileService + // QProfileService.class, depends on UserSession + // RuleActivatorContextFactory.class, indirectly only used in Web Services + // QProfileFactory.class, indirectly only used in Web Services + // QProfileCopier.class, indirectly only used in Web Services + // QProfileBackuper.class, indirectly only used in Web Services + // QProfileReset.class, indirectly only used in Web Services + // RubyQProfileActivityService.class, only used by JRuby + + // rule + // RuleIndexDefinition.class, ES maintenance, responsibility of Web Server + RuleIndexer.class, + AnnotationRuleParser.class, + XMLRuleParser.class, + DefaultRuleFinder.class, + // RuleOperations.class, supposed to be dropped in 4.4 + // RubyRuleService.class, used by JRuby + RuleRepositories.class, + DeprecatedRulesDefinitionLoader.class, + CommonRuleDefinitionsImpl.class, + RuleDefinitionsLoader.class, + RulesDefinitionXmlLoader.class, + // RuleUpdater.class, only used in Web Services + // RuleCreator.class, only used from Ruby or Web Service + // RuleDeleter.class, only used from Ruby or Web Service + // RuleService.class, only used from Ruby or Web Service + // org.sonar.server.rule.ws.UpdateAction.class, no Web Service in CE + // RulesWs.class, no Web Service in CE + // org.sonar.server.rule.ws.SearchAction.class, no Web Service in CE + // org.sonar.server.rule.ws.ShowAction.class, no Web Service in CE + // org.sonar.server.rule.ws.CreateAction.class, no Web Service in CE + // org.sonar.server.rule.ws.DeleteAction.class, no Web Service in CE + // org.sonar.server.rule.ws.ListAction.class, no Web Service in CE + // TagsAction.class, no Web Service in CE + // RuleMapper.class, only used in Web Services + // ActiveRuleCompleter.class, only used in Web Services + // RepositoriesAction.class, no Web Service in CE + // org.sonar.server.rule.ws.AppAction.class, no Web Service in CE + + // languages + Languages.class, // used by CommonRuleDefinitionsImpl + // org.sonar.server.language.ws.ListAction.class, no Web Service in CE + // LanguageWs.class, no Web Service in CE + + // activity + // ActivityMapping.class, no Web Service in CE + // org.sonar.server.activity.ws.SearchAction.class, no Web Service in CE + // ActivitiesWs.class, no Web Service in CE + + // measure + // MeasureFilterFactory.class, used only in MeasureFilterEngine + // MeasureFilterExecutor.class, used only in MeasureFilterEngine + // MeasureFilterEngine.class, used only in JRubyFacade + // MetricsWsModule.class, no Web Service in CE + // MeasuresWsModule.class, no Web Service in CE + // CustomMeasuresWsModule.class, no Web Service in CE + // ProjectFilter.class, used only in GlobalDefaultDashboard + // MyFavouritesFilter.class, used only in GlobalDefaultDashboard + CoreCustomMetrics.class, + DefaultMetricFinder.class, + // TimeMachineWs.class, no Web Service in CE + + // quality gates + // QualityGates.class, used only in Web Service and RegisterQualityGates + // QgateProjectFinder.class, used only in Web Service + // org.sonar.server.qualitygate.ws.ListAction.class, no Web Service in CE + // org.sonar.server.qualitygate.ws.SearchAction.class, no Web Service in CE + // org.sonar.server.qualitygate.ws.ShowAction.class, no Web Service in CE + // org.sonar.server.qualitygate.ws.CreateAction.class, no Web Service in CE + // org.sonar.server.qualitygate.ws.RenameAction.class, no Web Service in CE + // org.sonar.server.qualitygate.ws.CopyAction.class, no Web Service in CE + // DestroyAction.class, no Web Service in CE + // SetAsDefaultAction.class, no Web Service in CE + // UnsetDefaultAction.class, no Web Service in CE + // SelectAction.class, no Web Service in CE + // DeselectAction.class, no Web Service in CE + // CreateConditionAction.class, no Web Service in CE + // DeleteConditionAction.class, no Web Service in CE + // UpdateConditionAction.class, no Web Service in CE + // org.sonar.server.qualitygate.ws.AppAction.class, no Web Service in CE + // ProjectStatusAction.class, no Web Service in CE + // QGatesWs.class, no Web Service in CE + + // web services + // WebServiceEngine.class, no Web Service in CE + // WebServicesWs.class, no Web Service in CE + + // localization + // L10nWs.class, no Web Service in CE + + // authentication + // AuthenticationModule.class, only used for Web Server security + + // users + // SecurityRealmFactory.class, only used for Web Server security + DeprecatedUserFinder.class, + // NewUserNotifier.class, only used in UI or UserUpdater + DefaultUserFinder.class, + // DefaultUserService.class, used only by Ruby + // UserJsonWriter.class, used only in Web Service + // UsersWs.class, no Web Service in CE + // org.sonar.server.user.ws.CreateAction.class, no Web Service in CE + // org.sonar.server.user.ws.UpdateAction.class, no Web Service in CE + // org.sonar.server.user.ws.DeactivateAction.class, no Web Service in CE + // org.sonar.server.user.ws.ChangePasswordAction.class, no Web Service in CE + // CurrentAction.class, no Web Service in CE + // org.sonar.server.user.ws.SearchAction.class, no Web Service in CE + // org.sonar.server.user.ws.GroupsAction.class, no Web Service in CE + // FavoritesWs.class, no Web Service in CE + // UserPropertiesWs.class, no Web Service in CE + // UserIndexDefinition.class, ES maintenance, responsibility of Web Server + UserIndexer.class, + UserIndex.class, + // UserUpdater.class, + // UserTokenModule.class, + + // groups + // GroupMembershipFinder.class, // only used byGroupMembershipService + // GroupMembershipService.class, // only used by Ruby + // UserGroupsModule.class, no Web Service in CE + + // permissions + PermissionRepository.class, + // PermissionService.class, // depends on UserSession + // PermissionUpdater.class, // depends on UserSession + // PermissionFinder.class, used only in Web Service + // PermissionsWsModule.class, no Web Service in CE + + // components + // ProjectsWsModule.class, no Web Service in CE + // ComponentsWsModule.class, no Web Service in CE + // DefaultComponentFinder.class, only used in DefaultRubyComponentService + // DefaultRubyComponentService.class, only used by Ruby + ComponentFinder.class, // used in ComponentService + ComponentService.class, // used in ReportSubmitter + NewAlerts.class, + NewAlerts.newMetadata(), + ComponentCleanerService.class, + + // views + // ViewIndexDefinition.class, ES maintenance, responsibility of Web Server + ViewIndexer.class, + ViewIndex.class, + + // issues + // IssueIndexDefinition.class, + IssueIndexer.class, + IssueAuthorizationIndexer.class, + // ServerIssueStorage.class, indirectly used only in Web Services + IssueUpdater.class, // used in Web Services and CE's DebtCalculator + FunctionExecutor.class, // used by IssueWorkflow + IssueWorkflow.class, // used in Web Services and CE's DebtCalculator + // IssueCommentService.class, indirectly used only in Web Services + // InternalRubyIssueService.class, indirectly used only in Web Services + // IssueChangelogService.class, indirectly used only in Web Services + // ActionService.class, indirectly used only in Web Services + // IssueBulkChangeService.class, indirectly used only in Web Services + // WsResponseCommonFormat.class, indirectly used only in Web Services + // IssueWsModule.class, no Web Service in CE + // IssueService.class, indirectly used only in Web Services + // IssueQueryService.class, used only in Web Services and Ruby + NewIssuesEmailTemplate.class, + MyNewIssuesEmailTemplate.class, + IssueChangesEmailTemplate.class, + AlertsEmailTemplate.class, + ChangesOnMyIssueNotificationDispatcher.class, + ChangesOnMyIssueNotificationDispatcher.newMetadata(), + NewIssuesNotificationDispatcher.class, + NewIssuesNotificationDispatcher.newMetadata(), + MyNewIssuesNotificationDispatcher.class, + MyNewIssuesNotificationDispatcher.newMetadata(), + DoNotFixNotificationDispatcher.class, + DoNotFixNotificationDispatcher.newMetadata(), + NewIssuesNotificationFactory.class, // used by SendIssueNotificationsStep + EmailNotificationChannel.class, + + // IssueFilterWsModule.class, no Web Service in CE + + // action plan + // ActionPlanWs.class, no Web Service in CE + // ActionPlanService.class, no Web Service in CE + + // issues actions + // AssignAction.class, no Web Service in CE + // SetTypeAction.class, no Web Service in CE + // PlanAction.class, no Web Service in CE + // SetSeverityAction.class, no Web Service in CE + // CommentAction.class, no Web Service in CE + // TransitionAction.class, no Web Service in CE + // AddTagsAction.class, no Web Service in CE + // RemoveTagsAction.class, no Web Service in CE + + // technical debt + // DebtModelService.class, + // DebtModelBackup.class, + DebtModelPluginRepository.class, + // DebtModelXMLExporter.class, + DebtRulesXMLImporter.class, + + // source + // HtmlSourceDecorator.class, indirectly used only in Web Service + // SourceService.class, indirectly used only in Web Service + // SourcesWs.class, no Web Service in CE + // org.sonar.server.source.ws.ShowAction.class, no Web Service in CE + // LinesAction.class, no Web Service in CE + // HashAction.class, no Web Service in CE + // RawAction.class, no Web Service in CE + // IndexAction.class, no Web Service in CE + // ScmAction.class, no Web Service in CE + + // // Duplications + // DuplicationsParser.class, + // DuplicationsWs.class, no Web Service in CE + // DuplicationsJsonWriter.class, + // org.sonar.server.duplication.ws.ShowAction.class, no Web Service in CE + + // text + // MacroInterpreter.class, only used in Web Services and Ruby + // RubyTextService.class, + + // Notifications + EmailSettings.class, + NotificationService.class, + NotificationCenter.class, + DefaultNotificationManager.class, + + // Tests + // CoverageService.class, + // TestsWs.class, + // CoveredFilesAction.class, + // org.sonar.server.test.ws.ListAction.class, + // TestIndexDefinition.class, + // TestIndex.class, + TestIndexer.class, + + // Properties + // PropertiesWs.class, no Web Service in CE + + // TypeValidationModule.class, indirectly used only in Web Service + + // System + ServerLogging.class, + // RestartAction.class, no Web Service in CE + // InfoAction.class, no Web Service in CE + // UpgradesAction.class, no Web Service in CE + // StatusAction.class, no Web Service in CE + // SystemWs.class, no Web Service in CE + // SystemMonitor.class, no Monitor in CE, responsibility of Web Server + // SonarQubeMonitor.class, no Monitor in CE, responsibility of Web Server + // EsMonitor.class, no Monitor in CE, responsibility of Web Server + // PluginsMonitor.class, no Monitor in CE, responsibility of Web Server + // JvmPropsMonitor.class, no Monitor in CE, responsibility of Web Server + // DatabaseMonitor.class, no Monitor in CE, responsibility of Web Server + // MigrateDbAction.class, no Web Service in CE + // LogsAction.class, no Web Service in CE + // ChangeLogLevelAction.class, no Web Service in CE + // DbMigrationStatusAction.class, no Web Service in CE + + // Plugins WS + // PluginWSCommons.class, no Web Service in CE + // PluginUpdateAggregator.class, no Web Service in CE + // InstalledAction.class, no Web Service in CE + // AvailableAction.class, no Web Service in CE + // UpdatesAction.class, no Web Service in CE + // PendingAction.class, no Web Service in CE + // InstallAction.class, no Web Service in CE + // org.sonar.server.plugins.ws.UpdateAction.class, no Web Service in CE + // UninstallAction.class, no Web Service in CE + // CancelAllAction.class, no Web Service in CE + // PluginsWs.class, no Web Service in CE + + // Views plugin + // ViewsBootstrap.class, Views not supported in 5.5 + // ViewsStopper.class, Views not supported in 5.5 + + // privileged plugins + PrivilegedPluginsBootstraper.class, + PrivilegedPluginsStopper.class, + + // Compute engine (must be after Views and Developer Cockpit) + CeModule.class, + CeQueueModule.class, + ReportProcessingModule.class, + CeTaskProcessorModule.class, + // CeWsModule.class, no Web Service in CE + + ProjectSettingsFactory.class, + + // UI + // GlobalNavigationAction.class, no Web Service in CE + // SettingsNavigationAction.class, no Web Service in CE + // ComponentNavigationAction.class, no Web Service in CE + // NavigationWs.class, no Web Service in CE + }; + } + + private static Object[] startupComponents() { + return new Object[] { + // IndexerStartupTask.class, ES maintenance, responsibility of Web Server + EsIndexerEnabler.class, + // RegisterMetrics.class, DB maintenance, responsibility of Web Server + // RegisterQualityGates.class, DB maintenance, responsibility of Web Server + // RegisterRules.class, DB maintenance, responsibility of Web Server + // RegisterQualityProfiles.class, DB maintenance, responsibility of Web Server + // GeneratePluginIndex.class, ES maintenance, responsibility of Web Server + // RegisterNewMeasureFilters.class, DB maintenance, responsibility of Web Server + // RegisterDashboards.class, UI related, anyway, DB maintenance, responsibility of Web Server + // RegisterPermissionTemplates.class, DB maintenance, responsibility of Web Server + // RenameDeprecatedPropertyKeys.class, DB maintenance, responsibility of Web Server + LogServerId.class, + // RegisterServletFilters.class, Web Server only + // RegisterIssueFilters.class, DB maintenance, responsibility of Web Server + // RenameIssueWidgets.class, UI related, anyway, DB maintenance, responsibility of Web Server + ServerLifecycleNotifier.class, + PurgeCeActivities.class, + // DisplayLogOnDeprecatedProjects.class, responsibility of Web Server + // ClearRulesOverloadedDebt.class, DB maintenance, responsibility of Web Server + }; + } + private static Object[] toArray(List list) { return list.toArray(new Object[list.size()]); } diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java index 60cbe067609..99b8afbb519 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java @@ -99,7 +99,7 @@ public class ComputeEngineContainerImplTest { ); assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize( COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION - + 22 // level 1 + + 23 // level 1 + 46 // content of DaoModule + 1 // content of EsSearchModule + 55 // content of CorePropertyDefinitions diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java index a248ffef263..2d23b102dee 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java @@ -21,10 +21,12 @@ package org.sonar.server.platform.platformlevel; import java.util.Properties; import javax.annotation.Nullable; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; -import org.sonar.api.internal.SonarRuntimeFactory; +import org.sonar.api.SonarQubeVersion; +import org.sonar.api.internal.ApiVersion; +import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.utils.System2; +import org.sonar.api.utils.Version; import org.sonar.api.utils.internal.TempFolderCleaner; import org.sonar.ce.property.CePropertyDefinitions; import org.sonar.core.config.CorePropertyDefinitions; @@ -69,8 +71,10 @@ public class PlatformLevel1 extends PlatformLevel { public void configureLevel() { add(platform, properties); addExtraRootComponents(); + Version apiVersion = ApiVersion.load(System2.INSTANCE); add( - SonarRuntimeFactory.create(System2.INSTANCE, SonarProduct.SONARQUBE, SonarQubeSide.SERVER), + new SonarQubeVersion(apiVersion), + SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SERVER), ProcessCommandWrapperImpl.class, RestartFlagHolderImpl.class, WebServerSettings.class, diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java b/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java index 8fb50a0b14c..965a1b13b01 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java @@ -33,14 +33,13 @@ import static java.util.Objects.requireNonNull; * This property is automatically set by sonar-packaging-maven-plugin when building plugin. *

Example of implementation *

- * package com.mycompany.sonarqube;
- * public class MyPlugin implements Plugin {
+  * public class MyPlugin implements Plugin {
  *  {@literal @}Override
  *   public void define(Context context) {
  *     context.addExtensions(MySensor.class, MyRules.class);
- *     if (context.getSonarQubeVersion().isGreaterThanOrEqual(SonarQubeVersion.V5_6)) {
- *       // Extension which supports only versions 5.6 and greater
- *       // See org.sonar.api.SonarQubeVersion for more details.
+ *     if (context.getRuntime().getApiVersion().isGreaterThanOrEqual(Version.create(6, 0))) {
+ *       // Extension which supports only versions 6.0 and greater
+ *       // See org.sonar.api.SonarRuntime for more details.
  *       context.addExtension(MyNewExtension.class);
  *     }
  *   }
@@ -73,8 +72,9 @@ import static java.util.Objects.requireNonNull;
  * MyPlugin underTest = new MyPlugin();
  *
  *{@literal @}Test
- * public void test_plugin_extensions_compatible_with_5_5() {
- *   Plugin.Context context = new Plugin.Context(SonarQubeVersion.V5_5);
+ * public void test_plugin_extensions_compatible_with_5_6() {
+ *   SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.create(5, 6));
+ *   Plugin.Context context = new Plugin.Context(runtime);
  *   underTest.define(context);
  *   assertThat(context.getExtensions()).hasSize(4);
  * }
@@ -93,7 +93,7 @@ public interface Plugin {
     }
 
     /**
-     * @deprecated since 6.0 use {@link #getRuntimeApiVersion()}
+     * @deprecated replaced by {@link #getRuntime()}.getApiVersion() in 6.0
      */
     @Deprecated
     public Version getSonarQubeVersion() {
@@ -101,11 +101,11 @@ public interface Plugin {
     }
 
     /**
-     * Runtime API version. Can be use to conditionnaly add some extensions.
+     * Runtime environment. Can be use to add some extensions only on some conditions.
      * @since 6.0
      */
-    public Version getRuntimeApiVersion() {
-      return sonarRuntime.getApiVersion();
+    public SonarRuntime getRuntime() {
+      return sonarRuntime;
     }
 
     /**
@@ -151,13 +151,6 @@ public interface Plugin {
       return extensions;
     }
 
-    /**
-     * Test the product the plugin is currently executed in. This can allow to implement a different behavior.
-     * @since 6.0
-     */
-    public SonarProduct getRuntimeProduct() {
-      return sonarRuntime.getProduct();
-    }
   }
 
   /**
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeSide.java b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeSide.java
index 5e02c2eae61..7aa312e76a1 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeSide.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeSide.java
@@ -20,13 +20,14 @@
 package org.sonar.api;
 
 /**
- * Differentiate runtime context in SonarQube product.
+ * Runtime stack in SonarQube product.
+ * @see SonarRuntime#getSonarQubeSide()
  * @since 6.0
  */
 public enum SonarQubeSide {
 
   SCANNER,
   SERVER,
-  COMPUTE_ENGINE;
+  COMPUTE_ENGINE
 
 }
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java
index 044df52a450..6b4e100939f 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java
@@ -19,118 +19,48 @@
  */
 package org.sonar.api;
 
-import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 import org.sonar.api.batch.ScannerSide;
-import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.ce.ComputeEngineSide;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.Version;
 
+import static java.util.Objects.requireNonNull;
+
 /**
- * Version of SonarQube at runtime. This component can be injected as a dependency
- * of plugin extensions. The main usage for a plugin is to benefit from new APIs
- * while keeping backward-compatibility with previous versions of SonarQube.
- * 

- * - * Example 1: a {@link Sensor} wants to use an API introduced in version 5.5 and still requires to support older versions - * at runtime. - *
- * public class MySensor implements Sensor {
- *
- *   public void execute(SensorContext context) {
- *     if (context.getSonarQubeVersion().isGreaterThanOrEqual(SonarQubeVersion.V5_5)) {
- *       context.newMethodIntroducedIn5_5();
- *     }
- *   }
- * }
- * 
- * - * Example 2: a plugin needs to use an API introduced in version 5.6 ({@code AnApi} in the following - * snippet) and still requires to support version 5.5 at runtime. - *
- *
- * // Component provided by sonar-plugin-api
- * // @since 5.5
- * public interface AnApi {
- *   // implicitly since 5.5
- *   public void foo();
- *
- *   // @since 5.6
- *   public void bar();
- * }
- * 
- * // Component provided by plugin
- * public class MyExtension {
- *   private final SonarQubeVersion sonarQubeVersion;
- *   private final AnApi api;
- *
- *   public MyExtension(SonarQubeVersion sonarQubeVersion, AnApi api) {
- *     this.sonarQubeVersion = sonarQubeVersion;
- *     this.api = api;
- *   }
- *
- *   public void doSomething() {
- *     // assume that runtime is 5.5+
- *     api.foo();
- *
- *     if (sonarQubeVersion.isGreaterThanOrEqual(SonarQubeVersion.V5_6)) {
- *       api.bar();
- *     }
- *   }
- * }
- * 
- *

- * The minimal supported version of SonarQube is verified at runtime. As plugin is built - * with sonar-plugin-api 5.6, we assume that the plugin requires v5.6 or greater at runtime. - * For this reason the plugin must default which is the minimal supported version - * in the configuration of sonar-packaging-maven-plugin 1.16+: - *

- *

- * <packaging>sonar-plugin</packaging>
- *
- * <dependencies>
- *   <dependency>
- *     <groupId>org.sonarsource.sonarqube</groupId>
- *     <artifactId>sonar-plugin-api</artifactId>
- *     <version>5.6</version>
- *     <scope>provided</scope>
- *   </dependency>
- * </dependencies>
- *
- * <build>
- *  <plugins>
- *    <plugin>
- *      <groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
- *      <artifactId>sonar-packaging-maven-plugin</artifactId>
- *      <version>1.16</version>
- *      <extensions>true</extensions>
- *      <configuration>
- *        <!-- Override the default value 5.6 which is guessed from sonar-plugin-api dependency -->
- *        <sonarQubeMinVersion>5.5</sonarQubeMinVersion>
- *      </configuration>
- *    </plugin>
- *  </plugins>
- * </build>
- * 
- * + * Version of SonarQube at runtime. Replaced by {@link SonarRuntime#getApiVersion()}. * * @since 5.5 - * @deprecated since 6.0 replaced by {@link SonarRuntime} + * @deprecated replaced by {@link SonarRuntime} in version 6.0 */ @ScannerSide @ServerSide @ComputeEngineSide @Immutable @Deprecated -public class SonarQubeVersion extends SonarRuntime { +public class SonarQubeVersion { + /** + * Constant for version 5.5 + */ + public static final Version V5_5 = Version.create(5, 5); - public SonarQubeVersion(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide) { - super(version, product, sonarQubeSide); + /** + * Constant for version 5.6 + */ + public static final Version V5_6 = Version.create(5, 6); + + private final Version version; + + public SonarQubeVersion(Version version) { + requireNonNull(version); + this.version = version; } public Version get() { - return super.getApiVersion(); + return this.version; } + public boolean isGreaterThanOrEqual(Version than) { + return this.version.isGreaterThanOrEqual(than); + } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/SonarRuntime.java b/sonar-plugin-api/src/main/java/org/sonar/api/SonarRuntime.java index 86b37e9e54c..b2663ca1da8 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/SonarRuntime.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/SonarRuntime.java @@ -19,75 +19,81 @@ */ package org.sonar.api; -import com.google.common.base.Preconditions; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; import org.sonar.api.utils.Version; import org.sonarsource.api.sonarlint.SonarLintSide; -import static java.util.Objects.requireNonNull; - /** - * Version of SonarQube at runtime. This component can be injected as a dependency - * of plugin extensions. The main usage for a plugin is to benefit from new APIs - * while keeping backward-compatibility with previous versions of SonarQube. - *

- * - * Example 1: a {@link Sensor} wants to use an API introduced in version 5.5 and still requires to support older versions - * at runtime. - *
- * public class MySensor implements Sensor {
+ * Information about runtime environment.
  *
- *   public void execute(SensorContext context) {
- *     if (context.getRuntimeApiVersion().isGreaterThanOrEqual(RuntimeApiVersion.V5_5)) {
- *       context.newMethodIntroducedIn5_5();
- *     }
- *   }
- * }
- * 
+ *

+ * A usage for plugins is to benefit from new APIs + * while keeping backward-compatibility with previous versions of SonarQube + * or SonarLint. + *

* - * Example 2: a plugin needs to use an API introduced in version 5.6 ({@code AnApi} in the following - * snippet) and still requires to support version 5.5 at runtime. - *
+ *

+ * Example: a plugin extension wants to use a new feature of API 6.0 without + * breaking compatibility with version 5.6 at runtime. This new feature + * would be enabled only in 6.0 and greater runtimes. + *

*
  * // Component provided by sonar-plugin-api
- * // @since 5.5
+ * // @since 5.6
  * public interface AnApi {
- *   // implicitly since 5.5
+ *   // implicitly since 5.6
  *   public void foo();
  *
- *   // @since 5.6
+ *   // @since 6.0
  *   public void bar();
  * }
  * 
- * // Component provided by plugin
+ * // Plugin extension
  * public class MyExtension {
- *   private final RuntimeApiVersion runtimeApiVersion;
+ *   private final SonarRuntime sonarRuntime;
  *   private final AnApi api;
  *
- *   public MyExtension(RuntimeApiVersion runtimeApiVersion, AnApi api) {
- *     this.runtimeApiVersion = runtimeApiVersion;
+ *   public MyExtension(SonarRuntime sonarRuntime, AnApi api) {
+ *     this.sonarRuntime = sonarRuntime;
  *     this.api = api;
  *   }
  *
  *   public void doSomething() {
- *     // assume that runtime is 5.5+
+ *     // assume that minimal supported runtime is 5.6
  *     api.foo();
  *
- *     if (runtimeApiVersion.isGreaterThanOrEqual(SonarQubeVersion.V5_6)) {
+ *     if (sonarRuntime.getApiVersion().isGreaterThanOrEqual(Version.create(6, 0))) {
  *       api.bar();
  *     }
  *   }
  * }
  * 
+ * + * + *

+ * Note that {@link Sensor} extensions can directly get {@link SonarRuntime} through + * {@link SensorContext#runtime()}, without using constructor injection: + *

+ *
+ * public class MySensor implements Sensor {
+ *
+ *   public void execute(SensorContext context) {
+ *     if (context.runtime().getApiVersion().isGreaterThanOrEqual(Version.create(6, 0)) {
+ *       context.newMethodIntroducedIn6_0();
+ *     }
+ *   }
+ *
+ * }
+ * 
+ * *

* The minimal supported version of plugin API is verified at runtime. As plugin is built - * with sonar-plugin-api 5.6, we assume that the plugin requires v5.6 or greater at runtime. - * For this reason the plugin must default which is the minimal supported version + * with sonar-plugin-api 6.0, we assume that the plugin requires v6.0 or greater at runtime. + * For this reason the plugin must override the minimal supported version * in the configuration of sonar-packaging-maven-plugin 1.16+: *

*

@@ -97,7 +103,7 @@ import static java.util.Objects.requireNonNull;
  *   <dependency>
  *     <groupId>org.sonarsource.sonarqube</groupId>
  *     <artifactId>sonar-plugin-api</artifactId>
- *     <version>5.6</version>
+ *     <version>6.0</version>
  *     <scope>provided</scope>
  *   </dependency>
  * </dependencies>
@@ -111,80 +117,42 @@ import static java.util.Objects.requireNonNull;
  *      <extensions>true</extensions>
  *      <configuration>
  *        <!-- Override the default value 5.6 which is guessed from sonar-plugin-api dependency -->
- *        <sonarQubeMinVersion>5.5</sonarQubeMinVersion>
+ *        <sonarQubeMinVersion>5.6</sonarQubeMinVersion>
  *      </configuration>
  *    </plugin>
  *  </plugins>
  * </build>
  * 
* - * + *

+ * Unit tests of plugin extensions can create instances of {@link SonarRuntime} + * via {@link org.sonar.api.internal.SonarRuntimeImpl}. + *

* @since 6.0 */ @ScannerSide @ServerSide @ComputeEngineSide @SonarLintSide -@Immutable -public class SonarRuntime { +public interface SonarRuntime { /** - * Constant for version 5.5 - */ - public static final Version V5_5 = Version.create(5, 5); - - /** - * Constant for version 5.6 - */ - public static final Version V5_6 = Version.create(5, 6); - - /** - * Constant for version 6.0 - */ - public static final Version V6_0 = Version.create(6, 0); - - private final Version version; - private final SonarProduct product; - private final SonarQubeSide sonarQubeSide; - - public SonarRuntime(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide) { - requireNonNull(version); - requireNonNull(product); - Preconditions.checkArgument((product == SonarProduct.SONARQUBE) == (sonarQubeSide != null), "sonarQubeSide should be provided only for SonarQube product"); - this.version = version; - this.product = product; - this.sonarQubeSide = sonarQubeSide; - } - - /** - * Runtime version of sonar-plugin-api. This could be used to test if a new feature can be used or not without using reflection. - */ - public Version getApiVersion() { - return this.version; - } - - public boolean isGreaterThanOrEqual(Version than) { - return this.version.isGreaterThanOrEqual(than); - } + * Version of API (sonar-plugin-api artifact) at runtime. + * It can be helpful to call some API classes/methods without checking their availability at + * runtime by using reflection. + */ + Version getApiVersion(); /** - * Allow to know what is current runtime product. Can be used to implement different behavior depending on runtime (SonarQube, SonarLint, ...). - * @since 6.0 + * The product being executed at runtime. It targets analysers so that they can implement + * different behaviours in SonarQube and SonarLint. */ - public SonarProduct getProduct() { - return product; - } + SonarProduct getProduct(); /** - * Allow to know the precise runtime context in SonarQube product. Only valid when {@link #getProduct()} returns {@link SonarProduct#SONARQUBE} - * @since 6.0 - * @throws UnsupportedOperationException if called and {@link #getProduct()} is not equal to {@link SonarProduct#SONARQUBE} + * The SonarQube stack being executed at runtime. + * @throws UnsupportedOperationException if {@link #getProduct()} is not equal to {@link SonarProduct#SONARQUBE} */ - public SonarQubeSide getSonarQubeSide() { - if (sonarQubeSide == null) { - throw new UnsupportedOperationException("Can only be called in SonarQube"); - } - return sonarQubeSide; - } + SonarQubeSide getSonarQubeSide(); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java index 9612521b23f..c92ab74a5d9 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java @@ -20,7 +20,7 @@ package org.sonar.api.batch.sensor; import java.io.Serializable; -import org.sonar.api.SonarProduct; +import org.sonar.api.SonarRuntime; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.rule.ActiveRules; @@ -66,25 +66,24 @@ public interface SensorContext { /** * @since 5.5 - * @deprecated since 6.0 replaced by {@link #getRuntimeApiVersion()} + * @deprecated replaced by {@link #runtime()}.getApiVersion() in version 6.0. */ @Deprecated Version getSonarQubeVersion(); /** + * Runtime information, mainly: + *
    + *
  • to be able to have different behaviours between SonarQube and SonarLint
  • + *
  • to enable new features depending on version of API available at runtime
  • + *
* @since 6.0 */ - Version getRuntimeApiVersion(); - - /** - * Test the product the plugin is currently executed in. This can allow to implement a different behavior. - * @since 6.0 - */ - SonarProduct getRuntimeProduct(); + SonarRuntime runtime(); /** * Test if a cancellation of the analysis was requested. Sensors should periodically test this flag - * and gracefully stop if value is true. For example it could be tested between each processed file. + * and gracefully stop if value is {@code true}. For example it could be tested between each processed file. * @since 6.0 */ boolean isCancelled(); @@ -139,7 +138,7 @@ public interface SensorContext { /** * Builder to declare errors that happened while processing a source file. - * Don't forget to call {@link NewAnalisisError#save()}. + * Don't forget to call {@link NewAnalysisError#save()}. * @since 6.0 */ NewAnalysisError newAnalysisError(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java index a2c8cd2ac26..ba9020829a4 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java @@ -19,7 +19,6 @@ */ package org.sonar.api.batch.sensor.internal; -import com.google.common.annotations.Beta; import java.io.File; import java.io.Serializable; import java.nio.file.Path; @@ -30,9 +29,8 @@ import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.CheckForNull; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; -import org.sonar.api.SonarQubeVersion; +import org.sonar.api.SonarRuntime; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.fs.TextRange; import org.sonar.api.batch.fs.internal.DefaultFileSystem; @@ -63,7 +61,8 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; import org.sonar.api.batch.sensor.symbol.NewSymbolTable; import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable; import org.sonar.api.config.Settings; -import org.sonar.api.internal.SonarRuntimeFactory; +import org.sonar.api.internal.ApiVersion; +import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.measures.Metric; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; @@ -84,7 +83,6 @@ import org.sonar.duplications.internal.pmd.TokensLine; * Then pass it to your {@link Sensor}. You can then query elements provided by your sensor using methods {@link #allIssues()}, ... * */ -@Beta public class SensorContextTester implements SensorContext { private Settings settings; @@ -92,7 +90,7 @@ public class SensorContextTester implements SensorContext { private ActiveRules activeRules; private InMemorySensorStorage sensorStorage; private InputModule module; - private SonarQubeVersion sqVersion; + private SonarRuntime runtime; private boolean cancelled; private SensorContextTester(Path moduleBaseDir) { @@ -101,7 +99,7 @@ public class SensorContextTester implements SensorContext { this.activeRules = new ActiveRulesBuilder().build(); this.sensorStorage = new InMemorySensorStorage(); this.module = new DefaultInputModule("projectKey"); - this.sqVersion = SonarRuntimeFactory.create(System2.INSTANCE, SonarProduct.SONARQUBE, SonarQubeSide.SCANNER); + this.runtime = SonarRuntimeImpl.forSonarQube(ApiVersion.load(System2.INSTANCE), SonarQubeSide.SCANNER); } public static SensorContextTester create(File moduleBaseDir) { @@ -143,26 +141,25 @@ public class SensorContextTester implements SensorContext { } /** - * Default value is the version of this API. You can override it - * using {@link #setSonarQubeVersion(Version)} to test your Sensor behavior. + * Default value is the version of this API at compilation time. You can override it + * using {@link #setRuntime(SonarRuntime)} to test your Sensor behaviour. */ @Override public Version getSonarQubeVersion() { - return sqVersion.getApiVersion(); - } - - @Override - public Version getRuntimeApiVersion() { - return sqVersion.getApiVersion(); + return runtime().getApiVersion(); } + /** + * @see #setRuntime(SonarRuntime) to override defaults (SonarQube scanner with version + * of this API as used at compilation time). + */ @Override - public SonarProduct getRuntimeProduct() { - return sqVersion.getProduct(); + public SonarRuntime runtime() { + return runtime; } - public SensorContextTester setRuntime(Version version, SonarProduct product, SonarQubeSide sonarQubeSide) { - this.sqVersion = new SonarQubeVersion(version, product, sonarQubeSide); + public SensorContextTester setRuntime(SonarRuntime runtime) { + this.runtime = runtime; return this; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/ApiVersion.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/ApiVersion.java new file mode 100644 index 00000000000..de57cf0761a --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/internal/ApiVersion.java @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.internal; + +import com.google.common.io.Resources; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import org.sonar.api.utils.System2; +import org.sonar.api.utils.Version; + +/** + * For internal use + * + * @since 6.0 + */ +public class ApiVersion { + + private static final String FILE_PATH = "/sq-version.txt"; + + private ApiVersion() { + // only static methods + } + + public static Version load(System2 system) { + try { + URL url = system.getResource(FILE_PATH); + String versionInFile = Resources.toString(url, StandardCharsets.UTF_8); + return Version.parse(versionInFile); + } catch (IOException e) { + throw new IllegalStateException("Can not load " + FILE_PATH + " from classpath", e); + } + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeFactory.java deleted file mode 100644 index b47189b58a8..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.api.internal; - -import com.google.common.io.Resources; -import java.io.IOException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import javax.annotation.Nullable; -import org.sonar.api.SonarProduct; -import org.sonar.api.SonarQubeSide; -import org.sonar.api.SonarQubeVersion; -import org.sonar.api.utils.System2; -import org.sonar.api.utils.Version; - -/** - * For internal use only. - */ -public class SonarRuntimeFactory { - - private static final String FILE_PATH = "/sq-version.txt"; - - private SonarRuntimeFactory() { - // prevents instantiation - } - - public static SonarQubeVersion create(System2 system, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide) { - try { - URL url = system.getResource(FILE_PATH); - String versionInFile = Resources.toString(url, StandardCharsets.UTF_8); - return new SonarQubeVersion(Version.parse(versionInFile), product, sonarQubeSide); - } catch (IOException e) { - throw new IllegalStateException("Can not load " + FILE_PATH + " from classpath", e); - } - } -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java new file mode 100644 index 00000000000..601c8d017c2 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java @@ -0,0 +1,83 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.internal; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import org.sonar.api.SonarProduct; +import org.sonar.api.SonarQubeSide; +import org.sonar.api.SonarRuntime; +import org.sonar.api.utils.Version; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + +/** + * @since 6.0 + */ +@Immutable +public class SonarRuntimeImpl implements SonarRuntime { + + private final Version version; + private final SonarProduct product; + private final SonarQubeSide sonarQubeSide; + + private SonarRuntimeImpl(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide) { + requireNonNull(version); + requireNonNull(product); + checkArgument((product == SonarProduct.SONARQUBE) == (sonarQubeSide != null), "sonarQubeSide should be provided only for SonarQube product"); + this.version = version; + this.product = product; + this.sonarQubeSide = sonarQubeSide; + } + + @Override + public Version getApiVersion() { + return this.version; + } + + @Override + public SonarProduct getProduct() { + return product; + } + + @Override + public SonarQubeSide getSonarQubeSide() { + if (sonarQubeSide == null) { + throw new UnsupportedOperationException("Can only be called in SonarQube"); + } + return sonarQubeSide; + } + + /** + * Create an instance for SonarQube runtime environment. + */ + public static SonarRuntime forSonarQube(Version version, SonarQubeSide side) { + return new SonarRuntimeImpl(version, SonarProduct.SONARQUBE, side); + } + + /** + * Create an instance for SonarLint runtime environment. + */ + public static SonarRuntime forSonarLint(Version version) { + return new SonarRuntimeImpl(version, SonarProduct.SONARLINT, null); + } + +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java index caa022c0290..2ef2d212e59 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java @@ -21,17 +21,21 @@ package org.sonar.api; import java.util.Arrays; import org.junit.Test; +import org.sonar.api.internal.SonarRuntimeImpl; +import org.sonar.api.utils.Version; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.api.SonarRuntime.V5_5; public class PluginTest { + private static final Version VERSION_5_6 = Version.create(5, 6); + @Test public void test_context() { - Plugin.Context context = new Plugin.Context(new SonarRuntime(V5_5, SonarProduct.SONARQUBE, SonarQubeSide.SERVER)); + SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(VERSION_5_6, SonarQubeSide.SERVER); + Plugin.Context context = new Plugin.Context(runtime); - assertThat(context.getSonarQubeVersion()).isEqualTo(V5_5); + assertThat(context.getSonarQubeVersion()).isEqualTo(VERSION_5_6); assertThat(context.getExtensions()).isEmpty(); context.addExtension("foo"); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java index 8ee63aa98fd..ac430ad82f5 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java @@ -19,22 +19,17 @@ */ package org.sonar.api; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.sonar.api.utils.Version; import static org.assertj.core.api.Assertions.assertThat; public class SonarQubeVersionTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void isGte() { Version version = Version.parse("1.2.3"); - SonarQubeVersion qubeVersion = new SonarQubeVersion(version, SonarProduct.SONARLINT, null); + SonarQubeVersion qubeVersion = new SonarQubeVersion(version); assertThat(qubeVersion.get()).isEqualTo(version); assertThat(qubeVersion.isGreaterThanOrEqual(version)).isTrue(); assertThat(qubeVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue(); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/SonarRuntimeTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/SonarRuntimeTest.java deleted file mode 100644 index 6d26a5678ce..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/SonarRuntimeTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.api; - -import org.assertj.core.api.Assertions; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.utils.Version; - -import static org.assertj.core.api.Assertions.assertThat; - -public class SonarRuntimeTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void isGteInSQ() { - Version version = Version.parse("1.2.3"); - SonarRuntime apiVersion = new SonarRuntime(version, SonarProduct.SONARQUBE, SonarQubeSide.SCANNER); - assertThat(apiVersion.getApiVersion()).isEqualTo(version); - assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARQUBE); - assertThat(apiVersion.getSonarQubeSide()).isEqualTo(SonarQubeSide.SCANNER); - assertThat(apiVersion.isGreaterThanOrEqual(version)).isTrue(); - assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue(); - assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.3"))).isFalse(); - } - - @Test - public void inSL() { - Version version = Version.parse("1.2.3"); - SonarRuntime apiVersion = new SonarRuntime(version, SonarProduct.SONARLINT, null); - assertThat(apiVersion.getApiVersion()).isEqualTo(version); - assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARLINT); - assertThat(apiVersion.isGreaterThanOrEqual(version)).isTrue(); - assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue(); - assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.3"))).isFalse(); - try { - apiVersion.getSonarQubeSide(); - Assertions.fail("Expected exception"); - } catch (Exception e) { - assertThat(e).isInstanceOf(UnsupportedOperationException.class); - } - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructorMissSide() throws Exception { - new SonarRuntime(Version.parse("1.2.3"), SonarProduct.SONARQUBE, null); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructorNoSideOnSonarLint() throws Exception { - new SonarRuntime(Version.parse("1.2.3"), SonarProduct.SONARLINT, SonarQubeSide.COMPUTE_ENGINE); - } -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/internal/ApiVersionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/internal/ApiVersionTest.java new file mode 100644 index 00000000000..996b0648ddf --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/internal/ApiVersionTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.internal; + +import java.io.File; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.System2; +import org.sonar.api.utils.Version; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class ApiVersionTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void load_version_from_file_in_classpath() { + Version version = ApiVersion.load(System2.INSTANCE); + assertThat(version).isNotNull(); + assertThat(version.major()).isGreaterThanOrEqualTo(5); + } + + @Test + public void throw_ISE_if_fail_to_load_version() throws Exception { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Can not load /sq-version.txt from classpath"); + + System2 system = spy(System2.class); + when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURI().toURL()); + ApiVersion.load(system); + } + +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeFactoryTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeFactoryTest.java deleted file mode 100644 index 4db26447ca5..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeFactoryTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.api.internal; - -import java.io.File; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.SonarProduct; -import org.sonar.api.SonarQubeVersion; -import org.sonar.api.utils.System2; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -public class SonarRuntimeFactoryTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void create() { - SonarQubeVersion version = SonarRuntimeFactory.create(System2.INSTANCE, SonarProduct.SONARLINT, null); - assertThat(version).isNotNull(); - assertThat(version.getApiVersion().major()).isGreaterThanOrEqualTo(5); - assertThat(version.getProduct()).isEqualTo(SonarProduct.SONARLINT); - } - - @Test - public void throw_ISE_if_fail_to_load_version() throws Exception { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Can not load /sq-version.txt from classpath"); - - System2 system = spy(System2.class); - when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURI().toURL()); - SonarRuntimeFactory.create(system, SonarProduct.SONARLINT, null); - } - -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java new file mode 100644 index 00000000000..ea214d5bef1 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java @@ -0,0 +1,69 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.internal; + +import org.assertj.core.api.Assertions; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.SonarProduct; +import org.sonar.api.SonarQubeSide; +import org.sonar.api.SonarRuntime; +import org.sonar.api.utils.Version; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class SonarRuntimeImplTest { + + private static final Version A_VERSION = Version.parse("6.0"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void sonarQube_environment() { + SonarRuntime apiVersion = SonarRuntimeImpl.forSonarQube(A_VERSION, SonarQubeSide.SCANNER); + assertThat(apiVersion.getApiVersion()).isEqualTo(A_VERSION); + assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARQUBE); + assertThat(apiVersion.getSonarQubeSide()).isEqualTo(SonarQubeSide.SCANNER); + } + + @Test + public void sonarLint_environment() { + SonarRuntime apiVersion = SonarRuntimeImpl.forSonarLint(A_VERSION); + assertThat(apiVersion.getApiVersion()).isEqualTo(A_VERSION); + assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARLINT); + try { + apiVersion.getSonarQubeSide(); + Assertions.fail("Expected exception"); + } catch (Exception e) { + assertThat(e).isInstanceOf(UnsupportedOperationException.class); + } + } + + @Test(expected = IllegalArgumentException.class) + public void sonarqube_requires_side() throws Exception { + SonarRuntimeImpl.forSonarQube(A_VERSION, null); + } + + + +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java index 605a067c66f..cb98c42d047 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java @@ -21,13 +21,14 @@ package org.sonar.scanner.bootstrap; import java.util.List; import java.util.Map; - import org.sonar.api.Plugin; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; -import org.sonar.api.internal.SonarRuntimeFactory; +import org.sonar.api.SonarQubeVersion; +import org.sonar.api.internal.ApiVersion; +import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.utils.System2; import org.sonar.api.utils.UriReader; +import org.sonar.api.utils.Version; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.core.platform.ComponentContainer; @@ -69,6 +70,7 @@ public class GlobalContainer extends ComponentContainer { } private void addBootstrapComponents() { + Version apiVersion = ApiVersion.load(System2.INSTANCE); add( // plugins BatchPluginRepository.class, @@ -78,7 +80,8 @@ public class GlobalContainer extends ComponentContainer { BatchPluginPredicate.class, ExtensionInstaller.class, - SonarRuntimeFactory.create(System2.INSTANCE, SonarProduct.SONARQUBE, SonarQubeSide.SCANNER), + new SonarQubeVersion(apiVersion), + SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SCANNER), CachesManager.class, GlobalSettings.class, new BatchWsClientProvider(), diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java index d3cb867c509..f19633527af 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java @@ -20,7 +20,6 @@ package org.sonar.scanner.sensor; import java.io.Serializable; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarRuntime; import org.sonar.api.batch.AnalysisMode; import org.sonar.api.batch.fs.FileSystem; @@ -100,13 +99,8 @@ public class DefaultSensorContext implements SensorContext { } @Override - public Version getRuntimeApiVersion() { - return sonarRuntime.getApiVersion(); - } - - @Override - public SonarProduct getRuntimeProduct() { - return sonarRuntime.getProduct(); + public SonarRuntime runtime() { + return sonarRuntime; } @Override diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java index 1ebd459f0eb..d278fcaeb81 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java @@ -27,14 +27,10 @@ import org.junit.Test; import org.sonar.api.BatchExtension; import org.sonar.api.ExtensionProvider; import org.sonar.api.SonarPlugin; -import org.sonar.api.SonarQubeVersion; +import org.sonar.api.SonarRuntime; import org.sonar.api.batch.AnalysisMode; import org.sonar.core.platform.ComponentContainer; import org.sonar.core.platform.PluginInfo; -import org.sonar.scanner.bootstrap.BatchPluginRepository; -import org.sonar.scanner.bootstrap.ExtensionInstaller; -import org.sonar.scanner.bootstrap.ExtensionMatcher; -import org.sonar.scanner.bootstrap.GlobalMode; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -64,7 +60,7 @@ public class ExtensionInstallerTest { when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(Foo.class, Bar.class)); ComponentContainer container = new ComponentContainer(); - ExtensionInstaller installer = new ExtensionInstaller(mock(SonarQubeVersion.class), pluginRepository, mock(AnalysisMode.class)); + ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mock(AnalysisMode.class)); installer.install(container, new FooMatcher()); assertThat(container.getComponentByType(Foo.class)).isNotNull(); @@ -76,7 +72,7 @@ public class ExtensionInstallerTest { when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo"))); when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(new FooProvider(), new BarProvider())); ComponentContainer container = new ComponentContainer(); - ExtensionInstaller installer = new ExtensionInstaller(mock(SonarQubeVersion.class), pluginRepository, mock(AnalysisMode.class)); + ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mock(AnalysisMode.class)); installer.install(container, new FooMatcher()); @@ -89,7 +85,7 @@ public class ExtensionInstallerTest { when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo"))); when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(new FooBarProvider())); ComponentContainer container = new ComponentContainer(); - ExtensionInstaller installer = new ExtensionInstaller(mock(SonarQubeVersion.class), pluginRepository, mock(AnalysisMode.class)); + ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mock(AnalysisMode.class)); installer.install(container, new TrueMatcher()); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorContextTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorContextTest.java index edcdaf576fb..a5eace1c537 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorContextTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorContextTest.java @@ -24,9 +24,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; -import org.sonar.api.SonarQubeVersion; +import org.sonar.api.SonarRuntime; import org.sonar.api.batch.AnalysisMode; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.fs.internal.DefaultFileSystem; @@ -35,6 +34,7 @@ import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; import org.sonar.api.batch.sensor.internal.SensorStorage; import org.sonar.api.config.Settings; +import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.utils.Version; @@ -56,7 +56,7 @@ public class DefaultSensorContextTest { private Settings settings; private SensorStorage sensorStorage; private AnalysisMode analysisMode; - private SonarQubeVersion sqVersion; + private SonarRuntime runtime; @Before public void prepare() throws Exception { @@ -68,8 +68,8 @@ public class DefaultSensorContextTest { settings = new Settings(); sensorStorage = mock(SensorStorage.class); analysisMode = mock(AnalysisMode.class); - sqVersion = new SonarQubeVersion(Version.parse("5.5"), SonarProduct.SONARQUBE, SonarQubeSide.SCANNER); - adaptor = new DefaultSensorContext(mock(InputModule.class), settings, fs, activeRules, analysisMode, sensorStorage, sqVersion); + runtime = SonarRuntimeImpl.forSonarQube(Version.parse("5.5"), SonarQubeSide.SCANNER); + adaptor = new DefaultSensorContext(mock(InputModule.class), settings, fs, activeRules, analysisMode, sensorStorage, runtime); } @Test @@ -78,7 +78,7 @@ public class DefaultSensorContextTest { assertThat(adaptor.fileSystem()).isEqualTo(fs); assertThat(adaptor.settings()).isEqualTo(settings); assertThat(adaptor.getSonarQubeVersion()).isEqualTo(Version.parse("5.5")); - assertThat(adaptor.getRuntimeProduct()).isEqualTo(SonarProduct.SONARQUBE); + assertThat(adaptor.runtime()).isEqualTo(runtime); assertThat(adaptor.newIssue()).isNotNull(); assertThat(adaptor.newMeasure()).isNotNull(); -- cgit v1.2.3