From 314809259ca1540d1e015582d2263daebfa5f3a5 Mon Sep 17 00:00:00 2001 From: Sébastien Lesaint Date: Wed, 14 Aug 2019 12:46:39 +0200 Subject: rename sonar-webserver-common to sonar-webserver-api --- server/sonar-webserver-api/build.gradle | 58 ++++ .../sonar/server/app/ProcessCommandWrapper.java | 43 +++ .../server/app/ProcessCommandWrapperImpl.java | 95 +++++ .../org/sonar/server/app/RestartFlagHolder.java | 42 +++ .../sonar/server/app/RestartFlagHolderImpl.java | 41 +++ .../java/org/sonar/server/app/package-info.java | 24 ++ .../org/sonar/server/branch/BranchFeature.java | 26 ++ .../server/branch/BranchFeatureExtension.java | 30 ++ .../sonar/server/branch/BranchFeatureProxy.java | 29 ++ .../server/branch/BranchFeatureProxyImpl.java | 38 ++ .../java/org/sonar/server/branch/package-info.java | 23 ++ .../org/sonar/server/ce/http/CeHttpClient.java | 30 ++ .../org/sonar/server/ce/http/package-info.java | 23 ++ .../server/exceptions/BadRequestException.java | 75 ++++ .../server/exceptions/ForbiddenException.java | 34 ++ .../java/org/sonar/server/exceptions/Message.java | 66 ++++ .../sonar/server/exceptions/NotFoundException.java | 65 ++++ .../sonar/server/exceptions/ServerException.java | 35 ++ .../server/exceptions/UnauthorizedException.java | 32 ++ .../org/sonar/server/exceptions/package-info.java | 24 ++ .../org/sonar/server/health/ClusterHealth.java | 78 +++++ .../main/java/org/sonar/server/health/Health.java | 136 ++++++++ .../org/sonar/server/health/HealthChecker.java | 35 ++ .../java/org/sonar/server/health/package-info.java | 23 ++ .../org/sonar/server/platform/ClusterFeature.java | 31 ++ .../java/org/sonar/server/platform/Platform.java | 34 ++ .../sonar/server/platform/SystemInfoWriter.java | 26 ++ .../org/sonar/server/platform/package-info.java | 23 ++ .../org/sonar/server/plugins/InstalledPlugin.java | 81 +++++ .../org/sonar/server/plugins/PluginDownloader.java | 165 +++++++++ .../org/sonar/server/plugins/PluginFileSystem.java | 124 +++++++ .../sonar/server/plugins/PluginUninstaller.java | 90 +++++ .../server/plugins/ServerPluginJarExploder.java | 68 ++++ .../server/plugins/ServerPluginRepository.java | 372 ++++++++++++++++++++ .../sonar/server/plugins/UpdateCenterClient.java | 113 ++++++ .../server/plugins/UpdateCenterMatrixFactory.java | 55 +++ .../plugins/WebServerExtensionInstaller.java | 33 ++ .../plugins/edition/EditionBundledPlugins.java | 44 +++ .../sonar/server/plugins/edition/package-info.java | 24 ++ .../org/sonar/server/plugins/package-info.java | 23 ++ .../server/project/ProjectLifeCycleListener.java | 41 +++ .../server/project/ProjectLifeCycleListeners.java | 55 +++ .../project/ProjectLifeCycleListenersImpl.java | 91 +++++ .../org/sonar/server/project/RekeyedProject.java | 68 ++++ .../java/org/sonar/server/project/Visibility.java | 72 ++++ .../org/sonar/server/project/package-info.java | 23 ++ .../server/qualitygate/ProjectsInWarning.java | 44 +++ .../qualitygate/changeevent/QGChangeEvent.java | 101 ++++++ .../changeevent/QGChangeEventListener.java | 66 ++++ .../changeevent/QGChangeEventListeners.java | 29 ++ .../changeevent/QGChangeEventListenersImpl.java | 180 ++++++++++ .../server/qualitygate/changeevent/Trigger.java | 24 ++ .../qualitygate/changeevent/package-info.java | 23 ++ .../server/qualityprofile/BulkChangeResult.java | 60 ++++ .../sonar/server/qualityprofile/QProfileRules.java | 64 ++++ .../server/qualityprofile/RuleActivation.java | 91 +++++ .../sonar/server/qualityprofile/package-info.java | 23 ++ .../server/setting/ProjectConfigurationLoader.java | 49 +++ .../setting/ProjectConfigurationLoaderImpl.java | 73 ++++ .../server/setting/SettingsChangeNotifier.java | 46 +++ .../org/sonar/server/setting/package-info.java | 23 ++ .../org/sonar/server/telemetry/LicenseReader.java | 32 ++ .../org/sonar/server/telemetry/package-info.java | 23 ++ .../sonar/server/util/BooleanTypeValidation.java | 42 +++ .../org/sonar/server/util/FloatTypeValidation.java | 45 +++ .../org/sonar/server/util/GlobalLockManager.java | 59 ++++ .../sonar/server/util/IntegerTypeValidation.java | 45 +++ .../org/sonar/server/util/LongTypeValidation.java | 43 +++ .../server/util/MetricLevelTypeValidation.java | 44 +++ .../server/util/StringListTypeValidation.java | 41 +++ .../sonar/server/util/StringTypeValidation.java | 40 +++ .../org/sonar/server/util/TextTypeValidation.java | 40 +++ .../java/org/sonar/server/util/TypeValidation.java | 34 ++ .../sonar/server/util/TypeValidationModule.java | 39 +++ .../org/sonar/server/util/TypeValidations.java | 70 ++++ .../java/org/sonar/server/util/Validation.java | 33 ++ .../java/org/sonar/server/util/package-info.java | 24 ++ .../server/app/ProcessCommandWrapperImplTest.java | 158 +++++++++ .../server/branch/BranchFeatureProxyImplTest.java | 48 +++ .../org/sonar/server/branch/BranchFeatureRule.java | 46 +++ .../server/exceptions/BadRequestExceptionTest.java | 85 +++++ .../org/sonar/server/exceptions/MessageTest.java | 88 +++++ .../server/exceptions/ServerExceptionTest.java | 40 +++ .../server/health/TestStandaloneHealthChecker.java | 39 +++ .../sonar/server/plugins/PluginDownloaderTest.java | 322 +++++++++++++++++ .../sonar/server/plugins/PluginFileSystemTest.java | 142 ++++++++ .../server/plugins/PluginUninstallerTest.java | 105 ++++++ .../plugins/ServerPluginJarExploderTest.java | 67 ++++ .../server/plugins/ServerPluginRepositoryTest.java | 385 +++++++++++++++++++++ .../java/org/sonar/server/plugins/TestPluginA.java | 29 ++ .../org/sonar/server/plugins/TestProjectUtils.java | 40 +++ .../server/plugins/UpdateCenterClientTest.java | 104 ++++++ .../plugins/UpdateCenterMatrixFactoryTest.java | 47 +++ .../sonar/server/plugins/UpdateCenterServlet.java | 43 +++ .../plugins/edition/EditionBundledPluginsTest.java | 178 ++++++++++ .../project/ProjectLifeCycleListenersImplTest.java | 311 +++++++++++++++++ .../sonar/server/project/RekeyedProjectTest.java | 102 ++++++ .../QGChangeEventListenersImplTest.java | 358 +++++++++++++++++++ .../qualitygate/changeevent/QGChangeEventTest.java | 133 +++++++ .../ProjectConfigurationLoaderImplTest.java | 178 ++++++++++ .../server/setting/SettingsChangeNotifierTest.java | 50 +++ .../setting/TestProjectConfigurationLoader.java | 45 +++ .../server/util/BooleanTypeValidationTest.java | 57 +++ .../sonar/server/util/FloatTypeValidationTest.java | 56 +++ .../sonar/server/util/GlobalLockManagerTest.java | 76 ++++ .../server/util/IntegerTypeValidationTest.java | 63 ++++ .../sonar/server/util/LongTypeValidationTest.java | 62 ++++ .../server/util/StringListTypeValidationTest.java | 56 +++ .../server/util/StringTypeValidationTest.java | 47 +++ .../sonar/server/util/TextTypeValidationTest.java | 47 +++ .../server/util/TypeValidationModuleTest.java | 34 ++ .../org/sonar/server/util/TypeValidationsTest.java | 72 ++++ .../sonar/server/util/TypeValidationsTesting.java | 40 +++ .../src/test/projects/.gitignore | 7 + .../src/test/projects/README.txt | 3 + .../src/test/projects/fake-report-plugin/pom.xml | 36 ++ .../fake-report-plugin/src/BasePlugin.java | 30 ++ .../org/sonar/plugins/testbase/api/BaseApi.java | 25 ++ .../target/fake-report-plugin-0.1-SNAPSHOT.jar | Bin 0 -> 3411 bytes .../src/test/projects/fake-sqale-plugin/pom.xml | 36 ++ .../projects/fake-sqale-plugin/src/BasePlugin.java | 30 ++ .../org/sonar/plugins/testbase/api/BaseApi.java | 25 ++ .../target/fake-sqale-plugin-0.1-SNAPSHOT.jar | Bin 0 -> 3407 bytes .../src/test/projects/fake-views-plugin/pom.xml | 36 ++ .../projects/fake-views-plugin/src/BasePlugin.java | 30 ++ .../org/sonar/plugins/testbase/api/BaseApi.java | 25 ++ .../target/fake-views-plugin-0.1-SNAPSHOT.jar | Bin 0 -> 3403 bytes .../sonar-webserver-api/src/test/projects/pom.xml | 22 ++ .../src/test/projects/test-base-plugin-v2/pom.xml | 36 ++ .../test-base-plugin-v2/src/BasePlugin.java | 30 ++ .../org/sonar/plugins/testbase/api/BaseApi.java | 25 ++ .../target/test-base-plugin-0.2-SNAPSHOT.jar | Bin 0 -> 3447 bytes .../src/test/projects/test-base-plugin/pom.xml | 36 ++ .../projects/test-base-plugin/src/BasePlugin.java | 30 ++ .../org/sonar/plugins/testbase/api/BaseApi.java | 25 ++ .../target/test-base-plugin-0.1-SNAPSHOT.jar | Bin 0 -> 3447 bytes .../src/test/projects/test-extend-plugin/pom.xml | 37 ++ .../test-extend-plugin/src/ExtendPlugin.java | 30 ++ .../target/test-extend-plugin-0.1-SNAPSHOT.jar | Bin 0 -> 2522 bytes .../src/test/projects/test-libs-plugin/pom.xml | 49 +++ .../projects/test-libs-plugin/src/LibsPlugin.java | 30 ++ .../target/test-libs-plugin-0.1-SNAPSHOT.jar | Bin 0 -> 40139 bytes .../src/test/projects/test-require-plugin/pom.xml | 44 +++ .../test-require-plugin/src/RequirePlugin.java | 35 ++ .../target/test-require-plugin-0.1-SNAPSHOT.jar | Bin 0 -> 2622 bytes .../test/projects/test-requirenew-plugin/pom.xml | 44 +++ .../test-requirenew-plugin/src/RequirePlugin.java | 36 ++ .../target/test-requirenew-plugin-0.1-SNAPSHOT.jar | Bin 0 -> 2689 bytes .../src/test/resources/logback-test.xml | 26 ++ server/sonar-webserver-auth/build.gradle | 2 +- server/sonar-webserver-common/build.gradle | 56 --- .../sonar/server/app/ProcessCommandWrapper.java | 43 --- .../server/app/ProcessCommandWrapperImpl.java | 95 ----- .../org/sonar/server/app/RestartFlagHolder.java | 42 --- .../sonar/server/app/RestartFlagHolderImpl.java | 41 --- .../java/org/sonar/server/app/package-info.java | 24 -- .../org/sonar/server/branch/BranchFeature.java | 26 -- .../server/branch/BranchFeatureExtension.java | 30 -- .../sonar/server/branch/BranchFeatureProxy.java | 29 -- .../server/branch/BranchFeatureProxyImpl.java | 38 -- .../java/org/sonar/server/branch/package-info.java | 23 -- .../org/sonar/server/ce/http/CeHttpClient.java | 30 -- .../org/sonar/server/ce/http/package-info.java | 23 -- .../server/exceptions/BadRequestException.java | 75 ---- .../server/exceptions/ForbiddenException.java | 34 -- .../java/org/sonar/server/exceptions/Message.java | 66 ---- .../sonar/server/exceptions/NotFoundException.java | 65 ---- .../sonar/server/exceptions/ServerException.java | 35 -- .../server/exceptions/UnauthorizedException.java | 32 -- .../org/sonar/server/exceptions/package-info.java | 24 -- .../org/sonar/server/health/ClusterHealth.java | 78 ----- .../main/java/org/sonar/server/health/Health.java | 136 -------- .../org/sonar/server/health/HealthChecker.java | 35 -- .../java/org/sonar/server/health/package-info.java | 23 -- .../org/sonar/server/platform/ClusterFeature.java | 31 -- .../java/org/sonar/server/platform/Platform.java | 34 -- .../sonar/server/platform/SystemInfoWriter.java | 26 -- .../org/sonar/server/platform/package-info.java | 23 -- .../org/sonar/server/plugins/InstalledPlugin.java | 81 ----- .../org/sonar/server/plugins/PluginDownloader.java | 165 --------- .../org/sonar/server/plugins/PluginFileSystem.java | 124 ------- .../sonar/server/plugins/PluginUninstaller.java | 90 ----- .../server/plugins/ServerPluginJarExploder.java | 68 ---- .../server/plugins/ServerPluginRepository.java | 372 -------------------- .../sonar/server/plugins/UpdateCenterClient.java | 113 ------ .../server/plugins/UpdateCenterMatrixFactory.java | 55 --- .../plugins/WebServerExtensionInstaller.java | 33 -- .../plugins/edition/EditionBundledPlugins.java | 44 --- .../sonar/server/plugins/edition/package-info.java | 24 -- .../org/sonar/server/plugins/package-info.java | 23 -- .../server/project/ProjectLifeCycleListener.java | 41 --- .../server/project/ProjectLifeCycleListeners.java | 55 --- .../project/ProjectLifeCycleListenersImpl.java | 91 ----- .../org/sonar/server/project/RekeyedProject.java | 68 ---- .../java/org/sonar/server/project/Visibility.java | 72 ---- .../org/sonar/server/project/package-info.java | 23 -- .../server/qualitygate/ProjectsInWarning.java | 44 --- .../qualitygate/changeevent/QGChangeEvent.java | 101 ------ .../changeevent/QGChangeEventListener.java | 66 ---- .../changeevent/QGChangeEventListeners.java | 29 -- .../changeevent/QGChangeEventListenersImpl.java | 180 ---------- .../server/qualitygate/changeevent/Trigger.java | 24 -- .../qualitygate/changeevent/package-info.java | 23 -- .../server/qualityprofile/BulkChangeResult.java | 60 ---- .../sonar/server/qualityprofile/QProfileRules.java | 64 ---- .../server/qualityprofile/RuleActivation.java | 91 ----- .../sonar/server/qualityprofile/package-info.java | 23 -- .../server/setting/ProjectConfigurationLoader.java | 49 --- .../setting/ProjectConfigurationLoaderImpl.java | 73 ---- .../server/setting/SettingsChangeNotifier.java | 46 --- .../org/sonar/server/setting/package-info.java | 23 -- .../org/sonar/server/telemetry/LicenseReader.java | 32 -- .../org/sonar/server/telemetry/package-info.java | 23 -- .../sonar/server/util/BooleanTypeValidation.java | 42 --- .../org/sonar/server/util/FloatTypeValidation.java | 45 --- .../org/sonar/server/util/GlobalLockManager.java | 59 ---- .../sonar/server/util/IntegerTypeValidation.java | 45 --- .../org/sonar/server/util/LongTypeValidation.java | 43 --- .../server/util/MetricLevelTypeValidation.java | 44 --- .../server/util/StringListTypeValidation.java | 41 --- .../sonar/server/util/StringTypeValidation.java | 40 --- .../org/sonar/server/util/TextTypeValidation.java | 40 --- .../java/org/sonar/server/util/TypeValidation.java | 34 -- .../sonar/server/util/TypeValidationModule.java | 39 --- .../org/sonar/server/util/TypeValidations.java | 70 ---- .../java/org/sonar/server/util/Validation.java | 33 -- .../java/org/sonar/server/util/package-info.java | 24 -- .../server/app/ProcessCommandWrapperImplTest.java | 158 --------- .../server/branch/BranchFeatureProxyImplTest.java | 48 --- .../org/sonar/server/branch/BranchFeatureRule.java | 46 --- .../server/exceptions/BadRequestExceptionTest.java | 85 ----- .../org/sonar/server/exceptions/MessageTest.java | 88 ----- .../server/exceptions/ServerExceptionTest.java | 40 --- .../server/health/TestStandaloneHealthChecker.java | 39 --- .../sonar/server/plugins/PluginDownloaderTest.java | 322 ----------------- .../sonar/server/plugins/PluginFileSystemTest.java | 142 -------- .../server/plugins/PluginUninstallerTest.java | 105 ------ .../plugins/ServerPluginJarExploderTest.java | 67 ---- .../server/plugins/ServerPluginRepositoryTest.java | 385 --------------------- .../java/org/sonar/server/plugins/TestPluginA.java | 29 -- .../org/sonar/server/plugins/TestProjectUtils.java | 40 --- .../server/plugins/UpdateCenterClientTest.java | 104 ------ .../plugins/UpdateCenterMatrixFactoryTest.java | 47 --- .../sonar/server/plugins/UpdateCenterServlet.java | 43 --- .../plugins/edition/EditionBundledPluginsTest.java | 178 ---------- .../project/ProjectLifeCycleListenersImplTest.java | 311 ----------------- .../sonar/server/project/RekeyedProjectTest.java | 102 ------ .../QGChangeEventListenersImplTest.java | 358 ------------------- .../qualitygate/changeevent/QGChangeEventTest.java | 133 ------- .../ProjectConfigurationLoaderImplTest.java | 178 ---------- .../server/setting/SettingsChangeNotifierTest.java | 50 --- .../setting/TestProjectConfigurationLoader.java | 45 --- .../server/util/BooleanTypeValidationTest.java | 57 --- .../sonar/server/util/FloatTypeValidationTest.java | 56 --- .../sonar/server/util/GlobalLockManagerTest.java | 76 ---- .../server/util/IntegerTypeValidationTest.java | 63 ---- .../sonar/server/util/LongTypeValidationTest.java | 62 ---- .../server/util/StringListTypeValidationTest.java | 56 --- .../server/util/StringTypeValidationTest.java | 47 --- .../sonar/server/util/TextTypeValidationTest.java | 47 --- .../server/util/TypeValidationModuleTest.java | 34 -- .../org/sonar/server/util/TypeValidationsTest.java | 72 ---- .../sonar/server/util/TypeValidationsTesting.java | 40 --- .../src/test/projects/.gitignore | 7 - .../src/test/projects/README.txt | 3 - .../src/test/projects/fake-report-plugin/pom.xml | 36 -- .../fake-report-plugin/src/BasePlugin.java | 30 -- .../org/sonar/plugins/testbase/api/BaseApi.java | 25 -- .../target/fake-report-plugin-0.1-SNAPSHOT.jar | Bin 3411 -> 0 bytes .../src/test/projects/fake-sqale-plugin/pom.xml | 36 -- .../projects/fake-sqale-plugin/src/BasePlugin.java | 30 -- .../org/sonar/plugins/testbase/api/BaseApi.java | 25 -- .../target/fake-sqale-plugin-0.1-SNAPSHOT.jar | Bin 3407 -> 0 bytes .../src/test/projects/fake-views-plugin/pom.xml | 36 -- .../projects/fake-views-plugin/src/BasePlugin.java | 30 -- .../org/sonar/plugins/testbase/api/BaseApi.java | 25 -- .../target/fake-views-plugin-0.1-SNAPSHOT.jar | Bin 3403 -> 0 bytes .../src/test/projects/pom.xml | 22 -- .../src/test/projects/test-base-plugin-v2/pom.xml | 36 -- .../test-base-plugin-v2/src/BasePlugin.java | 30 -- .../org/sonar/plugins/testbase/api/BaseApi.java | 25 -- .../target/test-base-plugin-0.2-SNAPSHOT.jar | Bin 3447 -> 0 bytes .../src/test/projects/test-base-plugin/pom.xml | 36 -- .../projects/test-base-plugin/src/BasePlugin.java | 30 -- .../org/sonar/plugins/testbase/api/BaseApi.java | 25 -- .../target/test-base-plugin-0.1-SNAPSHOT.jar | Bin 3447 -> 0 bytes .../src/test/projects/test-extend-plugin/pom.xml | 37 -- .../test-extend-plugin/src/ExtendPlugin.java | 30 -- .../target/test-extend-plugin-0.1-SNAPSHOT.jar | Bin 2522 -> 0 bytes .../src/test/projects/test-libs-plugin/pom.xml | 49 --- .../projects/test-libs-plugin/src/LibsPlugin.java | 30 -- .../target/test-libs-plugin-0.1-SNAPSHOT.jar | Bin 40139 -> 0 bytes .../src/test/projects/test-require-plugin/pom.xml | 44 --- .../test-require-plugin/src/RequirePlugin.java | 35 -- .../target/test-require-plugin-0.1-SNAPSHOT.jar | Bin 2622 -> 0 bytes .../test/projects/test-requirenew-plugin/pom.xml | 44 --- .../test-requirenew-plugin/src/RequirePlugin.java | 36 -- .../target/test-requirenew-plugin-0.1-SNAPSHOT.jar | Bin 2689 -> 0 bytes .../src/test/resources/logback-test.xml | 26 -- server/sonar-webserver-core/build.gradle | 4 +- server/sonar-webserver-webapi/build.gradle | 2 +- server/sonar-webserver-ws/build.gradle | 2 +- server/sonar-webserver/build.gradle | 2 +- settings.gradle | 2 +- 304 files changed, 8889 insertions(+), 8887 deletions(-) create mode 100644 server/sonar-webserver-api/build.gradle create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/app/ProcessCommandWrapper.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/app/ProcessCommandWrapperImpl.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/app/RestartFlagHolder.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/app/RestartFlagHolderImpl.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/app/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeature.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureExtension.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureProxy.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureProxyImpl.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/branch/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/ce/http/CeHttpClient.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/ce/http/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/BadRequestException.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/ForbiddenException.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/Message.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/NotFoundException.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/ServerException.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/UnauthorizedException.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/health/ClusterHealth.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/health/Health.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/health/HealthChecker.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/health/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/platform/ClusterFeature.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/platform/Platform.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/platform/SystemInfoWriter.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/platform/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/InstalledPlugin.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginDownloader.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginFileSystem.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginUninstaller.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginJarExploder.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/WebServerExtensionInstaller.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/edition/EditionBundledPlugins.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/edition/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/project/RekeyedProject.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/project/Visibility.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/project/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/ProjectsInWarning.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/Trigger.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/setting/ProjectConfigurationLoader.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/setting/ProjectConfigurationLoaderImpl.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/setting/SettingsChangeNotifier.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/setting/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/telemetry/LicenseReader.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/telemetry/package-info.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/BooleanTypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/FloatTypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/GlobalLockManager.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/IntegerTypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/LongTypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/StringListTypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/StringTypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/TextTypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidationModule.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidations.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/Validation.java create mode 100644 server/sonar-webserver-api/src/main/java/org/sonar/server/util/package-info.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/branch/BranchFeatureProxyImplTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/branch/BranchFeatureRule.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/MessageTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/health/TestStandaloneHealthChecker.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginUninstallerTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginJarExploderTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/TestPluginA.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/TestProjectUtils.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixFactoryTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterServlet.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/edition/EditionBundledPluginsTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/project/RekeyedProjectTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/setting/ProjectConfigurationLoaderImplTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/setting/SettingsChangeNotifierTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/GlobalLockManagerTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/LongTypeValidationTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/StringTypeValidationTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/TextTypeValidationTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationModuleTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationsTest.java create mode 100644 server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationsTesting.java create mode 100644 server/sonar-webserver-api/src/test/projects/.gitignore create mode 100644 server/sonar-webserver-api/src/test/projects/README.txt create mode 100644 server/sonar-webserver-api/src/test/projects/fake-report-plugin/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/fake-report-plugin/src/BasePlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/fake-report-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java create mode 100644 server/sonar-webserver-api/src/test/projects/fake-report-plugin/target/fake-report-plugin-0.1-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/src/BasePlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java create mode 100644 server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/target/fake-sqale-plugin-0.1-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/projects/fake-views-plugin/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/fake-views-plugin/src/BasePlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/fake-views-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java create mode 100644 server/sonar-webserver-api/src/test/projects/fake-views-plugin/target/fake-views-plugin-0.1-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/projects/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/src/BasePlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/src/org/sonar/plugins/testbase/api/BaseApi.java create mode 100644 server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/projects/test-base-plugin/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/test-base-plugin/src/BasePlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/test-base-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java create mode 100644 server/sonar-webserver-api/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/projects/test-extend-plugin/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/test-extend-plugin/src/ExtendPlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/projects/test-libs-plugin/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/test-libs-plugin/src/LibsPlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/projects/test-require-plugin/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/test-require-plugin/src/RequirePlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/pom.xml create mode 100644 server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java create mode 100644 server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar create mode 100644 server/sonar-webserver-api/src/test/resources/logback-test.xml delete mode 100644 server/sonar-webserver-common/build.gradle delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/app/ProcessCommandWrapper.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/app/ProcessCommandWrapperImpl.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/app/RestartFlagHolder.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/app/RestartFlagHolderImpl.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/app/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeature.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureExtension.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureProxy.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureProxyImpl.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/branch/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/ce/http/CeHttpClient.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/ce/http/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/BadRequestException.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/ForbiddenException.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/Message.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/NotFoundException.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/ServerException.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/UnauthorizedException.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/health/ClusterHealth.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/health/Health.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/health/HealthChecker.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/health/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/platform/ClusterFeature.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/platform/Platform.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/platform/SystemInfoWriter.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/platform/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/InstalledPlugin.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginDownloader.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginFileSystem.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginUninstaller.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/ServerPluginJarExploder.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/WebServerExtensionInstaller.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/edition/EditionBundledPlugins.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/edition/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/project/RekeyedProject.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/project/Visibility.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/project/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/ProjectsInWarning.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/Trigger.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/setting/ProjectConfigurationLoader.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/setting/ProjectConfigurationLoaderImpl.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/setting/SettingsChangeNotifier.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/setting/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/telemetry/LicenseReader.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/telemetry/package-info.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/BooleanTypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/FloatTypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/GlobalLockManager.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/IntegerTypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/LongTypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/StringListTypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/StringTypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/TextTypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidationModule.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidations.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/Validation.java delete mode 100644 server/sonar-webserver-common/src/main/java/org/sonar/server/util/package-info.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/branch/BranchFeatureProxyImplTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/branch/BranchFeatureRule.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/MessageTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/health/TestStandaloneHealthChecker.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginUninstallerTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/ServerPluginJarExploderTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/TestPluginA.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/TestProjectUtils.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixFactoryTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterServlet.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/edition/EditionBundledPluginsTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/project/RekeyedProjectTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/setting/ProjectConfigurationLoaderImplTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/setting/SettingsChangeNotifierTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/GlobalLockManagerTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/LongTypeValidationTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/StringTypeValidationTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/TextTypeValidationTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationModuleTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationsTest.java delete mode 100644 server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationsTesting.java delete mode 100644 server/sonar-webserver-common/src/test/projects/.gitignore delete mode 100644 server/sonar-webserver-common/src/test/projects/README.txt delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-report-plugin/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-report-plugin/src/BasePlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-report-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-report-plugin/target/fake-report-plugin-0.1-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/src/BasePlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/target/fake-sqale-plugin-0.1-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-views-plugin/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-views-plugin/src/BasePlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-views-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java delete mode 100644 server/sonar-webserver-common/src/test/projects/fake-views-plugin/target/fake-views-plugin-0.1-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/projects/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/src/BasePlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/src/org/sonar/plugins/testbase/api/BaseApi.java delete mode 100644 server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/projects/test-base-plugin/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/test-base-plugin/src/BasePlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/test-base-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java delete mode 100644 server/sonar-webserver-common/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/projects/test-extend-plugin/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/test-extend-plugin/src/ExtendPlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/projects/test-libs-plugin/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/test-libs-plugin/src/LibsPlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/projects/test-require-plugin/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/test-require-plugin/src/RequirePlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/pom.xml delete mode 100644 server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java delete mode 100644 server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar delete mode 100644 server/sonar-webserver-common/src/test/resources/logback-test.xml diff --git a/server/sonar-webserver-api/build.gradle b/server/sonar-webserver-api/build.gradle new file mode 100644 index 00000000000..9c89a4b7de4 --- /dev/null +++ b/server/sonar-webserver-api/build.gradle @@ -0,0 +1,58 @@ +description = 'SonarQube WebServer internal APIs, used by other Web Server modules or Core Extensions' + +sonarqube { + properties { + property 'sonar.projectName', "${projectTitle} :: WebServer :: API" + } +} + +sourceSets { + test { + resources { + srcDirs += ['src/test/projects'] + } + } +} + +configurations { + tests + + testCompile.extendsFrom tests +} + +dependencies { + // please keep the list grouped by configuration and ordered by name + + compile 'com.google.guava:guava' + compile 'io.jsonwebtoken:jjwt-api' + compile 'io.jsonwebtoken:jjwt-impl' + compile project(':sonar-core') + compile project(':server:sonar-db-dao') + compile project(':server:sonar-process') + compile project(':server:sonar-server-common') + compile project(path: ':sonar-plugin-api', configuration: 'shadow') + compile project(':sonar-plugin-api-impl') + compile 'org.mindrot:jbcrypt' + + compileOnly 'com.google.code.findbugs:jsr305' + compileOnly 'javax.servlet:javax.servlet-api' + + testCompile 'org.assertj:assertj-guava' + testCompile 'com.google.code.findbugs:jsr305' + testCompile 'com.tngtech.java:junit-dataprovider' + testCompile 'javax.servlet:javax.servlet-api' + testCompile 'org.mockito:mockito-core' + testCompile project(':server:sonar-db-testing') + testCompile project(path: ":server:sonar-server-common", configuration: "tests") + testCompile project(path: ":server:sonar-webserver-ws", configuration: "tests") + testCompile project(':sonar-testing-harness') +} + +task testJar(type: Jar) { + classifier = 'tests' + from sourceSets.test.output +} + +artifacts { + tests testJar +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/app/ProcessCommandWrapper.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/ProcessCommandWrapper.java new file mode 100644 index 00000000000..44bdc4377e3 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/ProcessCommandWrapper.java @@ -0,0 +1,43 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.app; + +public interface ProcessCommandWrapper { + /** + * Requests to the main process that SQ be restarted. + */ + void requestSQRestart(); + + /** + * Requests to the main process that the WebServer is stopped. + */ + void requestHardStop(); + + /** + * Notifies any listening process that the WebServer is operational. + */ + void notifyOperational(); + + /** + * Checks whether the Compute Engine is operational. + */ + boolean isCeOperational(); + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/app/ProcessCommandWrapperImpl.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/ProcessCommandWrapperImpl.java new file mode 100644 index 00000000000..12b3f68543c --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/ProcessCommandWrapperImpl.java @@ -0,0 +1,95 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.app; + +import java.io.File; +import org.sonar.api.config.Configuration; +import org.sonar.process.ProcessId; +import org.sonar.process.sharedmemoryfile.DefaultProcessCommands; +import org.sonar.process.sharedmemoryfile.ProcessCommands; + +import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX; +import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; + +public class ProcessCommandWrapperImpl implements ProcessCommandWrapper { + + private static final ProcessMethod SET_OPERATIONAL = processCommands -> { + processCommands.setOperational(); + return null; + }; + private static final ProcessMethod ASK_FOR_RESTART = processCommands -> { + processCommands.askForRestart(); + return null; + }; + private static final ProcessMethod ASK_FOR_HARD_STOP = processCommands -> { + processCommands.askForHardStop(); + return null; + }; + private static final ProcessMethod IS_OPERATIONAL = ProcessCommands::isOperational; + + private final Configuration config; + + public ProcessCommandWrapperImpl(Configuration config) { + this.config = config; + } + + @Override + public void requestSQRestart() { + call(ASK_FOR_RESTART, selfProcessNumber()); + } + + @Override + public void requestHardStop() { + call(ASK_FOR_HARD_STOP, selfProcessNumber()); + } + + @Override + public void notifyOperational() { + call(SET_OPERATIONAL, selfProcessNumber()); + } + + @Override + public boolean isCeOperational() { + return call(IS_OPERATIONAL, ProcessId.COMPUTE_ENGINE.getIpcIndex()); + } + + private int selfProcessNumber() { + return nonNullAsInt(PROPERTY_PROCESS_INDEX); + } + + private T call(ProcessMethod command, int processNumber) { + File shareDir = nonNullValueAsFile(PROPERTY_SHARED_PATH); + try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(shareDir, processNumber)) { + return command.callOn(commands); + } + } + + private interface ProcessMethod { + T callOn(ProcessCommands processCommands); + } + + private int nonNullAsInt(String key) { + return config.getInt(key).orElseThrow(() -> new IllegalArgumentException(String.format("Property %s is not set", key))); + } + + private File nonNullValueAsFile(String key) { + return new File(config.get(key).orElseThrow(() -> new IllegalArgumentException(String.format("Property %s is not set", key)))); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/app/RestartFlagHolder.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/RestartFlagHolder.java new file mode 100644 index 00000000000..dfc6c8c8414 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/RestartFlagHolder.java @@ -0,0 +1,42 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.app; + +/** + * Holds a boolean flag representing the restarting status of the WebServer. + * This boolean is {@code false} by default and can safely be changed concurrently using methods {@link #set()} and + * {@link #unset()}. + */ +public interface RestartFlagHolder { + /** + * @return whether restarting flag has been set or not. + */ + boolean isRestarting(); + + /** + * Sets the restarting flag to {@code true}, no matter it already is or not. + */ + void set(); + + /** + * Sets the restarting flag to {@code false}, no matter it already is or not. + */ + void unset(); +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/app/RestartFlagHolderImpl.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/RestartFlagHolderImpl.java new file mode 100644 index 00000000000..98354a8e77b --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/RestartFlagHolderImpl.java @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.app; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class RestartFlagHolderImpl implements RestartFlagHolder { + private final AtomicBoolean restarting = new AtomicBoolean(false); + + @Override + public boolean isRestarting() { + return restarting.get(); + } + + @Override + public void set() { + restarting.set(true); + } + + @Override + public void unset() { + restarting.set(false); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/app/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/package-info.java new file mode 100644 index 00000000000..7170de2498d --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/app/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.app; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeature.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeature.java new file mode 100644 index 00000000000..7d60949c954 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeature.java @@ -0,0 +1,26 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.branch; + +interface BranchFeature { + + boolean isEnabled(); + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureExtension.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureExtension.java new file mode 100644 index 00000000000..20fc40ff324 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureExtension.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.branch; + +import org.sonar.api.server.ServerSide; + +/** + * The branch plugin needs to implement this in order to know that the branch feature is supported + */ +@ServerSide +public interface BranchFeatureExtension extends BranchFeature { + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureProxy.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureProxy.java new file mode 100644 index 00000000000..8647d7c421f --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureProxy.java @@ -0,0 +1,29 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.branch; + +/** + * The goal of this class is to handle the 2 different use case : + * - The branch plugin exists, the proxy will redirect method calls to the plugin + * - No branch plugin, feature is disabled + */ +public interface BranchFeatureProxy extends BranchFeature { + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureProxyImpl.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureProxyImpl.java new file mode 100644 index 00000000000..634e59721a7 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/BranchFeatureProxyImpl.java @@ -0,0 +1,38 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.branch; + +public class BranchFeatureProxyImpl implements BranchFeatureProxy { + + private final BranchFeatureExtension branchFeatureExtension; + + public BranchFeatureProxyImpl() { + this.branchFeatureExtension = null; + } + + public BranchFeatureProxyImpl(BranchFeatureExtension branchFeatureExtension) { + this.branchFeatureExtension = branchFeatureExtension; + } + + @Override + public boolean isEnabled() { + return branchFeatureExtension != null && branchFeatureExtension.isEnabled(); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/package-info.java new file mode 100644 index 00000000000..cb79dbcf31d --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/branch/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.branch; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/ce/http/CeHttpClient.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/ce/http/CeHttpClient.java new file mode 100644 index 00000000000..f86a08efb62 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/ce/http/CeHttpClient.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.ce.http; + +import java.util.Optional; +import org.sonar.api.utils.log.LoggerLevel; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +public interface CeHttpClient { + Optional retrieveSystemInfo(); + + void changeLogLevel(LoggerLevel level); +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/ce/http/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/ce/http/package-info.java new file mode 100644 index 00000000000..17b36c59125 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/ce/http/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.ce.http; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/BadRequestException.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/BadRequestException.java new file mode 100644 index 00000000000..3113d202d99 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/BadRequestException.java @@ -0,0 +1,75 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import com.google.common.base.MoreObjects; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.lang.String.format; +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.util.Arrays.asList; + +/** + * Request is not valid and can not be processed. + */ +public class BadRequestException extends ServerException { + + private final transient List errors; + + private BadRequestException(List errors) { + super(HTTP_BAD_REQUEST, errors.get(0)); + this.errors = errors; + } + + public static void checkRequest(boolean expression, String message, Object... messageArguments) { + if (!expression) { + throw create(format(message, messageArguments)); + } + } + + public static void checkRequest(boolean expression, List messages) { + if (!expression) { + throw create(messages); + } + } + + public static BadRequestException create(List errorMessages) { + checkArgument(!errorMessages.isEmpty(), "At least one error message is required"); + checkArgument(errorMessages.stream().noneMatch(message -> message == null || message.isEmpty()), "Message cannot be empty"); + return new BadRequestException(errorMessages); + } + + public static BadRequestException create(String... errorMessages) { + return create(asList(errorMessages)); + } + + public List errors() { + return errors; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("errors", errors) + .toString(); + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/ForbiddenException.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/ForbiddenException.java new file mode 100644 index 00000000000..d72eefbd02f --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/ForbiddenException.java @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import com.google.common.base.Preconditions; + +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; + +/** + * Permission denied. User does not have the required permissions. + */ +public class ForbiddenException extends ServerException { + + public ForbiddenException(String message) { + super(HTTP_FORBIDDEN, Preconditions.checkNotNull(message)); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/Message.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/Message.java new file mode 100644 index 00000000000..c069ead73d2 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/Message.java @@ -0,0 +1,66 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import com.google.common.base.Preconditions; + +import static com.google.common.base.Strings.isNullOrEmpty; +import static java.lang.String.format; + +public class Message { + + private final String msg; + + private Message(String format, Object... params) { + Preconditions.checkArgument(!isNullOrEmpty(format), "Message cannot be empty"); + this.msg = format(format, params); + } + + public String getMessage() { + return msg; + } + + public static Message of(String msg, Object... arguments) { + return new Message(msg, arguments); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Message other = (Message) o; + return this.msg.equals(other.msg); + } + + @Override + public int hashCode() { + return msg.hashCode(); + } + + @Override + public String toString() { + return msg; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/NotFoundException.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/NotFoundException.java new file mode 100644 index 00000000000..f21a98b5157 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/NotFoundException.java @@ -0,0 +1,65 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import com.google.common.base.Optional; +import javax.annotation.Nullable; + +import static java.lang.String.format; +import static java.net.HttpURLConnection.HTTP_NOT_FOUND; + +public class NotFoundException extends ServerException { + + public NotFoundException(String message) { + super(HTTP_NOT_FOUND, message); + } + + /** + * @throws NotFoundException if the value if null + * @return the value + */ + public static T checkFound(@Nullable T value, String message, Object... messageArguments) { + if (value == null) { + throw new NotFoundException(format(message, messageArguments)); + } + + return value; + } + + /** + * @throws NotFoundException if the value is not present + * @return the value + */ + public static T checkFoundWithOptional(Optional value, String message, Object... messageArguments) { + if (!value.isPresent()) { + throw new NotFoundException(format(message, messageArguments)); + } + + return value.get(); + } + + public static T checkFoundWithOptional(java.util.Optional value, String message, Object... messageArguments) { + if (!value.isPresent()) { + throw new NotFoundException(format(message, messageArguments)); + } + + return value.get(); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/ServerException.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/ServerException.java new file mode 100644 index 00000000000..491c17ed437 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/ServerException.java @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import static java.util.Objects.requireNonNull; + +public class ServerException extends RuntimeException { + private final int httpCode; + + public ServerException(int httpCode, String message) { + super(requireNonNull(message, "Error message cannot be null")); + this.httpCode = httpCode; + } + + public int httpCode() { + return httpCode; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/UnauthorizedException.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/UnauthorizedException.java new file mode 100644 index 00000000000..0b4af12beee --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/UnauthorizedException.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; + +/** + * User needs to be authenticated. HTTP request is generally redirected to login form. + */ +public class UnauthorizedException extends ServerException { + + public UnauthorizedException(String message) { + super(HTTP_UNAUTHORIZED, message); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/package-info.java new file mode 100644 index 00000000000..c1ac144f25a --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/exceptions/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.exceptions; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/health/ClusterHealth.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/health/ClusterHealth.java new file mode 100644 index 00000000000..23fcfca9f7a --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/health/ClusterHealth.java @@ -0,0 +1,78 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.health; + +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import org.sonar.process.cluster.health.NodeHealth; + +import static com.google.common.collect.ImmutableSet.copyOf; +import static java.util.Objects.requireNonNull; + +public class ClusterHealth { + private final Health health; + private final Set nodes; + + public ClusterHealth(Health health, Set nodes) { + this.health = requireNonNull(health, "health can't be null"); + this.nodes = copyOf(requireNonNull(nodes, "nodes can't be null")); + } + + public Health getHealth() { + return health; + } + + public Set getNodes() { + return nodes; + } + + public Optional getNodeHealth(String nodeName) { + return nodes.stream() + .filter(node -> nodeName.equals(node.getDetails().getName())) + .findFirst(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ClusterHealth that = (ClusterHealth) o; + return Objects.equals(health, that.health) && + Objects.equals(nodes, that.nodes); + } + + @Override + public int hashCode() { + return Objects.hash(health, nodes); + } + + @Override + public String toString() { + return "ClusterHealth{" + + "health=" + health + + ", nodes=" + nodes + + '}'; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/health/Health.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/health/Health.java new file mode 100644 index 00000000000..d5b49449bbe --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/health/Health.java @@ -0,0 +1,136 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.health; + +import com.google.common.collect.ImmutableSet; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + +public class Health { + /** + * The GREEN status without any cause as a constant, for convenience and optimisation. + */ + public static final Health GREEN = newHealthCheckBuilder() + .setStatus(Status.GREEN) + .build(); + + private final Status status; + private final Set causes; + + public Health(Builder builder) { + this.status = builder.status; + this.causes = ImmutableSet.copyOf(builder.causes); + } + + public Status getStatus() { + return status; + } + + public Set getCauses() { + return causes; + } + + public static Builder newHealthCheckBuilder() { + return new Builder(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Health health = (Health) o; + return status == health.status && + Objects.equals(causes, health.causes); + } + + @Override + public int hashCode() { + return Objects.hash(status, causes); + } + + @Override + public String toString() { + return "Health{" + status + + ", causes=" + causes + + '}'; + } + + /** + * Builder of {@link Health} which supports being reused for optimization. + */ + public static class Builder { + private Status status; + private Set causes = new HashSet<>(0); + + private Builder() { + // use static factory method + } + + public Builder clear() { + this.status = null; + this.causes.clear(); + return this; + } + + public Builder setStatus(Status status) { + this.status = checkStatus(status); + return this; + } + + public Builder addCause(String cause) { + requireNonNull(cause, "cause can't be null"); + checkArgument(!cause.trim().isEmpty(), "cause can't be empty"); + causes.add(cause); + return this; + } + + public Health build() { + checkStatus(this.status); + return new Health(this); + } + + private static Status checkStatus(Status status) { + return requireNonNull(status, "status can't be null"); + } + } + + public enum Status { + /** + * Fully working + */ + GREEN, + /** + * Yellow: Working but something must be fixed to make SQ fully operational + */ + YELLOW, + /** + * Red: Not working + */ + RED + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/health/HealthChecker.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/health/HealthChecker.java new file mode 100644 index 00000000000..80fb8aed1bf --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/health/HealthChecker.java @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.health; + +public interface HealthChecker { + /** + * Perform a check of the health of the current SonarQube node, either as a standalone node or as a member + * of a cluster. + */ + Health checkNode(); + + /** + * Perform a check of the health of the SonarQube cluster. + * + * @throws IllegalStateException if clustering is not enabled. + */ + ClusterHealth checkCluster(); +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/health/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/health/package-info.java new file mode 100644 index 00000000000..18ea762c56b --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/health/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.health; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/ClusterFeature.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/ClusterFeature.java new file mode 100644 index 00000000000..24d8617a4e1 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/ClusterFeature.java @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform; + +import org.sonar.api.ExtensionPoint; +import org.sonar.api.server.ServerSide; + +@ServerSide +@ExtensionPoint +public interface ClusterFeature { + + boolean isEnabled(); + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/Platform.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/Platform.java new file mode 100644 index 00000000000..22f3e451a97 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/Platform.java @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform; + +import org.sonar.core.platform.ComponentContainer; + +public interface Platform { + void doStart(); + + Status status(); + + ComponentContainer getContainer(); + + enum Status { + BOOTING, SAFEMODE, STARTING, UP + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/SystemInfoWriter.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/SystemInfoWriter.java new file mode 100644 index 00000000000..3a82f471f6a --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/SystemInfoWriter.java @@ -0,0 +1,26 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform; + +import org.sonar.api.utils.text.JsonWriter; + +public interface SystemInfoWriter { + void write(JsonWriter json) throws Exception; +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/package-info.java new file mode 100644 index 00000000000..71d187381a7 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/platform/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.platform; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/InstalledPlugin.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/InstalledPlugin.java new file mode 100644 index 00000000000..0fffb7b7d78 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/InstalledPlugin.java @@ -0,0 +1,81 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.FileUtils; +import org.sonar.core.platform.PluginInfo; + +import static java.util.Objects.requireNonNull; + +@Immutable +public class InstalledPlugin { + private final PluginInfo plugin; + private final FileAndMd5 loadedJar; + @Nullable + private final FileAndMd5 compressedJar; + + public InstalledPlugin(PluginInfo plugin, FileAndMd5 loadedJar, @Nullable FileAndMd5 compressedJar) { + this.plugin = requireNonNull(plugin); + this.loadedJar = requireNonNull(loadedJar); + this.compressedJar = compressedJar; + } + + public PluginInfo getPluginInfo() { + return plugin; + } + + public FileAndMd5 getLoadedJar() { + return loadedJar; + } + + @Nullable + public FileAndMd5 getCompressedJar() { + return compressedJar; + } + + @Immutable + public static final class FileAndMd5 { + private final File file; + private final String md5; + + public FileAndMd5(File file) { + try (InputStream fis = FileUtils.openInputStream(file)) { + this.file = file; + this.md5 = DigestUtils.md5Hex(fis); + } catch (IOException e) { + throw new IllegalStateException("Fail to compute md5 of " + file, e); + } + } + + public File getFile() { + return file; + } + + public String getMd5() { + return md5; + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginDownloader.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginDownloader.java new file mode 100644 index 00000000000..d61efac304c --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginDownloader.java @@ -0,0 +1,165 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import com.google.common.base.Optional; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.commons.io.FileUtils; +import org.picocontainer.Startable; +import org.sonar.api.utils.HttpDownloader; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.util.stream.MoreCollectors; +import org.sonar.server.platform.ServerFileSystem; +import org.sonar.updatecenter.common.Release; +import org.sonar.updatecenter.common.UpdateCenter; +import org.sonar.updatecenter.common.Version; + +import static org.apache.commons.io.FileUtils.copyFile; +import static org.apache.commons.io.FileUtils.copyFileToDirectory; +import static org.apache.commons.io.FileUtils.forceMkdir; +import static org.apache.commons.io.FileUtils.toFile; +import static org.apache.commons.lang.StringUtils.substringAfterLast; +import static org.sonar.core.util.FileUtils.deleteQuietly; +import static org.sonar.server.exceptions.BadRequestException.checkRequest; + +/** + * Downloads plugins from update center. Files are copied in the directory extensions/downloads and then + * moved to extensions/plugins after server restart. + */ +public class PluginDownloader implements Startable { + + private static final Logger LOG = Loggers.get(PluginDownloader.class); + private static final String TMP_SUFFIX = "tmp"; + private static final String PLUGIN_EXTENSION = "jar"; + + private final UpdateCenterMatrixFactory updateCenterMatrixFactory; + private final HttpDownloader downloader; + private final File downloadDir; + + public PluginDownloader(UpdateCenterMatrixFactory updateCenterMatrixFactory, HttpDownloader downloader, + ServerFileSystem fileSystem) { + this.updateCenterMatrixFactory = updateCenterMatrixFactory; + this.downloader = downloader; + this.downloadDir = fileSystem.getDownloadedPluginsDir(); + } + + /** + * Deletes the temporary files remaining from previous downloads + */ + @Override + public void start() { + try { + forceMkdir(downloadDir); + for (File tempFile : listTempFile(this.downloadDir)) { + deleteQuietly(tempFile); + } + } catch (IOException e) { + throw new IllegalStateException("Fail to create the directory: " + downloadDir, e); + } + } + + @Override + public void stop() { + // Nothing to do + } + + public void cancelDownloads() { + try { + if (downloadDir.exists()) { + org.sonar.core.util.FileUtils.cleanDirectory(downloadDir); + } + } catch (IOException e) { + throw new IllegalStateException("Fail to clean the plugin downloads directory: " + downloadDir, e); + } + } + + public List getDownloadedPluginFilenames() { + List names = new ArrayList<>(); + for (File file : listPlugins(this.downloadDir)) { + names.add(file.getName()); + } + return names; + } + + /** + * @return the list of download plugins as {@link PluginInfo} instances + */ + public Collection getDownloadedPlugins() { + return listPlugins(this.downloadDir) + .stream() + .map(PluginInfo::create) + .collect(MoreCollectors.toList()); + } + + public void download(String pluginKey, Version version) { + Optional updateCenter = updateCenterMatrixFactory.getUpdateCenter(true); + if (updateCenter.isPresent()) { + List installablePlugins = updateCenter.get().findInstallablePlugins(pluginKey, version); + checkRequest(!installablePlugins.isEmpty(), "Error while downloading plugin '%s' with version '%s'. No compatible plugin found.", pluginKey, version.getName()); + for (Release release : installablePlugins) { + try { + downloadRelease(release); + } catch (Exception e) { + String message = String.format("Fail to download the plugin (%s, version %s) from %s (error is : %s)", + release.getArtifact().getKey(), release.getVersion().getName(), release.getDownloadUrl(), e.getMessage()); + LOG.debug(message, e); + throw new IllegalStateException(message, e); + } + } + } + } + + private void downloadRelease(Release release) throws URISyntaxException, IOException { + String url = release.getDownloadUrl(); + + URI uri = new URI(url); + if (url.startsWith("file:")) { + // used for tests + File file = toFile(uri.toURL()); + copyFileToDirectory(file, downloadDir); + } else { + String filename = substringAfterLast(uri.getPath(), "/"); + if (!filename.endsWith("." + PLUGIN_EXTENSION)) { + filename = release.getKey() + "-" + release.getVersion() + "." + PLUGIN_EXTENSION; + } + File targetFile = new File(downloadDir, filename); + File tempFile = new File(downloadDir, filename + "." + TMP_SUFFIX); + downloader.download(uri, tempFile); + copyFile(tempFile, targetFile); + deleteQuietly(tempFile); + } + } + + private static Collection listTempFile(File dir) { + return FileUtils.listFiles(dir, new String[] {TMP_SUFFIX}, false); + } + + private static Collection listPlugins(File dir) { + return FileUtils.listFiles(dir, new String[] {PLUGIN_EXTENSION}, false); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginFileSystem.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginFileSystem.java new file mode 100644 index 00000000000..e65336a7586 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginFileSystem.java @@ -0,0 +1,124 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.jar.JarInputStream; +import java.util.jar.Pack200; +import java.util.zip.GZIPOutputStream; +import org.sonar.api.config.Configuration; +import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.api.utils.log.Profiler; +import org.sonar.core.platform.PluginInfo; +import org.sonar.server.plugins.InstalledPlugin.FileAndMd5; + +import static com.google.common.base.Preconditions.checkState; + +@ServerSide +public class PluginFileSystem { + + public static final String PROPERTY_PLUGIN_COMPRESSION_ENABLE = "sonar.pluginsCompression.enable"; + private static final Logger LOG = Loggers.get(PluginFileSystem.class); + + private final Configuration configuration; + private final Map installedFiles = new HashMap<>(); + + public PluginFileSystem(Configuration configuration) { + this.configuration = configuration; + } + + /** + * @param plugin + * @param loadedJar the JAR loaded by classloaders. It differs from {@code plugin.getJarFile()} + * which is the initial location of JAR as seen by users + */ + public void addInstalledPlugin(PluginInfo plugin, File loadedJar) { + checkState(!installedFiles.containsKey(plugin.getKey()), "Plugin %s is already loaded", plugin.getKey()); + checkState(loadedJar.exists(), "loadedJar does not exist: %s", loadedJar); + + Optional compressed = compressJar(plugin, loadedJar); + InstalledPlugin installedFile = new InstalledPlugin( + plugin, + new FileAndMd5(loadedJar), + compressed.map(FileAndMd5::new).orElse(null)); + installedFiles.put(plugin.getKey(), installedFile); + } + + public Optional getInstalledPlugin(String pluginKey) { + return Optional.ofNullable(installedFiles.get(pluginKey)); + } + + public Collection getInstalledFiles() { + return installedFiles.values(); + } + + private Optional compressJar(PluginInfo plugin, File jar) { + if (!configuration.getBoolean(PROPERTY_PLUGIN_COMPRESSION_ENABLE).orElse(false)) { + return Optional.empty(); + } + + Path targetPack200 = getPack200Path(jar.toPath()); + Path sourcePack200Path = getPack200Path(plugin.getNonNullJarFile().toPath()); + + // check if packed file was deployed alongside the jar. If that's the case, use it instead of generating it (SONAR-10395). + if (sourcePack200Path.toFile().exists()) { + try { + LOG.debug("Found pack200: " + sourcePack200Path); + Files.copy(sourcePack200Path, targetPack200); + } catch (IOException e) { + throw new IllegalStateException("Failed to copy pack200 file from " + sourcePack200Path + " to " + targetPack200, e); + } + } else { + pack200(jar.toPath(), targetPack200, plugin.getKey()); + } + return Optional.of(targetPack200.toFile()); + } + + private static void pack200(Path jarPath, Path toPack200Path, String pluginKey) { + Profiler profiler = Profiler.create(LOG); + profiler.startInfo("Compressing plugin " + pluginKey + " [pack200]"); + + try (JarInputStream in = new JarInputStream(new BufferedInputStream(Files.newInputStream(jarPath))); + OutputStream out = new GZIPOutputStream(new BufferedOutputStream(Files.newOutputStream(toPack200Path)))) { + Pack200.newPacker().pack(in, out); + } catch (IOException e) { + throw new IllegalStateException(String.format("Fail to pack200 plugin [%s] '%s' to '%s'", pluginKey, jarPath, toPack200Path), e); + } + profiler.stopInfo(); + } + + private static Path getPack200Path(Path jar) { + String jarFileName = jar.getFileName().toString(); + String filename = jarFileName.substring(0, jarFileName.length() - 3) + "pack.gz"; + return jar.resolveSibling(filename); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginUninstaller.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginUninstaller.java new file mode 100644 index 00000000000..8253dbaf8c1 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginUninstaller.java @@ -0,0 +1,90 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import org.apache.commons.io.FileUtils; +import org.picocontainer.Startable; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.util.stream.MoreCollectors; +import org.sonar.server.platform.ServerFileSystem; + +import static java.lang.String.format; +import static org.apache.commons.io.FileUtils.forceMkdir; + +public class PluginUninstaller implements Startable { + private static final String PLUGIN_EXTENSION = "jar"; + private final ServerPluginRepository serverPluginRepository; + private final File uninstallDir; + + public PluginUninstaller(ServerPluginRepository serverPluginRepository, ServerFileSystem fs) { + this.serverPluginRepository = serverPluginRepository; + this.uninstallDir = fs.getUninstalledPluginsDir(); + } + + private static Collection listJarFiles(File dir) { + if (dir.exists()) { + return FileUtils.listFiles(dir, new String[] {PLUGIN_EXTENSION}, false); + } + return Collections.emptyList(); + } + + @Override + public void start() { + try { + forceMkdir(uninstallDir); + } catch (IOException e) { + throw new IllegalStateException("Fail to create the directory: " + uninstallDir, e); + } + } + + @Override + public void stop() { + // Nothing to do + } + + public void uninstall(String pluginKey) { + ensurePluginIsInstalled(pluginKey); + serverPluginRepository.uninstall(pluginKey, uninstallDir); + } + + public void cancelUninstalls() { + serverPluginRepository.cancelUninstalls(uninstallDir); + } + + /** + * @return the list of plugins to be uninstalled as {@link PluginInfo} instances + */ + public Collection getUninstalledPlugins() { + return listJarFiles(uninstallDir) + .stream() + .map(PluginInfo::create) + .collect(MoreCollectors.toList()); + } + + private void ensurePluginIsInstalled(String key) { + if (!serverPluginRepository.hasPlugin(key)) { + throw new IllegalArgumentException(format("Plugin [%s] is not installed", key)); + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginJarExploder.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginJarExploder.java new file mode 100644 index 00000000000..1970d4475a5 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginJarExploder.java @@ -0,0 +1,68 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import java.io.File; +import org.apache.commons.io.FileUtils; +import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.ZipUtils; +import org.sonar.core.platform.ExplodedPlugin; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginJarExploder; +import org.sonar.server.platform.ServerFileSystem; + +import static org.apache.commons.io.FileUtils.forceMkdir; + +@ServerSide +public class ServerPluginJarExploder extends PluginJarExploder { + private final ServerFileSystem fs; + private final PluginFileSystem pluginFileSystem; + + public ServerPluginJarExploder(ServerFileSystem fs, PluginFileSystem pluginFileSystem) { + this.fs = fs; + this.pluginFileSystem = pluginFileSystem; + } + + /** + * JAR files of directory extensions/plugins can be moved when server is up and plugins are uninstalled. + * For this reason these files must not be locked by classloaders. They are copied to the directory + * web/deploy/plugins in order to be loaded by {@link org.sonar.core.platform.PluginLoader}. + */ + @Override + public ExplodedPlugin explode(PluginInfo pluginInfo) { + File toDir = new File(fs.getDeployedPluginsDir(), pluginInfo.getKey()); + try { + forceMkdir(toDir); + org.sonar.core.util.FileUtils.cleanDirectory(toDir); + + File jarSource = pluginInfo.getNonNullJarFile(); + File jarTarget = new File(toDir, jarSource.getName()); + + FileUtils.copyFile(jarSource, jarTarget); + ZipUtils.unzip(jarSource, toDir, newLibFilter()); + ExplodedPlugin explodedPlugin = explodeFromUnzippedDir(pluginInfo.getKey(), jarTarget, toDir); + pluginFileSystem.addInstalledPlugin(pluginInfo, jarTarget); + return explodedPlugin; + } catch (Exception e) { + throw new IllegalStateException(String.format( + "Fail to unzip plugin [%s] %s to %s", pluginInfo.getKey(), pluginInfo.getNonNullJarFile().getAbsolutePath(), toDir.getAbsolutePath()), e); + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java new file mode 100644 index 00000000000..ecc3abc2d76 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java @@ -0,0 +1,372 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Ordering; +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.annotation.CheckForNull; +import org.apache.commons.io.FileUtils; +import org.picocontainer.Startable; +import org.sonar.api.Plugin; +import org.sonar.api.SonarRuntime; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginLoader; +import org.sonar.core.platform.PluginRepository; +import org.sonar.server.platform.ServerFileSystem; +import org.sonar.updatecenter.common.Version; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.lang.String.format; +import static org.apache.commons.io.FileUtils.moveFile; +import static org.apache.commons.io.FileUtils.moveFileToDirectory; +import static org.sonar.core.util.FileUtils.deleteQuietly; + +/** + * Entry point to install and load plugins on server startup. It manages + *
    + *
  • installation of new plugins (effective after server startup)
  • + *
  • un-installation of plugins (effective after server startup)
  • + *
  • cancel pending installations/un-installations
  • + *
  • instantiation of plugin entry-points
  • + *
+ */ +public class ServerPluginRepository implements PluginRepository, Startable { + + private static final Logger LOG = Loggers.get(ServerPluginRepository.class); + private static final String[] JAR_FILE_EXTENSIONS = new String[] {"jar"}; + // List of plugins that are silently removed if installed + private static final Set DEFAULT_BLACKLISTED_PLUGINS = ImmutableSet.of("scmactivity", "issuesreport", "genericcoverage"); + // List of plugins that should prevent the server to finish its startup + private static final Set FORBIDDEN_COMPATIBLE_PLUGINS = ImmutableSet.of("sqale", "report", "views"); + private static final Joiner SLASH_JOINER = Joiner.on(" / ").skipNulls(); + private static final String NOT_STARTED_YET = "not started yet"; + + private final SonarRuntime runtime; + private final ServerFileSystem fs; + private final PluginLoader loader; + private final AtomicBoolean started = new AtomicBoolean(false); + private Set blacklistedPluginKeys = DEFAULT_BLACKLISTED_PLUGINS; + + // following fields are available after startup + private final Map pluginInfosByKeys = new HashMap<>(); + private final Map pluginInstancesByKeys = new HashMap<>(); + private final Map keysByClassLoader = new HashMap<>(); + + public ServerPluginRepository(SonarRuntime runtime, ServerFileSystem fs, PluginLoader loader) { + this.runtime = runtime; + this.fs = fs; + this.loader = loader; + } + + @VisibleForTesting + void setBlacklistedPluginKeys(Set keys) { + this.blacklistedPluginKeys = keys; + } + + @Override + public void start() { + loadPreInstalledPlugins(); + moveDownloadedPlugins(); + unloadIncompatiblePlugins(); + logInstalledPlugins(); + loadInstances(); + started.set(true); + } + + @Override + public void stop() { + // close classloaders + loader.unload(pluginInstancesByKeys.values()); + pluginInstancesByKeys.clear(); + pluginInfosByKeys.clear(); + keysByClassLoader.clear(); + started.set(true); + } + + /** + * Return the key of the plugin the extension (in the sense of {@link Plugin.Context#addExtension(Object)} is coming from. + */ + @CheckForNull + public String getPluginKey(Object extension) { + return keysByClassLoader.get(extension.getClass().getClassLoader()); + } + + /** + * Load the plugins that are located in extensions/plugins. Blacklisted plugins are + * deleted. + */ + private void loadPreInstalledPlugins() { + for (File file : listJarFiles(fs.getInstalledPluginsDir())) { + PluginInfo info = PluginInfo.create(file); + registerPluginInfo(info); + } + } + + /** + * Move the plugins recently downloaded to extensions/plugins. + */ + private void moveDownloadedPlugins() { + if (fs.getDownloadedPluginsDir().exists()) { + for (File sourceFile : listJarFiles(fs.getDownloadedPluginsDir())) { + overrideAndRegisterPlugin(sourceFile); + } + } + } + + private void registerPluginInfo(PluginInfo info) { + String pluginKey = info.getKey(); + if (blacklistedPluginKeys.contains(pluginKey)) { + LOG.warn("Plugin {} [{}] is blacklisted and is being uninstalled", info.getName(), pluginKey); + deleteQuietly(info.getNonNullJarFile()); + return; + } + if (FORBIDDEN_COMPATIBLE_PLUGINS.contains(pluginKey)) { + throw MessageException.of(String.format("Plugin '%s' is no longer compatible with this version of SonarQube", pluginKey)); + } + PluginInfo existing = pluginInfosByKeys.put(pluginKey, info); + if (existing != null) { + throw MessageException.of(format("Found two versions of the plugin %s [%s] in the directory extensions/plugins. Please remove one of %s or %s.", + info.getName(), pluginKey, info.getNonNullJarFile().getName(), existing.getNonNullJarFile().getName())); + } + + } + + /** + * Move or copy plugin to directory extensions/plugins. If a version of this plugin + * already exists then it's deleted. + */ + private void overrideAndRegisterPlugin(File sourceFile) { + File destDir = fs.getInstalledPluginsDir(); + File destFile = new File(destDir, sourceFile.getName()); + if (destFile.exists()) { + // plugin with same filename already installed + deleteQuietly(destFile); + } + + try { + moveFile(sourceFile, destFile); + + } catch (IOException e) { + throw new IllegalStateException(format("Fail to move plugin: %s to %s", + sourceFile.getAbsolutePath(), destFile.getAbsolutePath()), e); + } + + PluginInfo info = PluginInfo.create(destFile); + PluginInfo existing = pluginInfosByKeys.put(info.getKey(), info); + if (existing != null) { + if (!existing.getNonNullJarFile().getName().equals(destFile.getName())) { + deleteQuietly(existing.getNonNullJarFile()); + } + LOG.info("Plugin {} [{}] updated to version {}", info.getName(), info.getKey(), info.getVersion()); + } else { + LOG.info("Plugin {} [{}] installed", info.getName(), info.getKey()); + } + } + + /** + * Removes the plugins that are not compatible with current environment. + */ + private void unloadIncompatiblePlugins() { + // loop as long as the previous loop ignored some plugins. That allows to support dependencies + // on many levels, for example D extends C, which extends B, which requires A. If A is not installed, + // then B, C and D must be ignored. That's not possible to achieve this algorithm with a single + // iteration over plugins. + Set removedKeys = new HashSet<>(); + do { + removedKeys.clear(); + for (PluginInfo plugin : pluginInfosByKeys.values()) { + if (!isCompatible(plugin, runtime, pluginInfosByKeys)) { + removedKeys.add(plugin.getKey()); + } + } + for (String removedKey : removedKeys) { + pluginInfosByKeys.remove(removedKey); + } + } while (!removedKeys.isEmpty()); + } + + @VisibleForTesting + static boolean isCompatible(PluginInfo plugin, SonarRuntime runtime, Map allPluginsByKeys) { + if (Strings.isNullOrEmpty(plugin.getMainClass()) && Strings.isNullOrEmpty(plugin.getBasePlugin())) { + LOG.warn("Plugin {} [{}] is ignored because entry point class is not defined", plugin.getName(), plugin.getKey()); + return false; + } + + if (!plugin.isCompatibleWith(runtime.getApiVersion().toString())) { + throw MessageException.of(format( + "Plugin %s [%s] requires at least SonarQube %s", plugin.getName(), plugin.getKey(), plugin.getMinimalSqVersion())); + } + + if (!Strings.isNullOrEmpty(plugin.getBasePlugin()) && !allPluginsByKeys.containsKey(plugin.getBasePlugin())) { + // it extends a plugin that is not installed + LOG.warn("Plugin {} [{}] is ignored because its base plugin [{}] is not installed", plugin.getName(), plugin.getKey(), plugin.getBasePlugin()); + return false; + } + + for (PluginInfo.RequiredPlugin requiredPlugin : plugin.getRequiredPlugins()) { + PluginInfo installedRequirement = allPluginsByKeys.get(requiredPlugin.getKey()); + if (installedRequirement == null) { + // it requires a plugin that is not installed + LOG.warn("Plugin {} [{}] is ignored because the required plugin [{}] is not installed", plugin.getName(), plugin.getKey(), requiredPlugin.getKey()); + return false; + } + Version installedRequirementVersion = installedRequirement.getVersion(); + if (installedRequirementVersion != null && requiredPlugin.getMinimalVersion().compareToIgnoreQualifier(installedRequirementVersion) > 0) { + // it requires a more recent version + LOG.warn("Plugin {} [{}] is ignored because the version {} of required plugin [{}] is not supported", plugin.getName(), plugin.getKey(), + requiredPlugin.getKey(), requiredPlugin.getMinimalVersion()); + return false; + } + } + return true; + } + + private void logInstalledPlugins() { + List orderedPlugins = Ordering.natural().sortedCopy(pluginInfosByKeys.values()); + for (PluginInfo plugin : orderedPlugins) { + LOG.info("Deploy plugin {}", SLASH_JOINER.join(plugin.getName(), plugin.getVersion(), plugin.getImplementationBuild())); + } + } + + private void loadInstances() { + pluginInstancesByKeys.putAll(loader.load(pluginInfosByKeys)); + + for (Map.Entry e : pluginInstancesByKeys.entrySet()) { + keysByClassLoader.put(e.getValue().getClass().getClassLoader(), e.getKey()); + } + } + + /** + * Uninstall a plugin and its dependents + */ + public void uninstall(String pluginKey, File uninstallDir) { + Set uninstallKeys = new HashSet<>(); + uninstallKeys.add(pluginKey); + appendDependentPluginKeys(pluginKey, uninstallKeys); + + for (String uninstallKey : uninstallKeys) { + PluginInfo info = getPluginInfo(uninstallKey); + + try { + if (!getPluginFile(info).exists()) { + LOG.info("Plugin already uninstalled: {} [{}]", info.getName(), info.getKey()); + continue; + } + + LOG.info("Uninstalling plugin {} [{}]", info.getName(), info.getKey()); + + File masterFile = getPluginFile(info); + moveFileToDirectory(masterFile, uninstallDir, true); + } catch (IOException e) { + throw new IllegalStateException(format("Fail to uninstall plugin %s [%s]", info.getName(), info.getKey()), e); + } + } + } + + public void cancelUninstalls(File uninstallDir) { + for (File file : listJarFiles(uninstallDir)) { + try { + moveFileToDirectory(file, fs.getInstalledPluginsDir(), false); + } catch (IOException e) { + throw new IllegalStateException("Fail to cancel plugin uninstalls", e); + } + } + } + + /** + * Appends dependent plugins, only the ones that still exist in the plugins folder. + */ + private void appendDependentPluginKeys(String pluginKey, Set appendTo) { + for (PluginInfo otherPlugin : getPluginInfos()) { + if (!otherPlugin.getKey().equals(pluginKey)) { + for (PluginInfo.RequiredPlugin requirement : otherPlugin.getRequiredPlugins()) { + if (requirement.getKey().equals(pluginKey)) { + appendTo.add(otherPlugin.getKey()); + appendDependentPluginKeys(otherPlugin.getKey(), appendTo); + } + } + } + } + } + + private File getPluginFile(PluginInfo info) { + // we don't reuse info.getFile() just to be sure that file is located in from extensions/plugins + return new File(fs.getInstalledPluginsDir(), info.getNonNullJarFile().getName()); + } + + public Map getPluginInfosByKeys() { + return pluginInfosByKeys; + } + + @Override + public Collection getPluginInfos() { + checkState(started.get(), NOT_STARTED_YET); + return ImmutableList.copyOf(pluginInfosByKeys.values()); + } + + @Override + public PluginInfo getPluginInfo(String key) { + checkState(started.get(), NOT_STARTED_YET); + PluginInfo info = pluginInfosByKeys.get(key); + if (info == null) { + throw new IllegalArgumentException(format("Plugin [%s] does not exist", key)); + } + return info; + } + + @Override + public Plugin getPluginInstance(String key) { + checkState(started.get(), NOT_STARTED_YET); + Plugin plugin = pluginInstancesByKeys.get(key); + checkArgument(plugin != null, "Plugin [%s] does not exist", key); + return plugin; + } + + @Override + public boolean hasPlugin(String key) { + checkState(started.get(), NOT_STARTED_YET); + return pluginInfosByKeys.containsKey(key); + } + + private static Collection listJarFiles(File dir) { + if (dir.exists()) { + return FileUtils.listFiles(dir, JAR_FILE_EXTENSIONS, false); + } + return Collections.emptyList(); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java new file mode 100644 index 00000000000..2f5d0b2d357 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java @@ -0,0 +1,113 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import com.google.common.base.Optional; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import org.apache.commons.io.IOUtils; +import org.sonar.api.Properties; +import org.sonar.api.Property; +import org.sonar.api.config.Configuration; +import org.sonar.api.utils.UriReader; +import org.sonar.api.utils.log.Loggers; +import org.sonar.process.ProcessProperties; +import org.sonar.updatecenter.common.UpdateCenter; +import org.sonar.updatecenter.common.UpdateCenterDeserializer; +import org.sonar.updatecenter.common.UpdateCenterDeserializer.Mode; + +/** + * HTTP client to load data from the remote update center hosted at https://update.sonarsource.org. + * + * @since 2.4 + */ +@Properties({ + @Property( + key = UpdateCenterClient.URL_PROPERTY, + defaultValue = "https://update.sonarsource.org/update-center.properties", + name = "Update Center URL", + category = "Update Center", + project = false, + // hidden from UI + global = false) +}) +public class UpdateCenterClient { + + public static final String URL_PROPERTY = "sonar.updatecenter.url"; + public static final int PERIOD_IN_MILLISECONDS = 60 * 60 * 1000; + + private final URI uri; + private final UriReader uriReader; + private final boolean isActivated; + private UpdateCenter pluginCenter = null; + private long lastRefreshDate = 0; + + public UpdateCenterClient(UriReader uriReader, Configuration config) throws URISyntaxException { + this.uriReader = uriReader; + this.uri = new URI(config.get(URL_PROPERTY).get()); + this.isActivated = config.getBoolean(ProcessProperties.Property.SONAR_UPDATECENTER_ACTIVATE.getKey()).get(); + Loggers.get(getClass()).info("Update center: " + uriReader.description(uri)); + } + + public Optional getUpdateCenter() { + return getUpdateCenter(false); + } + + public Optional getUpdateCenter(boolean forceRefresh) { + if (!isActivated) { + return Optional.absent(); + } + + if (pluginCenter == null || forceRefresh || needsRefresh()) { + pluginCenter = init(); + lastRefreshDate = System.currentTimeMillis(); + } + return Optional.fromNullable(pluginCenter); + } + + public Date getLastRefreshDate() { + return lastRefreshDate > 0 ? new Date(lastRefreshDate) : null; + } + + private boolean needsRefresh() { + return lastRefreshDate + PERIOD_IN_MILLISECONDS < System.currentTimeMillis(); + } + + private UpdateCenter init() { + InputStream input = null; + try { + String content = uriReader.readString(uri, StandardCharsets.UTF_8); + java.util.Properties properties = new java.util.Properties(); + input = IOUtils.toInputStream(content, StandardCharsets.UTF_8); + properties.load(input); + return new UpdateCenterDeserializer(Mode.PROD, true).fromProperties(properties); + + } catch (Exception e) { + Loggers.get(getClass()).error("Fail to connect to update center", e); + return null; + + } finally { + IOUtils.closeQuietly(input); + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java new file mode 100644 index 00000000000..0c0a6730987 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java @@ -0,0 +1,55 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import com.google.common.base.Optional; +import org.sonar.api.SonarRuntime; +import org.sonar.updatecenter.common.UpdateCenter; +import org.sonar.updatecenter.common.Version; + +/** + * @since 2.4 + */ +public class UpdateCenterMatrixFactory { + + private final UpdateCenterClient centerClient; + private final SonarRuntime sonarRuntime; + private final InstalledPluginReferentialFactory installedPluginReferentialFactory; + + public UpdateCenterMatrixFactory(UpdateCenterClient centerClient, SonarRuntime runtime, + InstalledPluginReferentialFactory installedPluginReferentialFactory) { + this.centerClient = centerClient; + this.sonarRuntime = runtime; + this.installedPluginReferentialFactory = installedPluginReferentialFactory; + } + + public Optional getUpdateCenter(boolean refreshUpdateCenter) { + Optional updateCenter = centerClient.getUpdateCenter(refreshUpdateCenter); + if (updateCenter.isPresent()) { + org.sonar.api.utils.Version fullVersion = sonarRuntime.getApiVersion(); + org.sonar.api.utils.Version semanticVersion = org.sonar.api.utils.Version.create(fullVersion.major(), fullVersion.minor(), fullVersion.patch()); + + return Optional.of(updateCenter.get().setInstalledSonarVersion(Version.create(semanticVersion.toString())).registerInstalledPlugins( + installedPluginReferentialFactory.getInstalledPluginReferential()) + .setDate(centerClient.getLastRefreshDate())); + } + return Optional.absent(); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/WebServerExtensionInstaller.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/WebServerExtensionInstaller.java new file mode 100644 index 00000000000..9fa956d2a15 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/WebServerExtensionInstaller.java @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import org.sonar.api.SonarRuntime; +import org.sonar.api.server.ServerSide; +import org.sonar.core.platform.PluginRepository; + +import static java.util.Collections.singleton; + +@ServerSide +public class WebServerExtensionInstaller extends ServerExtensionInstaller { + public WebServerExtensionInstaller(SonarRuntime sonarRuntime, PluginRepository pluginRepository) { + super(sonarRuntime, pluginRepository, singleton(ServerSide.class)); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/edition/EditionBundledPlugins.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/edition/EditionBundledPlugins.java new file mode 100644 index 00000000000..f6c1db3b035 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/edition/EditionBundledPlugins.java @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins.edition; + +import java.util.Arrays; +import org.sonar.core.platform.PluginInfo; +import org.sonar.updatecenter.common.Plugin; + +public final class EditionBundledPlugins { + + private static final String SONARSOURCE_ORGANIZATION = "SonarSource"; + private static final String[] SONARSOURCE_COMMERCIAL_LICENSES = {"SonarSource", "Commercial"}; + + private EditionBundledPlugins() { + // prevents instantiation + } + + public static boolean isEditionBundled(Plugin plugin) { + return SONARSOURCE_ORGANIZATION.equalsIgnoreCase(plugin.getOrganization()) + && Arrays.stream(SONARSOURCE_COMMERCIAL_LICENSES).anyMatch(s -> s.equalsIgnoreCase(plugin.getLicense())); + } + + public static boolean isEditionBundled(PluginInfo pluginInfo) { + return SONARSOURCE_ORGANIZATION.equalsIgnoreCase(pluginInfo.getOrganizationName()) + && Arrays.stream(SONARSOURCE_COMMERCIAL_LICENSES).anyMatch(s -> s.equalsIgnoreCase(pluginInfo.getLicense())); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/edition/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/edition/package-info.java new file mode 100644 index 00000000000..e0a7b00bbf9 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/edition/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.plugins.edition; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/package-info.java new file mode 100644 index 00000000000..cc398bb88c6 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.plugins; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java new file mode 100644 index 00000000000..6afdea527e9 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.project; + +import java.util.Set; +import org.sonar.api.server.ServerSide; + +@ServerSide +public interface ProjectLifeCycleListener { + /** + * This method is called after the specified projects have been deleted. + */ + void onProjectsDeleted(Set projects); + + /** + * This method is called after the specified projects have been deleted. + */ + void onProjectBranchesDeleted(Set projects); + + /** + * This method is called after the specified projects' keys have been modified. + */ + void onProjectsRekeyed(Set rekeyedProjects); +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java new file mode 100644 index 00000000000..7f3d3f1867d --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java @@ -0,0 +1,55 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.project; + +import java.util.Set; + +public interface ProjectLifeCycleListeners { + /** + * This method is called after the specified projects have been deleted and will call method + * {@link ProjectLifeCycleListener#onProjectsDeleted(Set) onProjectsDeleted(Set)} of all known + * {@link ProjectLifeCycleListener} implementations. + *

+ * This method ensures all {@link ProjectLifeCycleListener} implementations are called, even if one or more of + * them fail with an exception. + */ + void onProjectsDeleted(Set projects); + + /** + * This method is called after the specified project branches have been deleted and will call method + * {@link ProjectLifeCycleListener#onProjectBranchesDeleted(Set)} of all known + * {@link ProjectLifeCycleListener} implementations. + *

+ * This method ensures all {@link ProjectLifeCycleListener} implementations are called, even if one or more of + * them fail with an exception. + */ + void onProjectBranchesDeleted(Set projects); + + /** + * This method is called after the specified project's key has been changed and will call method + * {@link ProjectLifeCycleListener#onProjectsRekeyed(Set) onProjectsRekeyed(Set)} of all known + * {@link ProjectLifeCycleListener} implementations. + *

+ * This method ensures all {@link ProjectLifeCycleListener} implementations are called, even if one or more of + * them fail with an exception. + */ + void onProjectsRekeyed(Set rekeyedProjects); + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java new file mode 100644 index 00000000000..af440d60adb --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java @@ -0,0 +1,91 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.project; + +import java.util.Arrays; +import java.util.Set; +import java.util.function.Consumer; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class ProjectLifeCycleListenersImpl implements ProjectLifeCycleListeners { + private static final Logger LOG = Loggers.get(ProjectLifeCycleListenersImpl.class); + + private final ProjectLifeCycleListener[] listeners; + + /** + * Used by Pico when there is no ProjectLifeCycleListener implementation in container. + */ + public ProjectLifeCycleListenersImpl() { + this.listeners = new ProjectLifeCycleListener[0]; + } + + /** + * Used by Pico when there is at least one ProjectLifeCycleListener implementation in container. + */ + public ProjectLifeCycleListenersImpl(ProjectLifeCycleListener[] listeners) { + this.listeners = listeners; + } + + @Override + public void onProjectsDeleted(Set projects) { + checkNotNull(projects, "projects can't be null"); + if (projects.isEmpty()) { + return; + } + + Arrays.stream(listeners) + .forEach(safelyCallListener(listener -> listener.onProjectsDeleted(projects))); + } + + @Override + public void onProjectBranchesDeleted(Set projects) { + checkNotNull(projects, "projects can't be null"); + if (projects.isEmpty()) { + return; + } + + Arrays.stream(listeners) + .forEach(safelyCallListener(listener -> listener.onProjectBranchesDeleted(projects))); + } + + @Override + public void onProjectsRekeyed(Set rekeyedProjects) { + checkNotNull(rekeyedProjects, "rekeyedProjects can't be null"); + if (rekeyedProjects.isEmpty()) { + return; + } + + Arrays.stream(listeners) + .forEach(safelyCallListener(listener -> listener.onProjectsRekeyed(rekeyedProjects))); + } + + private static Consumer safelyCallListener(Consumer task) { + return listener -> { + try { + task.accept(listener); + } catch (Error | Exception e) { + LOG.error("Call on ProjectLifeCycleListener \"{}\" failed", listener.getClass(), e); + } + }; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/project/RekeyedProject.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/RekeyedProject.java new file mode 100644 index 00000000000..ecab0b148f8 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/RekeyedProject.java @@ -0,0 +1,68 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.project; + +import java.util.Objects; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class RekeyedProject { + private final Project project; + private final String previousKey; + + public RekeyedProject(Project project, String previousKey) { + this.project = checkNotNull(project, "project can't be null"); + this.previousKey = checkNotNull(previousKey, "previousKey can't be null"); + } + + public Project getProject() { + return project; + } + + public String getPreviousKey() { + return previousKey; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RekeyedProject that = (RekeyedProject) o; + return Objects.equals(project, that.project) && + Objects.equals(previousKey, that.previousKey); + } + + @Override + public int hashCode() { + return Objects.hash(project, previousKey); + } + + @Override + public String toString() { + return "RekeyedProject{" + + "project=" + project + + ", previousKey='" + previousKey + '\'' + + '}'; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/project/Visibility.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/Visibility.java new file mode 100644 index 00000000000..edf05180276 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/Visibility.java @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.project; + +import java.util.List; + +import static java.util.Arrays.stream; +import static org.sonar.core.util.stream.MoreCollectors.toList; + +public enum Visibility { + + PRIVATE(true, "private"), + PUBLIC(false, "public"); + + private static final List LABELS = stream(values()).map(Visibility::getLabel).collect(toList(values().length)); + + private final boolean isPrivate; + private final String label; + + Visibility(boolean isPrivate, String label) { + this.isPrivate = isPrivate; + this.label = label; + } + + public String getLabel() { + return label; + } + + boolean isPrivate() { + return isPrivate; + } + + public static String getLabel(boolean isPrivate) { + return stream(values()) + .filter(v -> v.isPrivate == isPrivate) + .map(Visibility::getLabel) + .findAny() + .orElseThrow(() -> new IllegalStateException("Invalid visibility boolean '" + isPrivate + "'")); + } + + public static boolean isPrivate(String label) { + return parseVisibility(label).isPrivate(); + } + + public static Visibility parseVisibility(String label) { + return stream(values()) + .filter(v -> v.label.equals(label)) + .findAny() + .orElseThrow(() -> new IllegalStateException("Invalid visibility label '" + label + "'")); + } + + public static List getLabels() { + return LABELS; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/project/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/package-info.java new file mode 100644 index 00000000000..205d7058e06 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/project/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.project; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/ProjectsInWarning.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/ProjectsInWarning.java new file mode 100644 index 00000000000..7591c138d28 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/ProjectsInWarning.java @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * Store number of projects in warning in order for the web service api/components/search to know if warning value should be return in the quality gate facet. + * The value is updated each time the daemon {@link ProjectsInWarningDaemon} is executed + */ +public class ProjectsInWarning { + + private Long projectsInWarning; + + public void update(long projectsInWarning) { + this.projectsInWarning = projectsInWarning; + } + + public long count() { + checkArgument(isInitialized(), "Initialization has not be done"); + return projectsInWarning; + } + + boolean isInitialized() { + return projectsInWarning != null; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java new file mode 100644 index 00000000000..6953a77575e --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java @@ -0,0 +1,101 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate.changeevent; + +import java.util.Optional; +import java.util.function.Supplier; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import org.sonar.api.config.Configuration; +import org.sonar.api.measures.Metric; +import org.sonar.db.component.BranchDto; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.SnapshotDto; +import org.sonar.server.qualitygate.EvaluatedQualityGate; + +import static java.util.Objects.requireNonNull; + +@Immutable +public class QGChangeEvent { + private final ComponentDto project; + private final BranchDto branch; + private final SnapshotDto analysis; + private final Configuration projectConfiguration; + private final Metric.Level previousStatus; + private final Supplier> qualityGateSupplier; + + public QGChangeEvent(ComponentDto project, BranchDto branch, SnapshotDto analysis, Configuration projectConfiguration, + @Nullable Metric.Level previousStatus, Supplier> qualityGateSupplier) { + this.project = requireNonNull(project, "project can't be null"); + this.branch = requireNonNull(branch, "branch can't be null"); + this.analysis = requireNonNull(analysis, "analysis can't be null"); + this.projectConfiguration = requireNonNull(projectConfiguration, "projectConfiguration can't be null"); + this.previousStatus = previousStatus; + this.qualityGateSupplier = requireNonNull(qualityGateSupplier, "qualityGateSupplier can't be null"); + } + + public BranchDto getBranch() { + return branch; + } + + public ComponentDto getProject() { + return project; + } + + public SnapshotDto getAnalysis() { + return analysis; + } + + public Configuration getProjectConfiguration() { + return projectConfiguration; + } + + public Optional getPreviousStatus() { + return Optional.ofNullable(previousStatus); + } + + public Supplier> getQualityGateSupplier() { + return qualityGateSupplier; + } + + @Override + public String toString() { + return "QGChangeEvent{" + + "project=" + toString(project) + + ", branch=" + toString(branch) + + ", analysis=" + toString(analysis) + + ", projectConfiguration=" + projectConfiguration + + ", previousStatus=" + previousStatus + + ", qualityGateSupplier=" + qualityGateSupplier + + '}'; + } + + private static String toString(ComponentDto project) { + return project.uuid() + ":" + project.getKey(); + } + + private static String toString(BranchDto branch) { + return branch.getBranchType() + ":" + branch.getUuid() + ":" + branch.getProjectUuid() + ":" + branch.getMergeBranchUuid(); + } + + private static String toString(SnapshotDto analysis) { + return analysis.getUuid() + ":" + analysis.getCreatedAt(); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java new file mode 100644 index 00000000000..c3baf201471 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java @@ -0,0 +1,66 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate.changeevent; + +import java.util.EnumSet; +import java.util.Set; +import org.sonar.api.rules.RuleType; +import org.sonar.api.server.ServerSide; + +@ServerSide +public interface QGChangeEventListener { + /** + * Called consequently to a change done on one or more issue of a given project. + * + * @param qualityGateEvent can not be {@code null} + * @param changedIssues can not be {@code null} nor empty + */ + void onIssueChanges(QGChangeEvent qualityGateEvent, Set changedIssues); + + interface ChangedIssue { + + String getKey(); + + Status getStatus(); + + RuleType getType(); + + String getSeverity(); + + default boolean isNotClosed() { + return !Status.CLOSED_STATUSES.contains(getStatus()); + } + } + + enum Status { + OPEN, + CONFIRMED, + REOPENED, + RESOLVED_FP, + RESOLVED_WF, + RESOLVED_FIXED, + TO_REVIEW, + IN_REVIEW, + REVIEWED; + + protected static final Set CLOSED_STATUSES = EnumSet.of(CONFIRMED, RESOLVED_FIXED, RESOLVED_FP, RESOLVED_WF); + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java new file mode 100644 index 00000000000..e2e66b555de --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java @@ -0,0 +1,29 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate.changeevent; + +import java.util.Collection; +import java.util.List; +import org.sonar.core.issue.DefaultIssue; + +public interface QGChangeEventListeners { + + void broadcastOnIssueChange(List changedIssues, Collection qgChangeEvents); +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java new file mode 100644 index 00000000000..76a4c2bebf1 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java @@ -0,0 +1,180 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate.changeevent; + +import com.google.common.collect.Multimap; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import org.sonar.api.issue.Issue; +import org.sonar.api.rules.RuleType; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.util.stream.MoreCollectors; +import org.sonar.server.qualitygate.changeevent.QGChangeEventListener.ChangedIssue; + +import static java.lang.String.format; +import static org.sonar.core.util.stream.MoreCollectors.toSet; + +/** + * Broadcast a given collection of {@link QGChangeEvent} for a specific trigger to all the registered + * {@link QGChangeEventListener} in Pico. + * + * This class ensures that an {@link Exception} occurring calling one of the {@link QGChangeEventListener} doesn't + * prevent from calling the others. + */ +public class QGChangeEventListenersImpl implements QGChangeEventListeners { + private static final Logger LOG = Loggers.get(QGChangeEventListenersImpl.class); + + private final QGChangeEventListener[] listeners; + + /** + * Used by Pico when there is no QGChangeEventListener instance in container. + */ + public QGChangeEventListenersImpl() { + this.listeners = new QGChangeEventListener[0]; + } + + public QGChangeEventListenersImpl(QGChangeEventListener[] listeners) { + this.listeners = listeners; + } + + @Override + public void broadcastOnIssueChange(List issues, Collection changeEvents) { + if (listeners.length == 0 || issues.isEmpty() || changeEvents.isEmpty()) { + return; + } + + try { + Multimap eventsByComponentUuid = changeEvents.stream() + .collect(MoreCollectors.index(t -> t.getProject().uuid())); + Multimap issueByComponentUuid = issues.stream() + .collect(MoreCollectors.index(DefaultIssue::projectUuid)); + + issueByComponentUuid.asMap() + .forEach((componentUuid, value) -> { + Collection qgChangeEvents = eventsByComponentUuid.get(componentUuid); + if (!qgChangeEvents.isEmpty()) { + Set changedIssues = value.stream() + .map(ChangedIssueImpl::new) + .collect(toSet()); + qgChangeEvents + .forEach(changeEvent -> Arrays.stream(listeners) + .forEach(listener -> broadcastTo(changedIssues, changeEvent, listener))); + } + }); + } catch (Error e) { + LOG.warn(format("Broadcasting to listeners failed for %s events", changeEvents.size()), e); + } + } + + private static void broadcastTo(Set changedIssues, QGChangeEvent changeEvent, QGChangeEventListener listener) { + try { + LOG.trace("calling onChange() on listener {} for events {}...", listener.getClass().getName(), changeEvent); + listener.onIssueChanges(changeEvent, changedIssues); + } catch (Exception e) { + LOG.warn(format("onChange() call failed on listener %s for events %s", listener.getClass().getName(), changeEvent), e); + } + } + + static class ChangedIssueImpl implements ChangedIssue { + private final String key; + private final QGChangeEventListener.Status status; + private final RuleType type; + private final String severity; + + ChangedIssueImpl(DefaultIssue issue) { + this.key = issue.key(); + this.status = statusOf(issue); + this.type = issue.type(); + this.severity = issue.severity(); + } + + static QGChangeEventListener.Status statusOf(DefaultIssue issue) { + switch (issue.status()) { + case Issue.STATUS_OPEN: + return QGChangeEventListener.Status.OPEN; + case Issue.STATUS_CONFIRMED: + return QGChangeEventListener.Status.CONFIRMED; + case Issue.STATUS_REOPENED: + return QGChangeEventListener.Status.REOPENED; + case Issue.STATUS_TO_REVIEW: + return QGChangeEventListener.Status.TO_REVIEW; + case Issue.STATUS_IN_REVIEW: + return QGChangeEventListener.Status.IN_REVIEW; + case Issue.STATUS_REVIEWED: + return QGChangeEventListener.Status.REVIEWED; + case Issue.STATUS_RESOLVED: + return statusOfResolved(issue); + default: + throw new IllegalStateException("Unexpected status: " + issue.status()); + } + } + + private static QGChangeEventListener.Status statusOfResolved(DefaultIssue issue) { + String resolution = issue.resolution(); + Objects.requireNonNull(resolution, "A resolved issue should have a resolution"); + switch (resolution) { + case Issue.RESOLUTION_FALSE_POSITIVE: + return QGChangeEventListener.Status.RESOLVED_FP; + case Issue.RESOLUTION_WONT_FIX: + return QGChangeEventListener.Status.RESOLVED_WF; + case Issue.RESOLUTION_FIXED: + return QGChangeEventListener.Status.RESOLVED_FIXED; + default: + throw new IllegalStateException("Unexpected resolution for a resolved issue: " + resolution); + } + } + + @Override + public String getKey() { + return key; + } + + @Override + public QGChangeEventListener.Status getStatus() { + return status; + } + + @Override + public RuleType getType() { + return type; + } + + @Override + public String getSeverity() { + return severity; + } + + @Override + public String toString() { + return "ChangedIssueImpl{" + + "key='" + key + '\'' + + ", status=" + status + + ", type=" + type + + ", severity=" + severity + + '}'; + } + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/Trigger.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/Trigger.java new file mode 100644 index 00000000000..6ef8397046a --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/Trigger.java @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate.changeevent; + +public enum Trigger { + ISSUE_CHANGE +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/package-info.java new file mode 100644 index 00000000000..ed52cd87a47 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.qualitygate.changeevent; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java new file mode 100644 index 00000000000..91a31ca76d9 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java @@ -0,0 +1,60 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualityprofile; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class BulkChangeResult { + + private final List errors = new ArrayList<>(); + private int succeeded = 0; + private int failed = 0; + private final List changes = new ArrayList<>(); + + public List getErrors() { + return errors; + } + + public int countSucceeded() { + return succeeded; + } + + public int countFailed() { + return failed; + } + + void incrementSucceeded() { + succeeded++; + } + + void incrementFailed() { + failed++; + } + + void addChanges(Collection c) { + this.changes.addAll(c); + } + + public List getChanges() { + return changes; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java new file mode 100644 index 00000000000..32a11c072d8 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualityprofile; + +import java.util.Collection; +import java.util.List; +import javax.annotation.Nullable; +import org.sonar.api.server.ServerSide; +import org.sonar.db.DbSession; +import org.sonar.db.qualityprofile.QProfileDto; +import org.sonar.db.rule.RuleDefinitionDto; +import org.sonar.server.rule.index.RuleQuery; + +/** + * Operations related to activation and deactivation of rules on user profiles. + */ +@ServerSide +public interface QProfileRules { + + /** + * Activate multiple rules at once on a Quality profile. + * Db session is committed and Elasticsearch indices are updated. + * If an activation fails to be executed, then all others are + * canceled, db session is not committed and an exception is + * thrown. + */ + List activateAndCommit(DbSession dbSession, QProfileDto profile, Collection activations); + + /** + * Same as {@link #activateAndCommit(DbSession, QProfileDto, Collection)} except + * that: + * - rules are loaded from search engine + * - rules are activated with default parameters + * - an activation failure does not break others. No exception is thrown. + */ + BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity); + + List deactivateAndCommit(DbSession dbSession, QProfileDto profile, Collection ruleIds); + + BulkChangeResult bulkDeactivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery); + + /** + * Delete a rule from all Quality profiles. Db session is not committed. As a + * consequence Elasticsearch indices are NOT updated. + */ + List deleteRule(DbSession dbSession, RuleDefinitionDto rule); +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java new file mode 100644 index 00000000000..106fd158b26 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java @@ -0,0 +1,91 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualityprofile; + +import com.google.common.base.Strings; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import org.sonar.api.rule.Severity; + +/** + * The request for activation. + */ +@Immutable +public class RuleActivation { + + private final int ruleId; + private final boolean reset; + private final String severity; + private final Map parameters = new HashMap<>(); + + private RuleActivation(int ruleId, boolean reset, @Nullable String severity, @Nullable Map parameters) { + this.ruleId = ruleId; + this.reset = reset; + this.severity = severity; + if (severity != null && !Severity.ALL.contains(severity)) { + throw new IllegalArgumentException("Unknown severity: " + severity); + } + if (parameters != null) { + for (Map.Entry entry : parameters.entrySet()) { + this.parameters.put(entry.getKey(), Strings.emptyToNull(entry.getValue())); + } + } + } + + public static RuleActivation createReset(int ruleId) { + return new RuleActivation(ruleId, true, null, null); + } + + public static RuleActivation create(int ruleId, @Nullable String severity, @Nullable Map parameters) { + return new RuleActivation(ruleId, false, severity, parameters); + } + + public static RuleActivation create(int ruleId) { + return create(ruleId, null, null); + } + + /** + * Optional severity. Use the parent severity or default rule severity if null. + */ + @CheckForNull + public String getSeverity() { + return severity; + } + + public int getRuleId() { + return ruleId; + } + + @CheckForNull + public String getParameter(String key) { + return parameters.get(key); + } + + public boolean hasParameter(String key) { + return parameters.containsKey(key); + } + + public boolean isReset() { + return reset; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/package-info.java new file mode 100644 index 00000000000..5a3c798af36 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.qualityprofile; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/ProjectConfigurationLoader.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/ProjectConfigurationLoader.java new file mode 100644 index 00000000000..e261763e6f5 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/ProjectConfigurationLoader.java @@ -0,0 +1,49 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.setting; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import org.sonar.api.config.Configuration; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +public interface ProjectConfigurationLoader { + /** + * Loads configuration for the specified components. + * + *

+ * Returns the applicable component configuration with most specific configuration overriding more global ones + * (eg. global > project > branch). + * + *

+ * Any component is accepted but SQ only supports specific properties for projects and branches. + */ + Map loadProjectConfigurations(DbSession dbSession, Set projects); + + default Configuration loadProjectConfiguration(DbSession dbSession, ComponentDto project) { + Map configurations = loadProjectConfigurations(dbSession, Collections.singleton(project)); + return requireNonNull(configurations.get(project.uuid()), () -> format("Configuration for project '%s' is not found", project.getKey())); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/ProjectConfigurationLoaderImpl.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/ProjectConfigurationLoaderImpl.java new file mode 100644 index 00000000000..95e11242587 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/ProjectConfigurationLoaderImpl.java @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.setting; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.sonar.api.config.Configuration; +import org.sonar.api.config.Settings; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.property.PropertyDto; + +import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; + +public class ProjectConfigurationLoaderImpl implements ProjectConfigurationLoader { + private final Settings globalSettings; + private final DbClient dbClient; + + public ProjectConfigurationLoaderImpl(Settings globalSettings, DbClient dbClient) { + this.globalSettings = globalSettings; + this.dbClient = dbClient; + } + + @Override + public Map loadProjectConfigurations(DbSession dbSession, Set projects) { + Set mainBranchDbKeys = projects.stream().map(ComponentDto::getKey).collect(Collectors.toSet()); + Map mainBranchSettingsByDbKey = loadMainBranchConfigurations(dbSession, mainBranchDbKeys); + return projects.stream() + .collect(uniqueIndex(ComponentDto::uuid, component -> { + if (component.getDbKey().equals(component.getKey())) { + return mainBranchSettingsByDbKey.get(component.getKey()).asConfiguration(); + } + + ChildSettings settings = new ChildSettings(mainBranchSettingsByDbKey.get(component.getKey())); + dbClient.propertiesDao() + .selectProjectProperties(dbSession, component.getDbKey()) + .forEach(property -> settings.setProperty(property.getKey(), property.getValue())); + return settings.asConfiguration(); + })); + } + + private Map loadMainBranchConfigurations(DbSession dbSession, Set dbKeys) { + return dbKeys.stream().collect(uniqueIndex(Function.identity(), dbKey -> { + ChildSettings settings = new ChildSettings(globalSettings); + List propertyDtos = dbClient.propertiesDao() + .selectProjectProperties(dbSession, dbKey); + propertyDtos + .forEach(property -> settings.setProperty(property.getKey(), property.getValue())); + return settings; + })); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/SettingsChangeNotifier.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/SettingsChangeNotifier.java new file mode 100644 index 00000000000..de074ef5232 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/SettingsChangeNotifier.java @@ -0,0 +1,46 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.setting; + +import com.google.common.annotations.VisibleForTesting; +import org.sonar.api.config.GlobalPropertyChangeHandler; + +import javax.annotation.Nullable; + +public class SettingsChangeNotifier { + + @VisibleForTesting + GlobalPropertyChangeHandler[] changeHandlers; + + public SettingsChangeNotifier(GlobalPropertyChangeHandler[] changeHandlers) { + this.changeHandlers = changeHandlers; + } + + public SettingsChangeNotifier() { + this(new GlobalPropertyChangeHandler[0]); + } + + public void onGlobalPropertyChange(String key, @Nullable String value) { + GlobalPropertyChangeHandler.PropertyChange change = GlobalPropertyChangeHandler.PropertyChange.create(key, value); + for (GlobalPropertyChangeHandler changeHandler : changeHandlers) { + changeHandler.onChange(change); + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/package-info.java new file mode 100644 index 00000000000..e816bf4051c --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/setting/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.setting; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/telemetry/LicenseReader.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/telemetry/LicenseReader.java new file mode 100644 index 00000000000..22029d62a36 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/telemetry/LicenseReader.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.telemetry; + +import java.util.Optional; +import org.sonar.api.server.ServerSide; + +@ServerSide +public interface LicenseReader { + Optional read(); + + interface License { + String getType(); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/telemetry/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/telemetry/package-info.java new file mode 100644 index 00000000000..ce3724b93a5 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/telemetry/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.telemetry; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/BooleanTypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/BooleanTypeValidation.java new file mode 100644 index 00000000000..1b3ade32e60 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/BooleanTypeValidation.java @@ -0,0 +1,42 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import java.util.List; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.PropertyType; + +import static org.sonar.server.exceptions.BadRequestException.checkRequest; + +public class BooleanTypeValidation implements TypeValidation { + + @Override + public String key() { + return PropertyType.BOOLEAN.name(); + } + + @Override + public void validate(String value, @Nullable List options) { + checkRequest(StringUtils.equalsIgnoreCase(value, "true") || StringUtils.equalsIgnoreCase(value, "false"), + "Value '%s' must be one of \"true\" or \"false\".", value); + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/FloatTypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/FloatTypeValidation.java new file mode 100644 index 00000000000..fd221dced55 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/FloatTypeValidation.java @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import java.util.List; +import javax.annotation.Nullable; +import org.sonar.api.PropertyType; +import org.sonar.server.exceptions.BadRequestException; + +import static java.lang.String.format; + +public class FloatTypeValidation implements TypeValidation { + + @Override + public String key() { + return PropertyType.FLOAT.name(); + } + + @Override + public void validate(String value, @Nullable List options) { + try { + Double.parseDouble(value); + } catch (NumberFormatException e) { + throw BadRequestException.create(format("Value '%s' must be an floating point number.", value)); + } + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/GlobalLockManager.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/GlobalLockManager.java new file mode 100644 index 00000000000..81f13b22a1d --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/GlobalLockManager.java @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.api.server.ServerSide; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; + +/** + * Provide a simple mechanism to manage global locks across multiple nodes running in a cluster. + * In the target use case multiple nodes try to execute something at around the same time, + * and only the first should succeed, and the rest do nothing. + */ +@ComputeEngineSide +@ServerSide +public class GlobalLockManager { + + static final int DEFAULT_LOCK_DURATION_SECONDS = 180; + + private final DbClient dbClient; + + public GlobalLockManager(DbClient dbClient) { + this.dbClient = dbClient; + } + + /** + * Try to acquire a lock on the given name in the default namespace, + * using the generic locking mechanism of {@see org.sonar.db.property.InternalPropertiesDao}. + */ + public boolean tryLock(String name) { + return tryLock(name, DEFAULT_LOCK_DURATION_SECONDS); + } + + public boolean tryLock(String name, int durationSecond) { + try (DbSession dbSession = dbClient.openSession(false)) { + boolean success = dbClient.internalPropertiesDao().tryLock(dbSession, name, durationSecond); + dbSession.commit(); + return success; + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/IntegerTypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/IntegerTypeValidation.java new file mode 100644 index 00000000000..84502df47f7 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/IntegerTypeValidation.java @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import java.util.List; +import javax.annotation.Nullable; +import org.sonar.api.PropertyType; +import org.sonar.server.exceptions.BadRequestException; + +import static java.lang.String.format; + +public class IntegerTypeValidation implements TypeValidation { + + @Override + public String key() { + return PropertyType.INTEGER.name(); + } + + @Override + public void validate(String value, @Nullable List options) { + try { + Integer.parseInt(value); + } catch (NumberFormatException e) { + throw BadRequestException.create(format("Value '%s' must be an integer.", value)); + } + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/LongTypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/LongTypeValidation.java new file mode 100644 index 00000000000..9ca540a1d1d --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/LongTypeValidation.java @@ -0,0 +1,43 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import java.util.List; +import javax.annotation.Nullable; +import org.sonar.api.PropertyType; +import org.sonar.server.exceptions.BadRequestException; + +import static java.lang.String.format; + +public class LongTypeValidation implements TypeValidation { + @Override + public String key() { + return PropertyType.LONG.name(); + } + + @Override + public void validate(String value, @Nullable List options) { + try { + Long.parseLong(value); + } catch (NumberFormatException e) { + throw BadRequestException.create(format("Value '%s' must be a long.", value)); + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java new file mode 100644 index 00000000000..ba8598a7786 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import java.util.List; +import javax.annotation.Nullable; +import org.sonar.api.PropertyType; +import org.sonar.api.measures.Metric; +import org.sonar.server.exceptions.BadRequestException; + +import static java.lang.String.format; + +public class MetricLevelTypeValidation implements TypeValidation { + @Override + public String key() { + return PropertyType.METRIC_LEVEL.name(); + } + + @Override + public void validate(String value, @Nullable List options) { + try { + Metric.Level.valueOf(value); + } catch (IllegalArgumentException e) { + throw BadRequestException.create(format("Value '%s' must be one of \"OK\", \"ERROR\".", value)); + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/StringListTypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/StringListTypeValidation.java new file mode 100644 index 00000000000..acb1c7dca8f --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/StringListTypeValidation.java @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import java.util.List; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.PropertyType; + +import static org.sonar.server.exceptions.BadRequestException.checkRequest; + +public class StringListTypeValidation implements TypeValidation { + + @Override + public String key() { + return PropertyType.SINGLE_SELECT_LIST.name(); + } + + @Override + public void validate(String value, @Nullable List options) { + checkRequest(options == null || options.contains(value), "Value '%s' must be one of : %s.", value, StringUtils.join(options, ", ")); + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/StringTypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/StringTypeValidation.java new file mode 100644 index 00000000000..3851ede0e81 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/StringTypeValidation.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.sonar.api.PropertyType; + +import javax.annotation.Nullable; + +import java.util.List; + +public class StringTypeValidation implements TypeValidation { + + @Override + public String key() { + return PropertyType.STRING.name(); + } + + @Override + public void validate(String value, @Nullable List options) { + // Nothing to do + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TextTypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TextTypeValidation.java new file mode 100644 index 00000000000..c26ad125162 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TextTypeValidation.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.sonar.api.PropertyType; + +import javax.annotation.Nullable; + +import java.util.List; + +public class TextTypeValidation implements TypeValidation { + + @Override + public String key() { + return PropertyType.TEXT.name(); + } + + @Override + public void validate(String value, @Nullable List options) { + // Nothing to do + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidation.java new file mode 100644 index 00000000000..797a3438d8f --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidation.java @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.sonar.api.server.ServerSide; + +import javax.annotation.Nullable; + +import java.util.List; + +@ServerSide +public interface TypeValidation { + + String key(); + + void validate(String value, @Nullable List options); +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidationModule.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidationModule.java new file mode 100644 index 00000000000..3cc4f038e5e --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidationModule.java @@ -0,0 +1,39 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.sonar.core.platform.Module; + +public class TypeValidationModule extends Module { + @Override + protected void configureModule() { + add( + TypeValidations.class, + IntegerTypeValidation.class, + FloatTypeValidation.class, + BooleanTypeValidation.class, + TextTypeValidation.class, + StringTypeValidation.class, + StringListTypeValidation.class, + LongTypeValidation.class, + MetricLevelTypeValidation.class + ); + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidations.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidations.java new file mode 100644 index 00000000000..2c8883b77eb --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/TypeValidations.java @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.sonar.api.server.ServerSide; + +import static org.sonar.server.exceptions.BadRequestException.checkRequest; + +@ServerSide +public class TypeValidations { + + private final List typeValidationList; + + public TypeValidations(List typeValidationList) { + this.typeValidationList = typeValidationList; + } + + public void validate(List values, String type, List options) { + TypeValidation typeValidation = findByKey(type); + for (String value : values) { + typeValidation.validate(value, options); + } + } + + public void validate(String value, String type, @Nullable List options) { + TypeValidation typeValidation = findByKey(type); + typeValidation.validate(value, options); + } + + private TypeValidation findByKey(String key) { + TypeValidation typeValidation = Iterables.find(typeValidationList, new TypeValidationMatchKey(key), null); + checkRequest(typeValidation != null, "Type '%s' is not valid.", key); + return typeValidation; + } + + private static class TypeValidationMatchKey implements Predicate { + private final String key; + + public TypeValidationMatchKey(String key) { + this.key = key; + } + + @Override + public boolean apply(@Nonnull TypeValidation input) { + return input.key().equals(key); + } + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/Validation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/Validation.java new file mode 100644 index 00000000000..99d28d0bc96 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/Validation.java @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +public class Validation { + + public static final String CANT_BE_EMPTY_MESSAGE = "%s can't be empty"; + public static final String IS_TOO_SHORT_MESSAGE = "%s is too short (minimum is %s characters)"; + public static final String IS_TOO_LONG_MESSAGE = "%s is too long (maximum is %s characters)"; + public static final String IS_ALREADY_USED_MESSAGE = "%s has already been taken"; + + private Validation() { + // only static methods + } + +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/util/package-info.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/package-info.java new file mode 100644 index 00000000000..8fd4b5b3582 --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/util/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.util; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java new file mode 100644 index 00000000000..de5f24347fc --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java @@ -0,0 +1,158 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.app; + +import java.io.File; +import java.io.IOException; +import java.util.Random; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.process.sharedmemoryfile.DefaultProcessCommands; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX; +import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; + +public class ProcessCommandWrapperImplTest { + private static final int PROCESS_NUMBER = 2; + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private MapSettings settings = new MapSettings(); + + @Test + public void requestSQRestart_throws_IAE_if_process_index_property_not_set() { + ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Property process.index is not set"); + + processCommandWrapper.requestSQRestart(); + } + + @Test + public void requestSQRestart_throws_IAE_if_process_shared_path_property_not_set() { + settings.setProperty(PROPERTY_PROCESS_INDEX, 1); + ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Property process.sharedDir is not set"); + + processCommandWrapper.requestSQRestart(); + } + + @Test + public void requestSQRestart_updates_shareMemory_file() throws IOException { + File tmpDir = temp.newFolder().getAbsoluteFile(); + settings.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); + settings.setProperty(PROPERTY_PROCESS_INDEX, PROCESS_NUMBER); + + ProcessCommandWrapperImpl underTest = new ProcessCommandWrapperImpl(settings.asConfig()); + underTest.requestSQRestart(); + + try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tmpDir, PROCESS_NUMBER)) { + assertThat(processCommands.askedForRestart()).isTrue(); + } + } + + @Test + public void requestSQStop_throws_IAE_if_process_shared_path_property_not_set() { + settings.setProperty(PROPERTY_PROCESS_INDEX, 1); + ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Property process.sharedDir is not set"); + + processCommandWrapper.requestHardStop(); + } + + @Test + public void requestSQStop_updates_shareMemory_file() throws IOException { + File tmpDir = temp.newFolder().getAbsoluteFile(); + settings.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); + settings.setProperty(PROPERTY_PROCESS_INDEX, PROCESS_NUMBER); + + ProcessCommandWrapperImpl underTest = new ProcessCommandWrapperImpl(settings.asConfig()); + underTest.requestHardStop(); + + try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tmpDir, PROCESS_NUMBER)) { + assertThat(processCommands.askedForHardStop()).isTrue(); + } + } + + @Test + public void notifyOperational_throws_IAE_if_process_sharedDir_property_not_set() { + settings.setProperty(PROPERTY_PROCESS_INDEX, 1); + ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Property process.sharedDir is not set"); + + processCommandWrapper.notifyOperational(); + } + + @Test + public void notifyOperational_throws_IAE_if_process_index_property_not_set() { + ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Property process.index is not set"); + + processCommandWrapper.notifyOperational(); + } + + @Test + public void notifyOperational_updates_shareMemory_file() throws IOException { + File tmpDir = temp.newFolder().getAbsoluteFile(); + settings.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); + settings.setProperty(PROPERTY_PROCESS_INDEX, PROCESS_NUMBER); + + ProcessCommandWrapperImpl underTest = new ProcessCommandWrapperImpl(settings.asConfig()); + underTest.notifyOperational(); + + try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tmpDir, PROCESS_NUMBER)) { + assertThat(processCommands.isOperational()).isTrue(); + } + } + + @Test + public void isCeOperational_reads_shared_memory_operational_flag_in_location_3() throws IOException { + File tmpDir = temp.newFolder().getAbsoluteFile(); + settings.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); + + boolean expected = new Random().nextBoolean(); + if (expected) { + try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tmpDir, 3)) { + processCommands.setOperational(); + } + } + + ProcessCommandWrapperImpl underTest = new ProcessCommandWrapperImpl(settings.asConfig()); + + assertThat(underTest.isCeOperational()).isEqualTo(expected); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/branch/BranchFeatureProxyImplTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/branch/BranchFeatureProxyImplTest.java new file mode 100644 index 00000000000..6fb3d9a6449 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/branch/BranchFeatureProxyImplTest.java @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.branch; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class BranchFeatureProxyImplTest { + + private BranchFeatureExtension branchFeatureExtension = mock(BranchFeatureExtension.class); + + @Test + public void return_false_when_no_extension() { + assertThat(new BranchFeatureProxyImpl().isEnabled()).isFalse(); + } + + @Test + public void return_false_when_extension_returns_false() { + when(branchFeatureExtension.isEnabled()).thenReturn(false); + assertThat(new BranchFeatureProxyImpl(branchFeatureExtension).isEnabled()).isFalse(); + } + + @Test + public void return_true_when_extension_returns_ftrue() { + when(branchFeatureExtension.isEnabled()).thenReturn(true); + assertThat(new BranchFeatureProxyImpl(branchFeatureExtension).isEnabled()).isTrue(); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/branch/BranchFeatureRule.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/branch/BranchFeatureRule.java new file mode 100644 index 00000000000..2bf56463474 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/branch/BranchFeatureRule.java @@ -0,0 +1,46 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.branch; + +import org.junit.rules.ExternalResource; + +public class BranchFeatureRule extends ExternalResource implements BranchFeatureProxy { + + private boolean enabled; + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + protected void after() { + reset(); + } + + public void reset() { + this.enabled = false; + } + + @Override + public boolean isEnabled() { + return enabled; + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java new file mode 100644 index 00000000000..0dc82c559f0 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java @@ -0,0 +1,85 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import java.util.Collections; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; + +public class BadRequestExceptionTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void text_error() { + BadRequestException exception = BadRequestException.create("error"); + assertThat(exception.getMessage()).isEqualTo("error"); + } + + @Test + public void create_exception_from_list() { + BadRequestException underTest = BadRequestException.create(asList("error1", "error2")); + + assertThat(underTest.errors()).containsOnly("error1", "error2"); + } + + @Test + public void create_exception_from_var_args() { + BadRequestException underTest = BadRequestException.create("error1", "error2"); + + assertThat(underTest.errors()).containsOnly("error1", "error2"); + } + + @Test + public void getMessage_return_first_error() { + BadRequestException underTest = BadRequestException.create(asList("error1", "error2")); + + assertThat(underTest.getMessage()).isEqualTo("error1"); + } + + @Test + public void fail_when_creating_exception_with_empty_list() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("At least one error message is required"); + + BadRequestException.create(Collections.emptyList()); + } + + @Test + public void fail_when_creating_exception_with_one_empty_element() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Message cannot be empty"); + + BadRequestException.create(asList("error", "")); + } + + @Test + public void fail_when_creating_exception_with_one_null_element() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Message cannot be empty"); + + BadRequestException.create(asList("error", null)); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/MessageTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/MessageTest.java new file mode 100644 index 00000000000..f05bb55058a --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/MessageTest.java @@ -0,0 +1,88 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MessageTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void create_message() { + Message message = Message.of("key1 %s", "param1"); + assertThat(message.getMessage()).isEqualTo("key1 param1"); + } + + @Test + public void create_message_without_params() { + Message message = Message.of("key1"); + assertThat(message.getMessage()).isEqualTo("key1"); + } + + @Test + public void fail_when_message_is_null() { + expectedException.expect(IllegalArgumentException.class); + + Message.of(null); + } + + @Test + public void fail_when_message_is_empty() { + expectedException.expect(IllegalArgumentException.class); + + Message.of(""); + } + + @Test + public void test_equals_and_hashcode() { + Message message1 = Message.of("key1%s", "param1"); + Message message2 = Message.of("key2%s", "param2"); + Message message3 = Message.of("key1"); + Message message4 = Message.of("key1%s", "param2"); + Message sameAsMessage1 = Message.of("key1%s", "param1"); + + assertThat(message1).isEqualTo(message1); + assertThat(message1).isNotEqualTo(message2); + assertThat(message1).isNotEqualTo(message3); + assertThat(message1).isNotEqualTo(message4); + assertThat(message1).isEqualTo(sameAsMessage1); + assertThat(message1).isNotEqualTo(null); + assertThat(message1).isNotEqualTo(new Object()); + + assertThat(message1.hashCode()).isEqualTo(message1.hashCode()); + assertThat(message1.hashCode()).isNotEqualTo(message2.hashCode()); + assertThat(message1.hashCode()).isNotEqualTo(message3.hashCode()); + assertThat(message1.hashCode()).isNotEqualTo(message4.hashCode()); + assertThat(message1.hashCode()).isEqualTo(sameAsMessage1.hashCode()); + } + + @Test + public void to_string() { + assertThat(Message.of("key1 %s", "param1").toString()).isEqualTo("key1 param1"); + assertThat(Message.of("key1").toString()).isEqualTo("key1"); + assertThat(Message.of("key1", (Object[])null).toString()).isEqualTo("key1"); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java new file mode 100644 index 00000000000..ae2ce7846db --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.exceptions; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ServerExceptionTest { + + @Test + public void should_create_exception_with_status() { + ServerException exception = new ServerException(400, "error!"); + assertThat(exception.httpCode()).isEqualTo(400); + } + + @Test + public void should_create_exception_with_status_and_message() { + ServerException exception = new ServerException(404, "Not found"); + assertThat(exception.httpCode()).isEqualTo(404); + assertThat(exception.getMessage()).isEqualTo("Not found"); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/health/TestStandaloneHealthChecker.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/health/TestStandaloneHealthChecker.java new file mode 100644 index 00000000000..27c2e469dde --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/health/TestStandaloneHealthChecker.java @@ -0,0 +1,39 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.health; + +public class TestStandaloneHealthChecker implements HealthChecker { + + private Health health = Health.newHealthCheckBuilder().setStatus(Health.Status.GREEN).build(); + + public void setHealth(Health h) { + this.health = h; + } + + @Override + public Health checkNode() { + return health; + } + + @Override + public ClusterHealth checkCluster() { + throw new IllegalStateException(); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java new file mode 100644 index 00000000000..f984cd9bd1e --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java @@ -0,0 +1,322 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import com.google.common.base.Optional; +import java.io.File; +import java.net.URI; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.mockito.ArgumentMatcher; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.sonar.api.utils.HttpDownloader; +import org.sonar.core.platform.PluginInfo; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.platform.ServerFileSystem; +import org.sonar.updatecenter.common.Plugin; +import org.sonar.updatecenter.common.Release; +import org.sonar.updatecenter.common.UpdateCenter; +import org.sonar.updatecenter.common.Version; + +import static com.google.common.collect.Lists.newArrayList; +import static org.apache.commons.io.FileUtils.copyFileToDirectory; +import static org.apache.commons.io.FileUtils.touch; +import static org.apache.commons.io.FilenameUtils.separatorsToUnix; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.sonar.updatecenter.common.Version.create; + +public class PluginDownloaderTest { + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + private File downloadDir; + private UpdateCenterMatrixFactory updateCenterMatrixFactory; + private UpdateCenter updateCenter; + private HttpDownloader httpDownloader; + private PluginDownloader pluginDownloader; + + @Before + public void before() throws Exception { + updateCenterMatrixFactory = mock(UpdateCenterMatrixFactory.class); + updateCenter = mock(UpdateCenter.class); + when(updateCenterMatrixFactory.getUpdateCenter(anyBoolean())).thenReturn(Optional.of(updateCenter)); + + httpDownloader = mock(HttpDownloader.class); + doAnswer(new Answer() { + @Override + public Void answer(InvocationOnMock inv) throws Throwable { + File toFile = (File) inv.getArguments()[1]; + touch(toFile); + return null; + } + }).when(httpDownloader).download(any(URI.class), any(File.class)); + + ServerFileSystem fs = mock(ServerFileSystem.class); + downloadDir = testFolder.newFolder("downloads"); + when(fs.getDownloadedPluginsDir()).thenReturn(downloadDir); + + pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, fs); + } + + @After + public void stop() { + pluginDownloader.stop(); + } + + @Test + public void clean_temporary_files_at_startup() throws Exception { + touch(new File(downloadDir, "sonar-php.jar")); + touch(new File(downloadDir, "sonar-js.jar.tmp")); + assertThat(downloadDir.listFiles()).hasSize(2); + pluginDownloader.start(); + + File[] files = downloadDir.listFiles(); + assertThat(files).hasSize(1); + assertThat(files[0].getName()).isEqualTo("sonar-php.jar"); + } + + @Test + public void download_from_url() { + Plugin test = Plugin.factory("test"); + Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/test-1.0.jar"); + test.addRelease(test10); + + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); + + pluginDownloader.start(); + pluginDownloader.download("foo", create("1.0")); + + // SONAR-4523: do not corrupt JAR files when restarting the server while a plugin is being downloaded. + // The JAR file is downloaded in a temp file + verify(httpDownloader).download(any(URI.class), argThat(new HasFileName("test-1.0.jar.tmp"))); + assertThat(new File(downloadDir, "test-1.0.jar")).exists(); + assertThat(new File(downloadDir, "test-1.0.jar.tmp")).doesNotExist(); + } + + @Test + public void download_when_update_center_is_unavailable_with_no_exception_thrown() { + when(updateCenterMatrixFactory.getUpdateCenter(anyBoolean())).thenReturn(Optional.absent()); + + Plugin test = Plugin.factory("test"); + Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/test-1.0.jar"); + test.addRelease(test10); + + pluginDownloader.start(); + pluginDownloader.download("foo", create("1.0")); + } + + /** + * SONAR-4685 + */ + @Test + public void download_from_redirect_url() { + Plugin test = Plugin.factory("plugintest"); + Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/redirect?r=release&g=test&a=test&v=1.0&e=jar"); + test.addRelease(test10); + + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); + + pluginDownloader.start(); + pluginDownloader.download("foo", create("1.0")); + + // SONAR-4523: do not corrupt JAR files when restarting the server while a plugin is being downloaded. + // The JAR file is downloaded in a temp file + verify(httpDownloader).download(any(URI.class), argThat(new HasFileName("plugintest-1.0.jar.tmp"))); + assertThat(new File(downloadDir, "plugintest-1.0.jar")).exists(); + assertThat(new File(downloadDir, "plugintest-1.0.jar.tmp")).doesNotExist(); + } + + @Test + public void throw_exception_if_download_dir_is_invalid() throws Exception { + ServerFileSystem fs = mock(ServerFileSystem.class); + // download dir is a file instead of being a directory + File downloadDir = testFolder.newFile(); + when(fs.getDownloadedPluginsDir()).thenReturn(downloadDir); + + pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, fs); + try { + pluginDownloader.start(); + fail(); + } catch (IllegalStateException e) { + // ok + } + } + + @Test + public void fail_if_no_compatible_plugin_found() { + expectedException.expect(BadRequestException.class); + + pluginDownloader.download("foo", create("1.0")); + } + + @Test + public void download_from_file() throws Exception { + Plugin test = Plugin.factory("test"); + File file = testFolder.newFile("test-1.0.jar"); + file.createNewFile(); + Release test10 = new Release(test, "1.0").setDownloadUrl("file://" + separatorsToUnix(file.getCanonicalPath())); + test.addRelease(test10); + + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); + + pluginDownloader.start(); + pluginDownloader.download("foo", create("1.0")); + verify(httpDownloader, never()).download(any(URI.class), any(File.class)); + assertThat(noDownloadedFiles()).isGreaterThan(0); + } + + @Test + public void throw_exception_if_could_not_download() { + Plugin test = Plugin.factory("test"); + Release test10 = new Release(test, "1.0").setDownloadUrl("file://not_found"); + test.addRelease(test10); + + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); + + pluginDownloader.start(); + try { + pluginDownloader.download("foo", create("1.0")); + fail(); + } catch (IllegalStateException e) { + // ok + } + } + + @Test + public void throw_exception_if_download_fail() { + Plugin test = Plugin.factory("test"); + Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/test-1.0.jar"); + test.addRelease(test10); + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); + + doThrow(new RuntimeException()).when(httpDownloader).download(any(URI.class), any(File.class)); + + pluginDownloader.start(); + try { + pluginDownloader.download("foo", create("1.0")); + fail(); + } catch (IllegalStateException e) { + // ok + } + } + + @Test + public void read_download_folder() throws Exception { + pluginDownloader.start(); + assertThat(noDownloadedFiles()).isZero(); + + copyFileToDirectory(TestProjectUtils.jarOf("test-base-plugin"), downloadDir); + + assertThat(pluginDownloader.getDownloadedPlugins()).hasSize(1); + PluginInfo info = pluginDownloader.getDownloadedPlugins().iterator().next(); + assertThat(info.getKey()).isEqualTo("testbase"); + assertThat(info.getName()).isEqualTo("Base Plugin"); + assertThat(info.getVersion()).isEqualTo(Version.create("0.1-SNAPSHOT")); + assertThat(info.getMainClass()).isEqualTo("BasePlugin"); + } + + @Test + public void getDownloadedPluginFilenames_reads_plugin_info_of_files_in_download_folder() throws Exception { + pluginDownloader.start(); + assertThat(pluginDownloader.getDownloadedPlugins()).hasSize(0); + + File file1 = new File(downloadDir, "file1.jar"); + file1.createNewFile(); + File file2 = new File(downloadDir, "file2.jar"); + file2.createNewFile(); + + assertThat(noDownloadedFiles()).isEqualTo(2); + } + + @Test + public void cancel_downloads() throws Exception { + File file1 = new File(downloadDir, "file1.jar"); + file1.createNewFile(); + File file2 = new File(downloadDir, "file2.jar"); + file2.createNewFile(); + + pluginDownloader.start(); + assertThat(noDownloadedFiles()).isGreaterThan(0); + pluginDownloader.cancelDownloads(); + assertThat(noDownloadedFiles()).isZero(); + } + + private int noDownloadedFiles() { + return downloadDir.listFiles((file, name) -> name.endsWith(".jar")).length; + } + + // SONAR-5011 + @Test + public void download_common_transitive_dependency() { + Plugin test1 = Plugin.factory("test1"); + Release test1R = new Release(test1, "1.0").setDownloadUrl("http://server/test1-1.0.jar"); + test1.addRelease(test1R); + + Plugin test2 = Plugin.factory("test2"); + Release test2R = new Release(test2, "1.0").setDownloadUrl("http://server/test2-1.0.jar"); + test2.addRelease(test2R); + + Plugin testDep = Plugin.factory("testdep"); + Release testDepR = new Release(testDep, "1.0").setDownloadUrl("http://server/testdep-1.0.jar"); + testDep.addRelease(testDepR); + + when(updateCenter.findInstallablePlugins("test1", create("1.0"))).thenReturn(newArrayList(test1R, testDepR)); + when(updateCenter.findInstallablePlugins("test2", create("1.0"))).thenReturn(newArrayList(test2R, testDepR)); + + pluginDownloader.start(); + pluginDownloader.download("test1", create("1.0")); + pluginDownloader.download("test2", create("1.0")); + + assertThat(new File(downloadDir, "test1-1.0.jar")).exists(); + assertThat(new File(downloadDir, "test2-1.0.jar")).exists(); + assertThat(new File(downloadDir, "testdep-1.0.jar")).exists(); + } + + class HasFileName implements ArgumentMatcher { + private final String name; + + HasFileName(String name) { + this.name = name; + } + + @Override + public boolean matches(File file) { + return file.getName().equals(name); + } + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java new file mode 100644 index 00000000000..bc353f99778 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java @@ -0,0 +1,142 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.RandomStringUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.core.platform.PluginInfo; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.server.plugins.PluginFileSystem.PROPERTY_PLUGIN_COMPRESSION_ENABLE; + +public class PluginFileSystemTest { + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private MapSettings settings = new MapSettings(); + private Path targetJarPath; + private Path targetFolder; + private Path sourceFolder; + + @Before + public void setUp() throws IOException { + sourceFolder = temp.newFolder("source").toPath(); + targetFolder = temp.newFolder("target").toPath(); + targetJarPath = targetFolder.resolve("test.jar"); + Files.createFile(targetJarPath); + } + + @Test + public void add_plugin_to_list_of_installed_plugins() throws IOException { + File jar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); + PluginInfo info = new PluginInfo("foo"); + + PluginFileSystem underTest = new PluginFileSystem(settings.asConfig()); + underTest.addInstalledPlugin(info, jar); + + assertThat(underTest.getInstalledFiles()).hasSize(1); + InstalledPlugin installedPlugin = underTest.getInstalledPlugin("foo").get(); + assertThat(installedPlugin.getCompressedJar()).isNull(); + assertThat(installedPlugin.getLoadedJar().getFile().toPath()).isEqualTo(jar.toPath()); + assertThat(installedPlugin.getPluginInfo()).isSameAs(info); + } + + @Test + public void compress_jar_if_compression_enabled() throws IOException { + File jar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); + PluginInfo info = new PluginInfo("foo").setJarFile(jar); + // the JAR is copied somewhere else in order to be loaded by classloaders + File loadedJar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); + + settings.setProperty(PROPERTY_PLUGIN_COMPRESSION_ENABLE, true); + PluginFileSystem underTest = new PluginFileSystem(settings.asConfig()); + underTest.addInstalledPlugin(info, loadedJar); + + assertThat(underTest.getInstalledFiles()).hasSize(1); + + InstalledPlugin installedPlugin = underTest.getInstalledPlugin("foo").get(); + assertThat(installedPlugin.getPluginInfo()).isSameAs(info); + assertThat(installedPlugin.getLoadedJar().getFile().toPath()).isEqualTo(loadedJar.toPath()); + assertThat(installedPlugin.getCompressedJar().getFile()) + .exists() + .isFile() + .hasName("sonar-foo-plugin.pack.gz") + .hasParent(loadedJar.getParentFile()); + } + + @Test + public void copy_and_use_existing_packed_jar_if_compression_enabled() throws IOException { + File jar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); + File packedJar = touch(jar.getParentFile(), "sonar-foo-plugin.pack.gz"); + PluginInfo info = new PluginInfo("foo").setJarFile(jar); + // the JAR is copied somewhere else in order to be loaded by classloaders + File loadedJar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); + + settings.setProperty(PROPERTY_PLUGIN_COMPRESSION_ENABLE, true); + PluginFileSystem underTest = new PluginFileSystem(settings.asConfig()); + underTest.addInstalledPlugin(info, loadedJar); + + assertThat(underTest.getInstalledFiles()).hasSize(1); + + InstalledPlugin installedPlugin = underTest.getInstalledPlugin("foo").get(); + assertThat(installedPlugin.getPluginInfo()).isSameAs(info); + assertThat(installedPlugin.getLoadedJar().getFile().toPath()).isEqualTo(loadedJar.toPath()); + assertThat(installedPlugin.getCompressedJar().getFile()) + .exists() + .isFile() + .hasName(packedJar.getName()) + .hasParent(loadedJar.getParentFile()) + .hasSameContentAs(packedJar); + } + + private static File touch(File dir, String filename) throws IOException { + File file = new File(dir, filename); + FileUtils.write(file, RandomStringUtils.random(10)); + return file; + } + + // + // @Test + // public void should_use_deployed_packed_file() throws IOException { + // Path packedPath = sourceFolder.resolve("test.pack.gz"); + // Files.write(packedPath, new byte[] {1, 2, 3}); + // + // settings.setProperty(PROPERTY_PLUGIN_COMPRESSION_ENABLE, true); + // underTest = new PluginFileSystem(settings.asConfig()); + // underTest.compressJar("key", sourceFolder, targetJarPath); + // + // assertThat(Files.list(targetFolder)).containsOnly(targetJarPath, targetFolder.resolve("test.pack.gz")); + // assertThat(underTest.getPlugins()).hasSize(1); + // assertThat(underTest.getPlugins().get("key").getFilename()).isEqualTo("test.pack.gz"); + // + // // check that the file was copied, not generated + // assertThat(targetFolder.resolve("test.pack.gz")).hasSameContentAs(packedPath); + // } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginUninstallerTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginUninstallerTest.java new file mode 100644 index 00000000000..20eae5f2781 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginUninstallerTest.java @@ -0,0 +1,105 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import java.io.File; +import java.io.IOException; +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.server.platform.ServerFileSystem; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class PluginUninstallerTest { + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + @Rule + public ExpectedException exception = ExpectedException.none(); + + private File uninstallDir; + private PluginUninstaller underTest; + private ServerPluginRepository serverPluginRepository; + private ServerFileSystem fs; + + @Before + public void setUp() throws IOException { + serverPluginRepository = mock(ServerPluginRepository.class); + uninstallDir = testFolder.newFolder("uninstall"); + fs = mock(ServerFileSystem.class); + when(fs.getUninstalledPluginsDir()).thenReturn(uninstallDir); + underTest = new PluginUninstaller(serverPluginRepository, fs); + } + + @Test + public void uninstall() { + when(serverPluginRepository.hasPlugin("plugin")).thenReturn(true); + underTest.uninstall("plugin"); + verify(serverPluginRepository).uninstall("plugin", uninstallDir); + } + + @Test + public void fail_uninstall_if_plugin_not_installed() { + when(serverPluginRepository.hasPlugin("plugin")).thenReturn(false); + exception.expect(IllegalArgumentException.class); + exception.expectMessage("Plugin [plugin] is not installed"); + underTest.uninstall("plugin"); + verifyZeroInteractions(serverPluginRepository); + } + + @Test + public void create_uninstall_dir() { + File dir = new File(testFolder.getRoot(), "dir"); + when(fs.getUninstalledPluginsDir()).thenReturn(dir); + underTest = new PluginUninstaller(serverPluginRepository, fs); + underTest.start(); + assertThat(dir).isDirectory(); + } + + @Test + public void cancel() { + underTest.cancelUninstalls(); + verify(serverPluginRepository).cancelUninstalls(uninstallDir); + verifyNoMoreInteractions(serverPluginRepository); + } + + @Test + public void list_uninstalled_plugins() throws IOException { + new File(uninstallDir, "file1").createNewFile(); + copyTestPluginTo("test-base-plugin", uninstallDir); + assertThat(underTest.getUninstalledPlugins()).extracting("key").containsOnly("testbase"); + } + + private File copyTestPluginTo(String testPluginName, File toDir) throws IOException { + File jar = TestProjectUtils.jarOf(testPluginName); + // file is copied because it's supposed to be moved by the test + FileUtils.copyFileToDirectory(jar, toDir); + return new File(toDir, jar.getName()); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginJarExploderTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginJarExploderTest.java new file mode 100644 index 00000000000..8f4d928cd4c --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginJarExploderTest.java @@ -0,0 +1,67 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import java.io.File; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.core.platform.ExplodedPlugin; +import org.sonar.core.platform.PluginInfo; +import org.sonar.server.platform.ServerFileSystem; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class ServerPluginJarExploderTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private ServerFileSystem fs = mock(ServerFileSystem.class); + private PluginFileSystem pluginFileSystem = mock(PluginFileSystem.class); + private ServerPluginJarExploder underTest = new ServerPluginJarExploder(fs, pluginFileSystem); + + @Test + public void copy_all_classloader_files_to_dedicated_directory() throws Exception { + File deployDir = temp.newFolder(); + when(fs.getDeployedPluginsDir()).thenReturn(deployDir); + File sourceJar = TestProjectUtils.jarOf("test-libs-plugin"); + PluginInfo info = PluginInfo.create(sourceJar); + + ExplodedPlugin exploded = underTest.explode(info); + + // all the files loaded by classloaders (JAR + META-INF/libs/*.jar) are copied to the dedicated directory + // web/deploy/{pluginKey} + File pluginDeployDir = new File(deployDir, "testlibs"); + + assertThat(exploded.getKey()).isEqualTo("testlibs"); + assertThat(exploded.getMain()).isFile().exists().hasParent(pluginDeployDir); + assertThat(exploded.getLibs()).extracting("name").containsOnly("commons-daemon-1.0.15.jar", "commons-email-20030310.165926.jar"); + for (File lib : exploded.getLibs()) { + assertThat(lib).exists().isFile(); + assertThat(lib.getCanonicalPath()).startsWith(pluginDeployDir.getCanonicalPath()); + } + File targetJar = new File(fs.getDeployedPluginsDir(), "testlibs/test-libs-plugin-0.1-SNAPSHOT.jar"); + verify(pluginFileSystem).addInstalledPlugin(info, targetJar); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java new file mode 100644 index 00000000000..e426c9ebfea --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java @@ -0,0 +1,385 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.mockito.Mockito; +import org.sonar.api.SonarRuntime; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.log.LogTester; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginLoader; +import org.sonar.server.platform.ServerFileSystem; +import org.sonar.updatecenter.common.Version; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ServerPluginRepositoryTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Rule + public LogTester logs = new LogTester(); + + private SonarRuntime runtime = mock(SonarRuntime.class); + private ServerFileSystem fs = mock(ServerFileSystem.class, Mockito.RETURNS_DEEP_STUBS); + private PluginLoader pluginLoader = mock(PluginLoader.class); + private ServerPluginRepository underTest = new ServerPluginRepository(runtime, fs, pluginLoader); + + @Before + public void setUp() throws IOException { + when(fs.getDeployedPluginsDir()).thenReturn(temp.newFolder()); + when(fs.getDownloadedPluginsDir()).thenReturn(temp.newFolder()); + when(fs.getHomeDir()).thenReturn(temp.newFolder()); + when(fs.getInstalledPluginsDir()).thenReturn(temp.newFolder()); + when(fs.getTempDir()).thenReturn(temp.newFolder()); + when(runtime.getApiVersion()).thenReturn(org.sonar.api.utils.Version.parse("5.2")); + } + + @After + public void tearDown() { + underTest.stop(); + } + + @Test + public void standard_startup_loads_installed_plugins() throws Exception { + copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + + underTest.start(); + + assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); + } + + @Test + public void no_plugins_at_all_on_startup() { + underTest.start(); + + assertThat(underTest.getPluginInfos()).isEmpty(); + assertThat(underTest.getPluginInfosByKeys()).isEmpty(); + assertThat(underTest.hasPlugin("testbase")).isFalse(); + } + + @Test + public void fail_if_multiple_jars_for_same_installed_plugin_on_startup() throws Exception { + copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + copyTestPluginTo("test-base-plugin-v2", fs.getInstalledPluginsDir()); + + try { + underTest.start(); + fail(); + } catch (MessageException e) { + assertThat(e) + .hasMessageStartingWith("Found two versions of the plugin Base Plugin [testbase] in the directory extensions/plugins. Please remove one of ") + // order is not guaranteed, so assertion is split + .hasMessageContaining("test-base-plugin-0.1-SNAPSHOT.jar") + .hasMessageContaining("test-base-plugin-0.2-SNAPSHOT.jar"); + } + } + + @Test + public void install_downloaded_plugins_on_startup() throws Exception { + File downloadedJar = copyTestPluginTo("test-base-plugin", fs.getDownloadedPluginsDir()); + + underTest.start(); + + // plugin is moved to extensions/plugins then loaded + assertThat(downloadedJar).doesNotExist(); + assertThat(new File(fs.getInstalledPluginsDir(), downloadedJar.getName())).isFile().exists(); + assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); + } + + @Test + public void downloaded_file_overrides_existing_installed_file_on_startup() throws Exception { + File installedV1 = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + File downloadedV2 = copyTestPluginTo("test-base-plugin-v2", fs.getDownloadedPluginsDir()); + + underTest.start(); + + // plugin is moved to extensions/plugins and replaces v1 + assertThat(downloadedV2).doesNotExist(); + assertThat(installedV1).doesNotExist(); + assertThat(new File(fs.getInstalledPluginsDir(), downloadedV2.getName())).exists(); + assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); + assertThat(underTest.getPluginInfo("testbase").getVersion()).isEqualTo(Version.create("0.2-SNAPSHOT")); + } + + @Test + public void blacklisted_plugin_is_automatically_uninstalled_on_startup() throws Exception { + underTest.setBlacklistedPluginKeys(ImmutableSet.of("testbase", "issuesreport")); + File jar = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + + underTest.start(); + + // plugin is not installed and file is deleted + assertThat(underTest.getPluginInfos()).isEmpty(); + assertThat(jar).doesNotExist(); + } + + @Test + public void test_plugin_requirements_at_startup() throws Exception { + copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); + + underTest.start(); + + // both plugins are installed + assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase", "testrequire"); + } + + @Test + public void plugin_is_ignored_if_required_plugin_is_missing_at_startup() throws Exception { + copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); + + underTest.start(); + + // plugin is not installed as test-base-plugin is missing + assertThat(underTest.getPluginInfosByKeys()).isEmpty(); + } + + @Test + public void plugin_is_ignored_if_required_plugin_is_too_old_at_startup() throws Exception { + copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + copyTestPluginTo("test-requirenew-plugin", fs.getInstalledPluginsDir()); + + underTest.start(); + + // the plugin "requirenew" is not installed as it requires base 0.2+ to be installed. + assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); + } + + @Test + public void fail_if_plugin_does_not_support_sq_version() throws Exception { + when(runtime.getApiVersion()).thenReturn(org.sonar.api.utils.Version.parse("1.0")); + copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + + try { + underTest.start(); + fail(); + } catch (MessageException e) { + assertThat(e).hasMessage("Plugin Base Plugin [testbase] requires at least SonarQube 4.5.4"); + } + } + + @Test + public void uninstall() throws Exception { + File installedJar = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + File uninstallDir = temp.newFolder("uninstallDir"); + + underTest.start(); + assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); + underTest.uninstall("testbase", uninstallDir); + + assertThat(installedJar).doesNotExist(); + // still up. Will be dropped after next startup + assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); + assertThat(uninstallDir.list()).containsOnly(installedJar.getName()); + } + + @Test + public void uninstall_dependents() throws Exception { + File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); + File uninstallDir = temp.newFolder("uninstallDir"); + + underTest.start(); + assertThat(underTest.getPluginInfos()).hasSize(2); + underTest.uninstall("testbase", uninstallDir); + assertThat(base).doesNotExist(); + assertThat(extension).doesNotExist(); + assertThat(uninstallDir.list()).containsOnly(base.getName(), extension.getName()); + } + + @Test + public void dont_uninstall_non_existing_dependents() throws IOException { + File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); + File uninstallDir = temp.newFolder("uninstallDir"); + + underTest.start(); + assertThat(underTest.getPluginInfos()).hasSize(2); + underTest.uninstall("testrequire", uninstallDir); + assertThat(underTest.getPluginInfos()).hasSize(2); + + underTest.uninstall("testbase", uninstallDir); + assertThat(base).doesNotExist(); + assertThat(extension).doesNotExist(); + assertThat(uninstallDir.list()).containsOnly(base.getName(), extension.getName()); + } + + @Test + public void dont_uninstall_non_existing_files() throws IOException { + File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); + File uninstallDir = temp.newFolder("uninstallDir"); + + underTest.start(); + assertThat(underTest.getPluginInfos()).hasSize(2); + underTest.uninstall("testbase", uninstallDir); + assertThat(underTest.getPluginInfos()).hasSize(2); + + underTest.uninstall("testbase", uninstallDir); + assertThat(base).doesNotExist(); + assertThat(extension).doesNotExist(); + assertThat(uninstallDir.list()).containsOnly(base.getName(), extension.getName()); + } + + @Test + public void install_plugin_and_its_extension_plugins_at_startup() throws Exception { + copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); + copyTestPluginTo("test-extend-plugin", fs.getInstalledPluginsDir()); + + underTest.start(); + + // both plugins are installed + assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase", "testextend"); + } + + @Test + public void extension_plugin_is_ignored_if_base_plugin_is_missing_at_startup() throws Exception { + copyTestPluginTo("test-extend-plugin", fs.getInstalledPluginsDir()); + + underTest.start(); + + // plugin is not installed as its base plugin is not installed + assertThat(underTest.getPluginInfos()).isEmpty(); + } + + @Test + public void fail_to_get_missing_plugins() { + underTest.start(); + try { + underTest.getPluginInfo("unknown"); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Plugin [unknown] does not exist"); + } + + try { + underTest.getPluginInstance("unknown"); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Plugin [unknown] does not exist"); + } + } + + @Test + public void plugin_is_incompatible_if_no_entry_point_class() { + PluginInfo plugin = new PluginInfo("foo").setName("Foo"); + assertThat(ServerPluginRepository.isCompatible(plugin, runtime, Collections.emptyMap())).isFalse(); + assertThat(logs.logs()).contains("Plugin Foo [foo] is ignored because entry point class is not defined"); + } + + @Test + public void fail_when_views_is_installed() throws Exception { + copyTestPluginTo("fake-views-plugin", fs.getInstalledPluginsDir()); + + expectedException.expect(MessageException.class); + expectedException.expectMessage("Plugin 'views' is no longer compatible with this version of SonarQube"); + underTest.start(); + } + + @Test + public void fail_when_sqale_plugin_is_installed() throws Exception { + copyTestPluginTo("fake-sqale-plugin", fs.getInstalledPluginsDir()); + + expectedException.expect(MessageException.class); + expectedException.expectMessage("Plugin 'sqale' is no longer compatible with this version of SonarQube"); + underTest.start(); + } + + @Test + public void fail_when_report_is_installed() throws Exception { + copyTestPluginTo("fake-report-plugin", fs.getInstalledPluginsDir()); + + expectedException.expect(MessageException.class); + expectedException.expectMessage("Plugin 'report' is no longer compatible with this version of SonarQube"); + underTest.start(); + } + + /** + * Some plugins can only extend the classloader of base plugin, without declaring new extensions. + */ + @Test + public void plugin_is_compatible_if_no_entry_point_class_but_extend_other_plugin() { + PluginInfo basePlugin = new PluginInfo("base").setMainClass("org.bar.Bar"); + PluginInfo plugin = new PluginInfo("foo").setBasePlugin("base"); + Map plugins = ImmutableMap.of("base", basePlugin, "foo", plugin); + + assertThat(ServerPluginRepository.isCompatible(plugin, runtime, plugins)).isTrue(); + } + + @Test + public void getPluginInstance_throws_ISE_if_repo_is_not_started() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("not started yet"); + + underTest.getPluginInstance("foo"); + } + + @Test + public void getPluginInfo_throws_ISE_if_repo_is_not_started() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("not started yet"); + + underTest.getPluginInfo("foo"); + } + + @Test + public void hasPlugin_throws_ISE_if_repo_is_not_started() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("not started yet"); + + underTest.hasPlugin("foo"); + } + + @Test + public void getPluginInfos_throws_ISE_if_repo_is_not_started() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("not started yet"); + + underTest.getPluginInfos(); + } + + private File copyTestPluginTo(String testPluginName, File toDir) throws IOException { + File jar = TestProjectUtils.jarOf(testPluginName); + // file is copied because it's supposed to be moved by the test + FileUtils.copyFileToDirectory(jar, toDir); + return new File(toDir, jar.getName()); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/TestPluginA.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/TestPluginA.java new file mode 100644 index 00000000000..7952eb5799c --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/TestPluginA.java @@ -0,0 +1,29 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import org.sonar.api.Plugin; + +public class TestPluginA implements Plugin { + @Override + public void define(Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/TestProjectUtils.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/TestProjectUtils.java new file mode 100644 index 00000000000..9710a8689e4 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/TestProjectUtils.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.Collection; + +public class TestProjectUtils { + + /** + * Get the artifact of plugins stored in src/test/projects + */ + public static File jarOf(String dirName) { + File target = FileUtils.toFile(TestProjectUtils.class.getResource(String.format("/%s/target/", dirName))); + Collection jars = FileUtils.listFiles(target, new String[] {"jar"}, false); + if (jars == null || jars.size() != 1) { + throw new IllegalArgumentException("Test project is badly defined: " + dirName); + } + return jars.iterator().next(); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java new file mode 100644 index 00000000000..b1e50cba77c --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java @@ -0,0 +1,104 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.utils.SonarException; +import org.sonar.api.utils.UriReader; +import org.sonar.process.ProcessProperties; +import org.sonar.updatecenter.common.UpdateCenter; +import org.sonar.updatecenter.common.Version; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.guava.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class UpdateCenterClientTest { + + private static final String BASE_URL = "https://update.sonarsource.org"; + private UriReader reader = mock(UriReader.class); + private MapSettings settings = new MapSettings(); + private UpdateCenterClient underTest; + + @Before + public void startServer() throws Exception { + reader = mock(UriReader.class); + settings.setProperty(UpdateCenterClient.URL_PROPERTY, BASE_URL); + settings.setProperty(ProcessProperties.Property.SONAR_UPDATECENTER_ACTIVATE.getKey(), true); + underTest = new UpdateCenterClient(reader, settings.asConfig()); + } + + @Test + public void downloadUpdateCenter() throws URISyntaxException { + when(reader.readString(new URI(BASE_URL), StandardCharsets.UTF_8)).thenReturn("publicVersions=2.2,2.3"); + UpdateCenter plugins = underTest.getUpdateCenter().get(); + verify(reader, times(1)).readString(new URI(BASE_URL), StandardCharsets.UTF_8); + assertThat(plugins.getSonar().getVersions()).containsOnly(Version.create("2.2"), Version.create("2.3")); + assertThat(underTest.getLastRefreshDate()).isNotNull(); + } + + @Test + public void not_available_before_initialization() { + assertThat(underTest.getLastRefreshDate()).isNull(); + } + + @Test + public void ignore_connection_errors() { + when(reader.readString(any(URI.class), eq(StandardCharsets.UTF_8))).thenThrow(new SonarException()); + assertThat(underTest.getUpdateCenter()).isAbsent(); + } + + @Test + public void cache_data() throws Exception { + when(reader.readString(new URI(BASE_URL), StandardCharsets.UTF_8)).thenReturn("sonar.versions=2.2,2.3"); + + underTest.getUpdateCenter(); + underTest.getUpdateCenter(); + + verify(reader, times(1)).readString(new URI(BASE_URL), StandardCharsets.UTF_8); + } + + @Test + public void forceRefresh() throws Exception { + when(reader.readString(new URI(BASE_URL), StandardCharsets.UTF_8)).thenReturn("sonar.versions=2.2,2.3"); + + underTest.getUpdateCenter(); + underTest.getUpdateCenter(true); + + verify(reader, times(2)).readString(new URI(BASE_URL), StandardCharsets.UTF_8); + } + + @Test + public void update_center_is_null_when_property_is_false() { + settings.setProperty(ProcessProperties.Property.SONAR_UPDATECENTER_ACTIVATE.getKey(), false); + + assertThat(underTest.getUpdateCenter()).isAbsent(); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixFactoryTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixFactoryTest.java new file mode 100644 index 00000000000..a71522a77d5 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixFactoryTest.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import com.google.common.base.Optional; +import org.junit.Test; +import org.sonar.api.SonarRuntime; +import org.sonar.updatecenter.common.UpdateCenter; + +import static org.assertj.guava.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class UpdateCenterMatrixFactoryTest { + + private UpdateCenterMatrixFactory underTest; + + @Test + public void return_absent_update_center() { + UpdateCenterClient updateCenterClient = mock(UpdateCenterClient.class); + when(updateCenterClient.getUpdateCenter(anyBoolean())).thenReturn(Optional.absent()); + + underTest = new UpdateCenterMatrixFactory(updateCenterClient, mock(SonarRuntime.class), mock(InstalledPluginReferentialFactory.class)); + + Optional updateCenter = underTest.getUpdateCenter(false); + + assertThat(updateCenter).isAbsent(); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterServlet.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterServlet.java new file mode 100644 index 00000000000..d6d9904452d --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/UpdateCenterServlet.java @@ -0,0 +1,43 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins; + +import javax.servlet.GenericServlet; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Properties; + +public class UpdateCenterServlet extends GenericServlet { + + int count = 0; + + @Override + public void service(ServletRequest request, ServletResponse response) throws IOException { + count++; + Properties props = new Properties(); + props.setProperty("count", String.valueOf(count)); + props.setProperty("agent", ((HttpServletRequest)request).getHeader("User-Agent")); + props.store(response.getOutputStream(), null); + } +} + diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/edition/EditionBundledPluginsTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/edition/EditionBundledPluginsTest.java new file mode 100644 index 00000000000..907768f56fa --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/edition/EditionBundledPluginsTest.java @@ -0,0 +1,178 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins.edition; + +import java.util.Random; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.core.platform.PluginInfo; +import org.sonar.updatecenter.common.Plugin; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.assertj.core.api.Assertions.assertThat; + +public class EditionBundledPluginsTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private final Random random = new Random(); + + @Test + public void isEditionBundled_on_Plugin_fails_with_NPE_if_arg_is_null() { + expectedException.expect(NullPointerException.class); + + EditionBundledPlugins.isEditionBundled((Plugin) null); + } + + @Test + public void isEditionBundled_on_Plugin_returns_false_for_SonarSource_and_non_commercial_license() { + Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomAlphanumeric(3)); + + assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse(); + } + + @Test + public void isEditionBundled_on_Plugin_returns_false_for_license_SonarSource_and_non_SonarSource_organization() { + Plugin plugin = newPlugin(randomAlphanumeric(3), randomizeCase("SonarSource")); + + assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse(); + } + + @Test + public void isEditionBundled_on_Plugin_returns_false_for_license_Commercial_and_non_SonarSource_organization() { + Plugin plugin = newPlugin(randomAlphanumeric(3), randomizeCase("Commercial")); + + assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse(); + } + + @Test + public void isEditionBundled_on_Plugin_returns_true_for_organization_SonarSource_and_license_SonarSource_case_insensitive() { + Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomizeCase("SonarSource")); + + assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isTrue(); + } + + @Test + public void isEditionBundled_on_Plugin_returns_true_for_organization_SonarSource_and_license_Commercial_case_insensitive() { + Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomizeCase("Commercial")); + + assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isTrue(); + } + + @Test + public void isEditionBundled_on_PluginInfo_fails_with_NPE_if_arg_is_null() { + expectedException.expect(NullPointerException.class); + + EditionBundledPlugins.isEditionBundled((PluginInfo) null); + } + + @Test + public void isEditionBundled_on_PluginInfo_returns_false_for_SonarSource_and_non_commercial_license() { + PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomAlphanumeric(3)); + + assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse(); + } + + @Test + public void isEditionBundled_on_PluginInfo_returns_false_for_license_SonarSource_and_non_SonarSource_organization() { + PluginInfo pluginInfo = newPluginInfo(randomAlphanumeric(3), randomizeCase("SonarSource")); + + assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse(); + } + + @Test + public void isEditionBundled_on_PluginInfo_returns_false_for_license_Commercial_and_non_SonarSource_organization() { + PluginInfo pluginInfo = newPluginInfo(randomAlphanumeric(3), randomizeCase("Commercial")); + + assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse(); + } + + @Test + public void isEditionBundled_on_PluginInfo_returns_true_for_organization_SonarSource_and_license_SonarSource_case_insensitive() { + PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomizeCase("SonarSource")); + + assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isTrue(); + } + + @Test + public void isEditionBundled_on_PluginINfo_returns_true_for_organization_SonarSource_and_license_Commercial_case_insensitive() { + PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomizeCase("Commercial")); + + assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isTrue(); + } + + private String randomizeCase(String s) { + return s.chars() + .map(c -> random.nextBoolean() ? Character.toUpperCase(c) : Character.toLowerCase(c)) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) + .toString(); + } + + private PluginInfo newPluginInfo(String organization, String license) { + PluginInfo pluginInfo = new PluginInfo(randomAlphanumeric(2)); + if (random.nextBoolean()) { + pluginInfo.setName(randomAlphanumeric(3)); + } + if (random.nextBoolean()) { + pluginInfo.setOrganizationUrl(randomAlphanumeric(4)); + } + if (random.nextBoolean()) { + pluginInfo.setIssueTrackerUrl(randomAlphanumeric(5)); + } + if (random.nextBoolean()) { + pluginInfo.setIssueTrackerUrl(randomAlphanumeric(6)); + } + if (random.nextBoolean()) { + pluginInfo.setBasePlugin(randomAlphanumeric(7)); + } + if (random.nextBoolean()) { + pluginInfo.setHomepageUrl(randomAlphanumeric(8)); + } + return pluginInfo + .setOrganizationName(organization) + .setLicense(license); + } + + private Plugin newPlugin(String organization, String license) { + Plugin plugin = Plugin.factory(randomAlphanumeric(2)); + if (random.nextBoolean()) { + plugin.setName(randomAlphanumeric(3)); + } + if (random.nextBoolean()) { + plugin.setOrganizationUrl(randomAlphanumeric(4)); + } + if (random.nextBoolean()) { + plugin.setTermsConditionsUrl(randomAlphanumeric(5)); + } + if (random.nextBoolean()) { + plugin.setIssueTrackerUrl(randomAlphanumeric(6)); + } + if (random.nextBoolean()) { + plugin.setCategory(randomAlphanumeric(7)); + } + if (random.nextBoolean()) { + plugin.setHomepageUrl(randomAlphanumeric(8)); + } + return plugin + .setLicense(license) + .setOrganization(organization); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java new file mode 100644 index 00000000000..8085b643ede --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java @@ -0,0 +1,311 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.project; + +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import java.util.Collections; +import java.util.Random; +import java.util.Set; +import java.util.stream.IntStream; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mockito; +import org.sonar.core.util.stream.MoreCollectors; + +import static java.util.Collections.singleton; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; +import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; + +@RunWith(DataProviderRunner.class) +public class ProjectLifeCycleListenersImplTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private ProjectLifeCycleListener listener1 = mock(ProjectLifeCycleListener.class); + private ProjectLifeCycleListener listener2 = mock(ProjectLifeCycleListener.class); + private ProjectLifeCycleListener listener3 = mock(ProjectLifeCycleListener.class); + private ProjectLifeCycleListenersImpl underTestNoListeners = new ProjectLifeCycleListenersImpl(); + private ProjectLifeCycleListenersImpl underTestWithListeners = new ProjectLifeCycleListenersImpl( + new ProjectLifeCycleListener[] {listener1, listener2, listener3}); + + @Test + public void onProjectsDeleted_throws_NPE_if_set_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("projects can't be null"); + + underTestWithListeners.onProjectsDeleted(null); + } + + @Test + public void onProjectsDeleted_throws_NPE_if_set_is_null_even_if_no_listeners() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("projects can't be null"); + + underTestNoListeners.onProjectsDeleted(null); + } + + @Test + public void onProjectsDeleted_has_no_effect_if_set_is_empty() { + underTestNoListeners.onProjectsDeleted(Collections.emptySet()); + + underTestWithListeners.onProjectsDeleted(Collections.emptySet()); + verifyZeroInteractions(listener1, listener2, listener3); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectsDeleted_does_not_fail_if_there_is_no_listener(Set projects) { + underTestNoListeners.onProjectsDeleted(projects); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectsDeleted_calls_all_listeners_in_order_of_addition_to_constructor(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + + underTestWithListeners.onProjectsDeleted(projects); + + inOrder.verify(listener1).onProjectsDeleted(same(projects)); + inOrder.verify(listener2).onProjectsDeleted(same(projects)); + inOrder.verify(listener3).onProjectsDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectsDeleted_calls_all_listeners_even_if_one_throws_an_Exception(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + doThrow(new RuntimeException("Faking listener2 throwing an exception")) + .when(listener2) + .onProjectsDeleted(any()); + + underTestWithListeners.onProjectsDeleted(projects); + + inOrder.verify(listener1).onProjectsDeleted(same(projects)); + inOrder.verify(listener2).onProjectsDeleted(same(projects)); + inOrder.verify(listener3).onProjectsDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectsDeleted_calls_all_listeners_even_if_one_throws_an_Error(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + doThrow(new Error("Faking listener2 throwing an Error")) + .when(listener2) + .onProjectsDeleted(any()); + + underTestWithListeners.onProjectsDeleted(projects); + + inOrder.verify(listener1).onProjectsDeleted(same(projects)); + inOrder.verify(listener2).onProjectsDeleted(same(projects)); + inOrder.verify(listener3).onProjectsDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void onProjectBranchesDeleted_throws_NPE_if_set_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("projects can't be null"); + + underTestWithListeners.onProjectBranchesDeleted(null); + } + + @Test + public void onProjectBranchesDeleted_throws_NPE_if_set_is_null_even_if_no_listeners() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("projects can't be null"); + + underTestNoListeners.onProjectBranchesDeleted(null); + } + + @Test + public void onProjectBranchesDeleted_has_no_effect_if_set_is_empty() { + underTestNoListeners.onProjectBranchesDeleted(Collections.emptySet()); + + underTestWithListeners.onProjectBranchesDeleted(Collections.emptySet()); + verifyZeroInteractions(listener1, listener2, listener3); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectBranchesDeleted_does_not_fail_if_there_is_no_listener(Set projects) { + underTestNoListeners.onProjectBranchesDeleted(projects); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectBranchesDeleted_calls_all_listeners_in_order_of_addition_to_constructor(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + + underTestWithListeners.onProjectBranchesDeleted(projects); + + inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectBranchesDeleted_calls_all_listeners_even_if_one_throws_an_Exception(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + doThrow(new RuntimeException("Faking listener2 throwing an exception")) + .when(listener2) + .onProjectBranchesDeleted(any()); + + underTestWithListeners.onProjectBranchesDeleted(projects); + + inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectBranchesDeleted_calls_all_listeners_even_if_one_throws_an_Error(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + doThrow(new Error("Faking listener2 throwing an Error")) + .when(listener2) + .onProjectBranchesDeleted(any()); + + underTestWithListeners.onProjectBranchesDeleted(projects); + + inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @DataProvider + public static Object[][] oneOrManyProjects() { + return new Object[][] { + {singleton(newUniqueProject())}, + {IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> newUniqueProject()).collect(MoreCollectors.toSet())} + }; + } + // SDSDS + + @Test + public void onProjectsRekeyed_throws_NPE_if_set_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("rekeyedProjects can't be null"); + + underTestWithListeners.onProjectsRekeyed(null); + } + + @Test + public void onProjectsRekeyed_throws_NPE_if_set_is_null_even_if_no_listeners() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("rekeyedProjects can't be null"); + + underTestNoListeners.onProjectsRekeyed(null); + } + + @Test + public void onProjectsRekeyed_has_no_effect_if_set_is_empty() { + underTestNoListeners.onProjectsRekeyed(Collections.emptySet()); + + underTestWithListeners.onProjectsRekeyed(Collections.emptySet()); + verifyZeroInteractions(listener1, listener2, listener3); + } + + @Test + @UseDataProvider("oneOrManyRekeyedProjects") + public void onProjectsRekeyed_does_not_fail_if_there_is_no_listener(Set projects) { + underTestNoListeners.onProjectsRekeyed(projects); + } + + @Test + @UseDataProvider("oneOrManyRekeyedProjects") + public void onProjectsRekeyed_calls_all_listeners_in_order_of_addition_to_constructor(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + + underTestWithListeners.onProjectsRekeyed(projects); + + inOrder.verify(listener1).onProjectsRekeyed(same(projects)); + inOrder.verify(listener2).onProjectsRekeyed(same(projects)); + inOrder.verify(listener3).onProjectsRekeyed(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + @UseDataProvider("oneOrManyRekeyedProjects") + public void onProjectsRekeyed_calls_all_listeners_even_if_one_throws_an_Exception(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + doThrow(new RuntimeException("Faking listener2 throwing an exception")) + .when(listener2) + .onProjectsRekeyed(any()); + + underTestWithListeners.onProjectsRekeyed(projects); + + inOrder.verify(listener1).onProjectsRekeyed(same(projects)); + inOrder.verify(listener2).onProjectsRekeyed(same(projects)); + inOrder.verify(listener3).onProjectsRekeyed(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + @UseDataProvider("oneOrManyRekeyedProjects") + public void onProjectsRekeyed_calls_all_listeners_even_if_one_throws_an_Error(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + doThrow(new Error("Faking listener2 throwing an Error")) + .when(listener2) + .onProjectsRekeyed(any()); + + underTestWithListeners.onProjectsRekeyed(projects); + + inOrder.verify(listener1).onProjectsRekeyed(same(projects)); + inOrder.verify(listener2).onProjectsRekeyed(same(projects)); + inOrder.verify(listener3).onProjectsRekeyed(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @DataProvider + public static Object[][] oneOrManyRekeyedProjects() { + return new Object[][] { + {singleton(newUniqueRekeyedProject())}, + {IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> newUniqueRekeyedProject()).collect(MoreCollectors.toSet())} + }; + } + + private static Project newUniqueProject() { + return Project.from(newPrivateProjectDto(newOrganizationDto())); + } + + private static int counter = 3_989; + + private static RekeyedProject newUniqueRekeyedProject() { + int base = counter++; + Project project = Project.from(newPrivateProjectDto(newOrganizationDto())); + return new RekeyedProject(project, base + "_old_key"); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/project/RekeyedProjectTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/project/RekeyedProjectTest.java new file mode 100644 index 00000000000..a847d91d0d8 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/project/RekeyedProjectTest.java @@ -0,0 +1,102 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.project; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static java.util.Collections.emptyList; +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; +import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; + +public class RekeyedProjectTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void constructor_throws_NPE_if_project_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("project can't be null"); + + new RekeyedProject(null, randomAlphanumeric(3)); + } + + @Test + public void constructor_throws_NPE_if_previousKey_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("previousKey can't be null"); + + new RekeyedProject(newRandomProject(), null); + } + + @Test + public void verify_getters() { + Project project = newRandomProject(); + String previousKey = randomAlphanumeric(6); + RekeyedProject underTest = new RekeyedProject(project, previousKey); + + assertThat(underTest.getProject()).isSameAs(project); + assertThat(underTest.getPreviousKey()).isEqualTo(previousKey); + } + + @Test + public void equals_is_based_on_project_and_previousKey() { + Project project = newRandomProject(); + String previousKey = randomAlphanumeric(6); + RekeyedProject underTest = new RekeyedProject(project, previousKey); + + assertThat(underTest).isEqualTo(underTest); + assertThat(underTest).isEqualTo(new RekeyedProject(project, previousKey)); + assertThat(underTest).isNotEqualTo(new RekeyedProject(project, randomAlphanumeric(11))); + assertThat(underTest).isNotEqualTo(new RekeyedProject(newRandomProject(), previousKey)); + assertThat(underTest).isNotEqualTo(new Object()); + assertThat(underTest).isNotEqualTo(null); + } + + @Test + public void hashCode_is_based_on_project_and_previousKey() { + Project project = newRandomProject(); + String previousKey = randomAlphanumeric(6); + RekeyedProject underTest = new RekeyedProject(project, previousKey); + + assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); + assertThat(underTest.hashCode()).isEqualTo(new RekeyedProject(project, previousKey).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new RekeyedProject(project, randomAlphanumeric(11)).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new RekeyedProject(newRandomProject(), previousKey).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(null); + } + + @Test + public void verify_toString() { + Project project = new Project("A", "B", "C", "D", emptyList()); + String previousKey = "E"; + RekeyedProject underTest = new RekeyedProject(project, previousKey); + + assertThat(underTest.toString()).isEqualTo("RekeyedProject{project=Project{uuid='A', key='B', name='C', description='D'}, previousKey='E'}"); + } + + private static Project newRandomProject() { + return Project.from(newPrivateProjectDto(newOrganizationDto())); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java new file mode 100644 index 00000000000..964637487fb --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java @@ -0,0 +1,358 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate.changeevent; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang.RandomStringUtils; +import org.assertj.core.groups.Tuple; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.Mockito; +import org.sonar.api.issue.Issue; +import org.sonar.api.rules.RuleType; +import org.sonar.api.utils.log.LogTester; +import org.sonar.api.utils.log.LoggerLevel; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.db.component.ComponentDto; +import org.sonar.server.qualitygate.changeevent.QGChangeEventListener.ChangedIssue; +import org.sonar.server.qualitygate.changeevent.QGChangeEventListenersImpl.ChangedIssueImpl; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class QGChangeEventListenersImplTest { + @Rule + public LogTester logTester = new LogTester(); + + private QGChangeEventListener listener1 = mock(QGChangeEventListener.class); + private QGChangeEventListener listener2 = mock(QGChangeEventListener.class); + private QGChangeEventListener listener3 = mock(QGChangeEventListener.class); + private List listeners = Arrays.asList(listener1, listener2, listener3); + + private String component1Uuid = RandomStringUtils.randomAlphabetic(6); + private ComponentDto component1 = newComponentDto(component1Uuid); + private DefaultIssue component1Issue = newDefaultIssue(component1Uuid); + private List oneIssueOnComponent1 = singletonList(component1Issue); + private QGChangeEvent component1QGChangeEvent = newQGChangeEvent(component1); + + private InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + + private QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new QGChangeEventListener[] {listener1, listener2, listener3}); + + @Test + public void broadcastOnIssueChange_has_no_effect_when_issues_are_empty() { + underTest.broadcastOnIssueChange(emptyList(), singletonList(component1QGChangeEvent)); + + verifyZeroInteractions(listener1, listener2, listener3); + } + + @Test + public void broadcastOnIssueChange_has_no_effect_when_no_changeEvent() { + underTest.broadcastOnIssueChange(oneIssueOnComponent1, emptySet()); + + verifyZeroInteractions(listener1, listener2, listener3); + } + + @Test + public void broadcastOnIssueChange_passes_same_arguments_to_all_listeners_in_order_of_addition_to_constructor() { + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + + ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); + inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); + Set changedIssues = changedIssuesCaptor.getValue(); + inOrder.verify(listener2).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); + inOrder.verify(listener3).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void broadcastOnIssueChange_calls_all_listeners_even_if_one_throws_an_exception() { + QGChangeEventListener failingListener = new QGChangeEventListener[] {listener1, listener2, listener3}[new Random().nextInt(3)]; + doThrow(new RuntimeException("Faking an exception thrown by onChanges")) + .when(failingListener) + .onIssueChanges(any(), any()); + + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + + ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); + inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); + Set changedIssues = changedIssuesCaptor.getValue(); + inOrder.verify(listener2).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); + inOrder.verify(listener3).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); + inOrder.verifyNoMoreInteractions(); + assertThat(logTester.logs()).hasSize(4); + assertThat(logTester.logs(LoggerLevel.WARN)).hasSize(1); + } + + @Test + public void broadcastOnIssueChange_stops_calling_listeners_when_one_throws_an_ERROR() { + doThrow(new Error("Faking an error thrown by a listener")) + .when(listener2) + .onIssueChanges(any(), any()); + + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + + ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); + inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); + Set changedIssues = changedIssuesCaptor.getValue(); + inOrder.verify(listener2).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); + inOrder.verifyNoMoreInteractions(); + assertThat(logTester.logs()).hasSize(3); + assertThat(logTester.logs(LoggerLevel.WARN)).hasSize(1); + } + + @Test + public void broadcastOnIssueChange_logs_each_listener_call_at_TRACE_level() { + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + + assertThat(logTester.logs()).hasSize(3); + List traceLogs = logTester.logs(LoggerLevel.TRACE); + assertThat(traceLogs).hasSize(3) + .containsOnly( + "calling onChange() on listener " + listener1.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "...", + "calling onChange() on listener " + listener2.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "...", + "calling onChange() on listener " + listener3.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "..."); + } + + @Test + public void broadcastOnIssueChange_passes_immutable_set_of_ChangedIssues() { + QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new QGChangeEventListener[] {listener1}); + + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + + ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); + inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); + assertThat(changedIssuesCaptor.getValue()).isInstanceOf(ImmutableSet.class); + } + + @Test + public void broadcastOnIssueChange_has_no_effect_when_no_listener() { + QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(); + + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + + verifyZeroInteractions(listener1, listener2, listener3); + } + + @Test + public void broadcastOnIssueChange_calls_listener_for_each_component_uuid_with_at_least_one_QGChangeEvent() { + // component2 has multiple issues + ComponentDto component2 = newComponentDto(component1Uuid + "2"); + DefaultIssue[] component2Issues = {newDefaultIssue(component2.uuid()), newDefaultIssue(component2.uuid())}; + QGChangeEvent component2QGChangeEvent = newQGChangeEvent(component2); + + // component 3 has multiple QGChangeEvent and only one issue + ComponentDto component3 = newComponentDto(component1Uuid + "3"); + DefaultIssue component3Issue = newDefaultIssue(component3.uuid()); + QGChangeEvent[] component3QGChangeEvents = {newQGChangeEvent(component3), newQGChangeEvent(component3)}; + + // component 4 has multiple QGChangeEvent and multiples issues + ComponentDto component4 = newComponentDto(component1Uuid + "4"); + DefaultIssue[] component4Issues = {newDefaultIssue(component4.uuid()), newDefaultIssue(component4.uuid())}; + QGChangeEvent[] component4QGChangeEvents = {newQGChangeEvent(component4), newQGChangeEvent(component4)}; + + // component 5 has no QGChangeEvent but one issue + ComponentDto component5 = newComponentDto(component1Uuid + "5"); + DefaultIssue component5Issue = newDefaultIssue(component5.uuid()); + + List issues = Stream.of( + Stream.of(component1Issue), + Arrays.stream(component2Issues), + Stream.of(component3Issue), + Arrays.stream(component4Issues), + Stream.of(component5Issue)) + .flatMap(s -> s) + .collect(Collectors.toList()); + + List changedIssues = randomizedList(issues); + List qgChangeEvents = Stream.of( + Stream.of(component1QGChangeEvent), + Stream.of(component2QGChangeEvent), + Arrays.stream(component3QGChangeEvents), + Arrays.stream(component4QGChangeEvents)) + .flatMap(s -> s) + .collect(Collectors.toList()); + + underTest.broadcastOnIssueChange(changedIssues, randomizedList(qgChangeEvents)); + + listeners.forEach(listener -> { + verifyListenerCalled(listener, component1QGChangeEvent, component1Issue); + verifyListenerCalled(listener, component2QGChangeEvent, component2Issues); + Arrays.stream(component3QGChangeEvents) + .forEach(component3QGChangeEvent -> verifyListenerCalled(listener, component3QGChangeEvent, component3Issue)); + Arrays.stream(component4QGChangeEvents) + .forEach(component4QGChangeEvent -> verifyListenerCalled(listener, component4QGChangeEvent, component4Issues)); + }); + verifyNoMoreInteractions(listener1, listener2, listener3); + } + + @Test + public void isNotClosed_returns_true_if_issue_in_one_of_opened_states() { + DefaultIssue defaultIssue = new DefaultIssue(); + defaultIssue.setStatus(Issue.STATUS_REOPENED); + defaultIssue.setKey("abc"); + defaultIssue.setType(RuleType.BUG); + defaultIssue.setSeverity("BLOCKER"); + + ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue); + + assertThat(changedIssue.isNotClosed()).isTrue(); + } + + @Test + public void isNotClosed_returns_false_if_issue_in_one_of_closed_states() { + DefaultIssue defaultIssue = new DefaultIssue(); + defaultIssue.setStatus(Issue.STATUS_CONFIRMED); + defaultIssue.setKey("abc"); + defaultIssue.setType(RuleType.BUG); + defaultIssue.setSeverity("BLOCKER"); + + ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue); + + assertThat(changedIssue.isNotClosed()).isFalse(); + } + + @Test + public void test_status_mapping() { + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_OPEN))).isEqualTo(QGChangeEventListener.Status.OPEN); + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_REOPENED))).isEqualTo(QGChangeEventListener.Status.REOPENED); + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_CONFIRMED))).isEqualTo(QGChangeEventListener.Status.CONFIRMED); + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE))) + .isEqualTo(QGChangeEventListener.Status.RESOLVED_FP); + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX))) + .isEqualTo(QGChangeEventListener.Status.RESOLVED_WF); + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FIXED))) + .isEqualTo(QGChangeEventListener.Status.RESOLVED_FIXED); + try { + ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_CLOSED)); + fail("Expected exception"); + } catch (Exception e) { + assertThat(e).hasMessage("Unexpected status: CLOSED"); + } + try { + ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED)); + fail("Expected exception"); + } catch (Exception e) { + assertThat(e).hasMessage("A resolved issue should have a resolution"); + } + try { + ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_REMOVED)); + fail("Expected exception"); + } catch (Exception e) { + assertThat(e).hasMessage("Unexpected resolution for a resolved issue: REMOVED"); + } + } + + @Test + public void test_status_mapping_on_security_hotspots() { + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW))) + .isEqualTo(QGChangeEventListener.Status.TO_REVIEW); + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW))) + .isEqualTo(QGChangeEventListener.Status.IN_REVIEW); + assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED))) + .isEqualTo(QGChangeEventListener.Status.REVIEWED); + } + + private void verifyListenerCalled(QGChangeEventListener listener, QGChangeEvent changeEvent, DefaultIssue... issues) { + ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); + verify(listener).onIssueChanges(same(changeEvent), changedIssuesCaptor.capture()); + Set changedIssues = changedIssuesCaptor.getValue(); + Tuple[] expected = Arrays.stream(issues) + .map(issue -> tuple(issue.key(), ChangedIssueImpl.statusOf(issue), issue.type())) + .toArray(Tuple[]::new); + assertThat(changedIssues) + .hasSize(issues.length) + .extracting(ChangedIssue::getKey, ChangedIssue::getStatus, ChangedIssue::getType) + .containsOnly(expected); + } + + private static final String[] POSSIBLE_STATUSES = asList(Issue.STATUS_CONFIRMED, Issue.STATUS_REOPENED, Issue.STATUS_RESOLVED).stream().toArray(String[]::new); + private static int issueIdCounter = 0; + + private static DefaultIssue newDefaultIssue(String projectUuid) { + DefaultIssue defaultIssue = new DefaultIssue(); + defaultIssue.setKey("issue_" + issueIdCounter++); + defaultIssue.setProjectUuid(projectUuid); + defaultIssue.setType(RuleType.values()[new Random().nextInt(RuleType.values().length)]); + defaultIssue.setStatus(POSSIBLE_STATUSES[new Random().nextInt(POSSIBLE_STATUSES.length)]); + String[] possibleResolutions = possibleResolutions(defaultIssue.getStatus()); + if (possibleResolutions.length > 0) { + defaultIssue.setResolution(possibleResolutions[new Random().nextInt(possibleResolutions.length)]); + } + return defaultIssue; + } + + private static String[] possibleResolutions(String status) { + switch (status) { + case Issue.STATUS_RESOLVED: + return new String[] {Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_WONT_FIX}; + default: + return new String[0]; + } + } + + private static ComponentDto newComponentDto(String uuid) { + ComponentDto componentDto = new ComponentDto(); + componentDto.setUuid(uuid); + return componentDto; + } + + private static QGChangeEvent newQGChangeEvent(ComponentDto componentDto) { + QGChangeEvent res = mock(QGChangeEvent.class); + when(res.getProject()).thenReturn(componentDto); + return res; + } + + private static ArgumentCaptor> newSetCaptor() { + Class> clazz = (Class>) (Class) Set.class; + return ArgumentCaptor.forClass(clazz); + } + + private static List randomizedList(List issues) { + ArrayList res = new ArrayList<>(issues); + Collections.shuffle(res); + return ImmutableList.copyOf(res); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java new file mode 100644 index 00000000000..eb4ce5d6c60 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java @@ -0,0 +1,133 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate.changeevent; + +import java.util.Optional; +import java.util.Random; +import java.util.function.Supplier; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; +import org.sonar.api.config.Configuration; +import org.sonar.api.measures.Metric; +import org.sonar.db.component.BranchDto; +import org.sonar.db.component.BranchType; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.SnapshotDto; +import org.sonar.server.qualitygate.EvaluatedQualityGate; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QGChangeEventTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private ComponentDto project = new ComponentDto() + .setDbKey("foo") + .setUuid("bar"); + private BranchDto branch = new BranchDto() + .setBranchType(BranchType.SHORT) + .setUuid("bar") + .setProjectUuid("doh") + .setMergeBranchUuid("zop"); + private SnapshotDto analysis = new SnapshotDto() + .setUuid("pto") + .setCreatedAt(8_999_999_765L); + private Configuration configuration = Mockito.mock(Configuration.class); + private Metric.Level previousStatus = Metric.Level.values()[new Random().nextInt(Metric.Level.values().length)]; + private Supplier> supplier = Optional::empty; + + @Test + public void constructor_fails_with_NPE_if_project_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("project can't be null"); + + new QGChangeEvent(null, branch, analysis, configuration, previousStatus, supplier); + } + + @Test + public void constructor_fails_with_NPE_if_branch_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("branch can't be null"); + + new QGChangeEvent(project, null, analysis, configuration, previousStatus, supplier); + } + + @Test + public void constructor_fails_with_NPE_if_analysis_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("analysis can't be null"); + + new QGChangeEvent(project, branch, null, configuration, previousStatus, supplier); + } + + @Test + public void constructor_fails_with_NPE_if_configuration_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("projectConfiguration can't be null"); + + new QGChangeEvent(project, branch, analysis, null, previousStatus, supplier); + } + + @Test + public void constructor_does_not_fail_with_NPE_if_previousStatus_is_null() { + new QGChangeEvent(project, branch, analysis, configuration, null, supplier); + } + + @Test + public void constructor_fails_with_NPE_if_supplier_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("qualityGateSupplier can't be null"); + + new QGChangeEvent(project, branch, analysis, configuration, previousStatus, null); + } + + @Test + public void verify_getters() { + QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); + + assertThat(underTest.getProject()).isSameAs(project); + assertThat(underTest.getBranch()).isSameAs(branch); + assertThat(underTest.getAnalysis()).isSameAs(analysis); + assertThat(underTest.getProjectConfiguration()).isSameAs(configuration); + assertThat(underTest.getPreviousStatus()).contains(previousStatus); + assertThat(underTest.getQualityGateSupplier()).isSameAs(supplier); + } + + @Test + public void getPreviousStatus_returns_empty_when_previousStatus_is_null() { + QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); + + assertThat(underTest.getPreviousStatus()).contains(previousStatus); + } + + @Test + public void overrides_toString() { + QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); + + assertThat(underTest.toString()) + .isEqualTo("QGChangeEvent{project=bar:foo, branch=SHORT:bar:doh:zop, analysis=pto:8999999765" + + ", projectConfiguration=" + configuration.toString() + + ", previousStatus=" + previousStatus + + ", qualityGateSupplier=" + supplier + "}"); + + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/ProjectConfigurationLoaderImplTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/ProjectConfigurationLoaderImplTest.java new file mode 100644 index 00000000000..0fb88ee9b05 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/ProjectConfigurationLoaderImplTest.java @@ -0,0 +1,178 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.setting; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import java.util.Collections; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.config.Configuration; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.property.PropertiesDao; +import org.sonar.db.property.PropertyDto; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singleton; +import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class ProjectConfigurationLoaderImplTest { + private DbClient dbClient = mock(DbClient.class); + private DbSession dbSession = mock(DbSession.class); + private PropertiesDao propertiesDao = mock(PropertiesDao.class); + private MapSettings globalSettings = new MapSettings(); + private ProjectConfigurationLoaderImpl underTest = new ProjectConfigurationLoaderImpl(globalSettings, dbClient); + + @Before + public void setUp() throws Exception { + when(dbClient.openSession(anyBoolean())) + .thenThrow(new IllegalStateException("ProjectConfigurationLoaderImpl should not open DB session")); + when(dbClient.propertiesDao()).thenReturn(propertiesDao); + } + + @Test + public void returns_empty_map_when_no_component() { + assertThat(underTest.loadProjectConfigurations(dbSession, Collections.emptySet())) + .isEmpty(); + + verifyZeroInteractions(propertiesDao); + } + + @Test + public void return_configuration_with_just_global_settings_when_no_component_settings() { + String key = randomAlphanumeric(3); + String value = randomAlphanumeric(4); + String componentDbKey = randomAlphanumeric(5); + String componentUuid = randomAlphanumeric(6); + globalSettings.setProperty(key, value); + when(propertiesDao.selectProjectProperties(dbSession, componentDbKey)) + .thenReturn(emptyList()); + ComponentDto component = newComponentDto(componentDbKey, componentUuid); + + Map configurations = underTest.loadProjectConfigurations(dbSession, singleton(component)); + + assertThat(configurations) + .containsOnlyKeys(componentUuid); + assertThat(configurations.get(componentUuid).get(key)).contains(value); + } + + @Test + public void return_configuration_with_global_settings_and_component_settings() { + String globalKey = randomAlphanumeric(3); + String globalValue = randomAlphanumeric(4); + String componentDbKey = randomAlphanumeric(5); + String componentUuid = randomAlphanumeric(6); + String projectPropKey1 = randomAlphanumeric(7); + String projectPropValue1 = randomAlphanumeric(8); + String projectPropKey2 = randomAlphanumeric(9); + String projectPropValue2 = randomAlphanumeric(10); + globalSettings.setProperty(globalKey, globalValue); + when(propertiesDao.selectProjectProperties(dbSession, componentDbKey)) + .thenReturn(ImmutableList.of(newPropertyDto(projectPropKey1, projectPropValue1), newPropertyDto(projectPropKey2, projectPropValue2))); + ComponentDto component = newComponentDto(componentDbKey, componentUuid); + + Map configurations = underTest.loadProjectConfigurations(dbSession, singleton(component)); + + assertThat(configurations) + .containsOnlyKeys(componentUuid); + assertThat(configurations.get(componentUuid).get(globalKey)).contains(globalValue); + assertThat(configurations.get(componentUuid).get(projectPropKey1)).contains(projectPropValue1); + assertThat(configurations.get(componentUuid).get(projectPropKey2)).contains(projectPropValue2); + } + + @Test + public void return_configuration_with_global_settings_main_branch_settings_and_branch_settings() { + String globalKey = randomAlphanumeric(3); + String globalValue = randomAlphanumeric(4); + String mainBranchDbKey = randomAlphanumeric(5); + String branchDbKey = mainBranchDbKey + ComponentDto.BRANCH_KEY_SEPARATOR + randomAlphabetic(5); + String branchUuid = randomAlphanumeric(6); + String mainBranchPropKey = randomAlphanumeric(7); + String mainBranchPropValue = randomAlphanumeric(8); + String branchPropKey = randomAlphanumeric(9); + String branchPropValue = randomAlphanumeric(10); + globalSettings.setProperty(globalKey, globalValue); + when(propertiesDao.selectProjectProperties(dbSession, mainBranchDbKey)) + .thenReturn(ImmutableList.of(newPropertyDto(mainBranchPropKey, mainBranchPropValue))); + when(propertiesDao.selectProjectProperties(dbSession, branchDbKey)) + .thenReturn(ImmutableList.of(newPropertyDto(branchPropKey, branchPropValue))); + ComponentDto component = newComponentDto(branchDbKey, branchUuid); + + Map configurations = underTest.loadProjectConfigurations(dbSession, singleton(component)); + + assertThat(configurations) + .containsOnlyKeys(branchUuid); + assertThat(configurations.get(branchUuid).get(globalKey)).contains(globalValue); + assertThat(configurations.get(branchUuid).get(mainBranchPropKey)).contains(mainBranchPropValue); + assertThat(configurations.get(branchUuid).get(branchPropKey)).contains(branchPropValue); + } + + @Test + public void loads_configuration_of_any_given_component_only_once() { + String mainBranch1DbKey = randomAlphanumeric(4); + String mainBranch1Uuid = randomAlphanumeric(5); + String branch1DbKey = mainBranch1DbKey + ComponentDto.BRANCH_KEY_SEPARATOR + randomAlphabetic(5); + String branch1Uuid = randomAlphanumeric(6); + String branch2DbKey = mainBranch1DbKey + ComponentDto.BRANCH_KEY_SEPARATOR + randomAlphabetic(7); + String branch2Uuid = randomAlphanumeric(8); + String mainBranch2DbKey = randomAlphanumeric(14); + String mainBranch2Uuid = randomAlphanumeric(15); + String branch3DbKey = mainBranch2DbKey + ComponentDto.BRANCH_KEY_SEPARATOR + randomAlphabetic(5); + String branch3Uuid = randomAlphanumeric(16); + + ComponentDto mainBranch1 = newComponentDto(mainBranch1DbKey, mainBranch1Uuid); + ComponentDto branch1 = newComponentDto(branch1DbKey, branch1Uuid); + ComponentDto branch2 = newComponentDto(branch2DbKey, branch2Uuid); + ComponentDto mainBranch2 = newComponentDto(mainBranch2DbKey, mainBranch2Uuid); + ComponentDto branch3 = newComponentDto(branch3DbKey, branch3Uuid); + + underTest.loadProjectConfigurations(dbSession, ImmutableSet.of(mainBranch1, mainBranch2, branch1, branch2, branch3)); + + verify(propertiesDao, times(1)).selectProjectProperties(dbSession, mainBranch1DbKey); + verify(propertiesDao, times(1)).selectProjectProperties(dbSession, mainBranch2DbKey); + verify(propertiesDao, times(1)).selectProjectProperties(dbSession, branch1DbKey); + verify(propertiesDao, times(1)).selectProjectProperties(dbSession, branch2DbKey); + verify(propertiesDao, times(1)).selectProjectProperties(dbSession, branch3DbKey); + verifyNoMoreInteractions(propertiesDao); + } + + private ComponentDto newComponentDto(String componentDbKey, String componentUuid) { + return new ComponentDto().setDbKey(componentDbKey).setUuid(componentUuid); + } + + private PropertyDto newPropertyDto(String projectKey1, String projectValue1) { + return new PropertyDto() + .setKey(projectKey1) + .setValue(projectValue1); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/SettingsChangeNotifierTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/SettingsChangeNotifierTest.java new file mode 100644 index 00000000000..577eda83519 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/SettingsChangeNotifierTest.java @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.setting; + +import org.junit.Test; +import org.sonar.api.config.GlobalPropertyChangeHandler; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class SettingsChangeNotifierTest { + @Test + public void onGlobalPropertyChange() { + GlobalPropertyChangeHandler handler = mock(GlobalPropertyChangeHandler.class); + SettingsChangeNotifier notifier = new SettingsChangeNotifier(new GlobalPropertyChangeHandler[] {handler}); + + notifier.onGlobalPropertyChange("foo", "bar"); + + verify(handler).onChange(argThat(change -> change.getKey().equals("foo") && change.getNewValue().equals("bar"))); + } + + @Test + public void no_handlers() { + SettingsChangeNotifier notifier = new SettingsChangeNotifier(); + + assertThat(notifier.changeHandlers).isEmpty(); + + // does not fail + notifier.onGlobalPropertyChange("foo", "bar"); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java new file mode 100644 index 00000000000..e0c0b6d2854 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.setting; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.sonar.api.config.Configuration; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; + +public class TestProjectConfigurationLoader implements ProjectConfigurationLoader { + + private final Configuration config; + + public TestProjectConfigurationLoader(Configuration config) { + this.config = config; + } + + @Override + public Map loadProjectConfigurations(DbSession dbSession, Set projects) { + Map map = new HashMap<>(); + for (ComponentDto project : projects) { + map.put(project.uuid(), config); + } + return map; + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java new file mode 100644 index 00000000000..d11c03152b8 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java @@ -0,0 +1,57 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.server.exceptions.BadRequestException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BooleanTypeValidationTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private BooleanTypeValidation underTest = new BooleanTypeValidation(); + + @Test + public void key() { + assertThat(underTest.key()).isEqualTo("BOOLEAN"); + } + + @Test + public void not_fail_on_valid_boolean() { + underTest.validate("true", null); + underTest.validate("True", null); + underTest.validate("false", null); + underTest.validate("FALSE", null); + } + + @Test + public void fail_on_invalid_boolean() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value 'abc' must be one of \"true\" or \"false\"."); + + underTest.validate("abc", null); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java new file mode 100644 index 00000000000..b88c3fbb651 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.server.exceptions.BadRequestException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class FloatTypeValidationTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private FloatTypeValidation validation = new FloatTypeValidation(); + + @Test + public void key() { + assertThat(validation.key()).isEqualTo("FLOAT"); + } + + @Test + public void not_fail_on_valid_float() { + validation.validate("10.2", null); + validation.validate("10", null); + validation.validate("-10.3", null); + } + + @Test + public void fail_on_invalid_float() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value 'abc' must be an floating point number."); + + validation.validate("abc", null); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/GlobalLockManagerTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/GlobalLockManagerTest.java new file mode 100644 index 00000000000..8a069e1eae2 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/GlobalLockManagerTest.java @@ -0,0 +1,76 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.server.util.GlobalLockManager.DEFAULT_LOCK_DURATION_SECONDS; + +public class GlobalLockManagerTest { + + private final System2 system2 = mock(System2.class); + + @Rule + public final DbTester dbTester = DbTester.create(system2); + + private final GlobalLockManager underTest = new GlobalLockManager(dbTester.getDbClient()); + + @Test + public void tryLock_succeeds_when_created_for_the_first_time() { + assertThat(underTest.tryLock("newName")).isTrue(); + } + + @Test + public void tryLock_fails_when_previous_lock_is_too_recent() { + String name = "newName"; + assertThat(underTest.tryLock(name)).isTrue(); + assertThat(underTest.tryLock(name)).isFalse(); + } + + @Test + public void tryLock_succeeds_when_previous_lock_is_old_enough() { + String name = "newName"; + long firstLock = 0; + long longEnoughAfterFirstLock = firstLock + DEFAULT_LOCK_DURATION_SECONDS * 1000; + long notLongEnoughAfterFirstLock = longEnoughAfterFirstLock - 1; + + when(system2.now()).thenReturn(firstLock); + assertThat(underTest.tryLock(name)).isTrue(); + + when(system2.now()).thenReturn(notLongEnoughAfterFirstLock); + assertThat(underTest.tryLock(name)).isFalse(); + + when(system2.now()).thenReturn(longEnoughAfterFirstLock); + assertThat(underTest.tryLock(name)).isTrue(); + } + + @Test + public void locks_with_different_name_are_independent() { + assertThat(underTest.tryLock("newName1")).isTrue(); + assertThat(underTest.tryLock("newName2")).isTrue(); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java new file mode 100644 index 00000000000..e9b1953dd5a --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.server.exceptions.BadRequestException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class IntegerTypeValidationTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private IntegerTypeValidation validation = new IntegerTypeValidation(); + + @Test + public void key() { + assertThat(validation.key()).isEqualTo("INTEGER"); + } + + @Test + public void not_fail_on_valid_integer() { + validation.validate("10", null); + validation.validate("-10", null); + } + + @Test + public void fail_on_string() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value 'abc' must be an integer."); + + validation.validate("abc", null); + } + + @Test + public void fail_on_float() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value '10.1' must be an integer."); + + validation.validate("10.1", null); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/LongTypeValidationTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/LongTypeValidationTest.java new file mode 100644 index 00000000000..2f7d7e0946e --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/LongTypeValidationTest.java @@ -0,0 +1,62 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.PropertyType; +import org.sonar.server.exceptions.BadRequestException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LongTypeValidationTest { + + LongTypeValidation underTest = new LongTypeValidation(); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void key_is_long_type_name() { + assertThat(underTest.key()).isEqualTo(PropertyType.LONG.name()); + } + + @Test + public void do_not_fail_with_long_values() { + underTest.validate("1984", null); + underTest.validate("-1984", null); + } + + @Test + public void fail_when_float() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value '3.14' must be a long."); + + underTest.validate("3.14", null); + } + + @Test + public void fail_when_string() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value 'original string' must be a long."); + + underTest.validate("original string", null); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java new file mode 100644 index 00000000000..9f2630fd0de --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.server.exceptions.BadRequestException; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; + +public class StringListTypeValidationTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private StringListTypeValidation validation = new StringListTypeValidation(); + + @Test + public void key() { + assertThat(validation.key()).isEqualTo("SINGLE_SELECT_LIST"); + } + + @Test + public void not_fail_on_valid_option() { + validation.validate("a", newArrayList("a", "b", "c")); + validation.validate("a", null); + } + + @Test + public void fail_on_invalid_option() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value 'abc' must be one of : a, b, c."); + + validation.validate("abc", newArrayList("a", "b", "c")); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/StringTypeValidationTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/StringTypeValidationTest.java new file mode 100644 index 00000000000..dde3afa3543 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/StringTypeValidationTest.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class StringTypeValidationTest { + + StringTypeValidation validation; + + @Before + public void setUp() { + validation = new StringTypeValidation(); + } + + @Test + public void key() { + assertThat(validation.key()).isEqualTo("STRING"); + } + + @Test + public void not_fail_on_valid_string() { + validation.validate("10", null); + validation.validate("abc", null); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TextTypeValidationTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TextTypeValidationTest.java new file mode 100644 index 00000000000..4261f95c580 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TextTypeValidationTest.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TextTypeValidationTest { + + TextTypeValidation validation; + + @Before + public void setUp() { + validation = new TextTypeValidation(); + } + + @Test + public void key() { + assertThat(validation.key()).isEqualTo("TEXT"); + } + + @Test + public void not_fail_on_valid_text() { + validation.validate("10", null); + validation.validate("abc", null); + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationModuleTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationModuleTest.java new file mode 100644 index 00000000000..3ff709c8f0f --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationModuleTest.java @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Test; +import org.sonar.core.platform.ComponentContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TypeValidationModuleTest { + @Test + public void verify_count_of_added_components() { + ComponentContainer container = new ComponentContainer(); + new TypeValidationModule().configure(container); + assertThat(container.size()).isEqualTo(11); + } +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationsTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationsTest.java new file mode 100644 index 00000000000..4dbae47cb37 --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationsTest.java @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import org.junit.Test; +import org.sonar.server.exceptions.BadRequestException; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class TypeValidationsTest { + + @Test + public void validate() { + TypeValidation fakeTypeValidation = mock(TypeValidation.class); + when(fakeTypeValidation.key()).thenReturn("Fake"); + + TypeValidations typeValidations = new TypeValidations(newArrayList(fakeTypeValidation)); + typeValidations.validate("10", "Fake", newArrayList("a")); + + verify(fakeTypeValidation).validate("10", newArrayList("a")); + } + + @Test + public void validate__multiple_values() { + TypeValidation fakeTypeValidation = mock(TypeValidation.class); + when(fakeTypeValidation.key()).thenReturn("Fake"); + + TypeValidations typeValidations = new TypeValidations(newArrayList(fakeTypeValidation)); + typeValidations.validate(newArrayList("10", "11", "12"), "Fake", newArrayList("11")); + + verify(fakeTypeValidation).validate("10", newArrayList("11")); + } + + @Test + public void fail_on_unknown_type() { + TypeValidation fakeTypeValidation = mock(TypeValidation.class); + when(fakeTypeValidation.key()).thenReturn("Fake"); + + try { + TypeValidations typeValidations = new TypeValidations(newArrayList(fakeTypeValidation)); + typeValidations.validate("10", "Unknown", null); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(BadRequestException.class); + BadRequestException badRequestException = (BadRequestException) e; + assertThat(badRequestException.getMessage()).isEqualTo("Type 'Unknown' is not valid."); + } + } + +} diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationsTesting.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationsTesting.java new file mode 100644 index 00000000000..b237ba62aab --- /dev/null +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/util/TypeValidationsTesting.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.util; + +import java.util.Arrays; + +public class TypeValidationsTesting { + private TypeValidationsTesting() { + // utility class + } + + public static TypeValidations newFullTypeValidations() { + return new TypeValidations(Arrays.asList( + new BooleanTypeValidation(), + new IntegerTypeValidation(), + new LongTypeValidation(), + new FloatTypeValidation(), + new StringTypeValidation(), + new StringListTypeValidation(), + new MetricLevelTypeValidation() + )); + } +} diff --git a/server/sonar-webserver-api/src/test/projects/.gitignore b/server/sonar-webserver-api/src/test/projects/.gitignore new file mode 100644 index 00000000000..a945b8525e6 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/.gitignore @@ -0,0 +1,7 @@ +# see README.txt +!*/target/ +*/target/classes/ +*/target/maven-archiver/ +*/target/maven-status/ +*/target/test-*/ + diff --git a/server/sonar-webserver-api/src/test/projects/README.txt b/server/sonar-webserver-api/src/test/projects/README.txt new file mode 100644 index 00000000000..c53a66d52f2 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/README.txt @@ -0,0 +1,3 @@ +This directory provides the fake plugins used by tests. These tests are rarely changed, so generated +artifacts are stored in Git repository (see .gitignore). It avoids from adding unnecessary modules +to build. diff --git a/server/sonar-webserver-api/src/test/projects/fake-report-plugin/pom.xml b/server/sonar-webserver-api/src/test/projects/fake-report-plugin/pom.xml new file mode 100644 index 00000000000..72a04dbe04f --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-report-plugin/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + fake-report-plugin + 0.1-SNAPSHOT + sonar-plugin + Fake Report Plugin + Fake Report Plugin + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + report + BasePlugin + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/fake-report-plugin/src/BasePlugin.java b/server/sonar-webserver-api/src/test/projects/fake-report-plugin/src/BasePlugin.java new file mode 100644 index 00000000000..d12daff3e57 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-report-plugin/src/BasePlugin.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class BasePlugin extends Plugin { + + public void define(Plugin.Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/projects/fake-report-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-api/src/test/projects/fake-report-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java new file mode 100644 index 00000000000..e0b54398eaf --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-report-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java @@ -0,0 +1,25 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.plugins.testbase.api; + +public class BaseApi { + public void doNothing() { + } +} diff --git a/server/sonar-webserver-api/src/test/projects/fake-report-plugin/target/fake-report-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/fake-report-plugin/target/fake-report-plugin-0.1-SNAPSHOT.jar new file mode 100644 index 00000000000..6085e44fdca Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/fake-report-plugin/target/fake-report-plugin-0.1-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/pom.xml b/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/pom.xml new file mode 100644 index 00000000000..e417dd96fba --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + fake-sqale-plugin + 0.1-SNAPSHOT + sonar-plugin + Fake SQALE Plugin + Fake SQALE Plugin + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + sqale + BasePlugin + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/src/BasePlugin.java b/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/src/BasePlugin.java new file mode 100644 index 00000000000..d12daff3e57 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/src/BasePlugin.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class BasePlugin extends Plugin { + + public void define(Plugin.Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java new file mode 100644 index 00000000000..e0b54398eaf --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java @@ -0,0 +1,25 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.plugins.testbase.api; + +public class BaseApi { + public void doNothing() { + } +} diff --git a/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/target/fake-sqale-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/target/fake-sqale-plugin-0.1-SNAPSHOT.jar new file mode 100644 index 00000000000..b5c99f721b3 Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/fake-sqale-plugin/target/fake-sqale-plugin-0.1-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/projects/fake-views-plugin/pom.xml b/server/sonar-webserver-api/src/test/projects/fake-views-plugin/pom.xml new file mode 100644 index 00000000000..1ef73d2ffda --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-views-plugin/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + fake-views-plugin + 0.1-SNAPSHOT + sonar-plugin + Fake Views Plugin + Fake Views Plugin + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + views + BasePlugin + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/fake-views-plugin/src/BasePlugin.java b/server/sonar-webserver-api/src/test/projects/fake-views-plugin/src/BasePlugin.java new file mode 100644 index 00000000000..d12daff3e57 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-views-plugin/src/BasePlugin.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class BasePlugin extends Plugin { + + public void define(Plugin.Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/projects/fake-views-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-api/src/test/projects/fake-views-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java new file mode 100644 index 00000000000..e0b54398eaf --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/fake-views-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java @@ -0,0 +1,25 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.plugins.testbase.api; + +public class BaseApi { + public void doNothing() { + } +} diff --git a/server/sonar-webserver-api/src/test/projects/fake-views-plugin/target/fake-views-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/fake-views-plugin/target/fake-views-plugin-0.1-SNAPSHOT.jar new file mode 100644 index 00000000000..a47d93d94a8 Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/fake-views-plugin/target/fake-views-plugin-0.1-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/projects/pom.xml b/server/sonar-webserver-api/src/test/projects/pom.xml new file mode 100644 index 00000000000..37338313ac0 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + parent + 0.1-SNAPSHOT + pom + + test-base-plugin + test-base-plugin-v2 + test-core-plugin + test-extend-plugin + test-libs-plugin + test-require-plugin + test-requirenew-plugin + fake-report-plugin + fake-sqale-plugin + fake-views-plugin + + + diff --git a/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/pom.xml b/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/pom.xml new file mode 100644 index 00000000000..982be1c0170 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + test-base-plugin + 0.2-SNAPSHOT + sonar-plugin + Base Plugin + Simple standalone plugin. Used by other fake plugins. + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + testbase + BasePlugin + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/src/BasePlugin.java b/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/src/BasePlugin.java new file mode 100644 index 00000000000..d12daff3e57 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/src/BasePlugin.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class BasePlugin extends Plugin { + + public void define(Plugin.Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/src/org/sonar/plugins/testbase/api/BaseApi.java new file mode 100644 index 00000000000..e0b54398eaf --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/src/org/sonar/plugins/testbase/api/BaseApi.java @@ -0,0 +1,25 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.plugins.testbase.api; + +public class BaseApi { + public void doNothing() { + } +} diff --git a/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar new file mode 100644 index 00000000000..1d4ef5430c7 Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/projects/test-base-plugin/pom.xml b/server/sonar-webserver-api/src/test/projects/test-base-plugin/pom.xml new file mode 100644 index 00000000000..c4e95936e74 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-base-plugin/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + test-base-plugin + 0.1-SNAPSHOT + sonar-plugin + Base Plugin + Simple standalone plugin. Used by other fake plugins. + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + testbase + BasePlugin + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/test-base-plugin/src/BasePlugin.java b/server/sonar-webserver-api/src/test/projects/test-base-plugin/src/BasePlugin.java new file mode 100644 index 00000000000..d12daff3e57 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-base-plugin/src/BasePlugin.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class BasePlugin extends Plugin { + + public void define(Plugin.Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/projects/test-base-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-api/src/test/projects/test-base-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java new file mode 100644 index 00000000000..e0b54398eaf --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-base-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java @@ -0,0 +1,25 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.plugins.testbase.api; + +public class BaseApi { + public void doNothing() { + } +} diff --git a/server/sonar-webserver-api/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar new file mode 100644 index 00000000000..739a22fcdae Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/projects/test-extend-plugin/pom.xml b/server/sonar-webserver-api/src/test/projects/test-extend-plugin/pom.xml new file mode 100644 index 00000000000..e23667e6318 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-extend-plugin/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + test-extend-plugin + 0.1-SNAPSHOT + sonar-plugin + Test Extend Plugin + Fake plugin that extends the plugin with key "base" + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + testextend + ExtendPlugin + testbase + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/test-extend-plugin/src/ExtendPlugin.java b/server/sonar-webserver-api/src/test/projects/test-extend-plugin/src/ExtendPlugin.java new file mode 100644 index 00000000000..d364a2f9dd4 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-extend-plugin/src/ExtendPlugin.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class ExtendPlugin extends Plugin { + + public void define(Plugin.Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar new file mode 100644 index 00000000000..2f63c2e652c Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/projects/test-libs-plugin/pom.xml b/server/sonar-webserver-api/src/test/projects/test-libs-plugin/pom.xml new file mode 100644 index 00000000000..2d49cca2cf2 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-libs-plugin/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + test-libs-plugin + 0.1-SNAPSHOT + sonar-plugin + Test Libs Plugin + Fake plugin that embeds some libraries + + + + + commons-email + commons-email + 20030310.165926 + + + commons-daemon + commons-daemon + 1.0.15 + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + testlibs + LibsPlugin + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/test-libs-plugin/src/LibsPlugin.java b/server/sonar-webserver-api/src/test/projects/test-libs-plugin/src/LibsPlugin.java new file mode 100644 index 00000000000..7e3ebe0909c --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-libs-plugin/src/LibsPlugin.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class LibsPlugin extends Plugin { + + public void define(Plugin.Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar new file mode 100644 index 00000000000..6ebe8652d8b Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/projects/test-require-plugin/pom.xml b/server/sonar-webserver-api/src/test/projects/test-require-plugin/pom.xml new file mode 100644 index 00000000000..62462ffbf34 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-require-plugin/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + test-require-plugin + 0.1-SNAPSHOT + sonar-plugin + Test Require Plugin + This fake plugin depends on test-base-plugin + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + org.sonarsource.sonarqube.tests + test-base-plugin + 0.1-SNAPSHOT + sonar-plugin + provided + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + testrequire + RequirePlugin + testbase:0.1 + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/test-require-plugin/src/RequirePlugin.java b/server/sonar-webserver-api/src/test/projects/test-require-plugin/src/RequirePlugin.java new file mode 100644 index 00000000000..847ae2d994e --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-require-plugin/src/RequirePlugin.java @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class RequirePlugin extends Plugin { + + public RequirePlugin() { + // call a class that is in the api published by the base plugin + new org.sonar.plugins.testbase.api.BaseApi().doNothing(); + } + + public void define(Plugin.Context context) { + + } +} diff --git a/server/sonar-webserver-api/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar new file mode 100644 index 00000000000..f5fc95f9d0d Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/pom.xml b/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/pom.xml new file mode 100644 index 00000000000..044cd94e8f0 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + org.sonarsource.sonarqube.tests + test-requirenew-plugin + 0.1-SNAPSHOT + sonar-plugin + Test Require New Plugin + This fake plugin requires a version of test-base-plugin that is not installed + + + + org.codehaus.sonar + sonar-plugin-api + 4.5.4 + provided + + + org.sonarsource.sonarqube.tests + test-base-plugin + 0.1-SNAPSHOT + sonar-plugin + provided + + + + src + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + testrequire + RequirePlugin + testbase:0.2 + + + + + + diff --git a/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java b/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java new file mode 100644 index 00000000000..0d14cde33c1 --- /dev/null +++ b/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class RequirePlugin extends Plugin { + + public RequirePlugin() { + // call a class that is in the api published by the base plugin + new org.sonar.plugins.testbase.api.BaseApi().doNothing(); + } + + public void define(Plugin.Context context) { + + } + +} diff --git a/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar new file mode 100644 index 00000000000..0dd577fc360 Binary files /dev/null and b/server/sonar-webserver-api/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar differ diff --git a/server/sonar-webserver-api/src/test/resources/logback-test.xml b/server/sonar-webserver-api/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..3e34b0f9fc8 --- /dev/null +++ b/server/sonar-webserver-api/src/test/resources/logback-test.xml @@ -0,0 +1,26 @@ + + + + + + + + %d{yyyy.MM.dd HH:mm:ss} %-5level %msg%n + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-webserver-auth/build.gradle b/server/sonar-webserver-auth/build.gradle index 195dbbbe963..3d50a54a0ec 100644 --- a/server/sonar-webserver-auth/build.gradle +++ b/server/sonar-webserver-auth/build.gradle @@ -21,7 +21,7 @@ dependencies { compile project(':server:sonar-db-dao') compile project(':server:sonar-process') compile project(':server:sonar-server-common') - compile project(':server:sonar-webserver-common') + compile project(':server:sonar-webserver-api') compile project(path: ':sonar-plugin-api', configuration: 'shadow') compile project(':sonar-plugin-api-impl') compile 'org.mindrot:jbcrypt' diff --git a/server/sonar-webserver-common/build.gradle b/server/sonar-webserver-common/build.gradle deleted file mode 100644 index 17637fc201a..00000000000 --- a/server/sonar-webserver-common/build.gradle +++ /dev/null @@ -1,56 +0,0 @@ -sonarqube { - properties { - property 'sonar.projectName', "${projectTitle} :: WebServer :: Common" - } -} - -sourceSets { - test { - resources { - srcDirs += ['src/test/projects'] - } - } -} - -configurations { - tests - - testCompile.extendsFrom tests -} - -dependencies { - // please keep the list grouped by configuration and ordered by name - - compile 'com.google.guava:guava' - compile 'io.jsonwebtoken:jjwt-api' - compile 'io.jsonwebtoken:jjwt-impl' - compile project(':sonar-core') - compile project(':server:sonar-db-dao') - compile project(':server:sonar-process') - compile project(':server:sonar-server-common') - compile project(path: ':sonar-plugin-api', configuration: 'shadow') - compile project(':sonar-plugin-api-impl') - compile 'org.mindrot:jbcrypt' - - compileOnly 'com.google.code.findbugs:jsr305' - compileOnly 'javax.servlet:javax.servlet-api' - - testCompile 'org.assertj:assertj-guava' - testCompile 'com.google.code.findbugs:jsr305' - testCompile 'com.tngtech.java:junit-dataprovider' - testCompile 'javax.servlet:javax.servlet-api' - testCompile 'org.mockito:mockito-core' - testCompile project(':server:sonar-db-testing') - testCompile project(path: ":server:sonar-server-common", configuration: "tests") - testCompile project(path: ":server:sonar-webserver-ws", configuration: "tests") - testCompile project(':sonar-testing-harness') -} - -task testJar(type: Jar) { - classifier = 'tests' - from sourceSets.test.output -} - -artifacts { - tests testJar -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/ProcessCommandWrapper.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/app/ProcessCommandWrapper.java deleted file mode 100644 index 44bdc4377e3..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/ProcessCommandWrapper.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.app; - -public interface ProcessCommandWrapper { - /** - * Requests to the main process that SQ be restarted. - */ - void requestSQRestart(); - - /** - * Requests to the main process that the WebServer is stopped. - */ - void requestHardStop(); - - /** - * Notifies any listening process that the WebServer is operational. - */ - void notifyOperational(); - - /** - * Checks whether the Compute Engine is operational. - */ - boolean isCeOperational(); - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/ProcessCommandWrapperImpl.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/app/ProcessCommandWrapperImpl.java deleted file mode 100644 index 12b3f68543c..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/ProcessCommandWrapperImpl.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.app; - -import java.io.File; -import org.sonar.api.config.Configuration; -import org.sonar.process.ProcessId; -import org.sonar.process.sharedmemoryfile.DefaultProcessCommands; -import org.sonar.process.sharedmemoryfile.ProcessCommands; - -import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX; -import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; - -public class ProcessCommandWrapperImpl implements ProcessCommandWrapper { - - private static final ProcessMethod SET_OPERATIONAL = processCommands -> { - processCommands.setOperational(); - return null; - }; - private static final ProcessMethod ASK_FOR_RESTART = processCommands -> { - processCommands.askForRestart(); - return null; - }; - private static final ProcessMethod ASK_FOR_HARD_STOP = processCommands -> { - processCommands.askForHardStop(); - return null; - }; - private static final ProcessMethod IS_OPERATIONAL = ProcessCommands::isOperational; - - private final Configuration config; - - public ProcessCommandWrapperImpl(Configuration config) { - this.config = config; - } - - @Override - public void requestSQRestart() { - call(ASK_FOR_RESTART, selfProcessNumber()); - } - - @Override - public void requestHardStop() { - call(ASK_FOR_HARD_STOP, selfProcessNumber()); - } - - @Override - public void notifyOperational() { - call(SET_OPERATIONAL, selfProcessNumber()); - } - - @Override - public boolean isCeOperational() { - return call(IS_OPERATIONAL, ProcessId.COMPUTE_ENGINE.getIpcIndex()); - } - - private int selfProcessNumber() { - return nonNullAsInt(PROPERTY_PROCESS_INDEX); - } - - private T call(ProcessMethod command, int processNumber) { - File shareDir = nonNullValueAsFile(PROPERTY_SHARED_PATH); - try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(shareDir, processNumber)) { - return command.callOn(commands); - } - } - - private interface ProcessMethod { - T callOn(ProcessCommands processCommands); - } - - private int nonNullAsInt(String key) { - return config.getInt(key).orElseThrow(() -> new IllegalArgumentException(String.format("Property %s is not set", key))); - } - - private File nonNullValueAsFile(String key) { - return new File(config.get(key).orElseThrow(() -> new IllegalArgumentException(String.format("Property %s is not set", key)))); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/RestartFlagHolder.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/app/RestartFlagHolder.java deleted file mode 100644 index dfc6c8c8414..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/RestartFlagHolder.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.app; - -/** - * Holds a boolean flag representing the restarting status of the WebServer. - * This boolean is {@code false} by default and can safely be changed concurrently using methods {@link #set()} and - * {@link #unset()}. - */ -public interface RestartFlagHolder { - /** - * @return whether restarting flag has been set or not. - */ - boolean isRestarting(); - - /** - * Sets the restarting flag to {@code true}, no matter it already is or not. - */ - void set(); - - /** - * Sets the restarting flag to {@code false}, no matter it already is or not. - */ - void unset(); -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/RestartFlagHolderImpl.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/app/RestartFlagHolderImpl.java deleted file mode 100644 index 98354a8e77b..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/RestartFlagHolderImpl.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.app; - -import java.util.concurrent.atomic.AtomicBoolean; - -public class RestartFlagHolderImpl implements RestartFlagHolder { - private final AtomicBoolean restarting = new AtomicBoolean(false); - - @Override - public boolean isRestarting() { - return restarting.get(); - } - - @Override - public void set() { - restarting.set(true); - } - - @Override - public void unset() { - restarting.set(false); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/app/package-info.java deleted file mode 100644 index 7170de2498d..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/app/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.app; - -import javax.annotation.ParametersAreNonnullByDefault; - diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeature.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeature.java deleted file mode 100644 index 7d60949c954..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeature.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.branch; - -interface BranchFeature { - - boolean isEnabled(); - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureExtension.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureExtension.java deleted file mode 100644 index 20fc40ff324..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureExtension.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.branch; - -import org.sonar.api.server.ServerSide; - -/** - * The branch plugin needs to implement this in order to know that the branch feature is supported - */ -@ServerSide -public interface BranchFeatureExtension extends BranchFeature { - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureProxy.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureProxy.java deleted file mode 100644 index 8647d7c421f..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureProxy.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.branch; - -/** - * The goal of this class is to handle the 2 different use case : - * - The branch plugin exists, the proxy will redirect method calls to the plugin - * - No branch plugin, feature is disabled - */ -public interface BranchFeatureProxy extends BranchFeature { - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureProxyImpl.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureProxyImpl.java deleted file mode 100644 index 634e59721a7..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/BranchFeatureProxyImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.branch; - -public class BranchFeatureProxyImpl implements BranchFeatureProxy { - - private final BranchFeatureExtension branchFeatureExtension; - - public BranchFeatureProxyImpl() { - this.branchFeatureExtension = null; - } - - public BranchFeatureProxyImpl(BranchFeatureExtension branchFeatureExtension) { - this.branchFeatureExtension = branchFeatureExtension; - } - - @Override - public boolean isEnabled() { - return branchFeatureExtension != null && branchFeatureExtension.isEnabled(); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/package-info.java deleted file mode 100644 index cb79dbcf31d..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/branch/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.branch; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/ce/http/CeHttpClient.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/ce/http/CeHttpClient.java deleted file mode 100644 index f86a08efb62..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/ce/http/CeHttpClient.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.ce.http; - -import java.util.Optional; -import org.sonar.api.utils.log.LoggerLevel; -import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; - -public interface CeHttpClient { - Optional retrieveSystemInfo(); - - void changeLogLevel(LoggerLevel level); -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/ce/http/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/ce/http/package-info.java deleted file mode 100644 index 17b36c59125..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/ce/http/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.ce.http; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/BadRequestException.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/BadRequestException.java deleted file mode 100644 index 3113d202d99..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/BadRequestException.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import com.google.common.base.MoreObjects; -import java.util.List; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.lang.String.format; -import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; -import static java.util.Arrays.asList; - -/** - * Request is not valid and can not be processed. - */ -public class BadRequestException extends ServerException { - - private final transient List errors; - - private BadRequestException(List errors) { - super(HTTP_BAD_REQUEST, errors.get(0)); - this.errors = errors; - } - - public static void checkRequest(boolean expression, String message, Object... messageArguments) { - if (!expression) { - throw create(format(message, messageArguments)); - } - } - - public static void checkRequest(boolean expression, List messages) { - if (!expression) { - throw create(messages); - } - } - - public static BadRequestException create(List errorMessages) { - checkArgument(!errorMessages.isEmpty(), "At least one error message is required"); - checkArgument(errorMessages.stream().noneMatch(message -> message == null || message.isEmpty()), "Message cannot be empty"); - return new BadRequestException(errorMessages); - } - - public static BadRequestException create(String... errorMessages) { - return create(asList(errorMessages)); - } - - public List errors() { - return errors; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("errors", errors) - .toString(); - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/ForbiddenException.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/ForbiddenException.java deleted file mode 100644 index d72eefbd02f..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/ForbiddenException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import com.google.common.base.Preconditions; - -import static java.net.HttpURLConnection.HTTP_FORBIDDEN; - -/** - * Permission denied. User does not have the required permissions. - */ -public class ForbiddenException extends ServerException { - - public ForbiddenException(String message) { - super(HTTP_FORBIDDEN, Preconditions.checkNotNull(message)); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/Message.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/Message.java deleted file mode 100644 index c069ead73d2..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/Message.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import com.google.common.base.Preconditions; - -import static com.google.common.base.Strings.isNullOrEmpty; -import static java.lang.String.format; - -public class Message { - - private final String msg; - - private Message(String format, Object... params) { - Preconditions.checkArgument(!isNullOrEmpty(format), "Message cannot be empty"); - this.msg = format(format, params); - } - - public String getMessage() { - return msg; - } - - public static Message of(String msg, Object... arguments) { - return new Message(msg, arguments); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Message other = (Message) o; - return this.msg.equals(other.msg); - } - - @Override - public int hashCode() { - return msg.hashCode(); - } - - @Override - public String toString() { - return msg; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/NotFoundException.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/NotFoundException.java deleted file mode 100644 index f21a98b5157..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/NotFoundException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import com.google.common.base.Optional; -import javax.annotation.Nullable; - -import static java.lang.String.format; -import static java.net.HttpURLConnection.HTTP_NOT_FOUND; - -public class NotFoundException extends ServerException { - - public NotFoundException(String message) { - super(HTTP_NOT_FOUND, message); - } - - /** - * @throws NotFoundException if the value if null - * @return the value - */ - public static T checkFound(@Nullable T value, String message, Object... messageArguments) { - if (value == null) { - throw new NotFoundException(format(message, messageArguments)); - } - - return value; - } - - /** - * @throws NotFoundException if the value is not present - * @return the value - */ - public static T checkFoundWithOptional(Optional value, String message, Object... messageArguments) { - if (!value.isPresent()) { - throw new NotFoundException(format(message, messageArguments)); - } - - return value.get(); - } - - public static T checkFoundWithOptional(java.util.Optional value, String message, Object... messageArguments) { - if (!value.isPresent()) { - throw new NotFoundException(format(message, messageArguments)); - } - - return value.get(); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/ServerException.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/ServerException.java deleted file mode 100644 index 491c17ed437..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/ServerException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import static java.util.Objects.requireNonNull; - -public class ServerException extends RuntimeException { - private final int httpCode; - - public ServerException(int httpCode, String message) { - super(requireNonNull(message, "Error message cannot be null")); - this.httpCode = httpCode; - } - - public int httpCode() { - return httpCode; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/UnauthorizedException.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/UnauthorizedException.java deleted file mode 100644 index 0b4af12beee..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/UnauthorizedException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; - -/** - * User needs to be authenticated. HTTP request is generally redirected to login form. - */ -public class UnauthorizedException extends ServerException { - - public UnauthorizedException(String message) { - super(HTTP_UNAUTHORIZED, message); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/package-info.java deleted file mode 100644 index c1ac144f25a..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/exceptions/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.exceptions; - -import javax.annotation.ParametersAreNonnullByDefault; - diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/health/ClusterHealth.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/health/ClusterHealth.java deleted file mode 100644 index 23fcfca9f7a..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/health/ClusterHealth.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.health; - -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import org.sonar.process.cluster.health.NodeHealth; - -import static com.google.common.collect.ImmutableSet.copyOf; -import static java.util.Objects.requireNonNull; - -public class ClusterHealth { - private final Health health; - private final Set nodes; - - public ClusterHealth(Health health, Set nodes) { - this.health = requireNonNull(health, "health can't be null"); - this.nodes = copyOf(requireNonNull(nodes, "nodes can't be null")); - } - - public Health getHealth() { - return health; - } - - public Set getNodes() { - return nodes; - } - - public Optional getNodeHealth(String nodeName) { - return nodes.stream() - .filter(node -> nodeName.equals(node.getDetails().getName())) - .findFirst(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ClusterHealth that = (ClusterHealth) o; - return Objects.equals(health, that.health) && - Objects.equals(nodes, that.nodes); - } - - @Override - public int hashCode() { - return Objects.hash(health, nodes); - } - - @Override - public String toString() { - return "ClusterHealth{" + - "health=" + health + - ", nodes=" + nodes + - '}'; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/health/Health.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/health/Health.java deleted file mode 100644 index d5b49449bbe..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/health/Health.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.health; - -import com.google.common.collect.ImmutableSet; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.util.Objects.requireNonNull; - -public class Health { - /** - * The GREEN status without any cause as a constant, for convenience and optimisation. - */ - public static final Health GREEN = newHealthCheckBuilder() - .setStatus(Status.GREEN) - .build(); - - private final Status status; - private final Set causes; - - public Health(Builder builder) { - this.status = builder.status; - this.causes = ImmutableSet.copyOf(builder.causes); - } - - public Status getStatus() { - return status; - } - - public Set getCauses() { - return causes; - } - - public static Builder newHealthCheckBuilder() { - return new Builder(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Health health = (Health) o; - return status == health.status && - Objects.equals(causes, health.causes); - } - - @Override - public int hashCode() { - return Objects.hash(status, causes); - } - - @Override - public String toString() { - return "Health{" + status + - ", causes=" + causes + - '}'; - } - - /** - * Builder of {@link Health} which supports being reused for optimization. - */ - public static class Builder { - private Status status; - private Set causes = new HashSet<>(0); - - private Builder() { - // use static factory method - } - - public Builder clear() { - this.status = null; - this.causes.clear(); - return this; - } - - public Builder setStatus(Status status) { - this.status = checkStatus(status); - return this; - } - - public Builder addCause(String cause) { - requireNonNull(cause, "cause can't be null"); - checkArgument(!cause.trim().isEmpty(), "cause can't be empty"); - causes.add(cause); - return this; - } - - public Health build() { - checkStatus(this.status); - return new Health(this); - } - - private static Status checkStatus(Status status) { - return requireNonNull(status, "status can't be null"); - } - } - - public enum Status { - /** - * Fully working - */ - GREEN, - /** - * Yellow: Working but something must be fixed to make SQ fully operational - */ - YELLOW, - /** - * Red: Not working - */ - RED - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/health/HealthChecker.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/health/HealthChecker.java deleted file mode 100644 index 80fb8aed1bf..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/health/HealthChecker.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.health; - -public interface HealthChecker { - /** - * Perform a check of the health of the current SonarQube node, either as a standalone node or as a member - * of a cluster. - */ - Health checkNode(); - - /** - * Perform a check of the health of the SonarQube cluster. - * - * @throws IllegalStateException if clustering is not enabled. - */ - ClusterHealth checkCluster(); -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/health/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/health/package-info.java deleted file mode 100644 index 18ea762c56b..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/health/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.health; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/ClusterFeature.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/ClusterFeature.java deleted file mode 100644 index 24d8617a4e1..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/ClusterFeature.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.platform; - -import org.sonar.api.ExtensionPoint; -import org.sonar.api.server.ServerSide; - -@ServerSide -@ExtensionPoint -public interface ClusterFeature { - - boolean isEnabled(); - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/Platform.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/Platform.java deleted file mode 100644 index 22f3e451a97..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/Platform.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.platform; - -import org.sonar.core.platform.ComponentContainer; - -public interface Platform { - void doStart(); - - Status status(); - - ComponentContainer getContainer(); - - enum Status { - BOOTING, SAFEMODE, STARTING, UP - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/SystemInfoWriter.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/SystemInfoWriter.java deleted file mode 100644 index 3a82f471f6a..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/SystemInfoWriter.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.platform; - -import org.sonar.api.utils.text.JsonWriter; - -public interface SystemInfoWriter { - void write(JsonWriter json) throws Exception; -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/package-info.java deleted file mode 100644 index 71d187381a7..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/platform/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.platform; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/InstalledPlugin.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/InstalledPlugin.java deleted file mode 100644 index 0fffb7b7d78..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/InstalledPlugin.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.io.FileUtils; -import org.sonar.core.platform.PluginInfo; - -import static java.util.Objects.requireNonNull; - -@Immutable -public class InstalledPlugin { - private final PluginInfo plugin; - private final FileAndMd5 loadedJar; - @Nullable - private final FileAndMd5 compressedJar; - - public InstalledPlugin(PluginInfo plugin, FileAndMd5 loadedJar, @Nullable FileAndMd5 compressedJar) { - this.plugin = requireNonNull(plugin); - this.loadedJar = requireNonNull(loadedJar); - this.compressedJar = compressedJar; - } - - public PluginInfo getPluginInfo() { - return plugin; - } - - public FileAndMd5 getLoadedJar() { - return loadedJar; - } - - @Nullable - public FileAndMd5 getCompressedJar() { - return compressedJar; - } - - @Immutable - public static final class FileAndMd5 { - private final File file; - private final String md5; - - public FileAndMd5(File file) { - try (InputStream fis = FileUtils.openInputStream(file)) { - this.file = file; - this.md5 = DigestUtils.md5Hex(fis); - } catch (IOException e) { - throw new IllegalStateException("Fail to compute md5 of " + file, e); - } - } - - public File getFile() { - return file; - } - - public String getMd5() { - return md5; - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginDownloader.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginDownloader.java deleted file mode 100644 index d61efac304c..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginDownloader.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import com.google.common.base.Optional; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import org.apache.commons.io.FileUtils; -import org.picocontainer.Startable; -import org.sonar.api.utils.HttpDownloader; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.core.platform.PluginInfo; -import org.sonar.core.util.stream.MoreCollectors; -import org.sonar.server.platform.ServerFileSystem; -import org.sonar.updatecenter.common.Release; -import org.sonar.updatecenter.common.UpdateCenter; -import org.sonar.updatecenter.common.Version; - -import static org.apache.commons.io.FileUtils.copyFile; -import static org.apache.commons.io.FileUtils.copyFileToDirectory; -import static org.apache.commons.io.FileUtils.forceMkdir; -import static org.apache.commons.io.FileUtils.toFile; -import static org.apache.commons.lang.StringUtils.substringAfterLast; -import static org.sonar.core.util.FileUtils.deleteQuietly; -import static org.sonar.server.exceptions.BadRequestException.checkRequest; - -/** - * Downloads plugins from update center. Files are copied in the directory extensions/downloads and then - * moved to extensions/plugins after server restart. - */ -public class PluginDownloader implements Startable { - - private static final Logger LOG = Loggers.get(PluginDownloader.class); - private static final String TMP_SUFFIX = "tmp"; - private static final String PLUGIN_EXTENSION = "jar"; - - private final UpdateCenterMatrixFactory updateCenterMatrixFactory; - private final HttpDownloader downloader; - private final File downloadDir; - - public PluginDownloader(UpdateCenterMatrixFactory updateCenterMatrixFactory, HttpDownloader downloader, - ServerFileSystem fileSystem) { - this.updateCenterMatrixFactory = updateCenterMatrixFactory; - this.downloader = downloader; - this.downloadDir = fileSystem.getDownloadedPluginsDir(); - } - - /** - * Deletes the temporary files remaining from previous downloads - */ - @Override - public void start() { - try { - forceMkdir(downloadDir); - for (File tempFile : listTempFile(this.downloadDir)) { - deleteQuietly(tempFile); - } - } catch (IOException e) { - throw new IllegalStateException("Fail to create the directory: " + downloadDir, e); - } - } - - @Override - public void stop() { - // Nothing to do - } - - public void cancelDownloads() { - try { - if (downloadDir.exists()) { - org.sonar.core.util.FileUtils.cleanDirectory(downloadDir); - } - } catch (IOException e) { - throw new IllegalStateException("Fail to clean the plugin downloads directory: " + downloadDir, e); - } - } - - public List getDownloadedPluginFilenames() { - List names = new ArrayList<>(); - for (File file : listPlugins(this.downloadDir)) { - names.add(file.getName()); - } - return names; - } - - /** - * @return the list of download plugins as {@link PluginInfo} instances - */ - public Collection getDownloadedPlugins() { - return listPlugins(this.downloadDir) - .stream() - .map(PluginInfo::create) - .collect(MoreCollectors.toList()); - } - - public void download(String pluginKey, Version version) { - Optional updateCenter = updateCenterMatrixFactory.getUpdateCenter(true); - if (updateCenter.isPresent()) { - List installablePlugins = updateCenter.get().findInstallablePlugins(pluginKey, version); - checkRequest(!installablePlugins.isEmpty(), "Error while downloading plugin '%s' with version '%s'. No compatible plugin found.", pluginKey, version.getName()); - for (Release release : installablePlugins) { - try { - downloadRelease(release); - } catch (Exception e) { - String message = String.format("Fail to download the plugin (%s, version %s) from %s (error is : %s)", - release.getArtifact().getKey(), release.getVersion().getName(), release.getDownloadUrl(), e.getMessage()); - LOG.debug(message, e); - throw new IllegalStateException(message, e); - } - } - } - } - - private void downloadRelease(Release release) throws URISyntaxException, IOException { - String url = release.getDownloadUrl(); - - URI uri = new URI(url); - if (url.startsWith("file:")) { - // used for tests - File file = toFile(uri.toURL()); - copyFileToDirectory(file, downloadDir); - } else { - String filename = substringAfterLast(uri.getPath(), "/"); - if (!filename.endsWith("." + PLUGIN_EXTENSION)) { - filename = release.getKey() + "-" + release.getVersion() + "." + PLUGIN_EXTENSION; - } - File targetFile = new File(downloadDir, filename); - File tempFile = new File(downloadDir, filename + "." + TMP_SUFFIX); - downloader.download(uri, tempFile); - copyFile(tempFile, targetFile); - deleteQuietly(tempFile); - } - } - - private static Collection listTempFile(File dir) { - return FileUtils.listFiles(dir, new String[] {TMP_SUFFIX}, false); - } - - private static Collection listPlugins(File dir) { - return FileUtils.listFiles(dir, new String[] {PLUGIN_EXTENSION}, false); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginFileSystem.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginFileSystem.java deleted file mode 100644 index e65336a7586..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginFileSystem.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.jar.JarInputStream; -import java.util.jar.Pack200; -import java.util.zip.GZIPOutputStream; -import org.sonar.api.config.Configuration; -import org.sonar.api.server.ServerSide; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.api.utils.log.Profiler; -import org.sonar.core.platform.PluginInfo; -import org.sonar.server.plugins.InstalledPlugin.FileAndMd5; - -import static com.google.common.base.Preconditions.checkState; - -@ServerSide -public class PluginFileSystem { - - public static final String PROPERTY_PLUGIN_COMPRESSION_ENABLE = "sonar.pluginsCompression.enable"; - private static final Logger LOG = Loggers.get(PluginFileSystem.class); - - private final Configuration configuration; - private final Map installedFiles = new HashMap<>(); - - public PluginFileSystem(Configuration configuration) { - this.configuration = configuration; - } - - /** - * @param plugin - * @param loadedJar the JAR loaded by classloaders. It differs from {@code plugin.getJarFile()} - * which is the initial location of JAR as seen by users - */ - public void addInstalledPlugin(PluginInfo plugin, File loadedJar) { - checkState(!installedFiles.containsKey(plugin.getKey()), "Plugin %s is already loaded", plugin.getKey()); - checkState(loadedJar.exists(), "loadedJar does not exist: %s", loadedJar); - - Optional compressed = compressJar(plugin, loadedJar); - InstalledPlugin installedFile = new InstalledPlugin( - plugin, - new FileAndMd5(loadedJar), - compressed.map(FileAndMd5::new).orElse(null)); - installedFiles.put(plugin.getKey(), installedFile); - } - - public Optional getInstalledPlugin(String pluginKey) { - return Optional.ofNullable(installedFiles.get(pluginKey)); - } - - public Collection getInstalledFiles() { - return installedFiles.values(); - } - - private Optional compressJar(PluginInfo plugin, File jar) { - if (!configuration.getBoolean(PROPERTY_PLUGIN_COMPRESSION_ENABLE).orElse(false)) { - return Optional.empty(); - } - - Path targetPack200 = getPack200Path(jar.toPath()); - Path sourcePack200Path = getPack200Path(plugin.getNonNullJarFile().toPath()); - - // check if packed file was deployed alongside the jar. If that's the case, use it instead of generating it (SONAR-10395). - if (sourcePack200Path.toFile().exists()) { - try { - LOG.debug("Found pack200: " + sourcePack200Path); - Files.copy(sourcePack200Path, targetPack200); - } catch (IOException e) { - throw new IllegalStateException("Failed to copy pack200 file from " + sourcePack200Path + " to " + targetPack200, e); - } - } else { - pack200(jar.toPath(), targetPack200, plugin.getKey()); - } - return Optional.of(targetPack200.toFile()); - } - - private static void pack200(Path jarPath, Path toPack200Path, String pluginKey) { - Profiler profiler = Profiler.create(LOG); - profiler.startInfo("Compressing plugin " + pluginKey + " [pack200]"); - - try (JarInputStream in = new JarInputStream(new BufferedInputStream(Files.newInputStream(jarPath))); - OutputStream out = new GZIPOutputStream(new BufferedOutputStream(Files.newOutputStream(toPack200Path)))) { - Pack200.newPacker().pack(in, out); - } catch (IOException e) { - throw new IllegalStateException(String.format("Fail to pack200 plugin [%s] '%s' to '%s'", pluginKey, jarPath, toPack200Path), e); - } - profiler.stopInfo(); - } - - private static Path getPack200Path(Path jar) { - String jarFileName = jar.getFileName().toString(); - String filename = jarFileName.substring(0, jarFileName.length() - 3) + "pack.gz"; - return jar.resolveSibling(filename); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginUninstaller.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginUninstaller.java deleted file mode 100644 index 8253dbaf8c1..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/PluginUninstaller.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import org.apache.commons.io.FileUtils; -import org.picocontainer.Startable; -import org.sonar.core.platform.PluginInfo; -import org.sonar.core.util.stream.MoreCollectors; -import org.sonar.server.platform.ServerFileSystem; - -import static java.lang.String.format; -import static org.apache.commons.io.FileUtils.forceMkdir; - -public class PluginUninstaller implements Startable { - private static final String PLUGIN_EXTENSION = "jar"; - private final ServerPluginRepository serverPluginRepository; - private final File uninstallDir; - - public PluginUninstaller(ServerPluginRepository serverPluginRepository, ServerFileSystem fs) { - this.serverPluginRepository = serverPluginRepository; - this.uninstallDir = fs.getUninstalledPluginsDir(); - } - - private static Collection listJarFiles(File dir) { - if (dir.exists()) { - return FileUtils.listFiles(dir, new String[] {PLUGIN_EXTENSION}, false); - } - return Collections.emptyList(); - } - - @Override - public void start() { - try { - forceMkdir(uninstallDir); - } catch (IOException e) { - throw new IllegalStateException("Fail to create the directory: " + uninstallDir, e); - } - } - - @Override - public void stop() { - // Nothing to do - } - - public void uninstall(String pluginKey) { - ensurePluginIsInstalled(pluginKey); - serverPluginRepository.uninstall(pluginKey, uninstallDir); - } - - public void cancelUninstalls() { - serverPluginRepository.cancelUninstalls(uninstallDir); - } - - /** - * @return the list of plugins to be uninstalled as {@link PluginInfo} instances - */ - public Collection getUninstalledPlugins() { - return listJarFiles(uninstallDir) - .stream() - .map(PluginInfo::create) - .collect(MoreCollectors.toList()); - } - - private void ensurePluginIsInstalled(String key) { - if (!serverPluginRepository.hasPlugin(key)) { - throw new IllegalArgumentException(format("Plugin [%s] is not installed", key)); - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/ServerPluginJarExploder.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/ServerPluginJarExploder.java deleted file mode 100644 index 1970d4475a5..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/ServerPluginJarExploder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import java.io.File; -import org.apache.commons.io.FileUtils; -import org.sonar.api.server.ServerSide; -import org.sonar.api.utils.ZipUtils; -import org.sonar.core.platform.ExplodedPlugin; -import org.sonar.core.platform.PluginInfo; -import org.sonar.core.platform.PluginJarExploder; -import org.sonar.server.platform.ServerFileSystem; - -import static org.apache.commons.io.FileUtils.forceMkdir; - -@ServerSide -public class ServerPluginJarExploder extends PluginJarExploder { - private final ServerFileSystem fs; - private final PluginFileSystem pluginFileSystem; - - public ServerPluginJarExploder(ServerFileSystem fs, PluginFileSystem pluginFileSystem) { - this.fs = fs; - this.pluginFileSystem = pluginFileSystem; - } - - /** - * JAR files of directory extensions/plugins can be moved when server is up and plugins are uninstalled. - * For this reason these files must not be locked by classloaders. They are copied to the directory - * web/deploy/plugins in order to be loaded by {@link org.sonar.core.platform.PluginLoader}. - */ - @Override - public ExplodedPlugin explode(PluginInfo pluginInfo) { - File toDir = new File(fs.getDeployedPluginsDir(), pluginInfo.getKey()); - try { - forceMkdir(toDir); - org.sonar.core.util.FileUtils.cleanDirectory(toDir); - - File jarSource = pluginInfo.getNonNullJarFile(); - File jarTarget = new File(toDir, jarSource.getName()); - - FileUtils.copyFile(jarSource, jarTarget); - ZipUtils.unzip(jarSource, toDir, newLibFilter()); - ExplodedPlugin explodedPlugin = explodeFromUnzippedDir(pluginInfo.getKey(), jarTarget, toDir); - pluginFileSystem.addInstalledPlugin(pluginInfo, jarTarget); - return explodedPlugin; - } catch (Exception e) { - throw new IllegalStateException(String.format( - "Fail to unzip plugin [%s] %s to %s", pluginInfo.getKey(), pluginInfo.getNonNullJarFile().getAbsolutePath(), toDir.getAbsolutePath()), e); - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java deleted file mode 100644 index ecc3abc2d76..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java +++ /dev/null @@ -1,372 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Joiner; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Ordering; -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.annotation.CheckForNull; -import org.apache.commons.io.FileUtils; -import org.picocontainer.Startable; -import org.sonar.api.Plugin; -import org.sonar.api.SonarRuntime; -import org.sonar.api.utils.MessageException; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.core.platform.PluginInfo; -import org.sonar.core.platform.PluginLoader; -import org.sonar.core.platform.PluginRepository; -import org.sonar.server.platform.ServerFileSystem; -import org.sonar.updatecenter.common.Version; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; -import static java.lang.String.format; -import static org.apache.commons.io.FileUtils.moveFile; -import static org.apache.commons.io.FileUtils.moveFileToDirectory; -import static org.sonar.core.util.FileUtils.deleteQuietly; - -/** - * Entry point to install and load plugins on server startup. It manages - *

    - *
  • installation of new plugins (effective after server startup)
  • - *
  • un-installation of plugins (effective after server startup)
  • - *
  • cancel pending installations/un-installations
  • - *
  • instantiation of plugin entry-points
  • - *
- */ -public class ServerPluginRepository implements PluginRepository, Startable { - - private static final Logger LOG = Loggers.get(ServerPluginRepository.class); - private static final String[] JAR_FILE_EXTENSIONS = new String[] {"jar"}; - // List of plugins that are silently removed if installed - private static final Set DEFAULT_BLACKLISTED_PLUGINS = ImmutableSet.of("scmactivity", "issuesreport", "genericcoverage"); - // List of plugins that should prevent the server to finish its startup - private static final Set FORBIDDEN_COMPATIBLE_PLUGINS = ImmutableSet.of("sqale", "report", "views"); - private static final Joiner SLASH_JOINER = Joiner.on(" / ").skipNulls(); - private static final String NOT_STARTED_YET = "not started yet"; - - private final SonarRuntime runtime; - private final ServerFileSystem fs; - private final PluginLoader loader; - private final AtomicBoolean started = new AtomicBoolean(false); - private Set blacklistedPluginKeys = DEFAULT_BLACKLISTED_PLUGINS; - - // following fields are available after startup - private final Map pluginInfosByKeys = new HashMap<>(); - private final Map pluginInstancesByKeys = new HashMap<>(); - private final Map keysByClassLoader = new HashMap<>(); - - public ServerPluginRepository(SonarRuntime runtime, ServerFileSystem fs, PluginLoader loader) { - this.runtime = runtime; - this.fs = fs; - this.loader = loader; - } - - @VisibleForTesting - void setBlacklistedPluginKeys(Set keys) { - this.blacklistedPluginKeys = keys; - } - - @Override - public void start() { - loadPreInstalledPlugins(); - moveDownloadedPlugins(); - unloadIncompatiblePlugins(); - logInstalledPlugins(); - loadInstances(); - started.set(true); - } - - @Override - public void stop() { - // close classloaders - loader.unload(pluginInstancesByKeys.values()); - pluginInstancesByKeys.clear(); - pluginInfosByKeys.clear(); - keysByClassLoader.clear(); - started.set(true); - } - - /** - * Return the key of the plugin the extension (in the sense of {@link Plugin.Context#addExtension(Object)} is coming from. - */ - @CheckForNull - public String getPluginKey(Object extension) { - return keysByClassLoader.get(extension.getClass().getClassLoader()); - } - - /** - * Load the plugins that are located in extensions/plugins. Blacklisted plugins are - * deleted. - */ - private void loadPreInstalledPlugins() { - for (File file : listJarFiles(fs.getInstalledPluginsDir())) { - PluginInfo info = PluginInfo.create(file); - registerPluginInfo(info); - } - } - - /** - * Move the plugins recently downloaded to extensions/plugins. - */ - private void moveDownloadedPlugins() { - if (fs.getDownloadedPluginsDir().exists()) { - for (File sourceFile : listJarFiles(fs.getDownloadedPluginsDir())) { - overrideAndRegisterPlugin(sourceFile); - } - } - } - - private void registerPluginInfo(PluginInfo info) { - String pluginKey = info.getKey(); - if (blacklistedPluginKeys.contains(pluginKey)) { - LOG.warn("Plugin {} [{}] is blacklisted and is being uninstalled", info.getName(), pluginKey); - deleteQuietly(info.getNonNullJarFile()); - return; - } - if (FORBIDDEN_COMPATIBLE_PLUGINS.contains(pluginKey)) { - throw MessageException.of(String.format("Plugin '%s' is no longer compatible with this version of SonarQube", pluginKey)); - } - PluginInfo existing = pluginInfosByKeys.put(pluginKey, info); - if (existing != null) { - throw MessageException.of(format("Found two versions of the plugin %s [%s] in the directory extensions/plugins. Please remove one of %s or %s.", - info.getName(), pluginKey, info.getNonNullJarFile().getName(), existing.getNonNullJarFile().getName())); - } - - } - - /** - * Move or copy plugin to directory extensions/plugins. If a version of this plugin - * already exists then it's deleted. - */ - private void overrideAndRegisterPlugin(File sourceFile) { - File destDir = fs.getInstalledPluginsDir(); - File destFile = new File(destDir, sourceFile.getName()); - if (destFile.exists()) { - // plugin with same filename already installed - deleteQuietly(destFile); - } - - try { - moveFile(sourceFile, destFile); - - } catch (IOException e) { - throw new IllegalStateException(format("Fail to move plugin: %s to %s", - sourceFile.getAbsolutePath(), destFile.getAbsolutePath()), e); - } - - PluginInfo info = PluginInfo.create(destFile); - PluginInfo existing = pluginInfosByKeys.put(info.getKey(), info); - if (existing != null) { - if (!existing.getNonNullJarFile().getName().equals(destFile.getName())) { - deleteQuietly(existing.getNonNullJarFile()); - } - LOG.info("Plugin {} [{}] updated to version {}", info.getName(), info.getKey(), info.getVersion()); - } else { - LOG.info("Plugin {} [{}] installed", info.getName(), info.getKey()); - } - } - - /** - * Removes the plugins that are not compatible with current environment. - */ - private void unloadIncompatiblePlugins() { - // loop as long as the previous loop ignored some plugins. That allows to support dependencies - // on many levels, for example D extends C, which extends B, which requires A. If A is not installed, - // then B, C and D must be ignored. That's not possible to achieve this algorithm with a single - // iteration over plugins. - Set removedKeys = new HashSet<>(); - do { - removedKeys.clear(); - for (PluginInfo plugin : pluginInfosByKeys.values()) { - if (!isCompatible(plugin, runtime, pluginInfosByKeys)) { - removedKeys.add(plugin.getKey()); - } - } - for (String removedKey : removedKeys) { - pluginInfosByKeys.remove(removedKey); - } - } while (!removedKeys.isEmpty()); - } - - @VisibleForTesting - static boolean isCompatible(PluginInfo plugin, SonarRuntime runtime, Map allPluginsByKeys) { - if (Strings.isNullOrEmpty(plugin.getMainClass()) && Strings.isNullOrEmpty(plugin.getBasePlugin())) { - LOG.warn("Plugin {} [{}] is ignored because entry point class is not defined", plugin.getName(), plugin.getKey()); - return false; - } - - if (!plugin.isCompatibleWith(runtime.getApiVersion().toString())) { - throw MessageException.of(format( - "Plugin %s [%s] requires at least SonarQube %s", plugin.getName(), plugin.getKey(), plugin.getMinimalSqVersion())); - } - - if (!Strings.isNullOrEmpty(plugin.getBasePlugin()) && !allPluginsByKeys.containsKey(plugin.getBasePlugin())) { - // it extends a plugin that is not installed - LOG.warn("Plugin {} [{}] is ignored because its base plugin [{}] is not installed", plugin.getName(), plugin.getKey(), plugin.getBasePlugin()); - return false; - } - - for (PluginInfo.RequiredPlugin requiredPlugin : plugin.getRequiredPlugins()) { - PluginInfo installedRequirement = allPluginsByKeys.get(requiredPlugin.getKey()); - if (installedRequirement == null) { - // it requires a plugin that is not installed - LOG.warn("Plugin {} [{}] is ignored because the required plugin [{}] is not installed", plugin.getName(), plugin.getKey(), requiredPlugin.getKey()); - return false; - } - Version installedRequirementVersion = installedRequirement.getVersion(); - if (installedRequirementVersion != null && requiredPlugin.getMinimalVersion().compareToIgnoreQualifier(installedRequirementVersion) > 0) { - // it requires a more recent version - LOG.warn("Plugin {} [{}] is ignored because the version {} of required plugin [{}] is not supported", plugin.getName(), plugin.getKey(), - requiredPlugin.getKey(), requiredPlugin.getMinimalVersion()); - return false; - } - } - return true; - } - - private void logInstalledPlugins() { - List orderedPlugins = Ordering.natural().sortedCopy(pluginInfosByKeys.values()); - for (PluginInfo plugin : orderedPlugins) { - LOG.info("Deploy plugin {}", SLASH_JOINER.join(plugin.getName(), plugin.getVersion(), plugin.getImplementationBuild())); - } - } - - private void loadInstances() { - pluginInstancesByKeys.putAll(loader.load(pluginInfosByKeys)); - - for (Map.Entry e : pluginInstancesByKeys.entrySet()) { - keysByClassLoader.put(e.getValue().getClass().getClassLoader(), e.getKey()); - } - } - - /** - * Uninstall a plugin and its dependents - */ - public void uninstall(String pluginKey, File uninstallDir) { - Set uninstallKeys = new HashSet<>(); - uninstallKeys.add(pluginKey); - appendDependentPluginKeys(pluginKey, uninstallKeys); - - for (String uninstallKey : uninstallKeys) { - PluginInfo info = getPluginInfo(uninstallKey); - - try { - if (!getPluginFile(info).exists()) { - LOG.info("Plugin already uninstalled: {} [{}]", info.getName(), info.getKey()); - continue; - } - - LOG.info("Uninstalling plugin {} [{}]", info.getName(), info.getKey()); - - File masterFile = getPluginFile(info); - moveFileToDirectory(masterFile, uninstallDir, true); - } catch (IOException e) { - throw new IllegalStateException(format("Fail to uninstall plugin %s [%s]", info.getName(), info.getKey()), e); - } - } - } - - public void cancelUninstalls(File uninstallDir) { - for (File file : listJarFiles(uninstallDir)) { - try { - moveFileToDirectory(file, fs.getInstalledPluginsDir(), false); - } catch (IOException e) { - throw new IllegalStateException("Fail to cancel plugin uninstalls", e); - } - } - } - - /** - * Appends dependent plugins, only the ones that still exist in the plugins folder. - */ - private void appendDependentPluginKeys(String pluginKey, Set appendTo) { - for (PluginInfo otherPlugin : getPluginInfos()) { - if (!otherPlugin.getKey().equals(pluginKey)) { - for (PluginInfo.RequiredPlugin requirement : otherPlugin.getRequiredPlugins()) { - if (requirement.getKey().equals(pluginKey)) { - appendTo.add(otherPlugin.getKey()); - appendDependentPluginKeys(otherPlugin.getKey(), appendTo); - } - } - } - } - } - - private File getPluginFile(PluginInfo info) { - // we don't reuse info.getFile() just to be sure that file is located in from extensions/plugins - return new File(fs.getInstalledPluginsDir(), info.getNonNullJarFile().getName()); - } - - public Map getPluginInfosByKeys() { - return pluginInfosByKeys; - } - - @Override - public Collection getPluginInfos() { - checkState(started.get(), NOT_STARTED_YET); - return ImmutableList.copyOf(pluginInfosByKeys.values()); - } - - @Override - public PluginInfo getPluginInfo(String key) { - checkState(started.get(), NOT_STARTED_YET); - PluginInfo info = pluginInfosByKeys.get(key); - if (info == null) { - throw new IllegalArgumentException(format("Plugin [%s] does not exist", key)); - } - return info; - } - - @Override - public Plugin getPluginInstance(String key) { - checkState(started.get(), NOT_STARTED_YET); - Plugin plugin = pluginInstancesByKeys.get(key); - checkArgument(plugin != null, "Plugin [%s] does not exist", key); - return plugin; - } - - @Override - public boolean hasPlugin(String key) { - checkState(started.get(), NOT_STARTED_YET); - return pluginInfosByKeys.containsKey(key); - } - - private static Collection listJarFiles(File dir) { - if (dir.exists()) { - return FileUtils.listFiles(dir, JAR_FILE_EXTENSIONS, false); - } - return Collections.emptyList(); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java deleted file mode 100644 index 2f5d0b2d357..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import com.google.common.base.Optional; -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.util.Date; -import org.apache.commons.io.IOUtils; -import org.sonar.api.Properties; -import org.sonar.api.Property; -import org.sonar.api.config.Configuration; -import org.sonar.api.utils.UriReader; -import org.sonar.api.utils.log.Loggers; -import org.sonar.process.ProcessProperties; -import org.sonar.updatecenter.common.UpdateCenter; -import org.sonar.updatecenter.common.UpdateCenterDeserializer; -import org.sonar.updatecenter.common.UpdateCenterDeserializer.Mode; - -/** - * HTTP client to load data from the remote update center hosted at https://update.sonarsource.org. - * - * @since 2.4 - */ -@Properties({ - @Property( - key = UpdateCenterClient.URL_PROPERTY, - defaultValue = "https://update.sonarsource.org/update-center.properties", - name = "Update Center URL", - category = "Update Center", - project = false, - // hidden from UI - global = false) -}) -public class UpdateCenterClient { - - public static final String URL_PROPERTY = "sonar.updatecenter.url"; - public static final int PERIOD_IN_MILLISECONDS = 60 * 60 * 1000; - - private final URI uri; - private final UriReader uriReader; - private final boolean isActivated; - private UpdateCenter pluginCenter = null; - private long lastRefreshDate = 0; - - public UpdateCenterClient(UriReader uriReader, Configuration config) throws URISyntaxException { - this.uriReader = uriReader; - this.uri = new URI(config.get(URL_PROPERTY).get()); - this.isActivated = config.getBoolean(ProcessProperties.Property.SONAR_UPDATECENTER_ACTIVATE.getKey()).get(); - Loggers.get(getClass()).info("Update center: " + uriReader.description(uri)); - } - - public Optional getUpdateCenter() { - return getUpdateCenter(false); - } - - public Optional getUpdateCenter(boolean forceRefresh) { - if (!isActivated) { - return Optional.absent(); - } - - if (pluginCenter == null || forceRefresh || needsRefresh()) { - pluginCenter = init(); - lastRefreshDate = System.currentTimeMillis(); - } - return Optional.fromNullable(pluginCenter); - } - - public Date getLastRefreshDate() { - return lastRefreshDate > 0 ? new Date(lastRefreshDate) : null; - } - - private boolean needsRefresh() { - return lastRefreshDate + PERIOD_IN_MILLISECONDS < System.currentTimeMillis(); - } - - private UpdateCenter init() { - InputStream input = null; - try { - String content = uriReader.readString(uri, StandardCharsets.UTF_8); - java.util.Properties properties = new java.util.Properties(); - input = IOUtils.toInputStream(content, StandardCharsets.UTF_8); - properties.load(input); - return new UpdateCenterDeserializer(Mode.PROD, true).fromProperties(properties); - - } catch (Exception e) { - Loggers.get(getClass()).error("Fail to connect to update center", e); - return null; - - } finally { - IOUtils.closeQuietly(input); - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java deleted file mode 100644 index 0c0a6730987..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import com.google.common.base.Optional; -import org.sonar.api.SonarRuntime; -import org.sonar.updatecenter.common.UpdateCenter; -import org.sonar.updatecenter.common.Version; - -/** - * @since 2.4 - */ -public class UpdateCenterMatrixFactory { - - private final UpdateCenterClient centerClient; - private final SonarRuntime sonarRuntime; - private final InstalledPluginReferentialFactory installedPluginReferentialFactory; - - public UpdateCenterMatrixFactory(UpdateCenterClient centerClient, SonarRuntime runtime, - InstalledPluginReferentialFactory installedPluginReferentialFactory) { - this.centerClient = centerClient; - this.sonarRuntime = runtime; - this.installedPluginReferentialFactory = installedPluginReferentialFactory; - } - - public Optional getUpdateCenter(boolean refreshUpdateCenter) { - Optional updateCenter = centerClient.getUpdateCenter(refreshUpdateCenter); - if (updateCenter.isPresent()) { - org.sonar.api.utils.Version fullVersion = sonarRuntime.getApiVersion(); - org.sonar.api.utils.Version semanticVersion = org.sonar.api.utils.Version.create(fullVersion.major(), fullVersion.minor(), fullVersion.patch()); - - return Optional.of(updateCenter.get().setInstalledSonarVersion(Version.create(semanticVersion.toString())).registerInstalledPlugins( - installedPluginReferentialFactory.getInstalledPluginReferential()) - .setDate(centerClient.getLastRefreshDate())); - } - return Optional.absent(); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/WebServerExtensionInstaller.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/WebServerExtensionInstaller.java deleted file mode 100644 index 9fa956d2a15..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/WebServerExtensionInstaller.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import org.sonar.api.SonarRuntime; -import org.sonar.api.server.ServerSide; -import org.sonar.core.platform.PluginRepository; - -import static java.util.Collections.singleton; - -@ServerSide -public class WebServerExtensionInstaller extends ServerExtensionInstaller { - public WebServerExtensionInstaller(SonarRuntime sonarRuntime, PluginRepository pluginRepository) { - super(sonarRuntime, pluginRepository, singleton(ServerSide.class)); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/edition/EditionBundledPlugins.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/edition/EditionBundledPlugins.java deleted file mode 100644 index f6c1db3b035..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/edition/EditionBundledPlugins.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins.edition; - -import java.util.Arrays; -import org.sonar.core.platform.PluginInfo; -import org.sonar.updatecenter.common.Plugin; - -public final class EditionBundledPlugins { - - private static final String SONARSOURCE_ORGANIZATION = "SonarSource"; - private static final String[] SONARSOURCE_COMMERCIAL_LICENSES = {"SonarSource", "Commercial"}; - - private EditionBundledPlugins() { - // prevents instantiation - } - - public static boolean isEditionBundled(Plugin plugin) { - return SONARSOURCE_ORGANIZATION.equalsIgnoreCase(plugin.getOrganization()) - && Arrays.stream(SONARSOURCE_COMMERCIAL_LICENSES).anyMatch(s -> s.equalsIgnoreCase(plugin.getLicense())); - } - - public static boolean isEditionBundled(PluginInfo pluginInfo) { - return SONARSOURCE_ORGANIZATION.equalsIgnoreCase(pluginInfo.getOrganizationName()) - && Arrays.stream(SONARSOURCE_COMMERCIAL_LICENSES).anyMatch(s -> s.equalsIgnoreCase(pluginInfo.getLicense())); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/edition/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/edition/package-info.java deleted file mode 100644 index e0a7b00bbf9..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/edition/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.plugins.edition; - -import javax.annotation.ParametersAreNonnullByDefault; - diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/package-info.java deleted file mode 100644 index cc398bb88c6..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/plugins/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.plugins; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java deleted file mode 100644 index 6afdea527e9..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.project; - -import java.util.Set; -import org.sonar.api.server.ServerSide; - -@ServerSide -public interface ProjectLifeCycleListener { - /** - * This method is called after the specified projects have been deleted. - */ - void onProjectsDeleted(Set projects); - - /** - * This method is called after the specified projects have been deleted. - */ - void onProjectBranchesDeleted(Set projects); - - /** - * This method is called after the specified projects' keys have been modified. - */ - void onProjectsRekeyed(Set rekeyedProjects); -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java deleted file mode 100644 index 7f3d3f1867d..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.project; - -import java.util.Set; - -public interface ProjectLifeCycleListeners { - /** - * This method is called after the specified projects have been deleted and will call method - * {@link ProjectLifeCycleListener#onProjectsDeleted(Set) onProjectsDeleted(Set)} of all known - * {@link ProjectLifeCycleListener} implementations. - *

- * This method ensures all {@link ProjectLifeCycleListener} implementations are called, even if one or more of - * them fail with an exception. - */ - void onProjectsDeleted(Set projects); - - /** - * This method is called after the specified project branches have been deleted and will call method - * {@link ProjectLifeCycleListener#onProjectBranchesDeleted(Set)} of all known - * {@link ProjectLifeCycleListener} implementations. - *

- * This method ensures all {@link ProjectLifeCycleListener} implementations are called, even if one or more of - * them fail with an exception. - */ - void onProjectBranchesDeleted(Set projects); - - /** - * This method is called after the specified project's key has been changed and will call method - * {@link ProjectLifeCycleListener#onProjectsRekeyed(Set) onProjectsRekeyed(Set)} of all known - * {@link ProjectLifeCycleListener} implementations. - *

- * This method ensures all {@link ProjectLifeCycleListener} implementations are called, even if one or more of - * them fail with an exception. - */ - void onProjectsRekeyed(Set rekeyedProjects); - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java deleted file mode 100644 index af440d60adb..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.project; - -import java.util.Arrays; -import java.util.Set; -import java.util.function.Consumer; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class ProjectLifeCycleListenersImpl implements ProjectLifeCycleListeners { - private static final Logger LOG = Loggers.get(ProjectLifeCycleListenersImpl.class); - - private final ProjectLifeCycleListener[] listeners; - - /** - * Used by Pico when there is no ProjectLifeCycleListener implementation in container. - */ - public ProjectLifeCycleListenersImpl() { - this.listeners = new ProjectLifeCycleListener[0]; - } - - /** - * Used by Pico when there is at least one ProjectLifeCycleListener implementation in container. - */ - public ProjectLifeCycleListenersImpl(ProjectLifeCycleListener[] listeners) { - this.listeners = listeners; - } - - @Override - public void onProjectsDeleted(Set projects) { - checkNotNull(projects, "projects can't be null"); - if (projects.isEmpty()) { - return; - } - - Arrays.stream(listeners) - .forEach(safelyCallListener(listener -> listener.onProjectsDeleted(projects))); - } - - @Override - public void onProjectBranchesDeleted(Set projects) { - checkNotNull(projects, "projects can't be null"); - if (projects.isEmpty()) { - return; - } - - Arrays.stream(listeners) - .forEach(safelyCallListener(listener -> listener.onProjectBranchesDeleted(projects))); - } - - @Override - public void onProjectsRekeyed(Set rekeyedProjects) { - checkNotNull(rekeyedProjects, "rekeyedProjects can't be null"); - if (rekeyedProjects.isEmpty()) { - return; - } - - Arrays.stream(listeners) - .forEach(safelyCallListener(listener -> listener.onProjectsRekeyed(rekeyedProjects))); - } - - private static Consumer safelyCallListener(Consumer task) { - return listener -> { - try { - task.accept(listener); - } catch (Error | Exception e) { - LOG.error("Call on ProjectLifeCycleListener \"{}\" failed", listener.getClass(), e); - } - }; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/RekeyedProject.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/project/RekeyedProject.java deleted file mode 100644 index ecab0b148f8..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/RekeyedProject.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.project; - -import java.util.Objects; - -import static com.google.common.base.Preconditions.checkNotNull; - -public final class RekeyedProject { - private final Project project; - private final String previousKey; - - public RekeyedProject(Project project, String previousKey) { - this.project = checkNotNull(project, "project can't be null"); - this.previousKey = checkNotNull(previousKey, "previousKey can't be null"); - } - - public Project getProject() { - return project; - } - - public String getPreviousKey() { - return previousKey; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - RekeyedProject that = (RekeyedProject) o; - return Objects.equals(project, that.project) && - Objects.equals(previousKey, that.previousKey); - } - - @Override - public int hashCode() { - return Objects.hash(project, previousKey); - } - - @Override - public String toString() { - return "RekeyedProject{" + - "project=" + project + - ", previousKey='" + previousKey + '\'' + - '}'; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/Visibility.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/project/Visibility.java deleted file mode 100644 index edf05180276..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/Visibility.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.project; - -import java.util.List; - -import static java.util.Arrays.stream; -import static org.sonar.core.util.stream.MoreCollectors.toList; - -public enum Visibility { - - PRIVATE(true, "private"), - PUBLIC(false, "public"); - - private static final List LABELS = stream(values()).map(Visibility::getLabel).collect(toList(values().length)); - - private final boolean isPrivate; - private final String label; - - Visibility(boolean isPrivate, String label) { - this.isPrivate = isPrivate; - this.label = label; - } - - public String getLabel() { - return label; - } - - boolean isPrivate() { - return isPrivate; - } - - public static String getLabel(boolean isPrivate) { - return stream(values()) - .filter(v -> v.isPrivate == isPrivate) - .map(Visibility::getLabel) - .findAny() - .orElseThrow(() -> new IllegalStateException("Invalid visibility boolean '" + isPrivate + "'")); - } - - public static boolean isPrivate(String label) { - return parseVisibility(label).isPrivate(); - } - - public static Visibility parseVisibility(String label) { - return stream(values()) - .filter(v -> v.label.equals(label)) - .findAny() - .orElseThrow(() -> new IllegalStateException("Invalid visibility label '" + label + "'")); - } - - public static List getLabels() { - return LABELS; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/project/package-info.java deleted file mode 100644 index 205d7058e06..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/project/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.project; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/ProjectsInWarning.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/ProjectsInWarning.java deleted file mode 100644 index 7591c138d28..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/ProjectsInWarning.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualitygate; - -import static com.google.common.base.Preconditions.checkArgument; - -/** - * Store number of projects in warning in order for the web service api/components/search to know if warning value should be return in the quality gate facet. - * The value is updated each time the daemon {@link ProjectsInWarningDaemon} is executed - */ -public class ProjectsInWarning { - - private Long projectsInWarning; - - public void update(long projectsInWarning) { - this.projectsInWarning = projectsInWarning; - } - - public long count() { - checkArgument(isInitialized(), "Initialization has not be done"); - return projectsInWarning; - } - - boolean isInitialized() { - return projectsInWarning != null; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java deleted file mode 100644 index 6953a77575e..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualitygate.changeevent; - -import java.util.Optional; -import java.util.function.Supplier; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; -import org.sonar.api.config.Configuration; -import org.sonar.api.measures.Metric; -import org.sonar.db.component.BranchDto; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.SnapshotDto; -import org.sonar.server.qualitygate.EvaluatedQualityGate; - -import static java.util.Objects.requireNonNull; - -@Immutable -public class QGChangeEvent { - private final ComponentDto project; - private final BranchDto branch; - private final SnapshotDto analysis; - private final Configuration projectConfiguration; - private final Metric.Level previousStatus; - private final Supplier> qualityGateSupplier; - - public QGChangeEvent(ComponentDto project, BranchDto branch, SnapshotDto analysis, Configuration projectConfiguration, - @Nullable Metric.Level previousStatus, Supplier> qualityGateSupplier) { - this.project = requireNonNull(project, "project can't be null"); - this.branch = requireNonNull(branch, "branch can't be null"); - this.analysis = requireNonNull(analysis, "analysis can't be null"); - this.projectConfiguration = requireNonNull(projectConfiguration, "projectConfiguration can't be null"); - this.previousStatus = previousStatus; - this.qualityGateSupplier = requireNonNull(qualityGateSupplier, "qualityGateSupplier can't be null"); - } - - public BranchDto getBranch() { - return branch; - } - - public ComponentDto getProject() { - return project; - } - - public SnapshotDto getAnalysis() { - return analysis; - } - - public Configuration getProjectConfiguration() { - return projectConfiguration; - } - - public Optional getPreviousStatus() { - return Optional.ofNullable(previousStatus); - } - - public Supplier> getQualityGateSupplier() { - return qualityGateSupplier; - } - - @Override - public String toString() { - return "QGChangeEvent{" + - "project=" + toString(project) + - ", branch=" + toString(branch) + - ", analysis=" + toString(analysis) + - ", projectConfiguration=" + projectConfiguration + - ", previousStatus=" + previousStatus + - ", qualityGateSupplier=" + qualityGateSupplier + - '}'; - } - - private static String toString(ComponentDto project) { - return project.uuid() + ":" + project.getKey(); - } - - private static String toString(BranchDto branch) { - return branch.getBranchType() + ":" + branch.getUuid() + ":" + branch.getProjectUuid() + ":" + branch.getMergeBranchUuid(); - } - - private static String toString(SnapshotDto analysis) { - return analysis.getUuid() + ":" + analysis.getCreatedAt(); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java deleted file mode 100644 index c3baf201471..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualitygate.changeevent; - -import java.util.EnumSet; -import java.util.Set; -import org.sonar.api.rules.RuleType; -import org.sonar.api.server.ServerSide; - -@ServerSide -public interface QGChangeEventListener { - /** - * Called consequently to a change done on one or more issue of a given project. - * - * @param qualityGateEvent can not be {@code null} - * @param changedIssues can not be {@code null} nor empty - */ - void onIssueChanges(QGChangeEvent qualityGateEvent, Set changedIssues); - - interface ChangedIssue { - - String getKey(); - - Status getStatus(); - - RuleType getType(); - - String getSeverity(); - - default boolean isNotClosed() { - return !Status.CLOSED_STATUSES.contains(getStatus()); - } - } - - enum Status { - OPEN, - CONFIRMED, - REOPENED, - RESOLVED_FP, - RESOLVED_WF, - RESOLVED_FIXED, - TO_REVIEW, - IN_REVIEW, - REVIEWED; - - protected static final Set CLOSED_STATUSES = EnumSet.of(CONFIRMED, RESOLVED_FIXED, RESOLVED_FP, RESOLVED_WF); - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java deleted file mode 100644 index e2e66b555de..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualitygate.changeevent; - -import java.util.Collection; -import java.util.List; -import org.sonar.core.issue.DefaultIssue; - -public interface QGChangeEventListeners { - - void broadcastOnIssueChange(List changedIssues, Collection qgChangeEvents); -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java deleted file mode 100644 index 76a4c2bebf1..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualitygate.changeevent; - -import com.google.common.collect.Multimap; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import org.sonar.api.issue.Issue; -import org.sonar.api.rules.RuleType; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.core.issue.DefaultIssue; -import org.sonar.core.util.stream.MoreCollectors; -import org.sonar.server.qualitygate.changeevent.QGChangeEventListener.ChangedIssue; - -import static java.lang.String.format; -import static org.sonar.core.util.stream.MoreCollectors.toSet; - -/** - * Broadcast a given collection of {@link QGChangeEvent} for a specific trigger to all the registered - * {@link QGChangeEventListener} in Pico. - * - * This class ensures that an {@link Exception} occurring calling one of the {@link QGChangeEventListener} doesn't - * prevent from calling the others. - */ -public class QGChangeEventListenersImpl implements QGChangeEventListeners { - private static final Logger LOG = Loggers.get(QGChangeEventListenersImpl.class); - - private final QGChangeEventListener[] listeners; - - /** - * Used by Pico when there is no QGChangeEventListener instance in container. - */ - public QGChangeEventListenersImpl() { - this.listeners = new QGChangeEventListener[0]; - } - - public QGChangeEventListenersImpl(QGChangeEventListener[] listeners) { - this.listeners = listeners; - } - - @Override - public void broadcastOnIssueChange(List issues, Collection changeEvents) { - if (listeners.length == 0 || issues.isEmpty() || changeEvents.isEmpty()) { - return; - } - - try { - Multimap eventsByComponentUuid = changeEvents.stream() - .collect(MoreCollectors.index(t -> t.getProject().uuid())); - Multimap issueByComponentUuid = issues.stream() - .collect(MoreCollectors.index(DefaultIssue::projectUuid)); - - issueByComponentUuid.asMap() - .forEach((componentUuid, value) -> { - Collection qgChangeEvents = eventsByComponentUuid.get(componentUuid); - if (!qgChangeEvents.isEmpty()) { - Set changedIssues = value.stream() - .map(ChangedIssueImpl::new) - .collect(toSet()); - qgChangeEvents - .forEach(changeEvent -> Arrays.stream(listeners) - .forEach(listener -> broadcastTo(changedIssues, changeEvent, listener))); - } - }); - } catch (Error e) { - LOG.warn(format("Broadcasting to listeners failed for %s events", changeEvents.size()), e); - } - } - - private static void broadcastTo(Set changedIssues, QGChangeEvent changeEvent, QGChangeEventListener listener) { - try { - LOG.trace("calling onChange() on listener {} for events {}...", listener.getClass().getName(), changeEvent); - listener.onIssueChanges(changeEvent, changedIssues); - } catch (Exception e) { - LOG.warn(format("onChange() call failed on listener %s for events %s", listener.getClass().getName(), changeEvent), e); - } - } - - static class ChangedIssueImpl implements ChangedIssue { - private final String key; - private final QGChangeEventListener.Status status; - private final RuleType type; - private final String severity; - - ChangedIssueImpl(DefaultIssue issue) { - this.key = issue.key(); - this.status = statusOf(issue); - this.type = issue.type(); - this.severity = issue.severity(); - } - - static QGChangeEventListener.Status statusOf(DefaultIssue issue) { - switch (issue.status()) { - case Issue.STATUS_OPEN: - return QGChangeEventListener.Status.OPEN; - case Issue.STATUS_CONFIRMED: - return QGChangeEventListener.Status.CONFIRMED; - case Issue.STATUS_REOPENED: - return QGChangeEventListener.Status.REOPENED; - case Issue.STATUS_TO_REVIEW: - return QGChangeEventListener.Status.TO_REVIEW; - case Issue.STATUS_IN_REVIEW: - return QGChangeEventListener.Status.IN_REVIEW; - case Issue.STATUS_REVIEWED: - return QGChangeEventListener.Status.REVIEWED; - case Issue.STATUS_RESOLVED: - return statusOfResolved(issue); - default: - throw new IllegalStateException("Unexpected status: " + issue.status()); - } - } - - private static QGChangeEventListener.Status statusOfResolved(DefaultIssue issue) { - String resolution = issue.resolution(); - Objects.requireNonNull(resolution, "A resolved issue should have a resolution"); - switch (resolution) { - case Issue.RESOLUTION_FALSE_POSITIVE: - return QGChangeEventListener.Status.RESOLVED_FP; - case Issue.RESOLUTION_WONT_FIX: - return QGChangeEventListener.Status.RESOLVED_WF; - case Issue.RESOLUTION_FIXED: - return QGChangeEventListener.Status.RESOLVED_FIXED; - default: - throw new IllegalStateException("Unexpected resolution for a resolved issue: " + resolution); - } - } - - @Override - public String getKey() { - return key; - } - - @Override - public QGChangeEventListener.Status getStatus() { - return status; - } - - @Override - public RuleType getType() { - return type; - } - - @Override - public String getSeverity() { - return severity; - } - - @Override - public String toString() { - return "ChangedIssueImpl{" + - "key='" + key + '\'' + - ", status=" + status + - ", type=" + type + - ", severity=" + severity + - '}'; - } - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/Trigger.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/Trigger.java deleted file mode 100644 index 6ef8397046a..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/Trigger.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualitygate.changeevent; - -public enum Trigger { - ISSUE_CHANGE -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/package-info.java deleted file mode 100644 index ed52cd87a47..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualitygate/changeevent/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.qualitygate.changeevent; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java deleted file mode 100644 index 91a31ca76d9..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/BulkChangeResult.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualityprofile; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class BulkChangeResult { - - private final List errors = new ArrayList<>(); - private int succeeded = 0; - private int failed = 0; - private final List changes = new ArrayList<>(); - - public List getErrors() { - return errors; - } - - public int countSucceeded() { - return succeeded; - } - - public int countFailed() { - return failed; - } - - void incrementSucceeded() { - succeeded++; - } - - void incrementFailed() { - failed++; - } - - void addChanges(Collection c) { - this.changes.addAll(c); - } - - public List getChanges() { - return changes; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java deleted file mode 100644 index 32a11c072d8..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualityprofile; - -import java.util.Collection; -import java.util.List; -import javax.annotation.Nullable; -import org.sonar.api.server.ServerSide; -import org.sonar.db.DbSession; -import org.sonar.db.qualityprofile.QProfileDto; -import org.sonar.db.rule.RuleDefinitionDto; -import org.sonar.server.rule.index.RuleQuery; - -/** - * Operations related to activation and deactivation of rules on user profiles. - */ -@ServerSide -public interface QProfileRules { - - /** - * Activate multiple rules at once on a Quality profile. - * Db session is committed and Elasticsearch indices are updated. - * If an activation fails to be executed, then all others are - * canceled, db session is not committed and an exception is - * thrown. - */ - List activateAndCommit(DbSession dbSession, QProfileDto profile, Collection activations); - - /** - * Same as {@link #activateAndCommit(DbSession, QProfileDto, Collection)} except - * that: - * - rules are loaded from search engine - * - rules are activated with default parameters - * - an activation failure does not break others. No exception is thrown. - */ - BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity); - - List deactivateAndCommit(DbSession dbSession, QProfileDto profile, Collection ruleIds); - - BulkChangeResult bulkDeactivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery); - - /** - * Delete a rule from all Quality profiles. Db session is not committed. As a - * consequence Elasticsearch indices are NOT updated. - */ - List deleteRule(DbSession dbSession, RuleDefinitionDto rule); -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java deleted file mode 100644 index 106fd158b26..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualityprofile; - -import com.google.common.base.Strings; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; -import org.sonar.api.rule.Severity; - -/** - * The request for activation. - */ -@Immutable -public class RuleActivation { - - private final int ruleId; - private final boolean reset; - private final String severity; - private final Map parameters = new HashMap<>(); - - private RuleActivation(int ruleId, boolean reset, @Nullable String severity, @Nullable Map parameters) { - this.ruleId = ruleId; - this.reset = reset; - this.severity = severity; - if (severity != null && !Severity.ALL.contains(severity)) { - throw new IllegalArgumentException("Unknown severity: " + severity); - } - if (parameters != null) { - for (Map.Entry entry : parameters.entrySet()) { - this.parameters.put(entry.getKey(), Strings.emptyToNull(entry.getValue())); - } - } - } - - public static RuleActivation createReset(int ruleId) { - return new RuleActivation(ruleId, true, null, null); - } - - public static RuleActivation create(int ruleId, @Nullable String severity, @Nullable Map parameters) { - return new RuleActivation(ruleId, false, severity, parameters); - } - - public static RuleActivation create(int ruleId) { - return create(ruleId, null, null); - } - - /** - * Optional severity. Use the parent severity or default rule severity if null. - */ - @CheckForNull - public String getSeverity() { - return severity; - } - - public int getRuleId() { - return ruleId; - } - - @CheckForNull - public String getParameter(String key) { - return parameters.get(key); - } - - public boolean hasParameter(String key) { - return parameters.containsKey(key); - } - - public boolean isReset() { - return reset; - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/package-info.java deleted file mode 100644 index 5a3c798af36..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/qualityprofile/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.qualityprofile; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/ProjectConfigurationLoader.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/ProjectConfigurationLoader.java deleted file mode 100644 index e261763e6f5..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/ProjectConfigurationLoader.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.setting; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import org.sonar.api.config.Configuration; -import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDto; - -import static java.lang.String.format; -import static java.util.Objects.requireNonNull; - -public interface ProjectConfigurationLoader { - /** - * Loads configuration for the specified components. - * - *

- * Returns the applicable component configuration with most specific configuration overriding more global ones - * (eg. global > project > branch). - * - *

- * Any component is accepted but SQ only supports specific properties for projects and branches. - */ - Map loadProjectConfigurations(DbSession dbSession, Set projects); - - default Configuration loadProjectConfiguration(DbSession dbSession, ComponentDto project) { - Map configurations = loadProjectConfigurations(dbSession, Collections.singleton(project)); - return requireNonNull(configurations.get(project.uuid()), () -> format("Configuration for project '%s' is not found", project.getKey())); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/ProjectConfigurationLoaderImpl.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/ProjectConfigurationLoaderImpl.java deleted file mode 100644 index 95e11242587..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/ProjectConfigurationLoaderImpl.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.setting; - -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.sonar.api.config.Configuration; -import org.sonar.api.config.Settings; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.property.PropertyDto; - -import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; - -public class ProjectConfigurationLoaderImpl implements ProjectConfigurationLoader { - private final Settings globalSettings; - private final DbClient dbClient; - - public ProjectConfigurationLoaderImpl(Settings globalSettings, DbClient dbClient) { - this.globalSettings = globalSettings; - this.dbClient = dbClient; - } - - @Override - public Map loadProjectConfigurations(DbSession dbSession, Set projects) { - Set mainBranchDbKeys = projects.stream().map(ComponentDto::getKey).collect(Collectors.toSet()); - Map mainBranchSettingsByDbKey = loadMainBranchConfigurations(dbSession, mainBranchDbKeys); - return projects.stream() - .collect(uniqueIndex(ComponentDto::uuid, component -> { - if (component.getDbKey().equals(component.getKey())) { - return mainBranchSettingsByDbKey.get(component.getKey()).asConfiguration(); - } - - ChildSettings settings = new ChildSettings(mainBranchSettingsByDbKey.get(component.getKey())); - dbClient.propertiesDao() - .selectProjectProperties(dbSession, component.getDbKey()) - .forEach(property -> settings.setProperty(property.getKey(), property.getValue())); - return settings.asConfiguration(); - })); - } - - private Map loadMainBranchConfigurations(DbSession dbSession, Set dbKeys) { - return dbKeys.stream().collect(uniqueIndex(Function.identity(), dbKey -> { - ChildSettings settings = new ChildSettings(globalSettings); - List propertyDtos = dbClient.propertiesDao() - .selectProjectProperties(dbSession, dbKey); - propertyDtos - .forEach(property -> settings.setProperty(property.getKey(), property.getValue())); - return settings; - })); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/SettingsChangeNotifier.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/SettingsChangeNotifier.java deleted file mode 100644 index de074ef5232..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/SettingsChangeNotifier.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.setting; - -import com.google.common.annotations.VisibleForTesting; -import org.sonar.api.config.GlobalPropertyChangeHandler; - -import javax.annotation.Nullable; - -public class SettingsChangeNotifier { - - @VisibleForTesting - GlobalPropertyChangeHandler[] changeHandlers; - - public SettingsChangeNotifier(GlobalPropertyChangeHandler[] changeHandlers) { - this.changeHandlers = changeHandlers; - } - - public SettingsChangeNotifier() { - this(new GlobalPropertyChangeHandler[0]); - } - - public void onGlobalPropertyChange(String key, @Nullable String value) { - GlobalPropertyChangeHandler.PropertyChange change = GlobalPropertyChangeHandler.PropertyChange.create(key, value); - for (GlobalPropertyChangeHandler changeHandler : changeHandlers) { - changeHandler.onChange(change); - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/package-info.java deleted file mode 100644 index e816bf4051c..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/setting/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.setting; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/telemetry/LicenseReader.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/telemetry/LicenseReader.java deleted file mode 100644 index 22029d62a36..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/telemetry/LicenseReader.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.telemetry; - -import java.util.Optional; -import org.sonar.api.server.ServerSide; - -@ServerSide -public interface LicenseReader { - Optional read(); - - interface License { - String getType(); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/telemetry/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/telemetry/package-info.java deleted file mode 100644 index ce3724b93a5..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/telemetry/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.telemetry; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/BooleanTypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/BooleanTypeValidation.java deleted file mode 100644 index 1b3ade32e60..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/BooleanTypeValidation.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import java.util.List; -import javax.annotation.Nullable; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.PropertyType; - -import static org.sonar.server.exceptions.BadRequestException.checkRequest; - -public class BooleanTypeValidation implements TypeValidation { - - @Override - public String key() { - return PropertyType.BOOLEAN.name(); - } - - @Override - public void validate(String value, @Nullable List options) { - checkRequest(StringUtils.equalsIgnoreCase(value, "true") || StringUtils.equalsIgnoreCase(value, "false"), - "Value '%s' must be one of \"true\" or \"false\".", value); - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/FloatTypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/FloatTypeValidation.java deleted file mode 100644 index fd221dced55..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/FloatTypeValidation.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import java.util.List; -import javax.annotation.Nullable; -import org.sonar.api.PropertyType; -import org.sonar.server.exceptions.BadRequestException; - -import static java.lang.String.format; - -public class FloatTypeValidation implements TypeValidation { - - @Override - public String key() { - return PropertyType.FLOAT.name(); - } - - @Override - public void validate(String value, @Nullable List options) { - try { - Double.parseDouble(value); - } catch (NumberFormatException e) { - throw BadRequestException.create(format("Value '%s' must be an floating point number.", value)); - } - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/GlobalLockManager.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/GlobalLockManager.java deleted file mode 100644 index 81f13b22a1d..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/GlobalLockManager.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.sonar.api.ce.ComputeEngineSide; -import org.sonar.api.server.ServerSide; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; - -/** - * Provide a simple mechanism to manage global locks across multiple nodes running in a cluster. - * In the target use case multiple nodes try to execute something at around the same time, - * and only the first should succeed, and the rest do nothing. - */ -@ComputeEngineSide -@ServerSide -public class GlobalLockManager { - - static final int DEFAULT_LOCK_DURATION_SECONDS = 180; - - private final DbClient dbClient; - - public GlobalLockManager(DbClient dbClient) { - this.dbClient = dbClient; - } - - /** - * Try to acquire a lock on the given name in the default namespace, - * using the generic locking mechanism of {@see org.sonar.db.property.InternalPropertiesDao}. - */ - public boolean tryLock(String name) { - return tryLock(name, DEFAULT_LOCK_DURATION_SECONDS); - } - - public boolean tryLock(String name, int durationSecond) { - try (DbSession dbSession = dbClient.openSession(false)) { - boolean success = dbClient.internalPropertiesDao().tryLock(dbSession, name, durationSecond); - dbSession.commit(); - return success; - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/IntegerTypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/IntegerTypeValidation.java deleted file mode 100644 index 84502df47f7..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/IntegerTypeValidation.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import java.util.List; -import javax.annotation.Nullable; -import org.sonar.api.PropertyType; -import org.sonar.server.exceptions.BadRequestException; - -import static java.lang.String.format; - -public class IntegerTypeValidation implements TypeValidation { - - @Override - public String key() { - return PropertyType.INTEGER.name(); - } - - @Override - public void validate(String value, @Nullable List options) { - try { - Integer.parseInt(value); - } catch (NumberFormatException e) { - throw BadRequestException.create(format("Value '%s' must be an integer.", value)); - } - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/LongTypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/LongTypeValidation.java deleted file mode 100644 index 9ca540a1d1d..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/LongTypeValidation.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import java.util.List; -import javax.annotation.Nullable; -import org.sonar.api.PropertyType; -import org.sonar.server.exceptions.BadRequestException; - -import static java.lang.String.format; - -public class LongTypeValidation implements TypeValidation { - @Override - public String key() { - return PropertyType.LONG.name(); - } - - @Override - public void validate(String value, @Nullable List options) { - try { - Long.parseLong(value); - } catch (NumberFormatException e) { - throw BadRequestException.create(format("Value '%s' must be a long.", value)); - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java deleted file mode 100644 index ba8598a7786..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/MetricLevelTypeValidation.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import java.util.List; -import javax.annotation.Nullable; -import org.sonar.api.PropertyType; -import org.sonar.api.measures.Metric; -import org.sonar.server.exceptions.BadRequestException; - -import static java.lang.String.format; - -public class MetricLevelTypeValidation implements TypeValidation { - @Override - public String key() { - return PropertyType.METRIC_LEVEL.name(); - } - - @Override - public void validate(String value, @Nullable List options) { - try { - Metric.Level.valueOf(value); - } catch (IllegalArgumentException e) { - throw BadRequestException.create(format("Value '%s' must be one of \"OK\", \"ERROR\".", value)); - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/StringListTypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/StringListTypeValidation.java deleted file mode 100644 index acb1c7dca8f..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/StringListTypeValidation.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import java.util.List; -import javax.annotation.Nullable; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.PropertyType; - -import static org.sonar.server.exceptions.BadRequestException.checkRequest; - -public class StringListTypeValidation implements TypeValidation { - - @Override - public String key() { - return PropertyType.SINGLE_SELECT_LIST.name(); - } - - @Override - public void validate(String value, @Nullable List options) { - checkRequest(options == null || options.contains(value), "Value '%s' must be one of : %s.", value, StringUtils.join(options, ", ")); - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/StringTypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/StringTypeValidation.java deleted file mode 100644 index 3851ede0e81..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/StringTypeValidation.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.sonar.api.PropertyType; - -import javax.annotation.Nullable; - -import java.util.List; - -public class StringTypeValidation implements TypeValidation { - - @Override - public String key() { - return PropertyType.STRING.name(); - } - - @Override - public void validate(String value, @Nullable List options) { - // Nothing to do - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TextTypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TextTypeValidation.java deleted file mode 100644 index c26ad125162..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TextTypeValidation.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.sonar.api.PropertyType; - -import javax.annotation.Nullable; - -import java.util.List; - -public class TextTypeValidation implements TypeValidation { - - @Override - public String key() { - return PropertyType.TEXT.name(); - } - - @Override - public void validate(String value, @Nullable List options) { - // Nothing to do - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidation.java deleted file mode 100644 index 797a3438d8f..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidation.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.sonar.api.server.ServerSide; - -import javax.annotation.Nullable; - -import java.util.List; - -@ServerSide -public interface TypeValidation { - - String key(); - - void validate(String value, @Nullable List options); -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidationModule.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidationModule.java deleted file mode 100644 index 3cc4f038e5e..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidationModule.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.sonar.core.platform.Module; - -public class TypeValidationModule extends Module { - @Override - protected void configureModule() { - add( - TypeValidations.class, - IntegerTypeValidation.class, - FloatTypeValidation.class, - BooleanTypeValidation.class, - TextTypeValidation.class, - StringTypeValidation.class, - StringListTypeValidation.class, - LongTypeValidation.class, - MetricLevelTypeValidation.class - ); - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidations.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidations.java deleted file mode 100644 index 2c8883b77eb..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/TypeValidations.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import java.util.List; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.sonar.api.server.ServerSide; - -import static org.sonar.server.exceptions.BadRequestException.checkRequest; - -@ServerSide -public class TypeValidations { - - private final List typeValidationList; - - public TypeValidations(List typeValidationList) { - this.typeValidationList = typeValidationList; - } - - public void validate(List values, String type, List options) { - TypeValidation typeValidation = findByKey(type); - for (String value : values) { - typeValidation.validate(value, options); - } - } - - public void validate(String value, String type, @Nullable List options) { - TypeValidation typeValidation = findByKey(type); - typeValidation.validate(value, options); - } - - private TypeValidation findByKey(String key) { - TypeValidation typeValidation = Iterables.find(typeValidationList, new TypeValidationMatchKey(key), null); - checkRequest(typeValidation != null, "Type '%s' is not valid.", key); - return typeValidation; - } - - private static class TypeValidationMatchKey implements Predicate { - private final String key; - - public TypeValidationMatchKey(String key) { - this.key = key; - } - - @Override - public boolean apply(@Nonnull TypeValidation input) { - return input.key().equals(key); - } - } -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/Validation.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/Validation.java deleted file mode 100644 index 99d28d0bc96..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/Validation.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -public class Validation { - - public static final String CANT_BE_EMPTY_MESSAGE = "%s can't be empty"; - public static final String IS_TOO_SHORT_MESSAGE = "%s is too short (minimum is %s characters)"; - public static final String IS_TOO_LONG_MESSAGE = "%s is too long (maximum is %s characters)"; - public static final String IS_ALREADY_USED_MESSAGE = "%s has already been taken"; - - private Validation() { - // only static methods - } - -} diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/util/package-info.java deleted file mode 100644 index 8fd4b5b3582..00000000000 --- a/server/sonar-webserver-common/src/main/java/org/sonar/server/util/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.util; - -import javax.annotation.ParametersAreNonnullByDefault; - diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java deleted file mode 100644 index de5f24347fc..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.app; - -import java.io.File; -import java.io.IOException; -import java.util.Random; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.config.internal.MapSettings; -import org.sonar.process.sharedmemoryfile.DefaultProcessCommands; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX; -import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; - -public class ProcessCommandWrapperImplTest { - private static final int PROCESS_NUMBER = 2; - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private MapSettings settings = new MapSettings(); - - @Test - public void requestSQRestart_throws_IAE_if_process_index_property_not_set() { - ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Property process.index is not set"); - - processCommandWrapper.requestSQRestart(); - } - - @Test - public void requestSQRestart_throws_IAE_if_process_shared_path_property_not_set() { - settings.setProperty(PROPERTY_PROCESS_INDEX, 1); - ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Property process.sharedDir is not set"); - - processCommandWrapper.requestSQRestart(); - } - - @Test - public void requestSQRestart_updates_shareMemory_file() throws IOException { - File tmpDir = temp.newFolder().getAbsoluteFile(); - settings.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); - settings.setProperty(PROPERTY_PROCESS_INDEX, PROCESS_NUMBER); - - ProcessCommandWrapperImpl underTest = new ProcessCommandWrapperImpl(settings.asConfig()); - underTest.requestSQRestart(); - - try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tmpDir, PROCESS_NUMBER)) { - assertThat(processCommands.askedForRestart()).isTrue(); - } - } - - @Test - public void requestSQStop_throws_IAE_if_process_shared_path_property_not_set() { - settings.setProperty(PROPERTY_PROCESS_INDEX, 1); - ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Property process.sharedDir is not set"); - - processCommandWrapper.requestHardStop(); - } - - @Test - public void requestSQStop_updates_shareMemory_file() throws IOException { - File tmpDir = temp.newFolder().getAbsoluteFile(); - settings.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); - settings.setProperty(PROPERTY_PROCESS_INDEX, PROCESS_NUMBER); - - ProcessCommandWrapperImpl underTest = new ProcessCommandWrapperImpl(settings.asConfig()); - underTest.requestHardStop(); - - try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tmpDir, PROCESS_NUMBER)) { - assertThat(processCommands.askedForHardStop()).isTrue(); - } - } - - @Test - public void notifyOperational_throws_IAE_if_process_sharedDir_property_not_set() { - settings.setProperty(PROPERTY_PROCESS_INDEX, 1); - ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Property process.sharedDir is not set"); - - processCommandWrapper.notifyOperational(); - } - - @Test - public void notifyOperational_throws_IAE_if_process_index_property_not_set() { - ProcessCommandWrapperImpl processCommandWrapper = new ProcessCommandWrapperImpl(settings.asConfig()); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Property process.index is not set"); - - processCommandWrapper.notifyOperational(); - } - - @Test - public void notifyOperational_updates_shareMemory_file() throws IOException { - File tmpDir = temp.newFolder().getAbsoluteFile(); - settings.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); - settings.setProperty(PROPERTY_PROCESS_INDEX, PROCESS_NUMBER); - - ProcessCommandWrapperImpl underTest = new ProcessCommandWrapperImpl(settings.asConfig()); - underTest.notifyOperational(); - - try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tmpDir, PROCESS_NUMBER)) { - assertThat(processCommands.isOperational()).isTrue(); - } - } - - @Test - public void isCeOperational_reads_shared_memory_operational_flag_in_location_3() throws IOException { - File tmpDir = temp.newFolder().getAbsoluteFile(); - settings.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); - - boolean expected = new Random().nextBoolean(); - if (expected) { - try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tmpDir, 3)) { - processCommands.setOperational(); - } - } - - ProcessCommandWrapperImpl underTest = new ProcessCommandWrapperImpl(settings.asConfig()); - - assertThat(underTest.isCeOperational()).isEqualTo(expected); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/branch/BranchFeatureProxyImplTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/branch/BranchFeatureProxyImplTest.java deleted file mode 100644 index 6fb3d9a6449..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/branch/BranchFeatureProxyImplTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.branch; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class BranchFeatureProxyImplTest { - - private BranchFeatureExtension branchFeatureExtension = mock(BranchFeatureExtension.class); - - @Test - public void return_false_when_no_extension() { - assertThat(new BranchFeatureProxyImpl().isEnabled()).isFalse(); - } - - @Test - public void return_false_when_extension_returns_false() { - when(branchFeatureExtension.isEnabled()).thenReturn(false); - assertThat(new BranchFeatureProxyImpl(branchFeatureExtension).isEnabled()).isFalse(); - } - - @Test - public void return_true_when_extension_returns_ftrue() { - when(branchFeatureExtension.isEnabled()).thenReturn(true); - assertThat(new BranchFeatureProxyImpl(branchFeatureExtension).isEnabled()).isTrue(); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/branch/BranchFeatureRule.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/branch/BranchFeatureRule.java deleted file mode 100644 index 2bf56463474..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/branch/BranchFeatureRule.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.branch; - -import org.junit.rules.ExternalResource; - -public class BranchFeatureRule extends ExternalResource implements BranchFeatureProxy { - - private boolean enabled; - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - @Override - protected void after() { - reset(); - } - - public void reset() { - this.enabled = false; - } - - @Override - public boolean isEnabled() { - return enabled; - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java deleted file mode 100644 index 0dc82c559f0..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/BadRequestExceptionTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import java.util.Collections; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; - -public class BadRequestExceptionTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void text_error() { - BadRequestException exception = BadRequestException.create("error"); - assertThat(exception.getMessage()).isEqualTo("error"); - } - - @Test - public void create_exception_from_list() { - BadRequestException underTest = BadRequestException.create(asList("error1", "error2")); - - assertThat(underTest.errors()).containsOnly("error1", "error2"); - } - - @Test - public void create_exception_from_var_args() { - BadRequestException underTest = BadRequestException.create("error1", "error2"); - - assertThat(underTest.errors()).containsOnly("error1", "error2"); - } - - @Test - public void getMessage_return_first_error() { - BadRequestException underTest = BadRequestException.create(asList("error1", "error2")); - - assertThat(underTest.getMessage()).isEqualTo("error1"); - } - - @Test - public void fail_when_creating_exception_with_empty_list() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("At least one error message is required"); - - BadRequestException.create(Collections.emptyList()); - } - - @Test - public void fail_when_creating_exception_with_one_empty_element() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Message cannot be empty"); - - BadRequestException.create(asList("error", "")); - } - - @Test - public void fail_when_creating_exception_with_one_null_element() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Message cannot be empty"); - - BadRequestException.create(asList("error", null)); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/MessageTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/MessageTest.java deleted file mode 100644 index f05bb55058a..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/MessageTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class MessageTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void create_message() { - Message message = Message.of("key1 %s", "param1"); - assertThat(message.getMessage()).isEqualTo("key1 param1"); - } - - @Test - public void create_message_without_params() { - Message message = Message.of("key1"); - assertThat(message.getMessage()).isEqualTo("key1"); - } - - @Test - public void fail_when_message_is_null() { - expectedException.expect(IllegalArgumentException.class); - - Message.of(null); - } - - @Test - public void fail_when_message_is_empty() { - expectedException.expect(IllegalArgumentException.class); - - Message.of(""); - } - - @Test - public void test_equals_and_hashcode() { - Message message1 = Message.of("key1%s", "param1"); - Message message2 = Message.of("key2%s", "param2"); - Message message3 = Message.of("key1"); - Message message4 = Message.of("key1%s", "param2"); - Message sameAsMessage1 = Message.of("key1%s", "param1"); - - assertThat(message1).isEqualTo(message1); - assertThat(message1).isNotEqualTo(message2); - assertThat(message1).isNotEqualTo(message3); - assertThat(message1).isNotEqualTo(message4); - assertThat(message1).isEqualTo(sameAsMessage1); - assertThat(message1).isNotEqualTo(null); - assertThat(message1).isNotEqualTo(new Object()); - - assertThat(message1.hashCode()).isEqualTo(message1.hashCode()); - assertThat(message1.hashCode()).isNotEqualTo(message2.hashCode()); - assertThat(message1.hashCode()).isNotEqualTo(message3.hashCode()); - assertThat(message1.hashCode()).isNotEqualTo(message4.hashCode()); - assertThat(message1.hashCode()).isEqualTo(sameAsMessage1.hashCode()); - } - - @Test - public void to_string() { - assertThat(Message.of("key1 %s", "param1").toString()).isEqualTo("key1 param1"); - assertThat(Message.of("key1").toString()).isEqualTo("key1"); - assertThat(Message.of("key1", (Object[])null).toString()).isEqualTo("key1"); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java deleted file mode 100644 index ae2ce7846db..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/exceptions/ServerExceptionTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.exceptions; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ServerExceptionTest { - - @Test - public void should_create_exception_with_status() { - ServerException exception = new ServerException(400, "error!"); - assertThat(exception.httpCode()).isEqualTo(400); - } - - @Test - public void should_create_exception_with_status_and_message() { - ServerException exception = new ServerException(404, "Not found"); - assertThat(exception.httpCode()).isEqualTo(404); - assertThat(exception.getMessage()).isEqualTo("Not found"); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/health/TestStandaloneHealthChecker.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/health/TestStandaloneHealthChecker.java deleted file mode 100644 index 27c2e469dde..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/health/TestStandaloneHealthChecker.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.health; - -public class TestStandaloneHealthChecker implements HealthChecker { - - private Health health = Health.newHealthCheckBuilder().setStatus(Health.Status.GREEN).build(); - - public void setHealth(Health h) { - this.health = h; - } - - @Override - public Health checkNode() { - return health; - } - - @Override - public ClusterHealth checkCluster() { - throw new IllegalStateException(); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java deleted file mode 100644 index f984cd9bd1e..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import com.google.common.base.Optional; -import java.io.File; -import java.net.URI; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.ArgumentMatcher; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.sonar.api.utils.HttpDownloader; -import org.sonar.core.platform.PluginInfo; -import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.platform.ServerFileSystem; -import org.sonar.updatecenter.common.Plugin; -import org.sonar.updatecenter.common.Release; -import org.sonar.updatecenter.common.UpdateCenter; -import org.sonar.updatecenter.common.Version; - -import static com.google.common.collect.Lists.newArrayList; -import static org.apache.commons.io.FileUtils.copyFileToDirectory; -import static org.apache.commons.io.FileUtils.touch; -import static org.apache.commons.io.FilenameUtils.separatorsToUnix; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.sonar.updatecenter.common.Version.create; - -public class PluginDownloaderTest { - - @Rule - public TemporaryFolder testFolder = new TemporaryFolder(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - private File downloadDir; - private UpdateCenterMatrixFactory updateCenterMatrixFactory; - private UpdateCenter updateCenter; - private HttpDownloader httpDownloader; - private PluginDownloader pluginDownloader; - - @Before - public void before() throws Exception { - updateCenterMatrixFactory = mock(UpdateCenterMatrixFactory.class); - updateCenter = mock(UpdateCenter.class); - when(updateCenterMatrixFactory.getUpdateCenter(anyBoolean())).thenReturn(Optional.of(updateCenter)); - - httpDownloader = mock(HttpDownloader.class); - doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock inv) throws Throwable { - File toFile = (File) inv.getArguments()[1]; - touch(toFile); - return null; - } - }).when(httpDownloader).download(any(URI.class), any(File.class)); - - ServerFileSystem fs = mock(ServerFileSystem.class); - downloadDir = testFolder.newFolder("downloads"); - when(fs.getDownloadedPluginsDir()).thenReturn(downloadDir); - - pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, fs); - } - - @After - public void stop() { - pluginDownloader.stop(); - } - - @Test - public void clean_temporary_files_at_startup() throws Exception { - touch(new File(downloadDir, "sonar-php.jar")); - touch(new File(downloadDir, "sonar-js.jar.tmp")); - assertThat(downloadDir.listFiles()).hasSize(2); - pluginDownloader.start(); - - File[] files = downloadDir.listFiles(); - assertThat(files).hasSize(1); - assertThat(files[0].getName()).isEqualTo("sonar-php.jar"); - } - - @Test - public void download_from_url() { - Plugin test = Plugin.factory("test"); - Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/test-1.0.jar"); - test.addRelease(test10); - - when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); - - pluginDownloader.start(); - pluginDownloader.download("foo", create("1.0")); - - // SONAR-4523: do not corrupt JAR files when restarting the server while a plugin is being downloaded. - // The JAR file is downloaded in a temp file - verify(httpDownloader).download(any(URI.class), argThat(new HasFileName("test-1.0.jar.tmp"))); - assertThat(new File(downloadDir, "test-1.0.jar")).exists(); - assertThat(new File(downloadDir, "test-1.0.jar.tmp")).doesNotExist(); - } - - @Test - public void download_when_update_center_is_unavailable_with_no_exception_thrown() { - when(updateCenterMatrixFactory.getUpdateCenter(anyBoolean())).thenReturn(Optional.absent()); - - Plugin test = Plugin.factory("test"); - Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/test-1.0.jar"); - test.addRelease(test10); - - pluginDownloader.start(); - pluginDownloader.download("foo", create("1.0")); - } - - /** - * SONAR-4685 - */ - @Test - public void download_from_redirect_url() { - Plugin test = Plugin.factory("plugintest"); - Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/redirect?r=release&g=test&a=test&v=1.0&e=jar"); - test.addRelease(test10); - - when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); - - pluginDownloader.start(); - pluginDownloader.download("foo", create("1.0")); - - // SONAR-4523: do not corrupt JAR files when restarting the server while a plugin is being downloaded. - // The JAR file is downloaded in a temp file - verify(httpDownloader).download(any(URI.class), argThat(new HasFileName("plugintest-1.0.jar.tmp"))); - assertThat(new File(downloadDir, "plugintest-1.0.jar")).exists(); - assertThat(new File(downloadDir, "plugintest-1.0.jar.tmp")).doesNotExist(); - } - - @Test - public void throw_exception_if_download_dir_is_invalid() throws Exception { - ServerFileSystem fs = mock(ServerFileSystem.class); - // download dir is a file instead of being a directory - File downloadDir = testFolder.newFile(); - when(fs.getDownloadedPluginsDir()).thenReturn(downloadDir); - - pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, fs); - try { - pluginDownloader.start(); - fail(); - } catch (IllegalStateException e) { - // ok - } - } - - @Test - public void fail_if_no_compatible_plugin_found() { - expectedException.expect(BadRequestException.class); - - pluginDownloader.download("foo", create("1.0")); - } - - @Test - public void download_from_file() throws Exception { - Plugin test = Plugin.factory("test"); - File file = testFolder.newFile("test-1.0.jar"); - file.createNewFile(); - Release test10 = new Release(test, "1.0").setDownloadUrl("file://" + separatorsToUnix(file.getCanonicalPath())); - test.addRelease(test10); - - when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); - - pluginDownloader.start(); - pluginDownloader.download("foo", create("1.0")); - verify(httpDownloader, never()).download(any(URI.class), any(File.class)); - assertThat(noDownloadedFiles()).isGreaterThan(0); - } - - @Test - public void throw_exception_if_could_not_download() { - Plugin test = Plugin.factory("test"); - Release test10 = new Release(test, "1.0").setDownloadUrl("file://not_found"); - test.addRelease(test10); - - when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); - - pluginDownloader.start(); - try { - pluginDownloader.download("foo", create("1.0")); - fail(); - } catch (IllegalStateException e) { - // ok - } - } - - @Test - public void throw_exception_if_download_fail() { - Plugin test = Plugin.factory("test"); - Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/test-1.0.jar"); - test.addRelease(test10); - when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); - - doThrow(new RuntimeException()).when(httpDownloader).download(any(URI.class), any(File.class)); - - pluginDownloader.start(); - try { - pluginDownloader.download("foo", create("1.0")); - fail(); - } catch (IllegalStateException e) { - // ok - } - } - - @Test - public void read_download_folder() throws Exception { - pluginDownloader.start(); - assertThat(noDownloadedFiles()).isZero(); - - copyFileToDirectory(TestProjectUtils.jarOf("test-base-plugin"), downloadDir); - - assertThat(pluginDownloader.getDownloadedPlugins()).hasSize(1); - PluginInfo info = pluginDownloader.getDownloadedPlugins().iterator().next(); - assertThat(info.getKey()).isEqualTo("testbase"); - assertThat(info.getName()).isEqualTo("Base Plugin"); - assertThat(info.getVersion()).isEqualTo(Version.create("0.1-SNAPSHOT")); - assertThat(info.getMainClass()).isEqualTo("BasePlugin"); - } - - @Test - public void getDownloadedPluginFilenames_reads_plugin_info_of_files_in_download_folder() throws Exception { - pluginDownloader.start(); - assertThat(pluginDownloader.getDownloadedPlugins()).hasSize(0); - - File file1 = new File(downloadDir, "file1.jar"); - file1.createNewFile(); - File file2 = new File(downloadDir, "file2.jar"); - file2.createNewFile(); - - assertThat(noDownloadedFiles()).isEqualTo(2); - } - - @Test - public void cancel_downloads() throws Exception { - File file1 = new File(downloadDir, "file1.jar"); - file1.createNewFile(); - File file2 = new File(downloadDir, "file2.jar"); - file2.createNewFile(); - - pluginDownloader.start(); - assertThat(noDownloadedFiles()).isGreaterThan(0); - pluginDownloader.cancelDownloads(); - assertThat(noDownloadedFiles()).isZero(); - } - - private int noDownloadedFiles() { - return downloadDir.listFiles((file, name) -> name.endsWith(".jar")).length; - } - - // SONAR-5011 - @Test - public void download_common_transitive_dependency() { - Plugin test1 = Plugin.factory("test1"); - Release test1R = new Release(test1, "1.0").setDownloadUrl("http://server/test1-1.0.jar"); - test1.addRelease(test1R); - - Plugin test2 = Plugin.factory("test2"); - Release test2R = new Release(test2, "1.0").setDownloadUrl("http://server/test2-1.0.jar"); - test2.addRelease(test2R); - - Plugin testDep = Plugin.factory("testdep"); - Release testDepR = new Release(testDep, "1.0").setDownloadUrl("http://server/testdep-1.0.jar"); - testDep.addRelease(testDepR); - - when(updateCenter.findInstallablePlugins("test1", create("1.0"))).thenReturn(newArrayList(test1R, testDepR)); - when(updateCenter.findInstallablePlugins("test2", create("1.0"))).thenReturn(newArrayList(test2R, testDepR)); - - pluginDownloader.start(); - pluginDownloader.download("test1", create("1.0")); - pluginDownloader.download("test2", create("1.0")); - - assertThat(new File(downloadDir, "test1-1.0.jar")).exists(); - assertThat(new File(downloadDir, "test2-1.0.jar")).exists(); - assertThat(new File(downloadDir, "testdep-1.0.jar")).exists(); - } - - class HasFileName implements ArgumentMatcher { - private final String name; - - HasFileName(String name) { - this.name = name; - } - - @Override - public boolean matches(File file) { - return file.getName().equals(name); - } - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java deleted file mode 100644 index bc353f99778..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.RandomStringUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.config.internal.MapSettings; -import org.sonar.core.platform.PluginInfo; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.server.plugins.PluginFileSystem.PROPERTY_PLUGIN_COMPRESSION_ENABLE; - -public class PluginFileSystemTest { - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - private MapSettings settings = new MapSettings(); - private Path targetJarPath; - private Path targetFolder; - private Path sourceFolder; - - @Before - public void setUp() throws IOException { - sourceFolder = temp.newFolder("source").toPath(); - targetFolder = temp.newFolder("target").toPath(); - targetJarPath = targetFolder.resolve("test.jar"); - Files.createFile(targetJarPath); - } - - @Test - public void add_plugin_to_list_of_installed_plugins() throws IOException { - File jar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); - PluginInfo info = new PluginInfo("foo"); - - PluginFileSystem underTest = new PluginFileSystem(settings.asConfig()); - underTest.addInstalledPlugin(info, jar); - - assertThat(underTest.getInstalledFiles()).hasSize(1); - InstalledPlugin installedPlugin = underTest.getInstalledPlugin("foo").get(); - assertThat(installedPlugin.getCompressedJar()).isNull(); - assertThat(installedPlugin.getLoadedJar().getFile().toPath()).isEqualTo(jar.toPath()); - assertThat(installedPlugin.getPluginInfo()).isSameAs(info); - } - - @Test - public void compress_jar_if_compression_enabled() throws IOException { - File jar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); - PluginInfo info = new PluginInfo("foo").setJarFile(jar); - // the JAR is copied somewhere else in order to be loaded by classloaders - File loadedJar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); - - settings.setProperty(PROPERTY_PLUGIN_COMPRESSION_ENABLE, true); - PluginFileSystem underTest = new PluginFileSystem(settings.asConfig()); - underTest.addInstalledPlugin(info, loadedJar); - - assertThat(underTest.getInstalledFiles()).hasSize(1); - - InstalledPlugin installedPlugin = underTest.getInstalledPlugin("foo").get(); - assertThat(installedPlugin.getPluginInfo()).isSameAs(info); - assertThat(installedPlugin.getLoadedJar().getFile().toPath()).isEqualTo(loadedJar.toPath()); - assertThat(installedPlugin.getCompressedJar().getFile()) - .exists() - .isFile() - .hasName("sonar-foo-plugin.pack.gz") - .hasParent(loadedJar.getParentFile()); - } - - @Test - public void copy_and_use_existing_packed_jar_if_compression_enabled() throws IOException { - File jar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); - File packedJar = touch(jar.getParentFile(), "sonar-foo-plugin.pack.gz"); - PluginInfo info = new PluginInfo("foo").setJarFile(jar); - // the JAR is copied somewhere else in order to be loaded by classloaders - File loadedJar = touch(temp.newFolder(), "sonar-foo-plugin.jar"); - - settings.setProperty(PROPERTY_PLUGIN_COMPRESSION_ENABLE, true); - PluginFileSystem underTest = new PluginFileSystem(settings.asConfig()); - underTest.addInstalledPlugin(info, loadedJar); - - assertThat(underTest.getInstalledFiles()).hasSize(1); - - InstalledPlugin installedPlugin = underTest.getInstalledPlugin("foo").get(); - assertThat(installedPlugin.getPluginInfo()).isSameAs(info); - assertThat(installedPlugin.getLoadedJar().getFile().toPath()).isEqualTo(loadedJar.toPath()); - assertThat(installedPlugin.getCompressedJar().getFile()) - .exists() - .isFile() - .hasName(packedJar.getName()) - .hasParent(loadedJar.getParentFile()) - .hasSameContentAs(packedJar); - } - - private static File touch(File dir, String filename) throws IOException { - File file = new File(dir, filename); - FileUtils.write(file, RandomStringUtils.random(10)); - return file; - } - - // - // @Test - // public void should_use_deployed_packed_file() throws IOException { - // Path packedPath = sourceFolder.resolve("test.pack.gz"); - // Files.write(packedPath, new byte[] {1, 2, 3}); - // - // settings.setProperty(PROPERTY_PLUGIN_COMPRESSION_ENABLE, true); - // underTest = new PluginFileSystem(settings.asConfig()); - // underTest.compressJar("key", sourceFolder, targetJarPath); - // - // assertThat(Files.list(targetFolder)).containsOnly(targetJarPath, targetFolder.resolve("test.pack.gz")); - // assertThat(underTest.getPlugins()).hasSize(1); - // assertThat(underTest.getPlugins().get("key").getFilename()).isEqualTo("test.pack.gz"); - // - // // check that the file was copied, not generated - // assertThat(targetFolder.resolve("test.pack.gz")).hasSameContentAs(packedPath); - // } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginUninstallerTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginUninstallerTest.java deleted file mode 100644 index 20eae5f2781..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/PluginUninstallerTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import java.io.File; -import java.io.IOException; -import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.sonar.server.platform.ServerFileSystem; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class PluginUninstallerTest { - @Rule - public TemporaryFolder testFolder = new TemporaryFolder(); - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private File uninstallDir; - private PluginUninstaller underTest; - private ServerPluginRepository serverPluginRepository; - private ServerFileSystem fs; - - @Before - public void setUp() throws IOException { - serverPluginRepository = mock(ServerPluginRepository.class); - uninstallDir = testFolder.newFolder("uninstall"); - fs = mock(ServerFileSystem.class); - when(fs.getUninstalledPluginsDir()).thenReturn(uninstallDir); - underTest = new PluginUninstaller(serverPluginRepository, fs); - } - - @Test - public void uninstall() { - when(serverPluginRepository.hasPlugin("plugin")).thenReturn(true); - underTest.uninstall("plugin"); - verify(serverPluginRepository).uninstall("plugin", uninstallDir); - } - - @Test - public void fail_uninstall_if_plugin_not_installed() { - when(serverPluginRepository.hasPlugin("plugin")).thenReturn(false); - exception.expect(IllegalArgumentException.class); - exception.expectMessage("Plugin [plugin] is not installed"); - underTest.uninstall("plugin"); - verifyZeroInteractions(serverPluginRepository); - } - - @Test - public void create_uninstall_dir() { - File dir = new File(testFolder.getRoot(), "dir"); - when(fs.getUninstalledPluginsDir()).thenReturn(dir); - underTest = new PluginUninstaller(serverPluginRepository, fs); - underTest.start(); - assertThat(dir).isDirectory(); - } - - @Test - public void cancel() { - underTest.cancelUninstalls(); - verify(serverPluginRepository).cancelUninstalls(uninstallDir); - verifyNoMoreInteractions(serverPluginRepository); - } - - @Test - public void list_uninstalled_plugins() throws IOException { - new File(uninstallDir, "file1").createNewFile(); - copyTestPluginTo("test-base-plugin", uninstallDir); - assertThat(underTest.getUninstalledPlugins()).extracting("key").containsOnly("testbase"); - } - - private File copyTestPluginTo(String testPluginName, File toDir) throws IOException { - File jar = TestProjectUtils.jarOf(testPluginName); - // file is copied because it's supposed to be moved by the test - FileUtils.copyFileToDirectory(jar, toDir); - return new File(toDir, jar.getName()); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/ServerPluginJarExploderTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/ServerPluginJarExploderTest.java deleted file mode 100644 index 8f4d928cd4c..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/ServerPluginJarExploderTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import java.io.File; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.sonar.core.platform.ExplodedPlugin; -import org.sonar.core.platform.PluginInfo; -import org.sonar.server.platform.ServerFileSystem; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class ServerPluginJarExploderTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - private ServerFileSystem fs = mock(ServerFileSystem.class); - private PluginFileSystem pluginFileSystem = mock(PluginFileSystem.class); - private ServerPluginJarExploder underTest = new ServerPluginJarExploder(fs, pluginFileSystem); - - @Test - public void copy_all_classloader_files_to_dedicated_directory() throws Exception { - File deployDir = temp.newFolder(); - when(fs.getDeployedPluginsDir()).thenReturn(deployDir); - File sourceJar = TestProjectUtils.jarOf("test-libs-plugin"); - PluginInfo info = PluginInfo.create(sourceJar); - - ExplodedPlugin exploded = underTest.explode(info); - - // all the files loaded by classloaders (JAR + META-INF/libs/*.jar) are copied to the dedicated directory - // web/deploy/{pluginKey} - File pluginDeployDir = new File(deployDir, "testlibs"); - - assertThat(exploded.getKey()).isEqualTo("testlibs"); - assertThat(exploded.getMain()).isFile().exists().hasParent(pluginDeployDir); - assertThat(exploded.getLibs()).extracting("name").containsOnly("commons-daemon-1.0.15.jar", "commons-email-20030310.165926.jar"); - for (File lib : exploded.getLibs()) { - assertThat(lib).exists().isFile(); - assertThat(lib.getCanonicalPath()).startsWith(pluginDeployDir.getCanonicalPath()); - } - File targetJar = new File(fs.getDeployedPluginsDir(), "testlibs/test-libs-plugin-0.1-SNAPSHOT.jar"); - verify(pluginFileSystem).addInstalledPlugin(info, targetJar); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java deleted file mode 100644 index e426c9ebfea..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.Map; -import org.apache.commons.io.FileUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; -import org.sonar.api.SonarRuntime; -import org.sonar.api.utils.MessageException; -import org.sonar.api.utils.log.LogTester; -import org.sonar.core.platform.PluginInfo; -import org.sonar.core.platform.PluginLoader; -import org.sonar.server.platform.ServerFileSystem; -import org.sonar.updatecenter.common.Version; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ServerPluginRepositoryTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - @Rule - public LogTester logs = new LogTester(); - - private SonarRuntime runtime = mock(SonarRuntime.class); - private ServerFileSystem fs = mock(ServerFileSystem.class, Mockito.RETURNS_DEEP_STUBS); - private PluginLoader pluginLoader = mock(PluginLoader.class); - private ServerPluginRepository underTest = new ServerPluginRepository(runtime, fs, pluginLoader); - - @Before - public void setUp() throws IOException { - when(fs.getDeployedPluginsDir()).thenReturn(temp.newFolder()); - when(fs.getDownloadedPluginsDir()).thenReturn(temp.newFolder()); - when(fs.getHomeDir()).thenReturn(temp.newFolder()); - when(fs.getInstalledPluginsDir()).thenReturn(temp.newFolder()); - when(fs.getTempDir()).thenReturn(temp.newFolder()); - when(runtime.getApiVersion()).thenReturn(org.sonar.api.utils.Version.parse("5.2")); - } - - @After - public void tearDown() { - underTest.stop(); - } - - @Test - public void standard_startup_loads_installed_plugins() throws Exception { - copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - - underTest.start(); - - assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); - } - - @Test - public void no_plugins_at_all_on_startup() { - underTest.start(); - - assertThat(underTest.getPluginInfos()).isEmpty(); - assertThat(underTest.getPluginInfosByKeys()).isEmpty(); - assertThat(underTest.hasPlugin("testbase")).isFalse(); - } - - @Test - public void fail_if_multiple_jars_for_same_installed_plugin_on_startup() throws Exception { - copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - copyTestPluginTo("test-base-plugin-v2", fs.getInstalledPluginsDir()); - - try { - underTest.start(); - fail(); - } catch (MessageException e) { - assertThat(e) - .hasMessageStartingWith("Found two versions of the plugin Base Plugin [testbase] in the directory extensions/plugins. Please remove one of ") - // order is not guaranteed, so assertion is split - .hasMessageContaining("test-base-plugin-0.1-SNAPSHOT.jar") - .hasMessageContaining("test-base-plugin-0.2-SNAPSHOT.jar"); - } - } - - @Test - public void install_downloaded_plugins_on_startup() throws Exception { - File downloadedJar = copyTestPluginTo("test-base-plugin", fs.getDownloadedPluginsDir()); - - underTest.start(); - - // plugin is moved to extensions/plugins then loaded - assertThat(downloadedJar).doesNotExist(); - assertThat(new File(fs.getInstalledPluginsDir(), downloadedJar.getName())).isFile().exists(); - assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); - } - - @Test - public void downloaded_file_overrides_existing_installed_file_on_startup() throws Exception { - File installedV1 = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - File downloadedV2 = copyTestPluginTo("test-base-plugin-v2", fs.getDownloadedPluginsDir()); - - underTest.start(); - - // plugin is moved to extensions/plugins and replaces v1 - assertThat(downloadedV2).doesNotExist(); - assertThat(installedV1).doesNotExist(); - assertThat(new File(fs.getInstalledPluginsDir(), downloadedV2.getName())).exists(); - assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); - assertThat(underTest.getPluginInfo("testbase").getVersion()).isEqualTo(Version.create("0.2-SNAPSHOT")); - } - - @Test - public void blacklisted_plugin_is_automatically_uninstalled_on_startup() throws Exception { - underTest.setBlacklistedPluginKeys(ImmutableSet.of("testbase", "issuesreport")); - File jar = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - - underTest.start(); - - // plugin is not installed and file is deleted - assertThat(underTest.getPluginInfos()).isEmpty(); - assertThat(jar).doesNotExist(); - } - - @Test - public void test_plugin_requirements_at_startup() throws Exception { - copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); - - underTest.start(); - - // both plugins are installed - assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase", "testrequire"); - } - - @Test - public void plugin_is_ignored_if_required_plugin_is_missing_at_startup() throws Exception { - copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); - - underTest.start(); - - // plugin is not installed as test-base-plugin is missing - assertThat(underTest.getPluginInfosByKeys()).isEmpty(); - } - - @Test - public void plugin_is_ignored_if_required_plugin_is_too_old_at_startup() throws Exception { - copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - copyTestPluginTo("test-requirenew-plugin", fs.getInstalledPluginsDir()); - - underTest.start(); - - // the plugin "requirenew" is not installed as it requires base 0.2+ to be installed. - assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); - } - - @Test - public void fail_if_plugin_does_not_support_sq_version() throws Exception { - when(runtime.getApiVersion()).thenReturn(org.sonar.api.utils.Version.parse("1.0")); - copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - - try { - underTest.start(); - fail(); - } catch (MessageException e) { - assertThat(e).hasMessage("Plugin Base Plugin [testbase] requires at least SonarQube 4.5.4"); - } - } - - @Test - public void uninstall() throws Exception { - File installedJar = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - File uninstallDir = temp.newFolder("uninstallDir"); - - underTest.start(); - assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); - underTest.uninstall("testbase", uninstallDir); - - assertThat(installedJar).doesNotExist(); - // still up. Will be dropped after next startup - assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); - assertThat(uninstallDir.list()).containsOnly(installedJar.getName()); - } - - @Test - public void uninstall_dependents() throws Exception { - File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); - File uninstallDir = temp.newFolder("uninstallDir"); - - underTest.start(); - assertThat(underTest.getPluginInfos()).hasSize(2); - underTest.uninstall("testbase", uninstallDir); - assertThat(base).doesNotExist(); - assertThat(extension).doesNotExist(); - assertThat(uninstallDir.list()).containsOnly(base.getName(), extension.getName()); - } - - @Test - public void dont_uninstall_non_existing_dependents() throws IOException { - File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); - File uninstallDir = temp.newFolder("uninstallDir"); - - underTest.start(); - assertThat(underTest.getPluginInfos()).hasSize(2); - underTest.uninstall("testrequire", uninstallDir); - assertThat(underTest.getPluginInfos()).hasSize(2); - - underTest.uninstall("testbase", uninstallDir); - assertThat(base).doesNotExist(); - assertThat(extension).doesNotExist(); - assertThat(uninstallDir.list()).containsOnly(base.getName(), extension.getName()); - } - - @Test - public void dont_uninstall_non_existing_files() throws IOException { - File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir()); - File uninstallDir = temp.newFolder("uninstallDir"); - - underTest.start(); - assertThat(underTest.getPluginInfos()).hasSize(2); - underTest.uninstall("testbase", uninstallDir); - assertThat(underTest.getPluginInfos()).hasSize(2); - - underTest.uninstall("testbase", uninstallDir); - assertThat(base).doesNotExist(); - assertThat(extension).doesNotExist(); - assertThat(uninstallDir.list()).containsOnly(base.getName(), extension.getName()); - } - - @Test - public void install_plugin_and_its_extension_plugins_at_startup() throws Exception { - copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir()); - copyTestPluginTo("test-extend-plugin", fs.getInstalledPluginsDir()); - - underTest.start(); - - // both plugins are installed - assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase", "testextend"); - } - - @Test - public void extension_plugin_is_ignored_if_base_plugin_is_missing_at_startup() throws Exception { - copyTestPluginTo("test-extend-plugin", fs.getInstalledPluginsDir()); - - underTest.start(); - - // plugin is not installed as its base plugin is not installed - assertThat(underTest.getPluginInfos()).isEmpty(); - } - - @Test - public void fail_to_get_missing_plugins() { - underTest.start(); - try { - underTest.getPluginInfo("unknown"); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Plugin [unknown] does not exist"); - } - - try { - underTest.getPluginInstance("unknown"); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Plugin [unknown] does not exist"); - } - } - - @Test - public void plugin_is_incompatible_if_no_entry_point_class() { - PluginInfo plugin = new PluginInfo("foo").setName("Foo"); - assertThat(ServerPluginRepository.isCompatible(plugin, runtime, Collections.emptyMap())).isFalse(); - assertThat(logs.logs()).contains("Plugin Foo [foo] is ignored because entry point class is not defined"); - } - - @Test - public void fail_when_views_is_installed() throws Exception { - copyTestPluginTo("fake-views-plugin", fs.getInstalledPluginsDir()); - - expectedException.expect(MessageException.class); - expectedException.expectMessage("Plugin 'views' is no longer compatible with this version of SonarQube"); - underTest.start(); - } - - @Test - public void fail_when_sqale_plugin_is_installed() throws Exception { - copyTestPluginTo("fake-sqale-plugin", fs.getInstalledPluginsDir()); - - expectedException.expect(MessageException.class); - expectedException.expectMessage("Plugin 'sqale' is no longer compatible with this version of SonarQube"); - underTest.start(); - } - - @Test - public void fail_when_report_is_installed() throws Exception { - copyTestPluginTo("fake-report-plugin", fs.getInstalledPluginsDir()); - - expectedException.expect(MessageException.class); - expectedException.expectMessage("Plugin 'report' is no longer compatible with this version of SonarQube"); - underTest.start(); - } - - /** - * Some plugins can only extend the classloader of base plugin, without declaring new extensions. - */ - @Test - public void plugin_is_compatible_if_no_entry_point_class_but_extend_other_plugin() { - PluginInfo basePlugin = new PluginInfo("base").setMainClass("org.bar.Bar"); - PluginInfo plugin = new PluginInfo("foo").setBasePlugin("base"); - Map plugins = ImmutableMap.of("base", basePlugin, "foo", plugin); - - assertThat(ServerPluginRepository.isCompatible(plugin, runtime, plugins)).isTrue(); - } - - @Test - public void getPluginInstance_throws_ISE_if_repo_is_not_started() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("not started yet"); - - underTest.getPluginInstance("foo"); - } - - @Test - public void getPluginInfo_throws_ISE_if_repo_is_not_started() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("not started yet"); - - underTest.getPluginInfo("foo"); - } - - @Test - public void hasPlugin_throws_ISE_if_repo_is_not_started() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("not started yet"); - - underTest.hasPlugin("foo"); - } - - @Test - public void getPluginInfos_throws_ISE_if_repo_is_not_started() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("not started yet"); - - underTest.getPluginInfos(); - } - - private File copyTestPluginTo(String testPluginName, File toDir) throws IOException { - File jar = TestProjectUtils.jarOf(testPluginName); - // file is copied because it's supposed to be moved by the test - FileUtils.copyFileToDirectory(jar, toDir); - return new File(toDir, jar.getName()); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/TestPluginA.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/TestPluginA.java deleted file mode 100644 index 7952eb5799c..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/TestPluginA.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import org.sonar.api.Plugin; - -public class TestPluginA implements Plugin { - @Override - public void define(Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/TestProjectUtils.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/TestProjectUtils.java deleted file mode 100644 index 9710a8689e4..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/TestProjectUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.util.Collection; - -public class TestProjectUtils { - - /** - * Get the artifact of plugins stored in src/test/projects - */ - public static File jarOf(String dirName) { - File target = FileUtils.toFile(TestProjectUtils.class.getResource(String.format("/%s/target/", dirName))); - Collection jars = FileUtils.listFiles(target, new String[] {"jar"}, false); - if (jars == null || jars.size() != 1) { - throw new IllegalArgumentException("Test project is badly defined: " + dirName); - } - return jars.iterator().next(); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java deleted file mode 100644 index b1e50cba77c..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.config.internal.MapSettings; -import org.sonar.api.utils.SonarException; -import org.sonar.api.utils.UriReader; -import org.sonar.process.ProcessProperties; -import org.sonar.updatecenter.common.UpdateCenter; -import org.sonar.updatecenter.common.Version; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.guava.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class UpdateCenterClientTest { - - private static final String BASE_URL = "https://update.sonarsource.org"; - private UriReader reader = mock(UriReader.class); - private MapSettings settings = new MapSettings(); - private UpdateCenterClient underTest; - - @Before - public void startServer() throws Exception { - reader = mock(UriReader.class); - settings.setProperty(UpdateCenterClient.URL_PROPERTY, BASE_URL); - settings.setProperty(ProcessProperties.Property.SONAR_UPDATECENTER_ACTIVATE.getKey(), true); - underTest = new UpdateCenterClient(reader, settings.asConfig()); - } - - @Test - public void downloadUpdateCenter() throws URISyntaxException { - when(reader.readString(new URI(BASE_URL), StandardCharsets.UTF_8)).thenReturn("publicVersions=2.2,2.3"); - UpdateCenter plugins = underTest.getUpdateCenter().get(); - verify(reader, times(1)).readString(new URI(BASE_URL), StandardCharsets.UTF_8); - assertThat(plugins.getSonar().getVersions()).containsOnly(Version.create("2.2"), Version.create("2.3")); - assertThat(underTest.getLastRefreshDate()).isNotNull(); - } - - @Test - public void not_available_before_initialization() { - assertThat(underTest.getLastRefreshDate()).isNull(); - } - - @Test - public void ignore_connection_errors() { - when(reader.readString(any(URI.class), eq(StandardCharsets.UTF_8))).thenThrow(new SonarException()); - assertThat(underTest.getUpdateCenter()).isAbsent(); - } - - @Test - public void cache_data() throws Exception { - when(reader.readString(new URI(BASE_URL), StandardCharsets.UTF_8)).thenReturn("sonar.versions=2.2,2.3"); - - underTest.getUpdateCenter(); - underTest.getUpdateCenter(); - - verify(reader, times(1)).readString(new URI(BASE_URL), StandardCharsets.UTF_8); - } - - @Test - public void forceRefresh() throws Exception { - when(reader.readString(new URI(BASE_URL), StandardCharsets.UTF_8)).thenReturn("sonar.versions=2.2,2.3"); - - underTest.getUpdateCenter(); - underTest.getUpdateCenter(true); - - verify(reader, times(2)).readString(new URI(BASE_URL), StandardCharsets.UTF_8); - } - - @Test - public void update_center_is_null_when_property_is_false() { - settings.setProperty(ProcessProperties.Property.SONAR_UPDATECENTER_ACTIVATE.getKey(), false); - - assertThat(underTest.getUpdateCenter()).isAbsent(); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixFactoryTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixFactoryTest.java deleted file mode 100644 index a71522a77d5..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixFactoryTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import com.google.common.base.Optional; -import org.junit.Test; -import org.sonar.api.SonarRuntime; -import org.sonar.updatecenter.common.UpdateCenter; - -import static org.assertj.guava.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class UpdateCenterMatrixFactoryTest { - - private UpdateCenterMatrixFactory underTest; - - @Test - public void return_absent_update_center() { - UpdateCenterClient updateCenterClient = mock(UpdateCenterClient.class); - when(updateCenterClient.getUpdateCenter(anyBoolean())).thenReturn(Optional.absent()); - - underTest = new UpdateCenterMatrixFactory(updateCenterClient, mock(SonarRuntime.class), mock(InstalledPluginReferentialFactory.class)); - - Optional updateCenter = underTest.getUpdateCenter(false); - - assertThat(updateCenter).isAbsent(); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterServlet.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterServlet.java deleted file mode 100644 index d6d9904452d..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/UpdateCenterServlet.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins; - -import javax.servlet.GenericServlet; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.util.Properties; - -public class UpdateCenterServlet extends GenericServlet { - - int count = 0; - - @Override - public void service(ServletRequest request, ServletResponse response) throws IOException { - count++; - Properties props = new Properties(); - props.setProperty("count", String.valueOf(count)); - props.setProperty("agent", ((HttpServletRequest)request).getHeader("User-Agent")); - props.store(response.getOutputStream(), null); - } -} - diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/edition/EditionBundledPluginsTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/edition/EditionBundledPluginsTest.java deleted file mode 100644 index 907768f56fa..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/plugins/edition/EditionBundledPluginsTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.plugins.edition; - -import java.util.Random; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.core.platform.PluginInfo; -import org.sonar.updatecenter.common.Plugin; - -import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; -import static org.assertj.core.api.Assertions.assertThat; - -public class EditionBundledPluginsTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private final Random random = new Random(); - - @Test - public void isEditionBundled_on_Plugin_fails_with_NPE_if_arg_is_null() { - expectedException.expect(NullPointerException.class); - - EditionBundledPlugins.isEditionBundled((Plugin) null); - } - - @Test - public void isEditionBundled_on_Plugin_returns_false_for_SonarSource_and_non_commercial_license() { - Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomAlphanumeric(3)); - - assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse(); - } - - @Test - public void isEditionBundled_on_Plugin_returns_false_for_license_SonarSource_and_non_SonarSource_organization() { - Plugin plugin = newPlugin(randomAlphanumeric(3), randomizeCase("SonarSource")); - - assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse(); - } - - @Test - public void isEditionBundled_on_Plugin_returns_false_for_license_Commercial_and_non_SonarSource_organization() { - Plugin plugin = newPlugin(randomAlphanumeric(3), randomizeCase("Commercial")); - - assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse(); - } - - @Test - public void isEditionBundled_on_Plugin_returns_true_for_organization_SonarSource_and_license_SonarSource_case_insensitive() { - Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomizeCase("SonarSource")); - - assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isTrue(); - } - - @Test - public void isEditionBundled_on_Plugin_returns_true_for_organization_SonarSource_and_license_Commercial_case_insensitive() { - Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomizeCase("Commercial")); - - assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isTrue(); - } - - @Test - public void isEditionBundled_on_PluginInfo_fails_with_NPE_if_arg_is_null() { - expectedException.expect(NullPointerException.class); - - EditionBundledPlugins.isEditionBundled((PluginInfo) null); - } - - @Test - public void isEditionBundled_on_PluginInfo_returns_false_for_SonarSource_and_non_commercial_license() { - PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomAlphanumeric(3)); - - assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse(); - } - - @Test - public void isEditionBundled_on_PluginInfo_returns_false_for_license_SonarSource_and_non_SonarSource_organization() { - PluginInfo pluginInfo = newPluginInfo(randomAlphanumeric(3), randomizeCase("SonarSource")); - - assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse(); - } - - @Test - public void isEditionBundled_on_PluginInfo_returns_false_for_license_Commercial_and_non_SonarSource_organization() { - PluginInfo pluginInfo = newPluginInfo(randomAlphanumeric(3), randomizeCase("Commercial")); - - assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse(); - } - - @Test - public void isEditionBundled_on_PluginInfo_returns_true_for_organization_SonarSource_and_license_SonarSource_case_insensitive() { - PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomizeCase("SonarSource")); - - assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isTrue(); - } - - @Test - public void isEditionBundled_on_PluginINfo_returns_true_for_organization_SonarSource_and_license_Commercial_case_insensitive() { - PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomizeCase("Commercial")); - - assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isTrue(); - } - - private String randomizeCase(String s) { - return s.chars() - .map(c -> random.nextBoolean() ? Character.toUpperCase(c) : Character.toLowerCase(c)) - .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) - .toString(); - } - - private PluginInfo newPluginInfo(String organization, String license) { - PluginInfo pluginInfo = new PluginInfo(randomAlphanumeric(2)); - if (random.nextBoolean()) { - pluginInfo.setName(randomAlphanumeric(3)); - } - if (random.nextBoolean()) { - pluginInfo.setOrganizationUrl(randomAlphanumeric(4)); - } - if (random.nextBoolean()) { - pluginInfo.setIssueTrackerUrl(randomAlphanumeric(5)); - } - if (random.nextBoolean()) { - pluginInfo.setIssueTrackerUrl(randomAlphanumeric(6)); - } - if (random.nextBoolean()) { - pluginInfo.setBasePlugin(randomAlphanumeric(7)); - } - if (random.nextBoolean()) { - pluginInfo.setHomepageUrl(randomAlphanumeric(8)); - } - return pluginInfo - .setOrganizationName(organization) - .setLicense(license); - } - - private Plugin newPlugin(String organization, String license) { - Plugin plugin = Plugin.factory(randomAlphanumeric(2)); - if (random.nextBoolean()) { - plugin.setName(randomAlphanumeric(3)); - } - if (random.nextBoolean()) { - plugin.setOrganizationUrl(randomAlphanumeric(4)); - } - if (random.nextBoolean()) { - plugin.setTermsConditionsUrl(randomAlphanumeric(5)); - } - if (random.nextBoolean()) { - plugin.setIssueTrackerUrl(randomAlphanumeric(6)); - } - if (random.nextBoolean()) { - plugin.setCategory(randomAlphanumeric(7)); - } - if (random.nextBoolean()) { - plugin.setHomepageUrl(randomAlphanumeric(8)); - } - return plugin - .setLicense(license) - .setOrganization(organization); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java deleted file mode 100644 index 8085b643ede..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.project; - -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.util.Collections; -import java.util.Random; -import java.util.Set; -import java.util.stream.IntStream; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.mockito.InOrder; -import org.mockito.Mockito; -import org.sonar.core.util.stream.MoreCollectors; - -import static java.util.Collections.singleton; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; -import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; - -@RunWith(DataProviderRunner.class) -public class ProjectLifeCycleListenersImplTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private ProjectLifeCycleListener listener1 = mock(ProjectLifeCycleListener.class); - private ProjectLifeCycleListener listener2 = mock(ProjectLifeCycleListener.class); - private ProjectLifeCycleListener listener3 = mock(ProjectLifeCycleListener.class); - private ProjectLifeCycleListenersImpl underTestNoListeners = new ProjectLifeCycleListenersImpl(); - private ProjectLifeCycleListenersImpl underTestWithListeners = new ProjectLifeCycleListenersImpl( - new ProjectLifeCycleListener[] {listener1, listener2, listener3}); - - @Test - public void onProjectsDeleted_throws_NPE_if_set_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("projects can't be null"); - - underTestWithListeners.onProjectsDeleted(null); - } - - @Test - public void onProjectsDeleted_throws_NPE_if_set_is_null_even_if_no_listeners() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("projects can't be null"); - - underTestNoListeners.onProjectsDeleted(null); - } - - @Test - public void onProjectsDeleted_has_no_effect_if_set_is_empty() { - underTestNoListeners.onProjectsDeleted(Collections.emptySet()); - - underTestWithListeners.onProjectsDeleted(Collections.emptySet()); - verifyZeroInteractions(listener1, listener2, listener3); - } - - @Test - @UseDataProvider("oneOrManyProjects") - public void onProjectsDeleted_does_not_fail_if_there_is_no_listener(Set projects) { - underTestNoListeners.onProjectsDeleted(projects); - } - - @Test - @UseDataProvider("oneOrManyProjects") - public void onProjectsDeleted_calls_all_listeners_in_order_of_addition_to_constructor(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - - underTestWithListeners.onProjectsDeleted(projects); - - inOrder.verify(listener1).onProjectsDeleted(same(projects)); - inOrder.verify(listener2).onProjectsDeleted(same(projects)); - inOrder.verify(listener3).onProjectsDeleted(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - @UseDataProvider("oneOrManyProjects") - public void onProjectsDeleted_calls_all_listeners_even_if_one_throws_an_Exception(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - doThrow(new RuntimeException("Faking listener2 throwing an exception")) - .when(listener2) - .onProjectsDeleted(any()); - - underTestWithListeners.onProjectsDeleted(projects); - - inOrder.verify(listener1).onProjectsDeleted(same(projects)); - inOrder.verify(listener2).onProjectsDeleted(same(projects)); - inOrder.verify(listener3).onProjectsDeleted(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - @UseDataProvider("oneOrManyProjects") - public void onProjectsDeleted_calls_all_listeners_even_if_one_throws_an_Error(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - doThrow(new Error("Faking listener2 throwing an Error")) - .when(listener2) - .onProjectsDeleted(any()); - - underTestWithListeners.onProjectsDeleted(projects); - - inOrder.verify(listener1).onProjectsDeleted(same(projects)); - inOrder.verify(listener2).onProjectsDeleted(same(projects)); - inOrder.verify(listener3).onProjectsDeleted(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void onProjectBranchesDeleted_throws_NPE_if_set_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("projects can't be null"); - - underTestWithListeners.onProjectBranchesDeleted(null); - } - - @Test - public void onProjectBranchesDeleted_throws_NPE_if_set_is_null_even_if_no_listeners() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("projects can't be null"); - - underTestNoListeners.onProjectBranchesDeleted(null); - } - - @Test - public void onProjectBranchesDeleted_has_no_effect_if_set_is_empty() { - underTestNoListeners.onProjectBranchesDeleted(Collections.emptySet()); - - underTestWithListeners.onProjectBranchesDeleted(Collections.emptySet()); - verifyZeroInteractions(listener1, listener2, listener3); - } - - @Test - @UseDataProvider("oneOrManyProjects") - public void onProjectBranchesDeleted_does_not_fail_if_there_is_no_listener(Set projects) { - underTestNoListeners.onProjectBranchesDeleted(projects); - } - - @Test - @UseDataProvider("oneOrManyProjects") - public void onProjectBranchesDeleted_calls_all_listeners_in_order_of_addition_to_constructor(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - - underTestWithListeners.onProjectBranchesDeleted(projects); - - inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); - inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); - inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - @UseDataProvider("oneOrManyProjects") - public void onProjectBranchesDeleted_calls_all_listeners_even_if_one_throws_an_Exception(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - doThrow(new RuntimeException("Faking listener2 throwing an exception")) - .when(listener2) - .onProjectBranchesDeleted(any()); - - underTestWithListeners.onProjectBranchesDeleted(projects); - - inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); - inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); - inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - @UseDataProvider("oneOrManyProjects") - public void onProjectBranchesDeleted_calls_all_listeners_even_if_one_throws_an_Error(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - doThrow(new Error("Faking listener2 throwing an Error")) - .when(listener2) - .onProjectBranchesDeleted(any()); - - underTestWithListeners.onProjectBranchesDeleted(projects); - - inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); - inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); - inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @DataProvider - public static Object[][] oneOrManyProjects() { - return new Object[][] { - {singleton(newUniqueProject())}, - {IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> newUniqueProject()).collect(MoreCollectors.toSet())} - }; - } - // SDSDS - - @Test - public void onProjectsRekeyed_throws_NPE_if_set_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("rekeyedProjects can't be null"); - - underTestWithListeners.onProjectsRekeyed(null); - } - - @Test - public void onProjectsRekeyed_throws_NPE_if_set_is_null_even_if_no_listeners() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("rekeyedProjects can't be null"); - - underTestNoListeners.onProjectsRekeyed(null); - } - - @Test - public void onProjectsRekeyed_has_no_effect_if_set_is_empty() { - underTestNoListeners.onProjectsRekeyed(Collections.emptySet()); - - underTestWithListeners.onProjectsRekeyed(Collections.emptySet()); - verifyZeroInteractions(listener1, listener2, listener3); - } - - @Test - @UseDataProvider("oneOrManyRekeyedProjects") - public void onProjectsRekeyed_does_not_fail_if_there_is_no_listener(Set projects) { - underTestNoListeners.onProjectsRekeyed(projects); - } - - @Test - @UseDataProvider("oneOrManyRekeyedProjects") - public void onProjectsRekeyed_calls_all_listeners_in_order_of_addition_to_constructor(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - - underTestWithListeners.onProjectsRekeyed(projects); - - inOrder.verify(listener1).onProjectsRekeyed(same(projects)); - inOrder.verify(listener2).onProjectsRekeyed(same(projects)); - inOrder.verify(listener3).onProjectsRekeyed(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - @UseDataProvider("oneOrManyRekeyedProjects") - public void onProjectsRekeyed_calls_all_listeners_even_if_one_throws_an_Exception(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - doThrow(new RuntimeException("Faking listener2 throwing an exception")) - .when(listener2) - .onProjectsRekeyed(any()); - - underTestWithListeners.onProjectsRekeyed(projects); - - inOrder.verify(listener1).onProjectsRekeyed(same(projects)); - inOrder.verify(listener2).onProjectsRekeyed(same(projects)); - inOrder.verify(listener3).onProjectsRekeyed(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - @UseDataProvider("oneOrManyRekeyedProjects") - public void onProjectsRekeyed_calls_all_listeners_even_if_one_throws_an_Error(Set projects) { - InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - doThrow(new Error("Faking listener2 throwing an Error")) - .when(listener2) - .onProjectsRekeyed(any()); - - underTestWithListeners.onProjectsRekeyed(projects); - - inOrder.verify(listener1).onProjectsRekeyed(same(projects)); - inOrder.verify(listener2).onProjectsRekeyed(same(projects)); - inOrder.verify(listener3).onProjectsRekeyed(same(projects)); - inOrder.verifyNoMoreInteractions(); - } - - @DataProvider - public static Object[][] oneOrManyRekeyedProjects() { - return new Object[][] { - {singleton(newUniqueRekeyedProject())}, - {IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> newUniqueRekeyedProject()).collect(MoreCollectors.toSet())} - }; - } - - private static Project newUniqueProject() { - return Project.from(newPrivateProjectDto(newOrganizationDto())); - } - - private static int counter = 3_989; - - private static RekeyedProject newUniqueRekeyedProject() { - int base = counter++; - Project project = Project.from(newPrivateProjectDto(newOrganizationDto())); - return new RekeyedProject(project, base + "_old_key"); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/project/RekeyedProjectTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/project/RekeyedProjectTest.java deleted file mode 100644 index a847d91d0d8..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/project/RekeyedProjectTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.project; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static java.util.Collections.emptyList; -import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; -import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; -import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; - -public class RekeyedProjectTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void constructor_throws_NPE_if_project_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("project can't be null"); - - new RekeyedProject(null, randomAlphanumeric(3)); - } - - @Test - public void constructor_throws_NPE_if_previousKey_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("previousKey can't be null"); - - new RekeyedProject(newRandomProject(), null); - } - - @Test - public void verify_getters() { - Project project = newRandomProject(); - String previousKey = randomAlphanumeric(6); - RekeyedProject underTest = new RekeyedProject(project, previousKey); - - assertThat(underTest.getProject()).isSameAs(project); - assertThat(underTest.getPreviousKey()).isEqualTo(previousKey); - } - - @Test - public void equals_is_based_on_project_and_previousKey() { - Project project = newRandomProject(); - String previousKey = randomAlphanumeric(6); - RekeyedProject underTest = new RekeyedProject(project, previousKey); - - assertThat(underTest).isEqualTo(underTest); - assertThat(underTest).isEqualTo(new RekeyedProject(project, previousKey)); - assertThat(underTest).isNotEqualTo(new RekeyedProject(project, randomAlphanumeric(11))); - assertThat(underTest).isNotEqualTo(new RekeyedProject(newRandomProject(), previousKey)); - assertThat(underTest).isNotEqualTo(new Object()); - assertThat(underTest).isNotEqualTo(null); - } - - @Test - public void hashCode_is_based_on_project_and_previousKey() { - Project project = newRandomProject(); - String previousKey = randomAlphanumeric(6); - RekeyedProject underTest = new RekeyedProject(project, previousKey); - - assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); - assertThat(underTest.hashCode()).isEqualTo(new RekeyedProject(project, previousKey).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new RekeyedProject(project, randomAlphanumeric(11)).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new RekeyedProject(newRandomProject(), previousKey).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(null); - } - - @Test - public void verify_toString() { - Project project = new Project("A", "B", "C", "D", emptyList()); - String previousKey = "E"; - RekeyedProject underTest = new RekeyedProject(project, previousKey); - - assertThat(underTest.toString()).isEqualTo("RekeyedProject{project=Project{uuid='A', key='B', name='C', description='D'}, previousKey='E'}"); - } - - private static Project newRandomProject() { - return Project.from(newPrivateProjectDto(newOrganizationDto())); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java deleted file mode 100644 index 964637487fb..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualitygate.changeevent; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.apache.commons.lang.RandomStringUtils; -import org.assertj.core.groups.Tuple; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mockito; -import org.sonar.api.issue.Issue; -import org.sonar.api.rules.RuleType; -import org.sonar.api.utils.log.LogTester; -import org.sonar.api.utils.log.LoggerLevel; -import org.sonar.core.issue.DefaultIssue; -import org.sonar.db.component.ComponentDto; -import org.sonar.server.qualitygate.changeevent.QGChangeEventListener.ChangedIssue; -import org.sonar.server.qualitygate.changeevent.QGChangeEventListenersImpl.ChangedIssueImpl; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptySet; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class QGChangeEventListenersImplTest { - @Rule - public LogTester logTester = new LogTester(); - - private QGChangeEventListener listener1 = mock(QGChangeEventListener.class); - private QGChangeEventListener listener2 = mock(QGChangeEventListener.class); - private QGChangeEventListener listener3 = mock(QGChangeEventListener.class); - private List listeners = Arrays.asList(listener1, listener2, listener3); - - private String component1Uuid = RandomStringUtils.randomAlphabetic(6); - private ComponentDto component1 = newComponentDto(component1Uuid); - private DefaultIssue component1Issue = newDefaultIssue(component1Uuid); - private List oneIssueOnComponent1 = singletonList(component1Issue); - private QGChangeEvent component1QGChangeEvent = newQGChangeEvent(component1); - - private InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - - private QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new QGChangeEventListener[] {listener1, listener2, listener3}); - - @Test - public void broadcastOnIssueChange_has_no_effect_when_issues_are_empty() { - underTest.broadcastOnIssueChange(emptyList(), singletonList(component1QGChangeEvent)); - - verifyZeroInteractions(listener1, listener2, listener3); - } - - @Test - public void broadcastOnIssueChange_has_no_effect_when_no_changeEvent() { - underTest.broadcastOnIssueChange(oneIssueOnComponent1, emptySet()); - - verifyZeroInteractions(listener1, listener2, listener3); - } - - @Test - public void broadcastOnIssueChange_passes_same_arguments_to_all_listeners_in_order_of_addition_to_constructor() { - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); - - ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); - inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); - Set changedIssues = changedIssuesCaptor.getValue(); - inOrder.verify(listener2).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); - inOrder.verify(listener3).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void broadcastOnIssueChange_calls_all_listeners_even_if_one_throws_an_exception() { - QGChangeEventListener failingListener = new QGChangeEventListener[] {listener1, listener2, listener3}[new Random().nextInt(3)]; - doThrow(new RuntimeException("Faking an exception thrown by onChanges")) - .when(failingListener) - .onIssueChanges(any(), any()); - - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); - - ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); - inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); - Set changedIssues = changedIssuesCaptor.getValue(); - inOrder.verify(listener2).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); - inOrder.verify(listener3).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); - inOrder.verifyNoMoreInteractions(); - assertThat(logTester.logs()).hasSize(4); - assertThat(logTester.logs(LoggerLevel.WARN)).hasSize(1); - } - - @Test - public void broadcastOnIssueChange_stops_calling_listeners_when_one_throws_an_ERROR() { - doThrow(new Error("Faking an error thrown by a listener")) - .when(listener2) - .onIssueChanges(any(), any()); - - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); - - ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); - inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); - Set changedIssues = changedIssuesCaptor.getValue(); - inOrder.verify(listener2).onIssueChanges(same(component1QGChangeEvent), same(changedIssues)); - inOrder.verifyNoMoreInteractions(); - assertThat(logTester.logs()).hasSize(3); - assertThat(logTester.logs(LoggerLevel.WARN)).hasSize(1); - } - - @Test - public void broadcastOnIssueChange_logs_each_listener_call_at_TRACE_level() { - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); - - assertThat(logTester.logs()).hasSize(3); - List traceLogs = logTester.logs(LoggerLevel.TRACE); - assertThat(traceLogs).hasSize(3) - .containsOnly( - "calling onChange() on listener " + listener1.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "...", - "calling onChange() on listener " + listener2.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "...", - "calling onChange() on listener " + listener3.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "..."); - } - - @Test - public void broadcastOnIssueChange_passes_immutable_set_of_ChangedIssues() { - QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new QGChangeEventListener[] {listener1}); - - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); - - ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); - inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); - assertThat(changedIssuesCaptor.getValue()).isInstanceOf(ImmutableSet.class); - } - - @Test - public void broadcastOnIssueChange_has_no_effect_when_no_listener() { - QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(); - - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); - - verifyZeroInteractions(listener1, listener2, listener3); - } - - @Test - public void broadcastOnIssueChange_calls_listener_for_each_component_uuid_with_at_least_one_QGChangeEvent() { - // component2 has multiple issues - ComponentDto component2 = newComponentDto(component1Uuid + "2"); - DefaultIssue[] component2Issues = {newDefaultIssue(component2.uuid()), newDefaultIssue(component2.uuid())}; - QGChangeEvent component2QGChangeEvent = newQGChangeEvent(component2); - - // component 3 has multiple QGChangeEvent and only one issue - ComponentDto component3 = newComponentDto(component1Uuid + "3"); - DefaultIssue component3Issue = newDefaultIssue(component3.uuid()); - QGChangeEvent[] component3QGChangeEvents = {newQGChangeEvent(component3), newQGChangeEvent(component3)}; - - // component 4 has multiple QGChangeEvent and multiples issues - ComponentDto component4 = newComponentDto(component1Uuid + "4"); - DefaultIssue[] component4Issues = {newDefaultIssue(component4.uuid()), newDefaultIssue(component4.uuid())}; - QGChangeEvent[] component4QGChangeEvents = {newQGChangeEvent(component4), newQGChangeEvent(component4)}; - - // component 5 has no QGChangeEvent but one issue - ComponentDto component5 = newComponentDto(component1Uuid + "5"); - DefaultIssue component5Issue = newDefaultIssue(component5.uuid()); - - List issues = Stream.of( - Stream.of(component1Issue), - Arrays.stream(component2Issues), - Stream.of(component3Issue), - Arrays.stream(component4Issues), - Stream.of(component5Issue)) - .flatMap(s -> s) - .collect(Collectors.toList()); - - List changedIssues = randomizedList(issues); - List qgChangeEvents = Stream.of( - Stream.of(component1QGChangeEvent), - Stream.of(component2QGChangeEvent), - Arrays.stream(component3QGChangeEvents), - Arrays.stream(component4QGChangeEvents)) - .flatMap(s -> s) - .collect(Collectors.toList()); - - underTest.broadcastOnIssueChange(changedIssues, randomizedList(qgChangeEvents)); - - listeners.forEach(listener -> { - verifyListenerCalled(listener, component1QGChangeEvent, component1Issue); - verifyListenerCalled(listener, component2QGChangeEvent, component2Issues); - Arrays.stream(component3QGChangeEvents) - .forEach(component3QGChangeEvent -> verifyListenerCalled(listener, component3QGChangeEvent, component3Issue)); - Arrays.stream(component4QGChangeEvents) - .forEach(component4QGChangeEvent -> verifyListenerCalled(listener, component4QGChangeEvent, component4Issues)); - }); - verifyNoMoreInteractions(listener1, listener2, listener3); - } - - @Test - public void isNotClosed_returns_true_if_issue_in_one_of_opened_states() { - DefaultIssue defaultIssue = new DefaultIssue(); - defaultIssue.setStatus(Issue.STATUS_REOPENED); - defaultIssue.setKey("abc"); - defaultIssue.setType(RuleType.BUG); - defaultIssue.setSeverity("BLOCKER"); - - ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue); - - assertThat(changedIssue.isNotClosed()).isTrue(); - } - - @Test - public void isNotClosed_returns_false_if_issue_in_one_of_closed_states() { - DefaultIssue defaultIssue = new DefaultIssue(); - defaultIssue.setStatus(Issue.STATUS_CONFIRMED); - defaultIssue.setKey("abc"); - defaultIssue.setType(RuleType.BUG); - defaultIssue.setSeverity("BLOCKER"); - - ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue); - - assertThat(changedIssue.isNotClosed()).isFalse(); - } - - @Test - public void test_status_mapping() { - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_OPEN))).isEqualTo(QGChangeEventListener.Status.OPEN); - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_REOPENED))).isEqualTo(QGChangeEventListener.Status.REOPENED); - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_CONFIRMED))).isEqualTo(QGChangeEventListener.Status.CONFIRMED); - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE))) - .isEqualTo(QGChangeEventListener.Status.RESOLVED_FP); - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX))) - .isEqualTo(QGChangeEventListener.Status.RESOLVED_WF); - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FIXED))) - .isEqualTo(QGChangeEventListener.Status.RESOLVED_FIXED); - try { - ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_CLOSED)); - fail("Expected exception"); - } catch (Exception e) { - assertThat(e).hasMessage("Unexpected status: CLOSED"); - } - try { - ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED)); - fail("Expected exception"); - } catch (Exception e) { - assertThat(e).hasMessage("A resolved issue should have a resolution"); - } - try { - ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_REMOVED)); - fail("Expected exception"); - } catch (Exception e) { - assertThat(e).hasMessage("Unexpected resolution for a resolved issue: REMOVED"); - } - } - - @Test - public void test_status_mapping_on_security_hotspots() { - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW))) - .isEqualTo(QGChangeEventListener.Status.TO_REVIEW); - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW))) - .isEqualTo(QGChangeEventListener.Status.IN_REVIEW); - assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED))) - .isEqualTo(QGChangeEventListener.Status.REVIEWED); - } - - private void verifyListenerCalled(QGChangeEventListener listener, QGChangeEvent changeEvent, DefaultIssue... issues) { - ArgumentCaptor> changedIssuesCaptor = newSetCaptor(); - verify(listener).onIssueChanges(same(changeEvent), changedIssuesCaptor.capture()); - Set changedIssues = changedIssuesCaptor.getValue(); - Tuple[] expected = Arrays.stream(issues) - .map(issue -> tuple(issue.key(), ChangedIssueImpl.statusOf(issue), issue.type())) - .toArray(Tuple[]::new); - assertThat(changedIssues) - .hasSize(issues.length) - .extracting(ChangedIssue::getKey, ChangedIssue::getStatus, ChangedIssue::getType) - .containsOnly(expected); - } - - private static final String[] POSSIBLE_STATUSES = asList(Issue.STATUS_CONFIRMED, Issue.STATUS_REOPENED, Issue.STATUS_RESOLVED).stream().toArray(String[]::new); - private static int issueIdCounter = 0; - - private static DefaultIssue newDefaultIssue(String projectUuid) { - DefaultIssue defaultIssue = new DefaultIssue(); - defaultIssue.setKey("issue_" + issueIdCounter++); - defaultIssue.setProjectUuid(projectUuid); - defaultIssue.setType(RuleType.values()[new Random().nextInt(RuleType.values().length)]); - defaultIssue.setStatus(POSSIBLE_STATUSES[new Random().nextInt(POSSIBLE_STATUSES.length)]); - String[] possibleResolutions = possibleResolutions(defaultIssue.getStatus()); - if (possibleResolutions.length > 0) { - defaultIssue.setResolution(possibleResolutions[new Random().nextInt(possibleResolutions.length)]); - } - return defaultIssue; - } - - private static String[] possibleResolutions(String status) { - switch (status) { - case Issue.STATUS_RESOLVED: - return new String[] {Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_WONT_FIX}; - default: - return new String[0]; - } - } - - private static ComponentDto newComponentDto(String uuid) { - ComponentDto componentDto = new ComponentDto(); - componentDto.setUuid(uuid); - return componentDto; - } - - private static QGChangeEvent newQGChangeEvent(ComponentDto componentDto) { - QGChangeEvent res = mock(QGChangeEvent.class); - when(res.getProject()).thenReturn(componentDto); - return res; - } - - private static ArgumentCaptor> newSetCaptor() { - Class> clazz = (Class>) (Class) Set.class; - return ArgumentCaptor.forClass(clazz); - } - - private static List randomizedList(List issues) { - ArrayList res = new ArrayList<>(issues); - Collections.shuffle(res); - return ImmutableList.copyOf(res); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java deleted file mode 100644 index eb4ce5d6c60..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.qualitygate.changeevent; - -import java.util.Optional; -import java.util.Random; -import java.util.function.Supplier; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; -import org.sonar.api.config.Configuration; -import org.sonar.api.measures.Metric; -import org.sonar.db.component.BranchDto; -import org.sonar.db.component.BranchType; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.SnapshotDto; -import org.sonar.server.qualitygate.EvaluatedQualityGate; - -import static org.assertj.core.api.Assertions.assertThat; - -public class QGChangeEventTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private ComponentDto project = new ComponentDto() - .setDbKey("foo") - .setUuid("bar"); - private BranchDto branch = new BranchDto() - .setBranchType(BranchType.SHORT) - .setUuid("bar") - .setProjectUuid("doh") - .setMergeBranchUuid("zop"); - private SnapshotDto analysis = new SnapshotDto() - .setUuid("pto") - .setCreatedAt(8_999_999_765L); - private Configuration configuration = Mockito.mock(Configuration.class); - private Metric.Level previousStatus = Metric.Level.values()[new Random().nextInt(Metric.Level.values().length)]; - private Supplier> supplier = Optional::empty; - - @Test - public void constructor_fails_with_NPE_if_project_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("project can't be null"); - - new QGChangeEvent(null, branch, analysis, configuration, previousStatus, supplier); - } - - @Test - public void constructor_fails_with_NPE_if_branch_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("branch can't be null"); - - new QGChangeEvent(project, null, analysis, configuration, previousStatus, supplier); - } - - @Test - public void constructor_fails_with_NPE_if_analysis_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("analysis can't be null"); - - new QGChangeEvent(project, branch, null, configuration, previousStatus, supplier); - } - - @Test - public void constructor_fails_with_NPE_if_configuration_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("projectConfiguration can't be null"); - - new QGChangeEvent(project, branch, analysis, null, previousStatus, supplier); - } - - @Test - public void constructor_does_not_fail_with_NPE_if_previousStatus_is_null() { - new QGChangeEvent(project, branch, analysis, configuration, null, supplier); - } - - @Test - public void constructor_fails_with_NPE_if_supplier_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("qualityGateSupplier can't be null"); - - new QGChangeEvent(project, branch, analysis, configuration, previousStatus, null); - } - - @Test - public void verify_getters() { - QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); - - assertThat(underTest.getProject()).isSameAs(project); - assertThat(underTest.getBranch()).isSameAs(branch); - assertThat(underTest.getAnalysis()).isSameAs(analysis); - assertThat(underTest.getProjectConfiguration()).isSameAs(configuration); - assertThat(underTest.getPreviousStatus()).contains(previousStatus); - assertThat(underTest.getQualityGateSupplier()).isSameAs(supplier); - } - - @Test - public void getPreviousStatus_returns_empty_when_previousStatus_is_null() { - QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); - - assertThat(underTest.getPreviousStatus()).contains(previousStatus); - } - - @Test - public void overrides_toString() { - QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); - - assertThat(underTest.toString()) - .isEqualTo("QGChangeEvent{project=bar:foo, branch=SHORT:bar:doh:zop, analysis=pto:8999999765" + - ", projectConfiguration=" + configuration.toString() + - ", previousStatus=" + previousStatus + - ", qualityGateSupplier=" + supplier + "}"); - - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/ProjectConfigurationLoaderImplTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/ProjectConfigurationLoaderImplTest.java deleted file mode 100644 index 0fb88ee9b05..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/ProjectConfigurationLoaderImplTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.setting; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import java.util.Collections; -import java.util.Map; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.config.Configuration; -import org.sonar.api.config.internal.MapSettings; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.property.PropertiesDao; -import org.sonar.db.property.PropertyDto; - -import static java.util.Collections.emptyList; -import static java.util.Collections.singleton; -import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; -import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class ProjectConfigurationLoaderImplTest { - private DbClient dbClient = mock(DbClient.class); - private DbSession dbSession = mock(DbSession.class); - private PropertiesDao propertiesDao = mock(PropertiesDao.class); - private MapSettings globalSettings = new MapSettings(); - private ProjectConfigurationLoaderImpl underTest = new ProjectConfigurationLoaderImpl(globalSettings, dbClient); - - @Before - public void setUp() throws Exception { - when(dbClient.openSession(anyBoolean())) - .thenThrow(new IllegalStateException("ProjectConfigurationLoaderImpl should not open DB session")); - when(dbClient.propertiesDao()).thenReturn(propertiesDao); - } - - @Test - public void returns_empty_map_when_no_component() { - assertThat(underTest.loadProjectConfigurations(dbSession, Collections.emptySet())) - .isEmpty(); - - verifyZeroInteractions(propertiesDao); - } - - @Test - public void return_configuration_with_just_global_settings_when_no_component_settings() { - String key = randomAlphanumeric(3); - String value = randomAlphanumeric(4); - String componentDbKey = randomAlphanumeric(5); - String componentUuid = randomAlphanumeric(6); - globalSettings.setProperty(key, value); - when(propertiesDao.selectProjectProperties(dbSession, componentDbKey)) - .thenReturn(emptyList()); - ComponentDto component = newComponentDto(componentDbKey, componentUuid); - - Map configurations = underTest.loadProjectConfigurations(dbSession, singleton(component)); - - assertThat(configurations) - .containsOnlyKeys(componentUuid); - assertThat(configurations.get(componentUuid).get(key)).contains(value); - } - - @Test - public void return_configuration_with_global_settings_and_component_settings() { - String globalKey = randomAlphanumeric(3); - String globalValue = randomAlphanumeric(4); - String componentDbKey = randomAlphanumeric(5); - String componentUuid = randomAlphanumeric(6); - String projectPropKey1 = randomAlphanumeric(7); - String projectPropValue1 = randomAlphanumeric(8); - String projectPropKey2 = randomAlphanumeric(9); - String projectPropValue2 = randomAlphanumeric(10); - globalSettings.setProperty(globalKey, globalValue); - when(propertiesDao.selectProjectProperties(dbSession, componentDbKey)) - .thenReturn(ImmutableList.of(newPropertyDto(projectPropKey1, projectPropValue1), newPropertyDto(projectPropKey2, projectPropValue2))); - ComponentDto component = newComponentDto(componentDbKey, componentUuid); - - Map configurations = underTest.loadProjectConfigurations(dbSession, singleton(component)); - - assertThat(configurations) - .containsOnlyKeys(componentUuid); - assertThat(configurations.get(componentUuid).get(globalKey)).contains(globalValue); - assertThat(configurations.get(componentUuid).get(projectPropKey1)).contains(projectPropValue1); - assertThat(configurations.get(componentUuid).get(projectPropKey2)).contains(projectPropValue2); - } - - @Test - public void return_configuration_with_global_settings_main_branch_settings_and_branch_settings() { - String globalKey = randomAlphanumeric(3); - String globalValue = randomAlphanumeric(4); - String mainBranchDbKey = randomAlphanumeric(5); - String branchDbKey = mainBranchDbKey + ComponentDto.BRANCH_KEY_SEPARATOR + randomAlphabetic(5); - String branchUuid = randomAlphanumeric(6); - String mainBranchPropKey = randomAlphanumeric(7); - String mainBranchPropValue = randomAlphanumeric(8); - String branchPropKey = randomAlphanumeric(9); - String branchPropValue = randomAlphanumeric(10); - globalSettings.setProperty(globalKey, globalValue); - when(propertiesDao.selectProjectProperties(dbSession, mainBranchDbKey)) - .thenReturn(ImmutableList.of(newPropertyDto(mainBranchPropKey, mainBranchPropValue))); - when(propertiesDao.selectProjectProperties(dbSession, branchDbKey)) - .thenReturn(ImmutableList.of(newPropertyDto(branchPropKey, branchPropValue))); - ComponentDto component = newComponentDto(branchDbKey, branchUuid); - - Map configurations = underTest.loadProjectConfigurations(dbSession, singleton(component)); - - assertThat(configurations) - .containsOnlyKeys(branchUuid); - assertThat(configurations.get(branchUuid).get(globalKey)).contains(globalValue); - assertThat(configurations.get(branchUuid).get(mainBranchPropKey)).contains(mainBranchPropValue); - assertThat(configurations.get(branchUuid).get(branchPropKey)).contains(branchPropValue); - } - - @Test - public void loads_configuration_of_any_given_component_only_once() { - String mainBranch1DbKey = randomAlphanumeric(4); - String mainBranch1Uuid = randomAlphanumeric(5); - String branch1DbKey = mainBranch1DbKey + ComponentDto.BRANCH_KEY_SEPARATOR + randomAlphabetic(5); - String branch1Uuid = randomAlphanumeric(6); - String branch2DbKey = mainBranch1DbKey + ComponentDto.BRANCH_KEY_SEPARATOR + randomAlphabetic(7); - String branch2Uuid = randomAlphanumeric(8); - String mainBranch2DbKey = randomAlphanumeric(14); - String mainBranch2Uuid = randomAlphanumeric(15); - String branch3DbKey = mainBranch2DbKey + ComponentDto.BRANCH_KEY_SEPARATOR + randomAlphabetic(5); - String branch3Uuid = randomAlphanumeric(16); - - ComponentDto mainBranch1 = newComponentDto(mainBranch1DbKey, mainBranch1Uuid); - ComponentDto branch1 = newComponentDto(branch1DbKey, branch1Uuid); - ComponentDto branch2 = newComponentDto(branch2DbKey, branch2Uuid); - ComponentDto mainBranch2 = newComponentDto(mainBranch2DbKey, mainBranch2Uuid); - ComponentDto branch3 = newComponentDto(branch3DbKey, branch3Uuid); - - underTest.loadProjectConfigurations(dbSession, ImmutableSet.of(mainBranch1, mainBranch2, branch1, branch2, branch3)); - - verify(propertiesDao, times(1)).selectProjectProperties(dbSession, mainBranch1DbKey); - verify(propertiesDao, times(1)).selectProjectProperties(dbSession, mainBranch2DbKey); - verify(propertiesDao, times(1)).selectProjectProperties(dbSession, branch1DbKey); - verify(propertiesDao, times(1)).selectProjectProperties(dbSession, branch2DbKey); - verify(propertiesDao, times(1)).selectProjectProperties(dbSession, branch3DbKey); - verifyNoMoreInteractions(propertiesDao); - } - - private ComponentDto newComponentDto(String componentDbKey, String componentUuid) { - return new ComponentDto().setDbKey(componentDbKey).setUuid(componentUuid); - } - - private PropertyDto newPropertyDto(String projectKey1, String projectValue1) { - return new PropertyDto() - .setKey(projectKey1) - .setValue(projectValue1); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/SettingsChangeNotifierTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/SettingsChangeNotifierTest.java deleted file mode 100644 index 577eda83519..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/SettingsChangeNotifierTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.setting; - -import org.junit.Test; -import org.sonar.api.config.GlobalPropertyChangeHandler; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -public class SettingsChangeNotifierTest { - @Test - public void onGlobalPropertyChange() { - GlobalPropertyChangeHandler handler = mock(GlobalPropertyChangeHandler.class); - SettingsChangeNotifier notifier = new SettingsChangeNotifier(new GlobalPropertyChangeHandler[] {handler}); - - notifier.onGlobalPropertyChange("foo", "bar"); - - verify(handler).onChange(argThat(change -> change.getKey().equals("foo") && change.getNewValue().equals("bar"))); - } - - @Test - public void no_handlers() { - SettingsChangeNotifier notifier = new SettingsChangeNotifier(); - - assertThat(notifier.changeHandlers).isEmpty(); - - // does not fail - notifier.onGlobalPropertyChange("foo", "bar"); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java deleted file mode 100644 index e0c0b6d2854..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.setting; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import org.sonar.api.config.Configuration; -import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDto; - -public class TestProjectConfigurationLoader implements ProjectConfigurationLoader { - - private final Configuration config; - - public TestProjectConfigurationLoader(Configuration config) { - this.config = config; - } - - @Override - public Map loadProjectConfigurations(DbSession dbSession, Set projects) { - Map map = new HashMap<>(); - for (ComponentDto project : projects) { - map.put(project.uuid(), config); - } - return map; - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java deleted file mode 100644 index d11c03152b8..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/BooleanTypeValidationTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.server.exceptions.BadRequestException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class BooleanTypeValidationTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private BooleanTypeValidation underTest = new BooleanTypeValidation(); - - @Test - public void key() { - assertThat(underTest.key()).isEqualTo("BOOLEAN"); - } - - @Test - public void not_fail_on_valid_boolean() { - underTest.validate("true", null); - underTest.validate("True", null); - underTest.validate("false", null); - underTest.validate("FALSE", null); - } - - @Test - public void fail_on_invalid_boolean() { - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value 'abc' must be one of \"true\" or \"false\"."); - - underTest.validate("abc", null); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java deleted file mode 100644 index b88c3fbb651..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/FloatTypeValidationTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.server.exceptions.BadRequestException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class FloatTypeValidationTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private FloatTypeValidation validation = new FloatTypeValidation(); - - @Test - public void key() { - assertThat(validation.key()).isEqualTo("FLOAT"); - } - - @Test - public void not_fail_on_valid_float() { - validation.validate("10.2", null); - validation.validate("10", null); - validation.validate("-10.3", null); - } - - @Test - public void fail_on_invalid_float() { - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value 'abc' must be an floating point number."); - - validation.validate("abc", null); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/GlobalLockManagerTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/GlobalLockManagerTest.java deleted file mode 100644 index 8a069e1eae2..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/GlobalLockManagerTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Rule; -import org.junit.Test; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.server.util.GlobalLockManager.DEFAULT_LOCK_DURATION_SECONDS; - -public class GlobalLockManagerTest { - - private final System2 system2 = mock(System2.class); - - @Rule - public final DbTester dbTester = DbTester.create(system2); - - private final GlobalLockManager underTest = new GlobalLockManager(dbTester.getDbClient()); - - @Test - public void tryLock_succeeds_when_created_for_the_first_time() { - assertThat(underTest.tryLock("newName")).isTrue(); - } - - @Test - public void tryLock_fails_when_previous_lock_is_too_recent() { - String name = "newName"; - assertThat(underTest.tryLock(name)).isTrue(); - assertThat(underTest.tryLock(name)).isFalse(); - } - - @Test - public void tryLock_succeeds_when_previous_lock_is_old_enough() { - String name = "newName"; - long firstLock = 0; - long longEnoughAfterFirstLock = firstLock + DEFAULT_LOCK_DURATION_SECONDS * 1000; - long notLongEnoughAfterFirstLock = longEnoughAfterFirstLock - 1; - - when(system2.now()).thenReturn(firstLock); - assertThat(underTest.tryLock(name)).isTrue(); - - when(system2.now()).thenReturn(notLongEnoughAfterFirstLock); - assertThat(underTest.tryLock(name)).isFalse(); - - when(system2.now()).thenReturn(longEnoughAfterFirstLock); - assertThat(underTest.tryLock(name)).isTrue(); - } - - @Test - public void locks_with_different_name_are_independent() { - assertThat(underTest.tryLock("newName1")).isTrue(); - assertThat(underTest.tryLock("newName2")).isTrue(); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java deleted file mode 100644 index e9b1953dd5a..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/IntegerTypeValidationTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.server.exceptions.BadRequestException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class IntegerTypeValidationTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private IntegerTypeValidation validation = new IntegerTypeValidation(); - - @Test - public void key() { - assertThat(validation.key()).isEqualTo("INTEGER"); - } - - @Test - public void not_fail_on_valid_integer() { - validation.validate("10", null); - validation.validate("-10", null); - } - - @Test - public void fail_on_string() { - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value 'abc' must be an integer."); - - validation.validate("abc", null); - } - - @Test - public void fail_on_float() { - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value '10.1' must be an integer."); - - validation.validate("10.1", null); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/LongTypeValidationTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/LongTypeValidationTest.java deleted file mode 100644 index 2f7d7e0946e..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/LongTypeValidationTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.PropertyType; -import org.sonar.server.exceptions.BadRequestException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class LongTypeValidationTest { - - LongTypeValidation underTest = new LongTypeValidation(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void key_is_long_type_name() { - assertThat(underTest.key()).isEqualTo(PropertyType.LONG.name()); - } - - @Test - public void do_not_fail_with_long_values() { - underTest.validate("1984", null); - underTest.validate("-1984", null); - } - - @Test - public void fail_when_float() { - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value '3.14' must be a long."); - - underTest.validate("3.14", null); - } - - @Test - public void fail_when_string() { - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value 'original string' must be a long."); - - underTest.validate("original string", null); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java deleted file mode 100644 index 9f2630fd0de..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/StringListTypeValidationTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.server.exceptions.BadRequestException; - -import static com.google.common.collect.Lists.newArrayList; -import static org.assertj.core.api.Assertions.assertThat; - -public class StringListTypeValidationTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private StringListTypeValidation validation = new StringListTypeValidation(); - - @Test - public void key() { - assertThat(validation.key()).isEqualTo("SINGLE_SELECT_LIST"); - } - - @Test - public void not_fail_on_valid_option() { - validation.validate("a", newArrayList("a", "b", "c")); - validation.validate("a", null); - } - - @Test - public void fail_on_invalid_option() { - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value 'abc' must be one of : a, b, c."); - - validation.validate("abc", newArrayList("a", "b", "c")); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/StringTypeValidationTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/StringTypeValidationTest.java deleted file mode 100644 index dde3afa3543..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/StringTypeValidationTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Before; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class StringTypeValidationTest { - - StringTypeValidation validation; - - @Before - public void setUp() { - validation = new StringTypeValidation(); - } - - @Test - public void key() { - assertThat(validation.key()).isEqualTo("STRING"); - } - - @Test - public void not_fail_on_valid_string() { - validation.validate("10", null); - validation.validate("abc", null); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TextTypeValidationTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TextTypeValidationTest.java deleted file mode 100644 index 4261f95c580..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TextTypeValidationTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Before; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class TextTypeValidationTest { - - TextTypeValidation validation; - - @Before - public void setUp() { - validation = new TextTypeValidation(); - } - - @Test - public void key() { - assertThat(validation.key()).isEqualTo("TEXT"); - } - - @Test - public void not_fail_on_valid_text() { - validation.validate("10", null); - validation.validate("abc", null); - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationModuleTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationModuleTest.java deleted file mode 100644 index 3ff709c8f0f..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationModuleTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Test; -import org.sonar.core.platform.ComponentContainer; - -import static org.assertj.core.api.Assertions.assertThat; - -public class TypeValidationModuleTest { - @Test - public void verify_count_of_added_components() { - ComponentContainer container = new ComponentContainer(); - new TypeValidationModule().configure(container); - assertThat(container.size()).isEqualTo(11); - } -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationsTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationsTest.java deleted file mode 100644 index 4dbae47cb37..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationsTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import org.junit.Test; -import org.sonar.server.exceptions.BadRequestException; - -import static com.google.common.collect.Lists.newArrayList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class TypeValidationsTest { - - @Test - public void validate() { - TypeValidation fakeTypeValidation = mock(TypeValidation.class); - when(fakeTypeValidation.key()).thenReturn("Fake"); - - TypeValidations typeValidations = new TypeValidations(newArrayList(fakeTypeValidation)); - typeValidations.validate("10", "Fake", newArrayList("a")); - - verify(fakeTypeValidation).validate("10", newArrayList("a")); - } - - @Test - public void validate__multiple_values() { - TypeValidation fakeTypeValidation = mock(TypeValidation.class); - when(fakeTypeValidation.key()).thenReturn("Fake"); - - TypeValidations typeValidations = new TypeValidations(newArrayList(fakeTypeValidation)); - typeValidations.validate(newArrayList("10", "11", "12"), "Fake", newArrayList("11")); - - verify(fakeTypeValidation).validate("10", newArrayList("11")); - } - - @Test - public void fail_on_unknown_type() { - TypeValidation fakeTypeValidation = mock(TypeValidation.class); - when(fakeTypeValidation.key()).thenReturn("Fake"); - - try { - TypeValidations typeValidations = new TypeValidations(newArrayList(fakeTypeValidation)); - typeValidations.validate("10", "Unknown", null); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(BadRequestException.class); - BadRequestException badRequestException = (BadRequestException) e; - assertThat(badRequestException.getMessage()).isEqualTo("Type 'Unknown' is not valid."); - } - } - -} diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationsTesting.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationsTesting.java deleted file mode 100644 index b237ba62aab..00000000000 --- a/server/sonar-webserver-common/src/test/java/org/sonar/server/util/TypeValidationsTesting.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.util; - -import java.util.Arrays; - -public class TypeValidationsTesting { - private TypeValidationsTesting() { - // utility class - } - - public static TypeValidations newFullTypeValidations() { - return new TypeValidations(Arrays.asList( - new BooleanTypeValidation(), - new IntegerTypeValidation(), - new LongTypeValidation(), - new FloatTypeValidation(), - new StringTypeValidation(), - new StringListTypeValidation(), - new MetricLevelTypeValidation() - )); - } -} diff --git a/server/sonar-webserver-common/src/test/projects/.gitignore b/server/sonar-webserver-common/src/test/projects/.gitignore deleted file mode 100644 index a945b8525e6..00000000000 --- a/server/sonar-webserver-common/src/test/projects/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# see README.txt -!*/target/ -*/target/classes/ -*/target/maven-archiver/ -*/target/maven-status/ -*/target/test-*/ - diff --git a/server/sonar-webserver-common/src/test/projects/README.txt b/server/sonar-webserver-common/src/test/projects/README.txt deleted file mode 100644 index c53a66d52f2..00000000000 --- a/server/sonar-webserver-common/src/test/projects/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This directory provides the fake plugins used by tests. These tests are rarely changed, so generated -artifacts are stored in Git repository (see .gitignore). It avoids from adding unnecessary modules -to build. diff --git a/server/sonar-webserver-common/src/test/projects/fake-report-plugin/pom.xml b/server/sonar-webserver-common/src/test/projects/fake-report-plugin/pom.xml deleted file mode 100644 index 72a04dbe04f..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-report-plugin/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - fake-report-plugin - 0.1-SNAPSHOT - sonar-plugin - Fake Report Plugin - Fake Report Plugin - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - report - BasePlugin - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/fake-report-plugin/src/BasePlugin.java b/server/sonar-webserver-common/src/test/projects/fake-report-plugin/src/BasePlugin.java deleted file mode 100644 index d12daff3e57..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-report-plugin/src/BasePlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class BasePlugin extends Plugin { - - public void define(Plugin.Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/projects/fake-report-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-common/src/test/projects/fake-report-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java deleted file mode 100644 index e0b54398eaf..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-report-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.plugins.testbase.api; - -public class BaseApi { - public void doNothing() { - } -} diff --git a/server/sonar-webserver-common/src/test/projects/fake-report-plugin/target/fake-report-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/fake-report-plugin/target/fake-report-plugin-0.1-SNAPSHOT.jar deleted file mode 100644 index 6085e44fdca..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/fake-report-plugin/target/fake-report-plugin-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/pom.xml b/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/pom.xml deleted file mode 100644 index e417dd96fba..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - fake-sqale-plugin - 0.1-SNAPSHOT - sonar-plugin - Fake SQALE Plugin - Fake SQALE Plugin - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - sqale - BasePlugin - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/src/BasePlugin.java b/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/src/BasePlugin.java deleted file mode 100644 index d12daff3e57..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/src/BasePlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class BasePlugin extends Plugin { - - public void define(Plugin.Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java deleted file mode 100644 index e0b54398eaf..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.plugins.testbase.api; - -public class BaseApi { - public void doNothing() { - } -} diff --git a/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/target/fake-sqale-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/target/fake-sqale-plugin-0.1-SNAPSHOT.jar deleted file mode 100644 index b5c99f721b3..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/fake-sqale-plugin/target/fake-sqale-plugin-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/projects/fake-views-plugin/pom.xml b/server/sonar-webserver-common/src/test/projects/fake-views-plugin/pom.xml deleted file mode 100644 index 1ef73d2ffda..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-views-plugin/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - fake-views-plugin - 0.1-SNAPSHOT - sonar-plugin - Fake Views Plugin - Fake Views Plugin - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - views - BasePlugin - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/fake-views-plugin/src/BasePlugin.java b/server/sonar-webserver-common/src/test/projects/fake-views-plugin/src/BasePlugin.java deleted file mode 100644 index d12daff3e57..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-views-plugin/src/BasePlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class BasePlugin extends Plugin { - - public void define(Plugin.Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/projects/fake-views-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-common/src/test/projects/fake-views-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java deleted file mode 100644 index e0b54398eaf..00000000000 --- a/server/sonar-webserver-common/src/test/projects/fake-views-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.plugins.testbase.api; - -public class BaseApi { - public void doNothing() { - } -} diff --git a/server/sonar-webserver-common/src/test/projects/fake-views-plugin/target/fake-views-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/fake-views-plugin/target/fake-views-plugin-0.1-SNAPSHOT.jar deleted file mode 100644 index a47d93d94a8..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/fake-views-plugin/target/fake-views-plugin-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/projects/pom.xml b/server/sonar-webserver-common/src/test/projects/pom.xml deleted file mode 100644 index 37338313ac0..00000000000 --- a/server/sonar-webserver-common/src/test/projects/pom.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - parent - 0.1-SNAPSHOT - pom - - test-base-plugin - test-base-plugin-v2 - test-core-plugin - test-extend-plugin - test-libs-plugin - test-require-plugin - test-requirenew-plugin - fake-report-plugin - fake-sqale-plugin - fake-views-plugin - - - diff --git a/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/pom.xml b/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/pom.xml deleted file mode 100644 index 982be1c0170..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - test-base-plugin - 0.2-SNAPSHOT - sonar-plugin - Base Plugin - Simple standalone plugin. Used by other fake plugins. - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - testbase - BasePlugin - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/src/BasePlugin.java b/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/src/BasePlugin.java deleted file mode 100644 index d12daff3e57..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/src/BasePlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class BasePlugin extends Plugin { - - public void define(Plugin.Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/src/org/sonar/plugins/testbase/api/BaseApi.java deleted file mode 100644 index e0b54398eaf..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/src/org/sonar/plugins/testbase/api/BaseApi.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.plugins.testbase.api; - -public class BaseApi { - public void doNothing() { - } -} diff --git a/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar deleted file mode 100644 index 1d4ef5430c7..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/projects/test-base-plugin/pom.xml b/server/sonar-webserver-common/src/test/projects/test-base-plugin/pom.xml deleted file mode 100644 index c4e95936e74..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-base-plugin/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - test-base-plugin - 0.1-SNAPSHOT - sonar-plugin - Base Plugin - Simple standalone plugin. Used by other fake plugins. - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - testbase - BasePlugin - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/test-base-plugin/src/BasePlugin.java b/server/sonar-webserver-common/src/test/projects/test-base-plugin/src/BasePlugin.java deleted file mode 100644 index d12daff3e57..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-base-plugin/src/BasePlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class BasePlugin extends Plugin { - - public void define(Plugin.Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/projects/test-base-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java b/server/sonar-webserver-common/src/test/projects/test-base-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java deleted file mode 100644 index e0b54398eaf..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-base-plugin/src/org/sonar/plugins/testbase/api/BaseApi.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.plugins.testbase.api; - -public class BaseApi { - public void doNothing() { - } -} diff --git a/server/sonar-webserver-common/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar deleted file mode 100644 index 739a22fcdae..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/projects/test-extend-plugin/pom.xml b/server/sonar-webserver-common/src/test/projects/test-extend-plugin/pom.xml deleted file mode 100644 index e23667e6318..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-extend-plugin/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - test-extend-plugin - 0.1-SNAPSHOT - sonar-plugin - Test Extend Plugin - Fake plugin that extends the plugin with key "base" - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - testextend - ExtendPlugin - testbase - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/test-extend-plugin/src/ExtendPlugin.java b/server/sonar-webserver-common/src/test/projects/test-extend-plugin/src/ExtendPlugin.java deleted file mode 100644 index d364a2f9dd4..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-extend-plugin/src/ExtendPlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class ExtendPlugin extends Plugin { - - public void define(Plugin.Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar deleted file mode 100644 index 2f63c2e652c..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/projects/test-libs-plugin/pom.xml b/server/sonar-webserver-common/src/test/projects/test-libs-plugin/pom.xml deleted file mode 100644 index 2d49cca2cf2..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-libs-plugin/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - test-libs-plugin - 0.1-SNAPSHOT - sonar-plugin - Test Libs Plugin - Fake plugin that embeds some libraries - - - - - commons-email - commons-email - 20030310.165926 - - - commons-daemon - commons-daemon - 1.0.15 - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - testlibs - LibsPlugin - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/test-libs-plugin/src/LibsPlugin.java b/server/sonar-webserver-common/src/test/projects/test-libs-plugin/src/LibsPlugin.java deleted file mode 100644 index 7e3ebe0909c..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-libs-plugin/src/LibsPlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class LibsPlugin extends Plugin { - - public void define(Plugin.Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar deleted file mode 100644 index 6ebe8652d8b..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/projects/test-require-plugin/pom.xml b/server/sonar-webserver-common/src/test/projects/test-require-plugin/pom.xml deleted file mode 100644 index 62462ffbf34..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-require-plugin/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - test-require-plugin - 0.1-SNAPSHOT - sonar-plugin - Test Require Plugin - This fake plugin depends on test-base-plugin - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - org.sonarsource.sonarqube.tests - test-base-plugin - 0.1-SNAPSHOT - sonar-plugin - provided - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - testrequire - RequirePlugin - testbase:0.1 - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/test-require-plugin/src/RequirePlugin.java b/server/sonar-webserver-common/src/test/projects/test-require-plugin/src/RequirePlugin.java deleted file mode 100644 index 847ae2d994e..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-require-plugin/src/RequirePlugin.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class RequirePlugin extends Plugin { - - public RequirePlugin() { - // call a class that is in the api published by the base plugin - new org.sonar.plugins.testbase.api.BaseApi().doNothing(); - } - - public void define(Plugin.Context context) { - - } -} diff --git a/server/sonar-webserver-common/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar deleted file mode 100644 index f5fc95f9d0d..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/pom.xml b/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/pom.xml deleted file mode 100644 index 044cd94e8f0..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - 4.0.0 - org.sonarsource.sonarqube.tests - test-requirenew-plugin - 0.1-SNAPSHOT - sonar-plugin - Test Require New Plugin - This fake plugin requires a version of test-base-plugin that is not installed - - - - org.codehaus.sonar - sonar-plugin-api - 4.5.4 - provided - - - org.sonarsource.sonarqube.tests - test-base-plugin - 0.1-SNAPSHOT - sonar-plugin - provided - - - - src - - - org.sonarsource.sonar-packaging-maven-plugin - sonar-packaging-maven-plugin - 1.15 - true - - testrequire - RequirePlugin - testbase:0.2 - - - - - - diff --git a/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java b/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java deleted file mode 100644 index 0d14cde33c1..00000000000 --- a/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import org.sonar.api.Plugin; - -import java.util.Collections; -import java.util.List; - -public class RequirePlugin extends Plugin { - - public RequirePlugin() { - // call a class that is in the api published by the base plugin - new org.sonar.plugins.testbase.api.BaseApi().doNothing(); - } - - public void define(Plugin.Context context) { - - } - -} diff --git a/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar b/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar deleted file mode 100644 index 0dd577fc360..00000000000 Binary files a/server/sonar-webserver-common/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/server/sonar-webserver-common/src/test/resources/logback-test.xml b/server/sonar-webserver-common/src/test/resources/logback-test.xml deleted file mode 100644 index 3e34b0f9fc8..00000000000 --- a/server/sonar-webserver-common/src/test/resources/logback-test.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - %d{yyyy.MM.dd HH:mm:ss} %-5level %msg%n - - - - - - - - - - - - - - - - - - diff --git a/server/sonar-webserver-core/build.gradle b/server/sonar-webserver-core/build.gradle index 8d8daa84ad9..f8415d6f3a4 100644 --- a/server/sonar-webserver-core/build.gradle +++ b/server/sonar-webserver-core/build.gradle @@ -43,8 +43,8 @@ dependencies { compile project(':server:sonar-db-migration') compile project(':server:sonar-process') compile project(':server:sonar-server-common') + compile project(':server:sonar-webserver-api') compile project(':server:sonar-webserver-auth') - compile project(':server:sonar-webserver-common') compile project(':server:sonar-webserver-es') compile project(':sonar-core') compile project(':sonar-duplications') @@ -74,8 +74,8 @@ dependencies { testCompile 'org.subethamail:subethasmtp' testCompile project(':server:sonar-db-testing') testCompile project(path: ":server:sonar-server-common", configuration: "tests") + testCompile project(path: ":server:sonar-webserver-api", configuration: "tests") testCompile project(path: ":server:sonar-webserver-auth", configuration: "tests") - testCompile project(path: ":server:sonar-webserver-common", configuration: "tests") testCompile project(path: ":server:sonar-webserver-es", configuration: "tests") testCompile project(path: ":server:sonar-webserver-ws", configuration: "tests") testCompile project(':sonar-testing-harness') diff --git a/server/sonar-webserver-webapi/build.gradle b/server/sonar-webserver-webapi/build.gradle index c94534da997..d32bf648c4d 100644 --- a/server/sonar-webserver-webapi/build.gradle +++ b/server/sonar-webserver-webapi/build.gradle @@ -36,8 +36,8 @@ dependencies { testCompile 'org.mockito:mockito-core' testCompile project(':server:sonar-db-testing') testCompile project(path: ":server:sonar-server-common", configuration: "tests") + testCompile project(path: ":server:sonar-webserver-api", configuration: "tests") testCompile project(path: ":server:sonar-webserver-auth", configuration: "tests") - testCompile project(path: ":server:sonar-webserver-common", configuration: "tests") testCompile project(path: ":server:sonar-webserver-es", configuration: "tests") testCompile project(path: ":server:sonar-webserver-ws", configuration: "tests") testCompile project(':sonar-testing-harness') diff --git a/server/sonar-webserver-ws/build.gradle b/server/sonar-webserver-ws/build.gradle index 61535505c5e..7fa56ae5c0b 100644 --- a/server/sonar-webserver-ws/build.gradle +++ b/server/sonar-webserver-ws/build.gradle @@ -17,7 +17,7 @@ dependencies { compile 'com.google.guava:guava' compile project(':sonar-core') - compile project(':server:sonar-webserver-common') + compile project(':server:sonar-webserver-api') compile project(path: ':sonar-plugin-api', configuration: 'shadow') compile project(':sonar-plugin-api-impl') compile project(':sonar-ws') diff --git a/server/sonar-webserver/build.gradle b/server/sonar-webserver/build.gradle index 47925090c2f..863fa2769b9 100644 --- a/server/sonar-webserver/build.gradle +++ b/server/sonar-webserver/build.gradle @@ -28,8 +28,8 @@ dependencies { testCompile 'org.eclipse.jetty:jetty-servlet' testCompile project(':server:sonar-db-testing') testCompile project(path: ":server:sonar-server-common", configuration: "tests") + testCompile project(path: ":server:sonar-webserver-api", configuration: "tests") testCompile project(path: ":server:sonar-webserver-auth", configuration: "tests") - testCompile project(path: ":server:sonar-webserver-common", configuration: "tests") testCompile project(path: ":server:sonar-webserver-es", configuration: "tests") testCompile project(':sonar-testing-harness') } diff --git a/settings.gradle b/settings.gradle index 000a441e198..7ea694bb170 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,8 +17,8 @@ include 'server:sonar-server-common' include 'server:sonar-vsts' include 'server:sonar-web' include 'server:sonar-webserver' +include 'server:sonar-webserver-api' include 'server:sonar-webserver-auth' -include 'server:sonar-webserver-common' include 'server:sonar-webserver-core' include 'server:sonar-webserver-es' include 'server:sonar-webserver-webapi' -- cgit v1.2.3