]> source.dussan.org Git - sonarqube.git/commitdiff
consistent methods names for all WsAction classes
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Tue, 19 May 2015 15:32:19 +0000 (17:32 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Tue, 19 May 2015 15:32:19 +0000 (17:32 +0200)
375 files changed:
server/sonar-server/src/main/java/org/sonar/server/batch/GlobalAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/batch/GlobalRepositoryAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/batch/ProjectAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/component/ws/AppAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentsWs.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsDeleteAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsGhostsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsProvisionedAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWs.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/ws/ComputationWsAction.java
server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWs.java
server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/dashboard/ws/DashboardsShowAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/dashboard/ws/ShowAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/issue/ws/ShowAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java
server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbSystemAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbSystemWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/RestartAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/ServerWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/StatusAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemInfoWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemRestartWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemStatusWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/UpgradesAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/ws/UpgradesSystemWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/AvailableAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/AvailablePluginsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllPluginsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstallAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstallPluginsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallPluginsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatePluginsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatesAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatesPluginsWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/project/ws/DeleteAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/project/ws/GhostsAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/project/ws/ProvisionedAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/project/ws/package-info.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/AppAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ListAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesAppAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCopyAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCreateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCreateConditionAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDeleteConditionAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDeselectAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDestroyAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesListAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesRenameAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSearchAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSelectAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSetAsDefaultAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesShowAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesUnsetDefaultAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesUpdateConditionAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BackupAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangeParentAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CompareAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CopyAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeleteAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportersAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ImportersAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/InheritanceAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectsAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileBackupAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangelogAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCompareAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCopyAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCreateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileDeleteAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileExportAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileExportersAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileImportersAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileProjectsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRenameAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSearchAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RenameAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SetDefaultAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/test/ws/CoveredFilesAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsCoveredFilesAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsListAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentUserAction.java [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-create.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-ghosts.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-index.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-provisioned.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-create.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-ghosts.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-index.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-provisioned.json [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java
server/sonar-server/src/test/java/org/sonar/server/batch/GlobalActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/batch/GlobalRepositoryActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/batch/ProjectActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/component/ws/AppActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsDeleteActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsGhostsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsProvisionedActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsWsTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/ws/ComputationWsTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryActionMediumTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryWsActionMediumTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWsTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/issue/ws/ShowActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbSystemActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbSystemWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/RestartActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/StatusActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemInfoWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemRestartWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemStatusWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/ws/UpgradesActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/platform/ws/UpgradesSystemWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/AbstractUpdateCenterBasedPluginsWsActionTest.java
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/AvailableActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/AvailablePluginsWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllPluginsWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstallActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstallPluginsWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallPluginsWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatePluginsWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatesActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatesPluginsWsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/project/ws/GhostsActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/project/ws/ProvisionedActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/AppActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesAppActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesWsTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionMediumTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CompareActionMediumTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionMediumTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/DeleteActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportersActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ImportersActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ProjectsActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileBackupActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentActionMediumTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCreateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileDeleteActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileExportActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileExportersActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileImportersActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRenameActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RenameActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SetDefaultActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsCoveredFilesActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsListActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsWsTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentUserActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_global_referentials.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_global_settings.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_only_license_settings_without_scan_but_with_preview_permission.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_referentials.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_settings.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_only_license_settings_without_scan_but_with_preview_permission.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectActionTest/project_referentials.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectRepositoryActionTest/project_referentials.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_it_measure.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_measures.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_overall_measure.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_ut_measure.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_it_measure.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_measures.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_overall_measure.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_ut_measure.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsGhostsActionTest/all-projects.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsGhostsActionTest/pagination.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsProvisionedActionTest/all-projects.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryActionMediumTest/list_history_reports.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryWsActionMediumTest/list_history_reports.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueActionTest/list_queue_reports.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueWsActionTest/list_queue_reports.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_component.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_action_plan.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_actions.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_changelog.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_characteristics.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_comments.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_dates.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_sub_project.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_technical_debt.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_transitions.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_users.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_on_removed_component.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_action_plan.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_actions.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_changelog.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_characteristics.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_comments.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_dates.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_sub_project.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_technical_debt.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_transitions.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_users.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/AvailableActionTest/properties_per_plugin.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/AvailablePluginsWsActionTest/properties_per_plugin.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/InstalledActionTest/some.jar [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest/some.jar [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/UpdatablePluginsWsActionTest/properties_per_plugin.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/project/ws/GhostsActionTest/all-projects.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/project/ws/GhostsActionTest/pagination.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/project/ws/ProvisionedActionTest/all-projects.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_empty.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_no_login.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_no_param.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_nominal.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page1.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page2.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page3.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_nominal.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_param_on_left.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_param_on_right.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CopyActionTest/copy_nominal.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CopyActionTest/copy_with_parent.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-nominal.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-with-messages.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionTest/create-no-importer.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ExportersActionTest/exporters.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ImportersActionTest/importers.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest/inheritance-buWide.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest/inheritance-simple.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/all.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/all_filtered.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/authorized_selected.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/deselected.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/empty.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_page1.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_page2.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_ps3_page1.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_ps3_page2.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_empty.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_no_login.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_no_param.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_nominal.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page1.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page2.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page3.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_nominal.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_param_on_left.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_param_on_right.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest/copy_nominal.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest/copy_with_parent.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest/create-nominal.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest/create-with-messages.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionTest/create-no-importer.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileExportersActionTest/exporters.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileImportersActionTest/importers.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-buWide.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-simple.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/all.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/all_filtered.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/authorized_selected.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/deselected.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/empty.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_page1.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_page2.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_ps3_page1.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_ps3_page2.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileRestoreActionTest/restore_profile.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search_fields.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search_xoo1.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/RestoreActionTest/restore_profile.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search_fields.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search_xoo1.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/CoveredFilesActionTest/tests-covered-files.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-main-file.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-test-uuid.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsCoveredFilesActionTest/tests-covered-files.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsListActionTest/list-main-file.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsListActionTest/list-test-uuid.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show_from_test_data.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show_from_test_data_with_a_time_in_float.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentActionTest/anonymous.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentActionTest/authenticated.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentUserActionTest/anonymous.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentUserActionTest/authenticated.json [deleted file]

diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalAction.java
new file mode 100644 (file)
index 0000000..84529ca
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.batch;
+
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.batch.protocol.input.GlobalRepositories;
+import org.sonar.core.measure.db.MetricDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.properties.PropertiesDao;
+import org.sonar.core.properties.PropertyDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.plugins.MimeTypes;
+import org.sonar.server.user.UserSession;
+
+public class GlobalAction implements BatchWsAction {
+
+  private final DbClient dbClient;
+  private final PropertiesDao propertiesDao;
+  private final UserSession userSession;
+
+  public GlobalAction(DbClient dbClient, PropertiesDao propertiesDao, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.propertiesDao = propertiesDao;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("global")
+      .setDescription("Return metrics and global properties")
+      .setSince("4.5")
+      .setInternal(true)
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    boolean hasScanPerm = userSession.hasGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
+    boolean hasPreviewPerm = userSession.hasGlobalPermission(GlobalPermissions.PREVIEW_EXECUTION);
+    if (!hasPreviewPerm && !hasScanPerm) {
+      throw new ForbiddenException(Messages.NO_PERMISSION);
+    }
+
+    DbSession session = dbClient.openSession(false);
+    try {
+      GlobalRepositories ref = new GlobalRepositories();
+      addMetrics(ref, session);
+      addSettings(ref, hasScanPerm, hasPreviewPerm, session);
+
+      response.stream().setMediaType(MimeTypes.JSON);
+      IOUtils.write(ref.toJson(), response.stream().output());
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  private void addMetrics(GlobalRepositories ref, DbSession session) {
+    for (MetricDto metric : dbClient.metricDao().selectEnabled(session)) {
+      Boolean optimizedBestValue = metric.isOptimizedBestValue();
+      ref.addMetric(
+        new org.sonar.batch.protocol.input.Metric(metric.getId(), metric.getKey(),
+          metric.getValueType(),
+          metric.getDescription(),
+          metric.getDirection(),
+          metric.getKey(),
+          metric.isQualitative(),
+          metric.isUserManaged(),
+          metric.getWorstValue(),
+          metric.getBestValue(),
+          optimizedBestValue != null ? optimizedBestValue : false));
+    }
+  }
+
+  private void addSettings(GlobalRepositories ref, boolean hasScanPerm, boolean hasPreviewPerm, DbSession session) {
+    for (PropertyDto propertyDto : propertiesDao.selectGlobalProperties(session)) {
+      String key = propertyDto.getKey();
+      String value = propertyDto.getValue();
+
+      if (isPropertyAllowed(key, hasScanPerm, hasPreviewPerm)) {
+        ref.addGlobalSetting(key, value);
+      }
+    }
+  }
+
+  private static boolean isPropertyAllowed(String key, boolean hasScanPerm, boolean hasPreviewPerm) {
+    return !key.contains(".secured") || hasScanPerm || (key.contains(".license") && hasPreviewPerm);
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalRepositoryAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalRepositoryAction.java
deleted file mode 100644 (file)
index 92ca5e9..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.batch;
-
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.batch.protocol.input.GlobalRepositories;
-import org.sonar.core.measure.db.MetricDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.properties.PropertiesDao;
-import org.sonar.core.properties.PropertyDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.plugins.MimeTypes;
-import org.sonar.server.user.UserSession;
-
-public class GlobalRepositoryAction implements BatchWsAction {
-
-  private final DbClient dbClient;
-  private final PropertiesDao propertiesDao;
-  private final UserSession userSession;
-
-  public GlobalRepositoryAction(DbClient dbClient, PropertiesDao propertiesDao, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.propertiesDao = propertiesDao;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("global")
-      .setDescription("Return metrics and global properties")
-      .setSince("4.5")
-      .setInternal(true)
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    boolean hasScanPerm = userSession.hasGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
-    boolean hasPreviewPerm = userSession.hasGlobalPermission(GlobalPermissions.PREVIEW_EXECUTION);
-    if (!hasPreviewPerm && !hasScanPerm) {
-      throw new ForbiddenException(Messages.NO_PERMISSION);
-    }
-
-    DbSession session = dbClient.openSession(false);
-    try {
-      GlobalRepositories ref = new GlobalRepositories();
-      addMetrics(ref, session);
-      addSettings(ref, hasScanPerm, hasPreviewPerm, session);
-
-      response.stream().setMediaType(MimeTypes.JSON);
-      IOUtils.write(ref.toJson(), response.stream().output());
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  private void addMetrics(GlobalRepositories ref, DbSession session) {
-    for (MetricDto metric : dbClient.metricDao().selectEnabled(session)) {
-      Boolean optimizedBestValue = metric.isOptimizedBestValue();
-      ref.addMetric(
-        new org.sonar.batch.protocol.input.Metric(metric.getId(), metric.getKey(),
-          metric.getValueType(),
-          metric.getDescription(),
-          metric.getDirection(),
-          metric.getKey(),
-          metric.isQualitative(),
-          metric.isUserManaged(),
-          metric.getWorstValue(),
-          metric.getBestValue(),
-          optimizedBestValue != null ? optimizedBestValue : false));
-    }
-  }
-
-  private void addSettings(GlobalRepositories ref, boolean hasScanPerm, boolean hasPreviewPerm, DbSession session) {
-    for (PropertyDto propertyDto : propertiesDao.selectGlobalProperties(session)) {
-      String key = propertyDto.getKey();
-      String value = propertyDto.getValue();
-
-      if (isPropertyAllowed(key, hasScanPerm, hasPreviewPerm)) {
-        ref.addGlobalSetting(key, value);
-      }
-    }
-  }
-
-  private static boolean isPropertyAllowed(String key, boolean hasScanPerm, boolean hasPreviewPerm) {
-    return !key.contains(".secured") || hasScanPerm || (key.contains(".license") && hasPreviewPerm);
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectAction.java
new file mode 100644 (file)
index 0000000..77d9833
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.batch;
+
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+import org.sonar.server.plugins.MimeTypes;
+
+public class ProjectAction implements BatchWsAction {
+
+  private static final String PARAM_KEY = "key";
+  private static final String PARAM_PROFILE = "profile";
+  private static final String PARAM_PREVIEW = "preview";
+
+  private final ProjectRepositoryLoader projectReferentialsLoader;
+
+  public ProjectAction(ProjectRepositoryLoader projectReferentialsLoader) {
+    this.projectReferentialsLoader = projectReferentialsLoader;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("project")
+      .setDescription("Return project repository")
+      .setSince("4.5")
+      .setInternal(true)
+      .setHandler(this);
+
+    action
+      .createParam(PARAM_KEY)
+      .setRequired(true)
+      .setDescription("Project or module key")
+      .setExampleValue("org.codehaus.sonar:sonar");
+
+    action
+      .createParam(PARAM_PROFILE)
+      .setDescription("Profile name")
+      .setExampleValue("SonarQube Way");
+
+    action
+      .createParam(PARAM_PREVIEW)
+      .setDescription("Preview mode or not")
+      .setDefaultValue(false)
+      .setBooleanPossibleValues();
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    ProjectRepositories ref = projectReferentialsLoader.load(ProjectRepositoryQuery.create()
+      .setModuleKey(request.mandatoryParam(PARAM_KEY))
+      .setProfileName(request.param(PARAM_PROFILE))
+      .setPreview(request.mandatoryParamAsBoolean(PARAM_PREVIEW)));
+    response.stream().setMediaType(MimeTypes.JSON);
+    IOUtils.write(ref.toJson(), response.stream().output());
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java
deleted file mode 100644 (file)
index 9a1369f..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.batch;
-
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.batch.protocol.input.ProjectRepositories;
-import org.sonar.server.plugins.MimeTypes;
-
-public class ProjectRepositoryAction implements BatchWsAction {
-
-  private static final String PARAM_KEY = "key";
-  private static final String PARAM_PROFILE = "profile";
-  private static final String PARAM_PREVIEW = "preview";
-
-  private final ProjectRepositoryLoader projectReferentialsLoader;
-
-  public ProjectRepositoryAction(ProjectRepositoryLoader projectReferentialsLoader) {
-    this.projectReferentialsLoader = projectReferentialsLoader;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("project")
-      .setDescription("Return project repository")
-      .setSince("4.5")
-      .setInternal(true)
-      .setHandler(this);
-
-    action
-      .createParam(PARAM_KEY)
-      .setRequired(true)
-      .setDescription("Project or module key")
-      .setExampleValue("org.codehaus.sonar:sonar");
-
-    action
-      .createParam(PARAM_PROFILE)
-      .setDescription("Profile name")
-      .setExampleValue("SonarQube Way");
-
-    action
-      .createParam(PARAM_PREVIEW)
-      .setDescription("Preview mode or not")
-      .setDefaultValue(false)
-      .setBooleanPossibleValues();
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    ProjectRepositories ref = projectReferentialsLoader.load(ProjectRepositoryQuery.create()
-      .setModuleKey(request.mandatoryParam(PARAM_KEY))
-      .setProfileName(request.param(PARAM_PROFILE))
-      .setPreview(request.mandatoryParamAsBoolean(PARAM_PREVIEW)));
-    response.stream().setMediaType(MimeTypes.JSON);
-    IOUtils.write(ref.toJson(), response.stream().output());
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/AppAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/AppAction.java
new file mode 100644 (file)
index 0000000..6a09d72
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.component.ws;
+
+import org.apache.commons.lang.BooleanUtils;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.Durations;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.properties.PropertyDto;
+import org.sonar.core.properties.PropertyQuery;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newHashMap;
+
+public class AppAction implements RequestHandler {
+
+  private static final String PARAM_UUID = "uuid";
+  private static final String PARAM_PERIOD = "period";
+  private static final List<String> METRIC_KEYS = newArrayList(CoreMetrics.LINES_KEY, CoreMetrics.VIOLATIONS_KEY,
+    CoreMetrics.COVERAGE_KEY, CoreMetrics.IT_COVERAGE_KEY, CoreMetrics.OVERALL_COVERAGE_KEY,
+    CoreMetrics.DUPLICATED_LINES_DENSITY_KEY, CoreMetrics.TESTS_KEY,
+    CoreMetrics.TECHNICAL_DEBT_KEY, CoreMetrics.SQALE_RATING_KEY, CoreMetrics.SQALE_DEBT_RATIO_KEY);
+
+  private final DbClient dbClient;
+
+  private final Durations durations;
+  private final I18n i18n;
+  private final UserSession userSession;
+
+  public AppAction(DbClient dbClient, Durations durations, I18n i18n, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.durations = durations;
+    this.i18n = i18n;
+    this.userSession = userSession;
+  }
+
+  void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("app")
+      .setDescription("Coverage data required for rendering the component viewer")
+      .setSince("4.4")
+      .setInternal(true)
+      .setHandler(this);
+
+    action
+      .createParam(PARAM_UUID)
+      .setRequired(true)
+      .setDescription("Component UUID")
+      .setExampleValue("d6d9e1e5-5e13-44fa-ab82-3ec29efa8935");
+
+    action
+      .createParam(PARAM_PERIOD)
+      .setDescription("Period index in order to get differential measures")
+      .setPossibleValues(1, 2, 3, 4, 5);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    String componentUuid = request.mandatoryParam(PARAM_UUID);
+
+    JsonWriter json = response.newJsonWriter();
+    json.beginObject();
+
+    DbSession session = dbClient.openSession(false);
+    try {
+      ComponentDto component = dbClient.componentDao().selectNullableByUuid(session, componentUuid);
+      if (component == null) {
+        throw new NotFoundException(String.format("Component '%s' does not exist", componentUuid));
+      }
+      userSession.checkComponentPermission(UserRole.USER, component.getKey());
+
+      Map<String, MeasureDto> measuresByMetricKey = measuresByMetricKey(component, session);
+      appendComponent(json, component, userSession, session);
+      appendPermissions(json, component, userSession);
+      appendMeasures(json, measuresByMetricKey);
+
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+
+    json.endObject();
+    json.close();
+  }
+
+  private void appendComponent(JsonWriter json, ComponentDto component, UserSession userSession, DbSession session) {
+    List<PropertyDto> propertyDtos = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
+      .setKey("favourite")
+      .setComponentId(component.getId())
+      .setUserId(userSession.getUserId())
+      .build(),
+      session
+      );
+    boolean isFavourite = propertyDtos.size() == 1;
+
+    json.prop("key", component.key());
+    json.prop("uuid", component.uuid());
+    json.prop("path", component.path());
+    json.prop("name", component.name());
+    json.prop("longName", component.longName());
+    json.prop("q", component.qualifier());
+
+    ComponentDto parentProject = nullableComponentById(component.parentProjectId(), session);
+    ComponentDto project = dbClient.componentDao().selectByUuid(session, component.projectUuid());
+
+    // Do not display parent project if parent project and project are the same
+    boolean displayParentProject = parentProject != null && !parentProject.getId().equals(project.getId());
+    json.prop("subProject", displayParentProject ? parentProject.key() : null);
+    json.prop("subProjectName", displayParentProject ? parentProject.longName() : null);
+    json.prop("project", project.key());
+    json.prop("projectName", project.longName());
+
+    json.prop("fav", isFavourite);
+  }
+
+  private void appendPermissions(JsonWriter json, ComponentDto component, UserSession userSession) {
+    boolean hasBrowsePermission = userSession.hasComponentPermission(UserRole.USER, component.key());
+    json.prop("canMarkAsFavourite", userSession.isLoggedIn() && hasBrowsePermission);
+    json.prop("canCreateManualIssue", userSession.isLoggedIn() && hasBrowsePermission);
+  }
+
+  private void appendMeasures(JsonWriter json, Map<String, MeasureDto> measuresByMetricKey) {
+    json.name("measures").beginObject();
+    json.prop("lines", formatMeasure(measuresByMetricKey.get(CoreMetrics.LINES_KEY)));
+    json.prop("coverage", formatMeasure(coverageMeasure(measuresByMetricKey)));
+    json.prop("duplicationDensity", formatMeasure(measuresByMetricKey.get(CoreMetrics.DUPLICATED_LINES_DENSITY_KEY)));
+    json.prop("issues", formatMeasure(measuresByMetricKey.get(CoreMetrics.VIOLATIONS_KEY)));
+    json.prop("tests", formatMeasure(measuresByMetricKey.get(CoreMetrics.TESTS_KEY)));
+    json.prop("debt", formatMeasure(measuresByMetricKey.get(CoreMetrics.TECHNICAL_DEBT_KEY)));
+    json.prop("sqaleRating", formatMeasure(measuresByMetricKey.get(CoreMetrics.SQALE_RATING_KEY)));
+    json.prop("debtRatio", formatMeasure(measuresByMetricKey.get(CoreMetrics.SQALE_DEBT_RATIO_KEY)));
+    json.endObject();
+  }
+
+  private MeasureDto coverageMeasure(Map<String, MeasureDto> measuresByMetricKey) {
+    MeasureDto overallCoverage = measuresByMetricKey.get(CoreMetrics.OVERALL_COVERAGE_KEY);
+    MeasureDto itCoverage = measuresByMetricKey.get(CoreMetrics.IT_COVERAGE_KEY);
+    MeasureDto utCoverage = measuresByMetricKey.get(CoreMetrics.COVERAGE_KEY);
+    if (overallCoverage != null) {
+      return overallCoverage;
+    } else if (utCoverage != null) {
+      return utCoverage;
+    } else {
+      return itCoverage;
+    }
+  }
+
+  private Map<String, MeasureDto> measuresByMetricKey(ComponentDto component, DbSession session) {
+    Map<String, MeasureDto> measuresByMetricKey = newHashMap();
+    String fileKey = component.getKey();
+    for (MeasureDto measureDto : dbClient.measureDao().findByComponentKeyAndMetricKeys(session, fileKey, METRIC_KEYS)) {
+      measuresByMetricKey.put(measureDto.getMetricKey(), measureDto);
+    }
+    return measuresByMetricKey;
+  }
+
+  @CheckForNull
+  private ComponentDto nullableComponentById(@Nullable Long componentId, DbSession session) {
+    if (componentId != null) {
+      return dbClient.componentDao().selectById(componentId, session);
+    }
+    return null;
+  }
+
+  @CheckForNull
+  private String formatMeasure(@Nullable MeasureDto measure) {
+    if (measure == null) {
+      return null;
+    }
+
+    Metric metric = CoreMetrics.getMetric(measure.getMetricKey());
+    Metric.ValueType metricType = metric.getType();
+    Double value = measure.getValue();
+    String data = measure.getData();
+    if (BooleanUtils.isTrue(metric.isOptimizedBestValue()) && value == null) {
+      value = metric.getBestValue();
+    }
+    if (metricType.equals(Metric.ValueType.FLOAT) && value != null) {
+      return i18n.formatDouble(userSession.locale(), value);
+    }
+    if (metricType.equals(Metric.ValueType.INT) && value != null) {
+      return i18n.formatInteger(userSession.locale(), value.intValue());
+    }
+    if (metricType.equals(Metric.ValueType.PERCENT) && value != null) {
+      return i18n.formatDouble(userSession.locale(), value) + "%";
+    }
+    if (metricType.equals(Metric.ValueType.WORK_DUR) && value != null) {
+      return durations.format(userSession.locale(), durations.create(value.longValue()), Durations.DurationFormat.SHORT);
+    }
+    if ((metricType.equals(Metric.ValueType.STRING) || metricType.equals(Metric.ValueType.RATING)) && data != null) {
+      return data;
+    }
+    return null;
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java
deleted file mode 100644 (file)
index 85c835d..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import java.util.List;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.BooleanUtils;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.Durations;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.measure.db.MeasureDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.properties.PropertyDto;
-import org.sonar.core.properties.PropertyQuery;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.user.UserSession;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-
-public class ComponentAppAction implements RequestHandler {
-
-  private static final String PARAM_UUID = "uuid";
-  private static final String PARAM_PERIOD = "period";
-  private static final List<String> METRIC_KEYS = newArrayList(CoreMetrics.LINES_KEY, CoreMetrics.VIOLATIONS_KEY,
-    CoreMetrics.COVERAGE_KEY, CoreMetrics.IT_COVERAGE_KEY, CoreMetrics.OVERALL_COVERAGE_KEY,
-    CoreMetrics.DUPLICATED_LINES_DENSITY_KEY, CoreMetrics.TESTS_KEY,
-    CoreMetrics.TECHNICAL_DEBT_KEY, CoreMetrics.SQALE_RATING_KEY, CoreMetrics.SQALE_DEBT_RATIO_KEY);
-
-  private final DbClient dbClient;
-
-  private final Durations durations;
-  private final I18n i18n;
-  private final UserSession userSession;
-
-  public ComponentAppAction(DbClient dbClient, Durations durations, I18n i18n, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.durations = durations;
-    this.i18n = i18n;
-    this.userSession = userSession;
-  }
-
-  void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("app")
-      .setDescription("Coverage data required for rendering the component viewer")
-      .setSince("4.4")
-      .setInternal(true)
-      .setHandler(this);
-
-    action
-      .createParam(PARAM_UUID)
-      .setRequired(true)
-      .setDescription("Component UUID")
-      .setExampleValue("d6d9e1e5-5e13-44fa-ab82-3ec29efa8935");
-
-    action
-      .createParam(PARAM_PERIOD)
-      .setDescription("Period index in order to get differential measures")
-      .setPossibleValues(1, 2, 3, 4, 5);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    String componentUuid = request.mandatoryParam(PARAM_UUID);
-
-    JsonWriter json = response.newJsonWriter();
-    json.beginObject();
-
-    DbSession session = dbClient.openSession(false);
-    try {
-      ComponentDto component = dbClient.componentDao().selectNullableByUuid(session, componentUuid);
-      if (component == null) {
-        throw new NotFoundException(String.format("Component '%s' does not exist", componentUuid));
-      }
-      userSession.checkComponentPermission(UserRole.USER, component.getKey());
-
-      Map<String, MeasureDto> measuresByMetricKey = measuresByMetricKey(component, session);
-      appendComponent(json, component, userSession, session);
-      appendPermissions(json, component, userSession);
-      appendMeasures(json, measuresByMetricKey);
-
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-
-    json.endObject();
-    json.close();
-  }
-
-  private void appendComponent(JsonWriter json, ComponentDto component, UserSession userSession, DbSession session) {
-    List<PropertyDto> propertyDtos = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
-      .setKey("favourite")
-      .setComponentId(component.getId())
-      .setUserId(userSession.getUserId())
-      .build(),
-      session
-      );
-    boolean isFavourite = propertyDtos.size() == 1;
-
-    json.prop("key", component.key());
-    json.prop("uuid", component.uuid());
-    json.prop("path", component.path());
-    json.prop("name", component.name());
-    json.prop("longName", component.longName());
-    json.prop("q", component.qualifier());
-
-    ComponentDto parentProject = nullableComponentById(component.parentProjectId(), session);
-    ComponentDto project = dbClient.componentDao().selectByUuid(session, component.projectUuid());
-
-    // Do not display parent project if parent project and project are the same
-    boolean displayParentProject = parentProject != null && !parentProject.getId().equals(project.getId());
-    json.prop("subProject", displayParentProject ? parentProject.key() : null);
-    json.prop("subProjectName", displayParentProject ? parentProject.longName() : null);
-    json.prop("project", project.key());
-    json.prop("projectName", project.longName());
-
-    json.prop("fav", isFavourite);
-  }
-
-  private void appendPermissions(JsonWriter json, ComponentDto component, UserSession userSession) {
-    boolean hasBrowsePermission = userSession.hasComponentPermission(UserRole.USER, component.key());
-    json.prop("canMarkAsFavourite", userSession.isLoggedIn() && hasBrowsePermission);
-    json.prop("canCreateManualIssue", userSession.isLoggedIn() && hasBrowsePermission);
-  }
-
-  private void appendMeasures(JsonWriter json, Map<String, MeasureDto> measuresByMetricKey) {
-    json.name("measures").beginObject();
-    json.prop("lines", formatMeasure(measuresByMetricKey.get(CoreMetrics.LINES_KEY)));
-    json.prop("coverage", formatMeasure(coverageMeasure(measuresByMetricKey)));
-    json.prop("duplicationDensity", formatMeasure(measuresByMetricKey.get(CoreMetrics.DUPLICATED_LINES_DENSITY_KEY)));
-    json.prop("issues", formatMeasure(measuresByMetricKey.get(CoreMetrics.VIOLATIONS_KEY)));
-    json.prop("tests", formatMeasure(measuresByMetricKey.get(CoreMetrics.TESTS_KEY)));
-    json.prop("debt", formatMeasure(measuresByMetricKey.get(CoreMetrics.TECHNICAL_DEBT_KEY)));
-    json.prop("sqaleRating", formatMeasure(measuresByMetricKey.get(CoreMetrics.SQALE_RATING_KEY)));
-    json.prop("debtRatio", formatMeasure(measuresByMetricKey.get(CoreMetrics.SQALE_DEBT_RATIO_KEY)));
-    json.endObject();
-  }
-
-  private MeasureDto coverageMeasure(Map<String, MeasureDto> measuresByMetricKey) {
-    MeasureDto overallCoverage = measuresByMetricKey.get(CoreMetrics.OVERALL_COVERAGE_KEY);
-    MeasureDto itCoverage = measuresByMetricKey.get(CoreMetrics.IT_COVERAGE_KEY);
-    MeasureDto utCoverage = measuresByMetricKey.get(CoreMetrics.COVERAGE_KEY);
-    if (overallCoverage != null) {
-      return overallCoverage;
-    } else if (utCoverage != null) {
-      return utCoverage;
-    } else {
-      return itCoverage;
-    }
-  }
-
-  private Map<String, MeasureDto> measuresByMetricKey(ComponentDto component, DbSession session) {
-    Map<String, MeasureDto> measuresByMetricKey = newHashMap();
-    String fileKey = component.getKey();
-    for (MeasureDto measureDto : dbClient.measureDao().findByComponentKeyAndMetricKeys(session, fileKey, METRIC_KEYS)) {
-      measuresByMetricKey.put(measureDto.getMetricKey(), measureDto);
-    }
-    return measuresByMetricKey;
-  }
-
-  @CheckForNull
-  private ComponentDto nullableComponentById(@Nullable Long componentId, DbSession session) {
-    if (componentId != null) {
-      return dbClient.componentDao().selectById(componentId, session);
-    }
-    return null;
-  }
-
-  @CheckForNull
-  private String formatMeasure(@Nullable MeasureDto measure) {
-    if (measure == null) {
-      return null;
-    }
-
-    Metric metric = CoreMetrics.getMetric(measure.getMetricKey());
-    Metric.ValueType metricType = metric.getType();
-    Double value = measure.getValue();
-    String data = measure.getData();
-    if (BooleanUtils.isTrue(metric.isOptimizedBestValue()) && value == null) {
-      value = metric.getBestValue();
-    }
-    if (metricType.equals(Metric.ValueType.FLOAT) && value != null) {
-      return i18n.formatDouble(userSession.locale(), value);
-    }
-    if (metricType.equals(Metric.ValueType.INT) && value != null) {
-      return i18n.formatInteger(userSession.locale(), value.intValue());
-    }
-    if (metricType.equals(Metric.ValueType.PERCENT) && value != null) {
-      return i18n.formatDouble(userSession.locale(), value) + "%";
-    }
-    if (metricType.equals(Metric.ValueType.WORK_DUR) && value != null) {
-      return durations.format(userSession.locale(), durations.create(value.longValue()), Durations.DurationFormat.SHORT);
-    }
-    if ((metricType.equals(Metric.ValueType.STRING) || metricType.equals(Metric.ValueType.RATING)) && data != null) {
-      return data;
-    }
-    return null;
-  }
-}
index 94cadaa25f7e0cd68d49fc9cb6c23bcc74676397..aba52c5b1bb278b1dfa741e5c9a76180beca49af 100644 (file)
@@ -26,10 +26,10 @@ import org.sonar.api.server.ws.WebService;
 
 public class ComponentsWs implements WebService {
 
-  private final ComponentAppAction appAction;
+  private final AppAction appAction;
   private final SearchAction searchAction;
 
-  public ComponentsWs(ComponentAppAction appAction, SearchAction searchAction) {
+  public ComponentsWs(AppAction appAction, SearchAction searchAction) {
     this.appAction = appAction;
     this.searchAction = searchAction;
   }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsDeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsDeleteAction.java
deleted file mode 100644 (file)
index 179a24d..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.component.ComponentCleanerService;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.user.UserSession;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-
-public class ProjectsDeleteAction implements ProjectsWsAction {
-  private static final String ACTION = "delete";
-  private static final String PARAM_UUIDS = "uuids";
-  private static final String PARAM_KEYS = "keys";
-
-  private final ComponentCleanerService componentCleanerService;
-  private final DbClient dbClient;
-  private final UserSession userSession;
-
-  public ProjectsDeleteAction(ComponentCleanerService componentCleanerService, DbClient dbClient, UserSession userSession) {
-    this.componentCleanerService = componentCleanerService;
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context
-      .createAction(ACTION)
-      .setDescription("Delete one or several projects.<br /> Requires Admin permission.")
-      .setSince("5.2")
-      .setHandler(this);
-
-    action
-      .createParam(PARAM_UUIDS)
-      .setDescription("List of project UUIDs to delete")
-      .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d,c526ef20-131b-4486-9357-063fa64b5079");
-
-    action
-      .createParam(PARAM_KEYS)
-      .setDescription("List of project keys to delete")
-      .setExampleValue("org.apache.hbas:hbase,com.microsoft.roslyn:roslyn");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkGlobalPermission(UserRole.ADMIN);
-    List<String> uuids = request.paramAsStrings(PARAM_UUIDS);
-    List<String> keys = request.paramAsStrings(PARAM_KEYS);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      List<ComponentDto> projects = searchProjects(dbSession, uuids, keys);
-      componentCleanerService.delete(dbSession, projects);
-    } finally {
-      MyBatis.closeQuietly(dbSession);
-    }
-
-    response.noContent();
-  }
-
-  private List<ComponentDto> searchProjects(DbSession dbSession, @Nullable List<String> uuids, @Nullable List<String> keys) {
-    if (uuids != null) {
-      return dbClient.componentDao().selectByUuids(dbSession, uuids);
-    }
-    if (keys != null) {
-      return dbClient.componentDao().selectByKeys(dbSession, keys);
-    }
-
-    throw new IllegalArgumentException("UUIDs or keys must be provided");
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsGhostsAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsGhostsAction.java
deleted file mode 100644 (file)
index d230af2..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.user.UserSession;
-
-import javax.annotation.Nullable;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
-import static com.google.common.collect.Sets.newHashSet;
-
-public class ProjectsGhostsAction implements ProjectsWsAction {
-  public static final String ACTION = "ghosts";
-  private static final Set<String> POSSIBLE_FIELDS = newHashSet("uuid", "key", "name", "creationDate");
-
-  private final DbClient dbClient;
-  private final UserSession userSession;
-
-  public ProjectsGhostsAction(DbClient dbClient, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    context
-      .createAction(ACTION)
-      .setDescription("List ghost projects.<br /> Requires 'Administer System' permission.")
-      .setResponseExample(Resources.getResource(getClass(), "projects-example-ghosts.json"))
-      .setSince("5.2")
-      .addPagingParams(100)
-      .addFieldsParam(POSSIBLE_FIELDS)
-      .addSearchQuery("sonar", "names", "keys")
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkGlobalPermission(UserRole.ADMIN);
-    DbSession dbSession = dbClient.openSession(false);
-    SearchOptions searchOptions = new SearchOptions()
-      .setPage(request.mandatoryParamAsInt(Param.PAGE),
-        request.mandatoryParamAsInt(Param.PAGE_SIZE));
-    Set<String> desiredFields = fieldsToReturn(request.paramAsStrings(Param.FIELDS));
-    String query = request.param(Param.TEXT_QUERY);
-
-    try {
-      long nbOfProjects = dbClient.componentDao().countGhostProjects(dbSession, query);
-      List<ComponentDto> projects = dbClient.componentDao().selectGhostProjects(dbSession, query, searchOptions);
-      JsonWriter json = response.newJsonWriter().beginObject();
-      writeProjects(json, projects, desiredFields);
-      searchOptions.writeJson(json, nbOfProjects);
-      json.endObject().close();
-    } finally {
-      MyBatis.closeQuietly(dbSession);
-    }
-  }
-
-  private void writeProjects(JsonWriter json, List<ComponentDto> projects, Set<String> fieldsToReturn) {
-    json.name("projects");
-    json.beginArray();
-    for (ComponentDto project : projects) {
-      json.beginObject();
-      json.prop("uuid", project.uuid());
-      writeIfWished(json, "key", project.key(), fieldsToReturn);
-      writeIfWished(json, "name", project.name(), fieldsToReturn);
-      writeIfWished(json, "creationDate", project.getCreatedAt(), fieldsToReturn);
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-  private void writeIfWished(JsonWriter json, String key, String value, Set<String> fieldsToReturn) {
-    if (fieldsToReturn.contains(key)) {
-      json.prop(key, value);
-    }
-  }
-
-  private void writeIfWished(JsonWriter json, String key, Date value, Set<String> desiredFields) {
-    if (desiredFields.contains(key)) {
-      json.propDateTime(key, value);
-    }
-  }
-
-  private Set<String> fieldsToReturn(@Nullable List<String> desiredFieldsFromRequest) {
-    if (desiredFieldsFromRequest == null) {
-      return POSSIBLE_FIELDS;
-    }
-
-    return newHashSet(desiredFieldsFromRequest);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsProvisionedAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsProvisionedAction.java
deleted file mode 100644 (file)
index 90d2b8c..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.user.UserSession;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
-import static com.google.common.collect.Sets.newHashSet;
-
-public class ProjectsProvisionedAction implements ProjectsWsAction {
-  private static final Set<String> POSSIBLE_FIELDS = newHashSet("uuid", "key", "name", "creationDate");
-
-  private final DbClient dbClient;
-  private final UserSession userSession;
-
-  public ProjectsProvisionedAction(DbClient dbClient, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller
-      .createAction("provisioned")
-      .setDescription(
-        "Get the list of provisioned projects.<br /> " +
-          "Require 'Provision Projects' permission.")
-      .setSince("5.2")
-      .setResponseExample(Resources.getResource(getClass(), "projects-example-provisioned.json"))
-      .setHandler(this)
-      .addPagingParams(100)
-      .addSearchQuery("sonar", "names", "keys")
-      .addFieldsParam(POSSIBLE_FIELDS);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkGlobalPermission(GlobalPermissions.PROVISIONING);
-    SearchOptions options = new SearchOptions().setPage(
-      request.mandatoryParamAsInt(Param.PAGE),
-      request.mandatoryParamAsInt(Param.PAGE_SIZE)
-      );
-    Set<String> desiredFields = desiredFields(request);
-    String query = request.param(Param.TEXT_QUERY);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      List<ComponentDto> projects = dbClient.componentDao().selectProvisionedProjects(dbSession, options, query);
-      int nbOfProjects = dbClient.componentDao().countProvisionedProjects(dbSession, query);
-      JsonWriter json = response.newJsonWriter().beginObject();
-      writeProjects(projects, json, desiredFields);
-      options.writeJson(json, nbOfProjects);
-      json.endObject().close();
-    } finally {
-      MyBatis.closeQuietly(dbSession);
-    }
-  }
-
-  private void writeProjects(List<ComponentDto> projects, JsonWriter json, Set<String> desiredFields) {
-    json.name("projects");
-    json.beginArray();
-    for (ComponentDto project : projects) {
-      json.beginObject();
-      json.prop("uuid", project.uuid());
-      writeIfNeeded(json, "key", project.key(), desiredFields);
-      writeIfNeeded(json, "name", project.name(), desiredFields);
-      writeIfNeeded(json, "creationDate", project.getCreatedAt(), desiredFields);
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-  private void writeIfNeeded(JsonWriter json, String fieldName, String value, Set<String> desiredFields) {
-    if (desiredFields.contains(fieldName)) {
-      json.prop(fieldName, value);
-    }
-  }
-
-  private void writeIfNeeded(JsonWriter json, String fieldName, Date date, Set<String> desiredFields) {
-    if (desiredFields.contains(fieldName)) {
-      json.propDateTime(fieldName, date);
-    }
-  }
-
-  private Set<String> desiredFields(Request request) {
-    List<String> desiredFields = request.paramAsStrings(Param.FIELDS);
-    if (desiredFields == null) {
-      return POSSIBLE_FIELDS;
-    }
-
-    return newHashSet(desiredFields);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWs.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWs.java
deleted file mode 100644 (file)
index 4b6e9e1..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.RailsHandler;
-import org.sonar.api.server.ws.WebService;
-
-public class ProjectsWs implements WebService {
-  private static final String ENDPOINT = "api/projects";
-
-  private final ProjectsWsAction[] actions;
-
-  public ProjectsWs(ProjectsWsAction... actions) {
-    this.actions = actions;
-  }
-
-  @Override
-  public void define(Context context) {
-    NewController controller = context.createController(ENDPOINT)
-      .setSince("2.10")
-      .setDescription("Projects management");
-
-    defineIndexAction(controller);
-    defineCreateAction(controller);
-    defineDestroyAction(controller);
-
-    for (ProjectsWsAction action : actions) {
-      action.define(controller);
-    }
-
-    controller.done();
-  }
-
-  private void defineIndexAction(NewController controller) {
-    WebService.NewAction action = controller.createAction("index")
-      .setDescription("Search for projects")
-      .setSince("2.10")
-      .setHandler(RailsHandler.INSTANCE)
-      .setResponseExample(Resources.getResource(this.getClass(), "projects-example-index.json"));
-
-    action.createParam("key")
-      .setDescription("id or key of the project")
-      .setExampleValue("org.codehaus.sonar:sonar");
-
-    action.createParam("search")
-      .setDescription("Substring of project name, case insensitive")
-      .setExampleValue("Sonar");
-
-    action.createParam("desc")
-      .setDescription("Load project description")
-      .setDefaultValue("true")
-      .setPossibleValues("true", "false");
-
-    action.createParam("subprojects")
-      .setDescription("Load sub-projects. Ignored if the parameter key is set")
-      .setDefaultValue("false")
-      .setPossibleValues("true", "false");
-
-    action.createParam("views")
-      .setDescription("Load views and sub-views. Ignored if the parameter key is set")
-      .setDefaultValue("false")
-      .setPossibleValues("true", "false");
-
-    action.createParam("libs")
-      .setDescription("Load libraries. Ignored if the parameter key is set")
-      .setDefaultValue("false")
-      .setPossibleValues("true", "false");
-
-    action.createParam("versions")
-      .setDescription("Load version")
-      .setDefaultValue("false")
-      .setPossibleValues("true", "false", "last");
-
-    RailsHandler.addFormatParam(action);
-  }
-
-  private void defineCreateAction(NewController controller) {
-    WebService.NewAction action = controller.createAction("create")
-      .setDescription("Provision a project. Requires Provision Projects permission")
-      .setSince("4.0")
-      .setPost(true)
-      .setHandler(RailsHandler.INSTANCE)
-      .setResponseExample(Resources.getResource(this.getClass(), "projects-example-create.json"));
-
-    action.createParam("key")
-      .setDescription("Key of the project")
-      .setRequired(true)
-      .setExampleValue("org.codehaus.sonar:sonar");
-
-    action.createParam("name")
-      .setDescription("Name of the project")
-      .setRequired(true)
-      .setExampleValue("SonarQube");
-
-    action.createParam("branch")
-      .setDescription("SCM Branch of the project. The key of the project will become key:branch, for instance 'SonarQube:branch-5.0'")
-      .setRequired(false)
-      .setExampleValue("branch-5.0");
-
-    RailsHandler.addFormatParam(action);
-  }
-
-  private void defineDestroyAction(NewController controller) {
-    WebService.NewAction action = controller.createAction("destroy")
-      .setDescription("Delete a project. Requires Administer System permission")
-      .setSince("2.11")
-      .setPost(true)
-      .setHandler(RailsHandler.INSTANCE);
-
-    action.createParam("id")
-      .setDescription("id or key of the resource (ie: component)")
-      .setRequired(true)
-      .setExampleValue("org.codehaus.sonar:sonar");
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWsAction.java
deleted file mode 100644 (file)
index 6423e0c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import org.sonar.server.ws.WsAction;
-
-public interface ProjectsWsAction extends WsAction {
-  // marker interface
-}
index a4a9dd772c1182d96c9024d4e0e1e4659ed1b1a8..10ea28e79a9e0ba8b7d24347cf4de4446cd63154 100644 (file)
 package org.sonar.server.computation.ws;
 
 import org.sonar.api.server.ws.WebService;
+import org.sonar.server.ws.WsAction;
 
 /**
  * Used by {@link ComputationWs} to
  * loop over all its actions
  */
-interface ComputationWsAction {
+interface ComputationWsAction extends WsAction{
   void define(WebService.NewController controller);
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryAction.java
new file mode 100644 (file)
index 0000000..0320fcd
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.activity.Activity;
+import org.sonar.server.activity.index.ActivityDoc;
+import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.activity.index.ActivityQuery;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.es.SearchResult;
+import org.sonar.server.issue.ws.IssuesWs;
+import org.sonar.server.user.UserSession;
+
+import java.util.Arrays;
+import java.util.Map;
+
+// FIXME replace by api/activities/search
+public class HistoryAction implements ComputationWsAction {
+  private final ActivityIndex activityIndex;
+  private final UserSession userSession;
+
+  public HistoryAction(ActivityIndex activityIndex, UserSession userSession) {
+    this.activityIndex = activityIndex;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller
+      .createAction("history")
+      .setDescription("Past integrations of analysis reports")
+      .setSince("5.0")
+      .setInternal(true)
+      .setHandler(this);
+
+    action.addPagingParams(10);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+
+    ActivityQuery query = new ActivityQuery();
+    query.setTypes(Arrays.asList(Activity.Type.ANALYSIS_REPORT.name()));
+
+    SearchOptions options = new SearchOptions();
+    options.setPage(request.mandatoryParamAsInt(IssuesWs.Param.PAGE), request.mandatoryParamAsInt(IssuesWs.Param.PAGE_SIZE));
+    SearchResult<ActivityDoc> results = activityIndex.search(query, options);
+
+    JsonWriter json = response.newJsonWriter().beginObject();
+    options.writeJson(json, results.getTotal());
+    writeReports(results, json);
+    json.endObject().close();
+  }
+
+  private void writeReports(SearchResult<ActivityDoc> result, JsonWriter json) {
+    json.name("reports").beginArray();
+    for (ActivityDoc doc : result.getDocs()) {
+      json.beginObject();
+      for (Map.Entry<String, String> detail : doc.getDetails().entrySet()) {
+        json.prop(detail.getKey(), detail.getValue());
+      }
+      json.endObject();
+    }
+    json.endArray();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryWsAction.java
deleted file mode 100644 (file)
index 0bb4d2b..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import java.util.Arrays;
-import java.util.Map;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.index.ActivityDoc;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.activity.index.ActivityQuery;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.es.SearchResult;
-import org.sonar.server.issue.ws.IssuesWs;
-import org.sonar.server.user.UserSession;
-
-// FIXME replace by api/activities/search
-public class HistoryWsAction implements ComputationWsAction, RequestHandler {
-
-  public static final String PARAM_TYPE = "type";
-
-  private final ActivityIndex activityIndex;
-  private final UserSession userSession;
-
-  public HistoryWsAction(ActivityIndex activityIndex, UserSession userSession) {
-    this.activityIndex = activityIndex;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller
-      .createAction("history")
-      .setDescription("Past integrations of analysis reports")
-      .setSince("5.0")
-      .setInternal(true)
-      .setHandler(this);
-
-    action.addPagingParams(10);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
-
-    ActivityQuery query = new ActivityQuery();
-    query.setTypes(Arrays.asList(Activity.Type.ANALYSIS_REPORT.name()));
-
-    SearchOptions options = new SearchOptions();
-    options.setPage(request.mandatoryParamAsInt(IssuesWs.Param.PAGE), request.mandatoryParamAsInt(IssuesWs.Param.PAGE_SIZE));
-    SearchResult<ActivityDoc> results = activityIndex.search(query, options);
-
-    JsonWriter json = response.newJsonWriter().beginObject();
-    options.writeJson(json, results.getTotal());
-    writeReports(results, json);
-    json.endObject().close();
-  }
-
-  private void writeReports(SearchResult<ActivityDoc> result, JsonWriter json) {
-    json.name("reports").beginArray();
-    for (ActivityDoc doc : result.getDocs()) {
-      json.beginObject();
-      for (Map.Entry<String, String> detail : doc.getDetails().entrySet()) {
-        json.prop(detail.getKey(), detail.getValue());
-      }
-      json.endObject();
-    }
-    json.endArray();
-  }
-}
index d9c83b0fff1d250552f9288017fb210c340a1857..ab580c50a983164d50ba6149ed5d1217d888cd3f 100644 (file)
@@ -36,10 +36,10 @@ import java.util.List;
 public class IsQueueEmptyWs implements WebService {
   public static final String API_ENDPOINT = "api/analysis_reports";
 
-  private final IsQueueEmptyWsAction action;
+  private final IsQueueEmptyAction action;
 
   public IsQueueEmptyWs(ReportQueue queue) {
-    this.action = new IsQueueEmptyWsAction(queue);
+    this.action = new IsQueueEmptyAction(queue);
   }
 
   @Override
@@ -51,10 +51,10 @@ public class IsQueueEmptyWs implements WebService {
     controller.done();
   }
 
-  static class IsQueueEmptyWsAction implements RequestHandler {
+  static class IsQueueEmptyAction implements RequestHandler {
     private final ReportQueue queue;
 
-    public IsQueueEmptyWsAction(ReportQueue queue) {
+    public IsQueueEmptyAction(ReportQueue queue) {
       this.queue = queue;
     }
 
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueAction.java
new file mode 100644 (file)
index 0000000..fd20ecf
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.server.computation.ReportQueue;
+
+import java.util.List;
+
+import static org.sonar.api.utils.DateUtils.longToDate;
+
+/**
+ * @since 5.0
+ */
+public class QueueAction implements ComputationWsAction {
+  private final ReportQueue queue;
+
+  public QueueAction(ReportQueue queue) {
+    this.queue = queue;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller
+      .createAction("queue")
+      .setDescription("List all the active analysis reports")
+      .setSince("5.0")
+      .setInternal(true)
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    List<AnalysisReportDto> reports = queue.all();
+
+    JsonWriter json = response.newJsonWriter().beginObject();
+    writeReports(reports, json);
+    json.endObject();
+    json.close();
+  }
+
+  private void writeReports(List<AnalysisReportDto> reports, JsonWriter json) {
+    json.name("reports").beginArray();
+    for (AnalysisReportDto report : reports) {
+      json.beginObject();
+      json.prop("key", report.getId());
+      json.prop("projectKey", report.getProjectKey());
+      json.prop("projectName", report.getProjectKey());
+      json.propDateTime("startedAt", longToDate(report.getStartedAt()));
+      json.propDateTime("finishedAt", longToDate(report.getFinishedAt()));
+      json.propDateTime("submittedAt", longToDate(report.getCreatedAt()));
+      json.prop("status", report.getStatus().toString());
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueWsAction.java
deleted file mode 100644 (file)
index 39e6d3d..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.ReportQueue;
-
-import java.util.List;
-
-import static org.sonar.api.utils.DateUtils.longToDate;
-
-/**
- * @since 5.0
- */
-public class QueueWsAction implements ComputationWsAction, RequestHandler {
-  private final ReportQueue queue;
-
-  public QueueWsAction(ReportQueue queue) {
-    this.queue = queue;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller
-      .createAction("queue")
-      .setDescription("List all the active analysis reports")
-      .setSince("5.0")
-      .setInternal(true)
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    List<AnalysisReportDto> reports = queue.all();
-
-    JsonWriter json = response.newJsonWriter().beginObject();
-    writeReports(reports, json);
-    json.endObject();
-    json.close();
-  }
-
-  private void writeReports(List<AnalysisReportDto> reports, JsonWriter json) {
-    json.name("reports").beginArray();
-    for (AnalysisReportDto report : reports) {
-      json.beginObject();
-      json.prop("key", report.getId());
-      json.prop("projectKey", report.getProjectKey());
-      json.prop("projectName", report.getProjectKey());
-      json.propDateTime("startedAt", longToDate(report.getStartedAt()));
-      json.propDateTime("finishedAt", longToDate(report.getFinishedAt()));
-      json.propDateTime("submittedAt", longToDate(report.getCreatedAt()));
-      json.prop("status", report.getStatus().toString());
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportAction.java
new file mode 100644 (file)
index 0000000..86f290b
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.ws;
+
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.computation.ComputationThreadLauncher;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.user.UserSession;
+
+import java.io.InputStream;
+
+public class SubmitReportAction implements ComputationWsAction {
+
+  public static final String ACTION = "submit_report";
+  public static final String PARAM_PROJECT_KEY = "projectKey";
+  public static final String PARAM_REPORT_DATA = "report";
+
+  private final ReportQueue queue;
+  private final ComputationThreadLauncher workerLauncher;
+  private final UserSession userSession;
+
+  public SubmitReportAction(ReportQueue queue, ComputationThreadLauncher workerLauncher, UserSession userSession) {
+    this.queue = queue;
+    this.workerLauncher = workerLauncher;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction(ACTION)
+      .setDescription("Submit an analysis report to the queue. Report is integrated asynchronously.")
+      .setPost(true)
+      .setInternal(true)
+      .setHandler(this);
+
+    action
+      .createParam(PARAM_PROJECT_KEY)
+      .setRequired(true)
+      .setDescription("Project key")
+      .setExampleValue("org.codehaus.sonar:sonar");
+
+    action
+      .createParam(PARAM_REPORT_DATA)
+      .setRequired(true)
+      .setDescription("Report file. Format is not an API, it changes among SonarQube versions.");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
+    String projectKey = request.mandatoryParam(PARAM_PROJECT_KEY);
+    InputStream reportData = request.paramAsInputStream(PARAM_REPORT_DATA);
+    try {
+      ReportQueue.Item item = queue.add(projectKey, reportData);
+      workerLauncher.startAnalysisTaskNow();
+      response.newJsonWriter()
+        .beginObject()
+        // do not write integer for forward-compatibility, for example
+        // if we want to write UUID later
+        .prop("key", String.valueOf(item.dto.getId()))
+        .endObject()
+        .close();
+    } finally {
+      IOUtils.closeQuietly(reportData);
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportWsAction.java
deleted file mode 100644 (file)
index 2c1347e..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import java.io.InputStream;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.computation.ComputationThreadLauncher;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.user.UserSession;
-
-public class SubmitReportWsAction implements ComputationWsAction, RequestHandler {
-
-  public static final String ACTION = "submit_report";
-  public static final String PARAM_PROJECT_KEY = "projectKey";
-  public static final String PARAM_REPORT_DATA = "report";
-
-  private final ReportQueue queue;
-  private final ComputationThreadLauncher workerLauncher;
-  private final UserSession userSession;
-
-  public SubmitReportWsAction(ReportQueue queue, ComputationThreadLauncher workerLauncher, UserSession userSession) {
-    this.queue = queue;
-    this.workerLauncher = workerLauncher;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction(ACTION)
-      .setDescription("Submit an analysis report to the queue. Report is integrated asynchronously.")
-      .setPost(true)
-      .setInternal(true)
-      .setHandler(this);
-
-    action
-      .createParam(PARAM_PROJECT_KEY)
-      .setRequired(true)
-      .setDescription("Project key")
-      .setExampleValue("org.codehaus.sonar:sonar");
-
-    action
-      .createParam(PARAM_REPORT_DATA)
-      .setRequired(true)
-      .setDescription("Report file. Format is not an API, it changes among SonarQube versions.");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
-    String projectKey = request.mandatoryParam(PARAM_PROJECT_KEY);
-    InputStream reportData = request.paramAsInputStream(PARAM_REPORT_DATA);
-    try {
-      ReportQueue.Item item = queue.add(projectKey, reportData);
-      workerLauncher.startAnalysisTaskNow();
-      response.newJsonWriter()
-        .beginObject()
-        // do not write integer for forward-compatibility, for example
-        // if we want to write UUID later
-        .prop("key", String.valueOf(item.dto.getId()))
-        .endObject()
-        .close();
-    } finally {
-      IOUtils.closeQuietly(reportData);
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/dashboard/ws/DashboardsShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/dashboard/ws/DashboardsShowAction.java
deleted file mode 100644 (file)
index b70211d..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.dashboard.ws;
-
-import com.google.common.collect.ListMultimap;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.dashboard.DashboardDto;
-import org.sonar.core.dashboard.WidgetDto;
-import org.sonar.core.dashboard.WidgetPropertyDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.user.UserDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.user.UserSession;
-
-import java.util.Collection;
-
-public class DashboardsShowAction implements DashboardsWsAction {
-
-  private static final String PARAM_KEY = "key";
-
-  private final DbClient dbClient;
-  private final UserSession userSession;
-
-  public DashboardsShowAction(DbClient dbClient, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController newController) {
-    WebService.NewAction action = newController.createAction("show");
-    action.setDescription("Detail of a dashboard (name, description, layout and widgets)");
-    action.setInternal(true);
-    action.setHandler(this);
-    action.createParam(PARAM_KEY)
-      .setDescription("Dashboard key")
-      .setExampleValue("12345")
-      .setRequired(true);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      Integer userId = userSession.getUserId();
-      DashboardDto dashboard = dbClient.dashboardDao().getAllowedByKey(dbSession, request.mandatoryParamAsLong(PARAM_KEY),
-        userId != null ? userId.longValue() : null);
-      if (dashboard == null) {
-        throw new NotFoundException();
-      }
-
-      JsonWriter json = response.newJsonWriter();
-      json.beginObject();
-      json.prop("key", dashboard.getKey());
-      json.prop("name", dashboard.getName());
-      json.prop("layout", dashboard.getColumnLayout());
-      json.prop("desc", dashboard.getDescription());
-      json.prop("global", dashboard.getGlobal());
-      json.prop("shared", dashboard.getShared());
-      if (dashboard.getUserId() != null) {
-        UserDto user = dbClient.userDao().getUser(dashboard.getUserId());
-        if (user != null) {
-          json.name("owner").beginObject();
-          // TODO to be shared and extracted from here
-          json.prop("login", user.getLogin());
-          json.prop("name", user.getName());
-          json.endObject();
-        }
-      }
-      // load widgets and related properties
-      json.name("widgets").beginArray();
-      Collection<WidgetDto> widgets = dbClient.widgetDao().findByDashboard(dbSession, dashboard.getKey());
-      ListMultimap<Long, WidgetPropertyDto> propertiesByWidget = WidgetPropertyDto.groupByWidgetId(
-        dbClient.widgetPropertyDao().findByDashboard(dbSession, dashboard.getKey()));
-      for (WidgetDto widget : widgets) {
-        json.beginObject();
-        json.prop("id", widget.getId());
-        json.prop("key", widget.getWidgetKey());
-        json.prop("name", widget.getName());
-        json.prop("desc", widget.getDescription());
-        json.prop("col", widget.getColumnIndex());
-        json.prop("row", widget.getRowIndex());
-        json.prop("configured", widget.getConfigured());
-        json.prop("componentId", widget.getResourceId());
-        json.name("props").beginArray();
-        for (WidgetPropertyDto prop : propertiesByWidget.get(widget.getId())) {
-          json.beginObject();
-          json.prop("key", prop.getPropertyKey());
-          json.prop("val", prop.getTextValue());
-          json.endObject();
-        }
-        json.endArray().endObject();
-      }
-
-      json.endArray();
-      json.endObject();
-      json.close();
-    } finally {
-      dbSession.close();
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/dashboard/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/dashboard/ws/ShowAction.java
new file mode 100644 (file)
index 0000000..354239c
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.dashboard.ws;
+
+import com.google.common.collect.ListMultimap;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.dashboard.DashboardDto;
+import org.sonar.core.dashboard.WidgetDto;
+import org.sonar.core.dashboard.WidgetPropertyDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+
+import java.util.Collection;
+
+public class ShowAction implements DashboardsWsAction {
+
+  private static final String PARAM_KEY = "key";
+
+  private final DbClient dbClient;
+  private final UserSession userSession;
+
+  public ShowAction(DbClient dbClient, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController newController) {
+    WebService.NewAction action = newController.createAction("show");
+    action.setDescription("Detail of a dashboard (name, description, layout and widgets)");
+    action.setInternal(true);
+    action.setHandler(this);
+    action.createParam(PARAM_KEY)
+      .setDescription("Dashboard key")
+      .setExampleValue("12345")
+      .setRequired(true);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      Integer userId = userSession.getUserId();
+      DashboardDto dashboard = dbClient.dashboardDao().getAllowedByKey(dbSession, request.mandatoryParamAsLong(PARAM_KEY),
+        userId != null ? userId.longValue() : null);
+      if (dashboard == null) {
+        throw new NotFoundException();
+      }
+
+      JsonWriter json = response.newJsonWriter();
+      json.beginObject();
+      json.prop("key", dashboard.getKey());
+      json.prop("name", dashboard.getName());
+      json.prop("layout", dashboard.getColumnLayout());
+      json.prop("desc", dashboard.getDescription());
+      json.prop("global", dashboard.getGlobal());
+      json.prop("shared", dashboard.getShared());
+      if (dashboard.getUserId() != null) {
+        UserDto user = dbClient.userDao().getUser(dashboard.getUserId());
+        if (user != null) {
+          json.name("owner").beginObject();
+          // TODO to be shared and extracted from here
+          json.prop("login", user.getLogin());
+          json.prop("name", user.getName());
+          json.endObject();
+        }
+      }
+      // load widgets and related properties
+      json.name("widgets").beginArray();
+      Collection<WidgetDto> widgets = dbClient.widgetDao().findByDashboard(dbSession, dashboard.getKey());
+      ListMultimap<Long, WidgetPropertyDto> propertiesByWidget = WidgetPropertyDto.groupByWidgetId(
+        dbClient.widgetPropertyDao().findByDashboard(dbSession, dashboard.getKey()));
+      for (WidgetDto widget : widgets) {
+        json.beginObject();
+        json.prop("id", widget.getId());
+        json.prop("key", widget.getWidgetKey());
+        json.prop("name", widget.getName());
+        json.prop("desc", widget.getDescription());
+        json.prop("col", widget.getColumnIndex());
+        json.prop("row", widget.getRowIndex());
+        json.prop("configured", widget.getConfigured());
+        json.prop("componentId", widget.getResourceId());
+        json.name("props").beginArray();
+        for (WidgetPropertyDto prop : propertiesByWidget.get(widget.getId())) {
+          json.beginObject();
+          json.prop("key", prop.getPropertyKey());
+          json.prop("val", prop.getTextValue());
+          json.endObject();
+        }
+        json.endArray().endObject();
+      }
+
+      json.endArray();
+      json.endObject();
+      json.close();
+    } finally {
+      dbSession.close();
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowAction.java
deleted file mode 100644 (file)
index 2e73016..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.issue.ws;
-
-import com.google.common.io.Resources;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.issue.ActionPlan;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.IssueComment;
-import org.sonar.api.issue.internal.DefaultIssueComment;
-import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.server.debt.DebtCharacteristic;
-import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.user.User;
-import org.sonar.api.user.UserFinder;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.Duration;
-import org.sonar.api.utils.Durations;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.markdown.Markdown;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.debt.DebtModelService;
-import org.sonar.server.issue.IssueChangelog;
-import org.sonar.server.issue.IssueChangelogService;
-import org.sonar.server.issue.IssueCommentService;
-import org.sonar.server.issue.IssueService;
-import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.rule.Rule;
-import org.sonar.server.rule.RuleService;
-import org.sonar.server.user.UserSession;
-
-import static com.google.common.collect.Maps.newHashMap;
-
-public class IssueShowAction implements IssuesWsAction {
-
-  public static final String SHOW_ACTION = "show";
-
-  private final DbClient dbClient;
-
-  private final IssueService issueService;
-  private final IssueChangelogService issueChangelogService;
-  private final IssueCommentService commentService;
-  private final IssueActionsWriter actionsWriter;
-  private final ActionPlanService actionPlanService;
-  private final UserFinder userFinder;
-  private final DebtModelService debtModel;
-  private final RuleService ruleService;
-  private final I18n i18n;
-  private final Durations durations;
-  private final UserSession userSession;
-
-  public IssueShowAction(DbClient dbClient, IssueService issueService, IssueChangelogService issueChangelogService, IssueCommentService commentService,
-    IssueActionsWriter actionsWriter, ActionPlanService actionPlanService, UserFinder userFinder, DebtModelService debtModel, RuleService ruleService,
-    I18n i18n, Durations durations, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.issueService = issueService;
-    this.issueChangelogService = issueChangelogService;
-    this.commentService = commentService;
-    this.actionsWriter = actionsWriter;
-    this.actionPlanService = actionPlanService;
-    this.userFinder = userFinder;
-    this.debtModel = debtModel;
-    this.ruleService = ruleService;
-    this.i18n = i18n;
-    this.durations = durations;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction(SHOW_ACTION)
-      .setDescription("Detail of issue")
-      .setSince("4.2")
-      .setInternal(true)
-      .setHandler(this)
-      .setResponseExample(Resources.getResource(this.getClass(), "example-show.json"));
-    action.createParam("key")
-      .setDescription("Issue key")
-      .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    String issueKey = request.mandatoryParam("key");
-
-    JsonWriter json = response.newJsonWriter();
-    json.beginObject().name("issue").beginObject();
-
-    DbSession session = dbClient.openSession(false);
-    try {
-      Issue issue = issueService.getByKey(issueKey);
-
-      writeIssue(session, issue, json);
-      actionsWriter.writeActions(issue, json);
-      actionsWriter.writeTransitions(issue, json);
-      writeComments(issue, json);
-      writeChangelog(issue, json);
-
-    } finally {
-      session.close();
-    }
-
-    json.endObject().endObject().close();
-  }
-
-  private void writeIssue(DbSession session, Issue issue, JsonWriter json) {
-    String actionPlanKey = issue.actionPlanKey();
-    ActionPlan actionPlan = actionPlanKey == null ? null : actionPlanService.findByKey(actionPlanKey, userSession);
-    Duration debt = issue.debt();
-    Rule rule = ruleService.getNonNullByKey(issue.ruleKey());
-    Date updateDate = issue.updateDate();
-    Date closeDate = issue.closeDate();
-
-    json
-      .prop("key", issue.key())
-      .prop("rule", issue.ruleKey().toString())
-      .prop("ruleName", rule.name())
-      .prop("line", issue.line())
-      .prop("message", issue.message())
-      .prop("resolution", issue.resolution())
-      .prop("status", issue.status())
-      .prop("severity", issue.severity())
-      .prop("author", issue.authorLogin())
-      .prop("actionPlan", actionPlanKey)
-      .prop("actionPlanName", actionPlan != null ? actionPlan.name() : null)
-      .prop("debt", debt != null ? durations.encode(debt) : null)
-      .prop("creationDate", DateUtils.formatDateTime(issue.creationDate()))
-      .prop("fCreationDate", formatDate(issue.creationDate()))
-      .prop("updateDate", updateDate != null ? DateUtils.formatDateTime(updateDate) : null)
-      .prop("fUpdateDate", formatDate(updateDate))
-      .prop("fUpdateAge", formatAgeDate(updateDate))
-      .prop("closeDate", closeDate != null ? DateUtils.formatDateTime(closeDate) : null)
-      .prop("fCloseDate", formatDate(issue.closeDate()));
-
-    addComponents(session, issue, json);
-    addUserWithLabel(issue.assignee(), "assignee", json);
-    addUserWithLabel(issue.reporter(), "reporter", json);
-    addCharacteristics(rule, json);
-  }
-
-  private void addComponents(DbSession session, Issue issue, JsonWriter json) {
-    ComponentDto component = dbClient.componentDao().selectByUuid(session, issue.componentUuid());
-    Long parentProjectId = component.parentProjectId();
-    ComponentDto parentProject = parentProjectId != null ? dbClient.componentDao().selectNullableById(parentProjectId, session) : null;
-    ComponentDto project = dbClient.componentDao().selectByUuid(session, component.projectUuid());
-
-    String projectName = project.longName() != null ? project.longName() : project.name();
-    // Do not display sub project long name if sub project and project are the same
-    boolean displayParentProjectLongName = parentProject != null && !parentProject.getId().equals(project.getId());
-    String parentProjectKey = displayParentProjectLongName ? parentProject.key() : null;
-    String parentProjectName = displayParentProjectLongName ? parentProject.longName() != null ? parentProject.longName() : parentProject.name() : null;
-
-    json
-      .prop("component", component.key())
-      .prop("componentLongName", component.longName())
-      .prop("componentQualifier", component.qualifier())
-      .prop("componentEnabled", component.isEnabled())
-      .prop("project", project.key())
-      .prop("projectName", projectName)
-      // TODO replace subProject names by parentProject
-      .prop("subProject", parentProjectKey)
-      .prop("subProjectName", parentProjectName);
-  }
-
-  private void writeComments(Issue issue, JsonWriter json) {
-    json.name("comments").beginArray();
-    String login = userSession.getLogin();
-
-    Map<String, User> usersByLogin = newHashMap();
-    List<DefaultIssueComment> comments = commentService.findComments(issue.key());
-    for (IssueComment comment : comments) {
-      String userLogin = comment.userLogin();
-      User user = usersByLogin.get(userLogin);
-      if (user == null) {
-        user = userFinder.findByLogin(userLogin);
-        if (user != null) {
-          usersByLogin.put(userLogin, user);
-        }
-      }
-    }
-
-    for (IssueComment comment : comments) {
-      String userLogin = comment.userLogin();
-      User user = usersByLogin.get(userLogin);
-      json
-        .beginObject()
-        .prop("key", comment.key())
-        .prop("userName", user != null ? user.name() : null)
-        .prop("raw", comment.markdownText())
-        .prop("html", Markdown.convertToHtml(comment.markdownText()))
-        .prop("createdAt", DateUtils.formatDateTime(comment.createdAt()))
-        .prop("fCreatedAge", formatAgeDate(comment.createdAt()))
-        .prop("updatable", login != null && login.equals(userLogin))
-        .endObject();
-    }
-    json.endArray();
-  }
-
-  private void writeChangelog(Issue issue, JsonWriter json) {
-    json.name("changelog").beginArray()
-      .beginObject()
-      .prop("creationDate", DateUtils.formatDateTime(issue.creationDate()))
-      .prop("fCreationDate", formatDate(issue.creationDate()))
-      .name("diffs").beginArray()
-      .value(i18n.message(userSession.locale(), "created", null))
-      .endArray()
-      .endObject();
-
-    IssueChangelog changelog = issueChangelogService.changelog(issue);
-    for (FieldDiffs diffs : changelog.changes()) {
-      User user = changelog.user(diffs);
-      json
-        .beginObject()
-        .prop("userName", user != null ? user.name() : null)
-        .prop("creationDate", DateUtils.formatDateTime(diffs.creationDate()))
-        .prop("fCreationDate", formatDate(diffs.creationDate()));
-      json.name("diffs").beginArray();
-      List<String> diffsFormatted = issueChangelogService.formatDiffs(diffs);
-      for (String diff : diffsFormatted) {
-        json.value(diff);
-      }
-      json.endArray();
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-  private void addUserWithLabel(@Nullable String value, String field, JsonWriter json) {
-    if (value != null) {
-      User user = userFinder.findByLogin(value);
-      json
-        .prop(field, value)
-        .prop(field + "Name", user != null ? user.name() : null);
-    }
-  }
-
-  @CheckForNull
-  private String formatDate(@Nullable Date date) {
-    if (date != null) {
-      return i18n.formatDateTime(userSession.locale(), date);
-    }
-    return null;
-  }
-
-  @CheckForNull
-  private String formatAgeDate(@Nullable Date date) {
-    if (date != null) {
-      return i18n.ageFromNow(userSession.locale(), date);
-    }
-    return null;
-  }
-
-  private void addCharacteristics(Rule rule, JsonWriter json) {
-    String subCharacteristicKey = rule.debtCharacteristicKey();
-    DebtCharacteristic subCharacteristic = characteristicByKey(subCharacteristicKey);
-    if (subCharacteristic != null) {
-      json.prop("subCharacteristic", subCharacteristic.name());
-      DebtCharacteristic characteristic = characteristicById(((DefaultDebtCharacteristic) subCharacteristic).parentId());
-      json.prop("characteristic", characteristic != null ? characteristic.name() : null);
-    }
-  }
-
-  @CheckForNull
-  private DebtCharacteristic characteristicById(@Nullable Integer id) {
-    if (id != null) {
-      return debtModel.characteristicById(id);
-    }
-    return null;
-  }
-
-  @CheckForNull
-  private DebtCharacteristic characteristicByKey(@Nullable String key) {
-    if (key != null) {
-      return debtModel.characteristicByKey(key);
-    }
-    return null;
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/ShowAction.java
new file mode 100644 (file)
index 0000000..bafc954
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.issue.ActionPlan;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.IssueComment;
+import org.sonar.api.issue.internal.DefaultIssueComment;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.server.debt.DebtCharacteristic;
+import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.user.User;
+import org.sonar.api.user.UserFinder;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.Duration;
+import org.sonar.api.utils.Durations;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.markdown.Markdown;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.debt.DebtModelService;
+import org.sonar.server.issue.IssueChangelog;
+import org.sonar.server.issue.IssueChangelogService;
+import org.sonar.server.issue.IssueCommentService;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.rule.Rule;
+import org.sonar.server.rule.RuleService;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.collect.Maps.newHashMap;
+
+public class ShowAction implements IssuesWsAction {
+
+  public static final String SHOW_ACTION = "show";
+
+  private final DbClient dbClient;
+
+  private final IssueService issueService;
+  private final IssueChangelogService issueChangelogService;
+  private final IssueCommentService commentService;
+  private final IssueActionsWriter actionsWriter;
+  private final ActionPlanService actionPlanService;
+  private final UserFinder userFinder;
+  private final DebtModelService debtModel;
+  private final RuleService ruleService;
+  private final I18n i18n;
+  private final Durations durations;
+  private final UserSession userSession;
+
+  public ShowAction(DbClient dbClient, IssueService issueService, IssueChangelogService issueChangelogService, IssueCommentService commentService,
+                    IssueActionsWriter actionsWriter, ActionPlanService actionPlanService, UserFinder userFinder, DebtModelService debtModel, RuleService ruleService,
+                    I18n i18n, Durations durations, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.issueService = issueService;
+    this.issueChangelogService = issueChangelogService;
+    this.commentService = commentService;
+    this.actionsWriter = actionsWriter;
+    this.actionPlanService = actionPlanService;
+    this.userFinder = userFinder;
+    this.debtModel = debtModel;
+    this.ruleService = ruleService;
+    this.i18n = i18n;
+    this.durations = durations;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction(SHOW_ACTION)
+      .setDescription("Detail of issue")
+      .setSince("4.2")
+      .setInternal(true)
+      .setHandler(this)
+      .setResponseExample(Resources.getResource(this.getClass(), "example-show.json"));
+    action.createParam("key")
+      .setDescription("Issue key")
+      .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    String issueKey = request.mandatoryParam("key");
+
+    JsonWriter json = response.newJsonWriter();
+    json.beginObject().name("issue").beginObject();
+
+    DbSession session = dbClient.openSession(false);
+    try {
+      Issue issue = issueService.getByKey(issueKey);
+
+      writeIssue(session, issue, json);
+      actionsWriter.writeActions(issue, json);
+      actionsWriter.writeTransitions(issue, json);
+      writeComments(issue, json);
+      writeChangelog(issue, json);
+
+    } finally {
+      session.close();
+    }
+
+    json.endObject().endObject().close();
+  }
+
+  private void writeIssue(DbSession session, Issue issue, JsonWriter json) {
+    String actionPlanKey = issue.actionPlanKey();
+    ActionPlan actionPlan = actionPlanKey == null ? null : actionPlanService.findByKey(actionPlanKey, userSession);
+    Duration debt = issue.debt();
+    Rule rule = ruleService.getNonNullByKey(issue.ruleKey());
+    Date updateDate = issue.updateDate();
+    Date closeDate = issue.closeDate();
+
+    json
+      .prop("key", issue.key())
+      .prop("rule", issue.ruleKey().toString())
+      .prop("ruleName", rule.name())
+      .prop("line", issue.line())
+      .prop("message", issue.message())
+      .prop("resolution", issue.resolution())
+      .prop("status", issue.status())
+      .prop("severity", issue.severity())
+      .prop("author", issue.authorLogin())
+      .prop("actionPlan", actionPlanKey)
+      .prop("actionPlanName", actionPlan != null ? actionPlan.name() : null)
+      .prop("debt", debt != null ? durations.encode(debt) : null)
+      .prop("creationDate", DateUtils.formatDateTime(issue.creationDate()))
+      .prop("fCreationDate", formatDate(issue.creationDate()))
+      .prop("updateDate", updateDate != null ? DateUtils.formatDateTime(updateDate) : null)
+      .prop("fUpdateDate", formatDate(updateDate))
+      .prop("fUpdateAge", formatAgeDate(updateDate))
+      .prop("closeDate", closeDate != null ? DateUtils.formatDateTime(closeDate) : null)
+      .prop("fCloseDate", formatDate(issue.closeDate()));
+
+    addComponents(session, issue, json);
+    addUserWithLabel(issue.assignee(), "assignee", json);
+    addUserWithLabel(issue.reporter(), "reporter", json);
+    addCharacteristics(rule, json);
+  }
+
+  private void addComponents(DbSession session, Issue issue, JsonWriter json) {
+    ComponentDto component = dbClient.componentDao().selectByUuid(session, issue.componentUuid());
+    Long parentProjectId = component.parentProjectId();
+    ComponentDto parentProject = parentProjectId != null ? dbClient.componentDao().selectNullableById(parentProjectId, session) : null;
+    ComponentDto project = dbClient.componentDao().selectByUuid(session, component.projectUuid());
+
+    String projectName = project.longName() != null ? project.longName() : project.name();
+    // Do not display sub project long name if sub project and project are the same
+    boolean displayParentProjectLongName = parentProject != null && !parentProject.getId().equals(project.getId());
+    String parentProjectKey = displayParentProjectLongName ? parentProject.key() : null;
+    String parentProjectName = displayParentProjectLongName ? parentProject.longName() != null ? parentProject.longName() : parentProject.name() : null;
+
+    json
+      .prop("component", component.key())
+      .prop("componentLongName", component.longName())
+      .prop("componentQualifier", component.qualifier())
+      .prop("componentEnabled", component.isEnabled())
+      .prop("project", project.key())
+      .prop("projectName", projectName)
+      // TODO replace subProject names by parentProject
+      .prop("subProject", parentProjectKey)
+      .prop("subProjectName", parentProjectName);
+  }
+
+  private void writeComments(Issue issue, JsonWriter json) {
+    json.name("comments").beginArray();
+    String login = userSession.getLogin();
+
+    Map<String, User> usersByLogin = newHashMap();
+    List<DefaultIssueComment> comments = commentService.findComments(issue.key());
+    for (IssueComment comment : comments) {
+      String userLogin = comment.userLogin();
+      User user = usersByLogin.get(userLogin);
+      if (user == null) {
+        user = userFinder.findByLogin(userLogin);
+        if (user != null) {
+          usersByLogin.put(userLogin, user);
+        }
+      }
+    }
+
+    for (IssueComment comment : comments) {
+      String userLogin = comment.userLogin();
+      User user = usersByLogin.get(userLogin);
+      json
+        .beginObject()
+        .prop("key", comment.key())
+        .prop("userName", user != null ? user.name() : null)
+        .prop("raw", comment.markdownText())
+        .prop("html", Markdown.convertToHtml(comment.markdownText()))
+        .prop("createdAt", DateUtils.formatDateTime(comment.createdAt()))
+        .prop("fCreatedAge", formatAgeDate(comment.createdAt()))
+        .prop("updatable", login != null && login.equals(userLogin))
+        .endObject();
+    }
+    json.endArray();
+  }
+
+  private void writeChangelog(Issue issue, JsonWriter json) {
+    json.name("changelog").beginArray()
+      .beginObject()
+      .prop("creationDate", DateUtils.formatDateTime(issue.creationDate()))
+      .prop("fCreationDate", formatDate(issue.creationDate()))
+      .name("diffs").beginArray()
+      .value(i18n.message(userSession.locale(), "created", null))
+      .endArray()
+      .endObject();
+
+    IssueChangelog changelog = issueChangelogService.changelog(issue);
+    for (FieldDiffs diffs : changelog.changes()) {
+      User user = changelog.user(diffs);
+      json
+        .beginObject()
+        .prop("userName", user != null ? user.name() : null)
+        .prop("creationDate", DateUtils.formatDateTime(diffs.creationDate()))
+        .prop("fCreationDate", formatDate(diffs.creationDate()));
+      json.name("diffs").beginArray();
+      List<String> diffsFormatted = issueChangelogService.formatDiffs(diffs);
+      for (String diff : diffsFormatted) {
+        json.value(diff);
+      }
+      json.endArray();
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+  private void addUserWithLabel(@Nullable String value, String field, JsonWriter json) {
+    if (value != null) {
+      User user = userFinder.findByLogin(value);
+      json
+        .prop(field, value)
+        .prop(field + "Name", user != null ? user.name() : null);
+    }
+  }
+
+  @CheckForNull
+  private String formatDate(@Nullable Date date) {
+    if (date != null) {
+      return i18n.formatDateTime(userSession.locale(), date);
+    }
+    return null;
+  }
+
+  @CheckForNull
+  private String formatAgeDate(@Nullable Date date) {
+    if (date != null) {
+      return i18n.ageFromNow(userSession.locale(), date);
+    }
+    return null;
+  }
+
+  private void addCharacteristics(Rule rule, JsonWriter json) {
+    String subCharacteristicKey = rule.debtCharacteristicKey();
+    DebtCharacteristic subCharacteristic = characteristicByKey(subCharacteristicKey);
+    if (subCharacteristic != null) {
+      json.prop("subCharacteristic", subCharacteristic.name());
+      DebtCharacteristic characteristic = characteristicById(((DefaultDebtCharacteristic) subCharacteristic).parentId());
+      json.prop("characteristic", characteristic != null ? characteristic.name() : null);
+    }
+  }
+
+  @CheckForNull
+  private DebtCharacteristic characteristicById(@Nullable Integer id) {
+    if (id != null) {
+      return debtModel.characteristicById(id);
+    }
+    return null;
+  }
+
+  @CheckForNull
+  private DebtCharacteristic characteristicByKey(@Nullable String key) {
+    if (key != null) {
+      return debtModel.characteristicByKey(key);
+    }
+    return null;
+  }
+}
index 02ccd463befc164a5938520b08e3a4459d3346d4..8350f83f0a79575a91620a1fe710515863592627 100644 (file)
@@ -92,9 +92,9 @@ import org.sonar.server.activity.ws.ActivityMapping;
 import org.sonar.server.authentication.ws.AuthenticationWs;
 import org.sonar.server.batch.BatchIndex;
 import org.sonar.server.batch.BatchWs;
-import org.sonar.server.batch.GlobalRepositoryAction;
+import org.sonar.server.batch.GlobalAction;
 import org.sonar.server.batch.IssuesAction;
-import org.sonar.server.batch.ProjectRepositoryAction;
+import org.sonar.server.batch.ProjectAction;
 import org.sonar.server.batch.ProjectRepositoryLoader;
 import org.sonar.server.batch.UsersAction;
 import org.sonar.server.charts.ChartFactory;
@@ -106,27 +106,25 @@ import org.sonar.server.component.db.ComponentDao;
 import org.sonar.server.component.db.ComponentIndexDao;
 import org.sonar.server.component.db.ComponentLinkDao;
 import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.component.ws.ComponentAppAction;
 import org.sonar.server.component.ws.ComponentsWs;
 import org.sonar.server.component.ws.EventsWs;
-import org.sonar.server.component.ws.ProjectsGhostsAction;
-import org.sonar.server.component.ws.ProjectsWs;
-import org.sonar.server.component.ws.ProjectsProvisionedAction;
+import org.sonar.server.project.ws.GhostsAction;
+import org.sonar.server.project.ws.ProjectsWs;
+import org.sonar.server.project.ws.ProvisionedAction;
 import org.sonar.server.component.ws.ResourcesWs;
 import org.sonar.server.computation.ComputationThreadLauncher;
 import org.sonar.server.computation.ReportQueue;
 import org.sonar.server.computation.ReportQueueCleaner;
 import org.sonar.server.computation.db.AnalysisReportDao;
 import org.sonar.server.computation.ws.ComputationWs;
-import org.sonar.server.computation.ws.HistoryWsAction;
+import org.sonar.server.computation.ws.HistoryAction;
 import org.sonar.server.computation.ws.IsQueueEmptyWs;
-import org.sonar.server.computation.ws.QueueWsAction;
-import org.sonar.server.computation.ws.SubmitReportWsAction;
+import org.sonar.server.computation.ws.QueueAction;
+import org.sonar.server.computation.ws.SubmitReportAction;
 import org.sonar.server.config.ws.PropertiesWs;
 import org.sonar.server.dashboard.db.DashboardDao;
 import org.sonar.server.dashboard.db.WidgetDao;
 import org.sonar.server.dashboard.db.WidgetPropertyDao;
-import org.sonar.server.dashboard.ws.DashboardsShowAction;
 import org.sonar.server.dashboard.ws.DashboardsWs;
 import org.sonar.server.db.DatabaseChecker;
 import org.sonar.server.db.DbClient;
@@ -189,11 +187,9 @@ import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher;
 import org.sonar.server.issue.notification.NewIssuesNotificationFactory;
 import org.sonar.server.issue.ws.ComponentTagsAction;
 import org.sonar.server.issue.ws.IssueActionsWriter;
-import org.sonar.server.issue.ws.IssueShowAction;
 import org.sonar.server.issue.ws.IssuesWs;
 import org.sonar.server.issue.ws.SetTagsAction;
 import org.sonar.server.language.ws.LanguageWs;
-import org.sonar.server.language.ws.ListAction;
 import org.sonar.server.measure.MeasureFilterEngine;
 import org.sonar.server.measure.MeasureFilterExecutor;
 import org.sonar.server.measure.MeasureFilterFactory;
@@ -215,13 +211,13 @@ import org.sonar.server.platform.monitoring.PluginsMonitor;
 import org.sonar.server.platform.monitoring.SonarQubeMonitor;
 import org.sonar.server.platform.monitoring.SystemMonitor;
 import org.sonar.server.platform.ws.L10nWs;
-import org.sonar.server.platform.ws.MigrateDbSystemWsAction;
+import org.sonar.server.platform.ws.MigrateDbSystemAction;
 import org.sonar.server.platform.ws.ServerWs;
-import org.sonar.server.platform.ws.SystemInfoWsAction;
-import org.sonar.server.platform.ws.SystemRestartWsAction;
-import org.sonar.server.platform.ws.SystemStatusWsAction;
+import org.sonar.server.platform.ws.InfoAction;
+import org.sonar.server.platform.ws.RestartAction;
+import org.sonar.server.platform.ws.StatusAction;
 import org.sonar.server.platform.ws.SystemWs;
-import org.sonar.server.platform.ws.UpgradesSystemWsAction;
+import org.sonar.server.platform.ws.UpgradesAction;
 import org.sonar.server.plugins.InstalledPluginReferentialFactory;
 import org.sonar.server.plugins.PluginDownloader;
 import org.sonar.server.plugins.ServerExtensionInstaller;
@@ -229,36 +225,31 @@ import org.sonar.server.plugins.ServerPluginRepository;
 import org.sonar.server.plugins.ServerPluginExploder;
 import org.sonar.server.plugins.UpdateCenterClient;
 import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.plugins.ws.AvailablePluginsWsAction;
-import org.sonar.server.plugins.ws.CancelAllPluginsWsAction;
-import org.sonar.server.plugins.ws.InstallPluginsWsAction;
-import org.sonar.server.plugins.ws.InstalledPluginsWsAction;
-import org.sonar.server.plugins.ws.PendingPluginsWsAction;
+import org.sonar.server.plugins.ws.AvailableAction;
+import org.sonar.server.plugins.ws.CancelAllAction;
+import org.sonar.server.plugins.ws.InstallAction;
+import org.sonar.server.plugins.ws.InstalledAction;
+import org.sonar.server.plugins.ws.PendingAction;
 import org.sonar.server.plugins.ws.PluginUpdateAggregator;
 import org.sonar.server.plugins.ws.PluginWSCommons;
 import org.sonar.server.plugins.ws.PluginsWs;
-import org.sonar.server.plugins.ws.UninstallPluginsWsAction;
-import org.sonar.server.plugins.ws.UpdatePluginsWsAction;
-import org.sonar.server.plugins.ws.UpdatesPluginsWsAction;
+import org.sonar.server.plugins.ws.UninstallAction;
+import org.sonar.server.plugins.ws.UpdateAction;
+import org.sonar.server.plugins.ws.UpdatesAction;
 import org.sonar.server.properties.ProjectSettingsFactory;
 import org.sonar.server.qualitygate.QgateProjectFinder;
 import org.sonar.server.qualitygate.QualityGates;
 import org.sonar.server.qualitygate.RegisterQualityGates;
-import org.sonar.server.qualitygate.ws.QGatesAppAction;
-import org.sonar.server.qualitygate.ws.QGatesCopyAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeselectAction;
-import org.sonar.server.qualitygate.ws.QGatesDestroyAction;
-import org.sonar.server.qualitygate.ws.QGatesListAction;
-import org.sonar.server.qualitygate.ws.QGatesRenameAction;
-import org.sonar.server.qualitygate.ws.QGatesSearchAction;
-import org.sonar.server.qualitygate.ws.QGatesSelectAction;
-import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesShowAction;
-import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction;
+import org.sonar.server.qualitygate.ws.AppAction;
+import org.sonar.server.qualitygate.ws.CreateConditionAction;
+import org.sonar.server.qualitygate.ws.DeleteConditionAction;
+import org.sonar.server.qualitygate.ws.DeselectAction;
+import org.sonar.server.qualitygate.ws.DestroyAction;
+import org.sonar.server.qualitygate.ws.SelectAction;
+import org.sonar.server.qualitygate.ws.SetAsDefaultAction;
+import org.sonar.server.qualitygate.ws.ShowAction;
+import org.sonar.server.qualitygate.ws.UnsetDefaultAction;
+import org.sonar.server.qualitygate.ws.UpdateConditionAction;
 import org.sonar.server.qualitygate.ws.QGatesWs;
 import org.sonar.server.qualityprofile.BuiltInProfiles;
 import org.sonar.server.qualityprofile.QProfileBackuper;
@@ -282,23 +273,23 @@ import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
 import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions;
 import org.sonar.server.qualityprofile.ws.ProfilesWs;
 import org.sonar.server.qualityprofile.ws.ProjectAssociationActions;
-import org.sonar.server.qualityprofile.ws.QProfileBackupAction;
-import org.sonar.server.qualityprofile.ws.QProfileChangeParentAction;
-import org.sonar.server.qualityprofile.ws.QProfileChangelogAction;
-import org.sonar.server.qualityprofile.ws.QProfileCompareAction;
-import org.sonar.server.qualityprofile.ws.QProfileCopyAction;
-import org.sonar.server.qualityprofile.ws.QProfileCreateAction;
-import org.sonar.server.qualityprofile.ws.QProfileDeleteAction;
-import org.sonar.server.qualityprofile.ws.QProfileExportAction;
-import org.sonar.server.qualityprofile.ws.QProfileExportersAction;
-import org.sonar.server.qualityprofile.ws.QProfileImportersAction;
-import org.sonar.server.qualityprofile.ws.QProfileInheritanceAction;
-import org.sonar.server.qualityprofile.ws.QProfileProjectsAction;
-import org.sonar.server.qualityprofile.ws.QProfileRenameAction;
-import org.sonar.server.qualityprofile.ws.QProfileRestoreAction;
-import org.sonar.server.qualityprofile.ws.QProfileRestoreBuiltInAction;
-import org.sonar.server.qualityprofile.ws.QProfileSearchAction;
-import org.sonar.server.qualityprofile.ws.QProfileSetDefaultAction;
+import org.sonar.server.qualityprofile.ws.BackupAction;
+import org.sonar.server.qualityprofile.ws.ChangeParentAction;
+import org.sonar.server.qualityprofile.ws.ChangelogAction;
+import org.sonar.server.qualityprofile.ws.CompareAction;
+import org.sonar.server.qualityprofile.ws.CopyAction;
+import org.sonar.server.qualityprofile.ws.CreateAction;
+import org.sonar.server.qualityprofile.ws.DeleteAction;
+import org.sonar.server.qualityprofile.ws.ExportAction;
+import org.sonar.server.qualityprofile.ws.ExportersAction;
+import org.sonar.server.qualityprofile.ws.ImportersAction;
+import org.sonar.server.qualityprofile.ws.InheritanceAction;
+import org.sonar.server.qualityprofile.ws.ProjectsAction;
+import org.sonar.server.qualityprofile.ws.RenameAction;
+import org.sonar.server.qualityprofile.ws.RestoreAction;
+import org.sonar.server.qualityprofile.ws.RestoreBuiltInAction;
+import org.sonar.server.qualityprofile.ws.SearchAction;
+import org.sonar.server.qualityprofile.ws.SetDefaultAction;
 import org.sonar.server.qualityprofile.ws.QProfilesWs;
 import org.sonar.server.qualityprofile.ws.RuleActivationActions;
 import org.sonar.server.ruby.PlatformRackBridge;
@@ -318,14 +309,10 @@ import org.sonar.server.rule.db.RuleDao;
 import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleNormalizer;
 import org.sonar.server.rule.ws.ActiveRuleCompleter;
-import org.sonar.server.rule.ws.AppAction;
-import org.sonar.server.rule.ws.DeleteAction;
 import org.sonar.server.rule.ws.RepositoriesAction;
 import org.sonar.server.rule.ws.RuleMapping;
 import org.sonar.server.rule.ws.RulesWs;
-import org.sonar.server.rule.ws.SearchAction;
 import org.sonar.server.rule.ws.TagsAction;
-import org.sonar.server.rule.ws.UpdateAction;
 import org.sonar.server.search.IndexClient;
 import org.sonar.server.search.IndexQueue;
 import org.sonar.server.search.IndexSynchronizer;
@@ -341,7 +328,6 @@ import org.sonar.server.source.ws.IndexAction;
 import org.sonar.server.source.ws.LinesAction;
 import org.sonar.server.source.ws.RawAction;
 import org.sonar.server.source.ws.ScmAction;
-import org.sonar.server.source.ws.ShowAction;
 import org.sonar.server.source.ws.SourcesWs;
 import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules;
 import org.sonar.server.startup.GeneratePluginIndex;
@@ -360,8 +346,8 @@ import org.sonar.server.test.CoverageService;
 import org.sonar.server.test.index.TestIndex;
 import org.sonar.server.test.index.TestIndexDefinition;
 import org.sonar.server.test.index.TestIndexer;
-import org.sonar.server.test.ws.TestsCoveredFilesAction;
-import org.sonar.server.test.ws.TestsListAction;
+import org.sonar.server.test.ws.CoveredFilesAction;
+import org.sonar.server.test.ws.ListAction;
 import org.sonar.server.test.ws.TestsWs;
 import org.sonar.server.text.MacroInterpreter;
 import org.sonar.server.text.RubyTextService;
@@ -387,6 +373,7 @@ import org.sonar.server.user.db.UserGroupDao;
 import org.sonar.server.user.index.UserIndex;
 import org.sonar.server.user.index.UserIndexDefinition;
 import org.sonar.server.user.index.UserIndexer;
+import org.sonar.server.user.ws.CurrentAction;
 import org.sonar.server.user.ws.FavoritesWs;
 import org.sonar.server.user.ws.UserPropertiesWs;
 import org.sonar.server.user.ws.UsersWs;
@@ -565,8 +552,8 @@ class ServerComponents {
       ThreadLocalDatabaseSessionFactory.class,
 
       // Server WS
-      SystemStatusWsAction.class,
-      MigrateDbSystemWsAction.class,
+      StatusAction.class,
+      MigrateDbSystemAction.class,
       SystemWs.class,
 
       // Listing WS
@@ -616,17 +603,17 @@ class ServerComponents {
 
     // batch
     pico.addSingleton(BatchIndex.class);
-    pico.addSingleton(GlobalRepositoryAction.class);
-    pico.addSingleton(ProjectRepositoryAction.class);
+    pico.addSingleton(GlobalAction.class);
+    pico.addSingleton(ProjectAction.class);
     pico.addSingleton(ProjectRepositoryLoader.class);
-    pico.addSingleton(SubmitReportWsAction.class);
+    pico.addSingleton(SubmitReportAction.class);
     pico.addSingleton(IssuesAction.class);
     pico.addSingleton(UsersAction.class);
     pico.addSingleton(BatchWs.class);
 
     // Dashboard
     pico.addSingleton(DashboardsWs.class);
-    pico.addSingleton(DashboardsShowAction.class);
+    pico.addSingleton(org.sonar.server.dashboard.ws.ShowAction.class);
 
     // update center
     pico.addSingleton(UpdateCenterClient.class);
@@ -643,23 +630,23 @@ class ServerComponents {
     pico.addSingleton(QProfileProjectLookup.class);
     pico.addSingleton(QProfileComparison.class);
     pico.addSingleton(BuiltInProfiles.class);
-    pico.addSingleton(QProfileRestoreBuiltInAction.class);
-    pico.addSingleton(QProfileSearchAction.class);
-    pico.addSingleton(QProfileSetDefaultAction.class);
-    pico.addSingleton(QProfileProjectsAction.class);
-    pico.addSingleton(QProfileDeleteAction.class);
-    pico.addSingleton(QProfileRenameAction.class);
-    pico.addSingleton(QProfileCopyAction.class);
-    pico.addSingleton(QProfileBackupAction.class);
-    pico.addSingleton(QProfileRestoreAction.class);
-    pico.addSingleton(QProfileCreateAction.class);
-    pico.addSingleton(QProfileImportersAction.class);
-    pico.addSingleton(QProfileInheritanceAction.class);
-    pico.addSingleton(QProfileChangeParentAction.class);
-    pico.addSingleton(QProfileChangelogAction.class);
-    pico.addSingleton(QProfileCompareAction.class);
-    pico.addSingleton(QProfileExportAction.class);
-    pico.addSingleton(QProfileExportersAction.class);
+    pico.addSingleton(RestoreBuiltInAction.class);
+    pico.addSingleton(SearchAction.class);
+    pico.addSingleton(SetDefaultAction.class);
+    pico.addSingleton(ProjectsAction.class);
+    pico.addSingleton(DeleteAction.class);
+    pico.addSingleton(RenameAction.class);
+    pico.addSingleton(CopyAction.class);
+    pico.addSingleton(BackupAction.class);
+    pico.addSingleton(RestoreAction.class);
+    pico.addSingleton(CreateAction.class);
+    pico.addSingleton(ImportersAction.class);
+    pico.addSingleton(InheritanceAction.class);
+    pico.addSingleton(ChangeParentAction.class);
+    pico.addSingleton(ChangelogAction.class);
+    pico.addSingleton(CompareAction.class);
+    pico.addSingleton(ExportAction.class);
+    pico.addSingleton(ExportersAction.class);
     pico.addSingleton(QProfilesWs.class);
     pico.addSingleton(ProfilesWs.class);
     pico.addSingleton(RuleActivationActions.class);
@@ -690,22 +677,22 @@ class ServerComponents {
     pico.addSingleton(RuleUpdater.class);
     pico.addSingleton(RuleCreator.class);
     pico.addSingleton(RuleDeleter.class);
-    pico.addSingleton(UpdateAction.class);
+    pico.addSingleton(org.sonar.server.rule.ws.UpdateAction.class);
     pico.addSingleton(RulesWs.class);
-    pico.addSingleton(SearchAction.class);
+    pico.addSingleton(org.sonar.server.rule.ws.SearchAction.class);
     pico.addSingleton(org.sonar.server.rule.ws.ShowAction.class);
     pico.addSingleton(org.sonar.server.rule.ws.CreateAction.class);
-    pico.addSingleton(DeleteAction.class);
+    pico.addSingleton(org.sonar.server.rule.ws.DeleteAction.class);
     pico.addSingleton(TagsAction.class);
     pico.addSingleton(RuleMapping.class);
     pico.addSingleton(ActiveRuleCompleter.class);
     pico.addSingleton(RepositoriesAction.class);
-    pico.addSingleton(AppAction.class);
+    pico.addSingleton(org.sonar.server.rule.ws.AppAction.class);
 
     // languages
     pico.addSingleton(Languages.class);
     pico.addSingleton(LanguageWs.class);
-    pico.addSingleton(ListAction.class);
+    pico.addSingleton(org.sonar.server.language.ws.ListAction.class);
 
     // activity
     pico.addSingleton(ActivitiesWs.class);
@@ -730,21 +717,21 @@ class ServerComponents {
     pico.addSingleton(ProjectQgateAssociationDao.class);
     pico.addSingleton(QgateProjectFinder.class);
 
-    pico.addSingleton(QGatesListAction.class);
-    pico.addSingleton(QGatesSearchAction.class);
-    pico.addSingleton(QGatesShowAction.class);
-    pico.addSingleton(QGatesCreateAction.class);
-    pico.addSingleton(QGatesRenameAction.class);
-    pico.addSingleton(QGatesCopyAction.class);
-    pico.addSingleton(QGatesDestroyAction.class);
-    pico.addSingleton(QGatesSetAsDefaultAction.class);
-    pico.addSingleton(QGatesUnsetDefaultAction.class);
-    pico.addSingleton(QGatesSelectAction.class);
-    pico.addSingleton(QGatesDeselectAction.class);
-    pico.addSingleton(QGatesCreateConditionAction.class);
-    pico.addSingleton(QGatesDeleteConditionAction.class);
-    pico.addSingleton(QGatesUpdateConditionAction.class);
-    pico.addSingleton(QGatesAppAction.class);
+    pico.addSingleton(org.sonar.server.qualitygate.ws.ListAction.class);
+    pico.addSingleton(org.sonar.server.qualitygate.ws.SearchAction.class);
+    pico.addSingleton(ShowAction.class);
+    pico.addSingleton(org.sonar.server.qualitygate.ws.CreateAction.class);
+    pico.addSingleton(org.sonar.server.qualitygate.ws.RenameAction.class);
+    pico.addSingleton(org.sonar.server.qualitygate.ws.CopyAction.class);
+    pico.addSingleton(DestroyAction.class);
+    pico.addSingleton(SetAsDefaultAction.class);
+    pico.addSingleton(UnsetDefaultAction.class);
+    pico.addSingleton(SelectAction.class);
+    pico.addSingleton(DeselectAction.class);
+    pico.addSingleton(CreateConditionAction.class);
+    pico.addSingleton(DeleteConditionAction.class);
+    pico.addSingleton(UpdateConditionAction.class);
+    pico.addSingleton(AppAction.class);
     pico.addSingleton(QGatesWs.class);
 
     // web services
@@ -768,7 +755,7 @@ class ServerComponents {
     pico.addSingleton(org.sonar.server.user.ws.UpdateAction.class);
     pico.addSingleton(org.sonar.server.user.ws.DeactivateAction.class);
     pico.addSingleton(org.sonar.server.user.ws.ChangePasswordAction.class);
-    pico.addSingleton(org.sonar.server.user.ws.CurrentUserAction.class);
+    pico.addSingleton(CurrentAction.class);
     pico.addSingleton(org.sonar.server.user.ws.SearchAction.class);
     pico.addSingleton(org.sonar.server.user.ws.GroupsAction.class);
     pico.addSingleton(org.sonar.server.issue.ws.AuthorsAction.class);
@@ -797,12 +784,12 @@ class ServerComponents {
     pico.addSingleton(ResourcesWs.class);
     pico.addSingleton(ComponentsWs.class);
     pico.addSingleton(ProjectsWs.class);
-    pico.addSingleton(ComponentAppAction.class);
+    pico.addSingleton(org.sonar.server.component.ws.AppAction.class);
     pico.addSingleton(org.sonar.server.component.ws.SearchAction.class);
     pico.addSingleton(EventsWs.class);
     pico.addSingleton(ComponentCleanerService.class);
-    pico.addSingleton(ProjectsProvisionedAction.class);
-    pico.addSingleton(ProjectsGhostsAction.class);
+    pico.addSingleton(ProvisionedAction.class);
+    pico.addSingleton(GhostsAction.class);
 
     // views
     pico.addSingleton(ViewIndexDefinition.class);
@@ -825,7 +812,7 @@ class ServerComponents {
     pico.addSingleton(IssueBulkChangeService.class);
     pico.addSingleton(IssueChangelogFormatter.class);
     pico.addSingleton(IssuesWs.class);
-    pico.addSingleton(IssueShowAction.class);
+    pico.addSingleton(org.sonar.server.issue.ws.ShowAction.class);
     pico.addSingleton(org.sonar.server.issue.ws.SearchAction.class);
     pico.addSingleton(org.sonar.server.issue.ws.TagsAction.class);
     pico.addSingleton(SetTagsAction.class);
@@ -882,7 +869,7 @@ class ServerComponents {
     pico.addSingleton(HtmlSourceDecorator.class);
     pico.addSingleton(SourceService.class);
     pico.addSingleton(SourcesWs.class);
-    pico.addSingleton(ShowAction.class);
+    pico.addSingleton(org.sonar.server.source.ws.ShowAction.class);
     pico.addSingleton(LinesAction.class);
     pico.addSingleton(HashAction.class);
     pico.addSingleton(RawAction.class);
@@ -911,8 +898,8 @@ class ServerComponents {
     // Tests
     pico.addSingleton(CoverageService.class);
     pico.addSingleton(TestsWs.class);
-    pico.addSingleton(TestsCoveredFilesAction.class);
-    pico.addSingleton(TestsListAction.class);
+    pico.addSingleton(CoveredFilesAction.class);
+    pico.addSingleton(ListAction.class);
     pico.addSingleton(TestIndexDefinition.class);
     pico.addSingleton(TestIndex.class);
     pico.addSingleton(TestIndexer.class);
@@ -940,11 +927,11 @@ class ServerComponents {
 
     // System
     pico.addSingletons(Arrays.asList(
-      SystemRestartWsAction.class,
-      SystemInfoWsAction.class,
-      UpgradesSystemWsAction.class,
-      MigrateDbSystemWsAction.class,
-      SystemStatusWsAction.class,
+      RestartAction.class,
+      InfoAction.class,
+      UpgradesAction.class,
+      MigrateDbSystemAction.class,
+      StatusAction.class,
       SystemWs.class,
       SystemMonitor.class,
       SonarQubeMonitor.class,
@@ -957,14 +944,14 @@ class ServerComponents {
     // Plugins WS
     pico.addSingleton(PluginWSCommons.class);
     pico.addSingleton(PluginUpdateAggregator.class);
-    pico.addSingleton(InstalledPluginsWsAction.class);
-    pico.addSingleton(AvailablePluginsWsAction.class);
-    pico.addSingleton(UpdatesPluginsWsAction.class);
-    pico.addSingleton(PendingPluginsWsAction.class);
-    pico.addSingleton(InstallPluginsWsAction.class);
-    pico.addSingleton(UpdatePluginsWsAction.class);
-    pico.addSingleton(UninstallPluginsWsAction.class);
-    pico.addSingleton(CancelAllPluginsWsAction.class);
+    pico.addSingleton(InstalledAction.class);
+    pico.addSingleton(AvailableAction.class);
+    pico.addSingleton(UpdatesAction.class);
+    pico.addSingleton(PendingAction.class);
+    pico.addSingleton(InstallAction.class);
+    pico.addSingleton(UpdateAction.class);
+    pico.addSingleton(UninstallAction.class);
+    pico.addSingleton(CancelAllAction.class);
     pico.addSingleton(PluginsWs.class);
 
     // Compute engine
@@ -972,8 +959,8 @@ class ServerComponents {
     pico.addSingleton(ComputationThreadLauncher.class);
     pico.addSingleton(ComputationWs.class);
     pico.addSingleton(IsQueueEmptyWs.class);
-    pico.addSingleton(QueueWsAction.class);
-    pico.addSingleton(HistoryWsAction.class);
+    pico.addSingleton(QueueAction.class);
+    pico.addSingleton(HistoryAction.class);
     pico.addSingleton(DefaultPeriodCleaner.class);
     pico.addSingleton(DefaultPurgeTask.class);
     pico.addSingleton(ProjectCleaner.class);
index d451ca173068810bd4ce73affab6cc336dc73fa7..b647c6c35ebcdc56f85daa95d75cbc2b565237cf 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.platform.monitoring;
 
 import org.sonar.api.ServerSide;
+import org.sonar.server.platform.ws.InfoAction;
 
 import java.util.LinkedHashMap;
 
@@ -35,7 +36,7 @@ public interface Monitor {
 
   /**
    * Type of attribute values must be supported by {@link org.sonar.api.utils.text.JsonWriter#valueObject(Object)}
-   * because of JSON export by {@link org.sonar.server.platform.ws.SystemInfoWsAction}
+   * because of JSON export by {@link InfoAction}
    */
   LinkedHashMap<String, Object> attributes();
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java
new file mode 100644 (file)
index 0000000..2507352
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.platform.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.platform.monitoring.Monitor;
+import org.sonar.server.user.UserSession;
+
+import java.util.Map;
+
+/**
+ * Implementation of the {@code info} action for the System WebService.
+ */
+public class InfoAction implements SystemWsAction {
+
+  private final Monitor[] monitors;
+  private final UserSession userSession;
+
+  public InfoAction(UserSession userSession, Monitor... monitors) {
+    this.userSession = userSession;
+    this.monitors = monitors;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("info")
+      .setDescription("Detailed information about system configuration." +
+        "<br/>" +
+        "Requires user to be authenticated with Administer System permissions.")
+      .setSince("5.1")
+      .setResponseExample(getClass().getResource("/org/sonar/server/platform/ws/example-system-info.json"))
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+    JsonWriter json = response.newJsonWriter();
+    writeJson(json);
+    json.close();
+  }
+
+  private void writeJson(JsonWriter json) {
+    json.beginObject();
+    for (Monitor monitor : monitors) {
+      json.name(monitor.name());
+      json.beginObject();
+      for (Map.Entry<String, Object> attribute : monitor.attributes().entrySet()) {
+        json.name(attribute.getKey()).valueObject(attribute.getValue());
+      }
+      json.endObject();
+    }
+    json.endObject();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbSystemAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbSystemAction.java
new file mode 100644 (file)
index 0000000..d2dddb3
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.persistence.Database;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.server.db.migrations.DatabaseMigration;
+
+import static org.sonar.server.db.migrations.DatabaseMigration.Status.RUNNING;
+
+/**
+ * Implementation of the {@code migrate_db} action for the System WebService.
+ */
+public class MigrateDbSystemAction implements SystemWsAction {
+
+  private static final String UNSUPPORTED_DATABASE_MIGRATION_STATUS = "Unsupported DatabaseMigration status";
+  private static final String MESSAGE_STATUS_NONE = "Database is up-to-date, no migration needed.";
+  private static final String MESSAGE_STATUS_RUNNING = "Database migration is running.";
+  private static final String MESSAGE_STATUS_SUCCEEDED = "Migration succeeded.";
+  private static final String MESSAGE_STATUS_FAILED = "Migration failed: %s.<br/> Please check logs.";
+
+  private static final String STATUS_NO_MIGRATION = "NO_MIGRATION";
+  private static final String STATUS_NOT_SUPPORTED = "NOT_SUPPORTED";
+  private static final String STATUS_MIGRATION_RUNNING = "MIGRATION_RUNNING";
+  private static final String STATUS_MIGRATION_FAILED = "MIGRATION_FAILED";
+  private static final String STATUS_MIGRATION_SUCCEEDED = "MIGRATION_SUCCEEDED";
+
+  private static final String PROPERTY_STATE = "state";
+  private static final String PROPERTY_MESSAGE = "message";
+  private static final String PROPERTY_STARTED_AT = "startedAt";
+
+  private final DatabaseVersion databaseVersion;
+  private final DatabaseMigration databaseMigration;
+  private final Database database;
+
+  public MigrateDbSystemAction(DatabaseVersion databaseVersion,
+                               Database database,
+                               DatabaseMigration databaseMigration) {
+    this.databaseVersion = databaseVersion;
+    this.database = database;
+    this.databaseMigration = databaseMigration;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("migrate_db")
+      .setDescription("Migrate the database to match the current version of SonarQube." +
+        "<br/>" +
+        "Sending a POST request to this URL starts the DB migration. " +
+        "It is strongly advised to <strong>make a database backup</strong> before invoking this WS." +
+        "<br/>" +
+        "State values are:" +
+        "<ul>" +
+        "<li>NO_MIGRATION: DB is up to date with current version of SonarQube.</li>" +
+        "<li>NOT_SUPPORTED: Migration is not supported on embedded databases.</li>" +
+        "<li>MIGRATION_RUNNING: DB migration is under go.</li>" +
+        "<li>MIGRATION_SUCCEEDED: DB migration has run and has been successful.</li>" +
+        "<li>MIGRATION_FAILED: DB migration has run and failed. SonarQube must be restarted in order to retry a " +
+        "DB migration (optionally after DB has been restored from backup).</li>" +
+        "</ul>")
+      .setSince("5.2")
+      .setPost(true)
+      .setHandler(this)
+      .setResponseExample(Resources.getResource(this.getClass(), "example-migrate_db.json"));
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    Integer currentVersion = databaseVersion.getVersion();
+    if (currentVersion == null) {
+      throw new IllegalStateException("Version can not be retrieved from Database. Database is either blank or corrupted");
+    }
+
+    if (currentVersion >= DatabaseVersion.LAST_VERSION) {
+      writeResponse(response, databaseMigration);
+    } else if (!database.getDialect().supportsMigration()) {
+      writeNotSupportedResponse(response);
+    } else {
+      switch (databaseMigration.status()) {
+        case RUNNING:
+        case FAILED:
+        case SUCCEEDED:
+          writeResponse(response, databaseMigration);
+          break;
+        case NONE:
+          databaseMigration.startIt();
+          writeNoneResponse(response, databaseMigration);
+          break;
+        default:
+          throw new IllegalArgumentException(UNSUPPORTED_DATABASE_MIGRATION_STATUS);
+      }
+    }
+  }
+
+  private void writeNotSupportedResponse(Response response) {
+    JsonWriter jsonWriter = response.newJsonWriter();
+    jsonWriter.beginObject()
+      .prop(PROPERTY_STATE, STATUS_NOT_SUPPORTED)
+      .prop(PROPERTY_MESSAGE, "Upgrade is not supported on embedded database.")
+      .endObject();
+    jsonWriter.close();
+  }
+
+  private void writeNoneResponse(Response response, DatabaseMigration databaseMigration) {
+    JsonWriter jsonWriter = response.newJsonWriter();
+    jsonWriter.beginObject()
+        .prop(PROPERTY_STATE, statusToJson(RUNNING))
+        .prop(PROPERTY_MESSAGE, MESSAGE_STATUS_RUNNING)
+        .propDateTime(PROPERTY_STARTED_AT, databaseMigration.startedAt())
+        .endObject();
+    jsonWriter.close();
+  }
+
+  private void writeResponse(Response response, DatabaseMigration databaseMigration) {
+    JsonWriter jsonWriter = response.newJsonWriter();
+    jsonWriter.beginObject()
+      .prop(PROPERTY_STATE, statusToJson(databaseMigration.status()))
+      .prop(PROPERTY_MESSAGE, buildMessage(databaseMigration))
+      .propDateTime(PROPERTY_STARTED_AT, databaseMigration.startedAt())
+      .endObject();
+    jsonWriter.close();
+  }
+
+  private String statusToJson(DatabaseMigration.Status status) {
+    switch (status) {
+      case NONE:
+        return STATUS_NO_MIGRATION;
+      case RUNNING:
+        return STATUS_MIGRATION_RUNNING;
+      case FAILED:
+        return STATUS_MIGRATION_FAILED;
+      case SUCCEEDED:
+        return STATUS_MIGRATION_SUCCEEDED;
+      default:
+        throw new IllegalArgumentException(
+          "Unsupported DatabaseMigration.Status " + status + " can not be converted to JSON value");
+    }
+  }
+
+  private static String buildMessage(DatabaseMigration databaseMigration) {
+    switch (databaseMigration.status()) {
+      case NONE:
+        return MESSAGE_STATUS_NONE;
+      case RUNNING:
+        return MESSAGE_STATUS_RUNNING;
+      case SUCCEEDED:
+        return MESSAGE_STATUS_SUCCEEDED;
+      case FAILED:
+        return String.format(MESSAGE_STATUS_FAILED, failureMessage(databaseMigration));
+      default:
+        return UNSUPPORTED_DATABASE_MIGRATION_STATUS;
+    }
+  }
+
+  private static String failureMessage(DatabaseMigration databaseMigration) {
+    Throwable failureError = databaseMigration.failureError();
+    if (failureError == null) {
+      return "No failure error";
+    }
+    return failureError.getMessage();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbSystemWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbSystemWsAction.java
deleted file mode 100644 (file)
index 97601e5..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.ws;
-
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.persistence.Database;
-import org.sonar.core.persistence.DatabaseVersion;
-import org.sonar.server.db.migrations.DatabaseMigration;
-
-import static org.sonar.server.db.migrations.DatabaseMigration.Status.RUNNING;
-
-/**
- * Implementation of the {@code migrate_db} action for the System WebService.
- */
-public class MigrateDbSystemWsAction implements SystemWsAction {
-
-  private static final String UNSUPPORTED_DATABASE_MIGRATION_STATUS = "Unsupported DatabaseMigration status";
-  private static final String MESSAGE_STATUS_NONE = "Database is up-to-date, no migration needed.";
-  private static final String MESSAGE_STATUS_RUNNING = "Database migration is running.";
-  private static final String MESSAGE_STATUS_SUCCEEDED = "Migration succeeded.";
-  private static final String MESSAGE_STATUS_FAILED = "Migration failed: %s.<br/> Please check logs.";
-
-  private static final String STATUS_NO_MIGRATION = "NO_MIGRATION";
-  private static final String STATUS_NOT_SUPPORTED = "NOT_SUPPORTED";
-  private static final String STATUS_MIGRATION_RUNNING = "MIGRATION_RUNNING";
-  private static final String STATUS_MIGRATION_FAILED = "MIGRATION_FAILED";
-  private static final String STATUS_MIGRATION_SUCCEEDED = "MIGRATION_SUCCEEDED";
-
-  private static final String PROPERTY_STATE = "state";
-  private static final String PROPERTY_MESSAGE = "message";
-  private static final String PROPERTY_STARTED_AT = "startedAt";
-
-  private final DatabaseVersion databaseVersion;
-  private final DatabaseMigration databaseMigration;
-  private final Database database;
-
-  public MigrateDbSystemWsAction(DatabaseVersion databaseVersion,
-    Database database,
-    DatabaseMigration databaseMigration) {
-    this.databaseVersion = databaseVersion;
-    this.database = database;
-    this.databaseMigration = databaseMigration;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("migrate_db")
-      .setDescription("Migrate the database to match the current version of SonarQube." +
-        "<br/>" +
-        "Sending a POST request to this URL starts the DB migration. " +
-        "It is strongly advised to <strong>make a database backup</strong> before invoking this WS." +
-        "<br/>" +
-        "State values are:" +
-        "<ul>" +
-        "<li>NO_MIGRATION: DB is up to date with current version of SonarQube.</li>" +
-        "<li>NOT_SUPPORTED: Migration is not supported on embedded databases.</li>" +
-        "<li>MIGRATION_RUNNING: DB migration is under go.</li>" +
-        "<li>MIGRATION_SUCCEEDED: DB migration has run and has been successful.</li>" +
-        "<li>MIGRATION_FAILED: DB migration has run and failed. SonarQube must be restarted in order to retry a " +
-        "DB migration (optionally after DB has been restored from backup).</li>" +
-        "</ul>")
-      .setSince("5.2")
-      .setPost(true)
-      .setHandler(this)
-      .setResponseExample(Resources.getResource(this.getClass(), "example-migrate_db.json"));
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    Integer currentVersion = databaseVersion.getVersion();
-    if (currentVersion == null) {
-      throw new IllegalStateException("Version can not be retrieved from Database. Database is either blank or corrupted");
-    }
-
-    if (currentVersion >= DatabaseVersion.LAST_VERSION) {
-      writeResponse(response, databaseMigration);
-    } else if (!database.getDialect().supportsMigration()) {
-      writeNotSupportedResponse(response);
-    } else {
-      switch (databaseMigration.status()) {
-        case RUNNING:
-        case FAILED:
-        case SUCCEEDED:
-          writeResponse(response, databaseMigration);
-          break;
-        case NONE:
-          databaseMigration.startIt();
-          writeNoneResponse(response, databaseMigration);
-          break;
-        default:
-          throw new IllegalArgumentException(UNSUPPORTED_DATABASE_MIGRATION_STATUS);
-      }
-    }
-  }
-
-  private void writeNotSupportedResponse(Response response) {
-    JsonWriter jsonWriter = response.newJsonWriter();
-    jsonWriter.beginObject()
-      .prop(PROPERTY_STATE, STATUS_NOT_SUPPORTED)
-      .prop(PROPERTY_MESSAGE, "Upgrade is not supported on embedded database.")
-      .endObject();
-    jsonWriter.close();
-  }
-
-  private void writeNoneResponse(Response response, DatabaseMigration databaseMigration) {
-    JsonWriter jsonWriter = response.newJsonWriter();
-    jsonWriter.beginObject()
-        .prop(PROPERTY_STATE, statusToJson(RUNNING))
-        .prop(PROPERTY_MESSAGE, MESSAGE_STATUS_RUNNING)
-        .propDateTime(PROPERTY_STARTED_AT, databaseMigration.startedAt())
-        .endObject();
-    jsonWriter.close();
-  }
-
-  private void writeResponse(Response response, DatabaseMigration databaseMigration) {
-    JsonWriter jsonWriter = response.newJsonWriter();
-    jsonWriter.beginObject()
-      .prop(PROPERTY_STATE, statusToJson(databaseMigration.status()))
-      .prop(PROPERTY_MESSAGE, buildMessage(databaseMigration))
-      .propDateTime(PROPERTY_STARTED_AT, databaseMigration.startedAt())
-      .endObject();
-    jsonWriter.close();
-  }
-
-  private String statusToJson(DatabaseMigration.Status status) {
-    switch (status) {
-      case NONE:
-        return STATUS_NO_MIGRATION;
-      case RUNNING:
-        return STATUS_MIGRATION_RUNNING;
-      case FAILED:
-        return STATUS_MIGRATION_FAILED;
-      case SUCCEEDED:
-        return STATUS_MIGRATION_SUCCEEDED;
-      default:
-        throw new IllegalArgumentException(
-          "Unsupported DatabaseMigration.Status " + status + " can not be converted to JSON value");
-    }
-  }
-
-  private static String buildMessage(DatabaseMigration databaseMigration) {
-    switch (databaseMigration.status()) {
-      case NONE:
-        return MESSAGE_STATUS_NONE;
-      case RUNNING:
-        return MESSAGE_STATUS_RUNNING;
-      case SUCCEEDED:
-        return MESSAGE_STATUS_SUCCEEDED;
-      case FAILED:
-        return String.format(MESSAGE_STATUS_FAILED, failureMessage(databaseMigration));
-      default:
-        return UNSUPPORTED_DATABASE_MIGRATION_STATUS;
-    }
-  }
-
-  private static String failureMessage(DatabaseMigration databaseMigration) {
-    Throwable failureError = databaseMigration.failureError();
-    if (failureError == null) {
-      return "No failure error";
-    }
-    return failureError.getMessage();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/RestartAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/RestartAction.java
new file mode 100644 (file)
index 0000000..f420452
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.sonar.api.config.Settings;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.platform.Platform;
+
+/**
+ * Implementation of the {@code restart} action for the System WebService.
+ */
+public class RestartAction implements SystemWsAction {
+
+  private static final Logger LOGGER = Loggers.get(RestartAction.class);
+
+  private final Settings settings;
+  private final Platform platform;
+
+  public RestartAction(Settings settings, Platform platform) {
+    this.settings = settings;
+    this.platform = platform;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("restart")
+      .setDescription("Restart server. Available only on development mode (sonar.web.dev=true). " +
+        "Ruby on Rails extensions are not reloaded.")
+      .setSince("4.3")
+      .setPost(true)
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    if (!settings.getBoolean("sonar.web.dev")) {
+      throw new ForbiddenException("Webservice available only in dev mode");
+    }
+
+    LOGGER.info("Restart server");
+    platform.restart();
+    LOGGER.info("Server restarted");
+    response.noContent();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/ServerWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/ServerWsAction.java
deleted file mode 100644 (file)
index 2e22c06..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.platform.ws;
-
-import org.sonar.server.ws.WsAction;
-
-/**
- * Marker interface for actions of the WS on URL api/server.
- */
-public interface ServerWsAction extends WsAction {
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/StatusAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/StatusAction.java
new file mode 100644 (file)
index 0000000..cbead05
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.sonar.api.platform.Server;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.IsAliveMapper;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.platform.Platform;
+
+import com.google.common.io.Resources;
+
+/**
+ * Implementation of the {@code status} action for the System WebService.
+ */
+public class StatusAction implements SystemWsAction {
+
+  private static final Logger LOGGER = Loggers.get(StatusAction.class);
+
+  private final Server server;
+  private final DatabaseMigration databaseMigration;
+  private final Platform platform;
+  private final DbClient dbClient;
+
+  public StatusAction(Server server, DatabaseMigration databaseMigration, Platform platform, DbClient dbClient) {
+    this.server = server;
+    this.databaseMigration = databaseMigration;
+    this.platform = platform;
+    this.dbClient = dbClient;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("status")
+      .setDescription("Get the server status:" +
+        "<ul>" +
+        "<li>UP: SonarQube instance is up and running</li>" +
+        "<li>DOWN: SonarQube instance is up but not running because SQ can not connect to database or " +
+        "migration has failed (refer to WS /api/system/migrate_db for details) or some other reason (check logs).</li>" +
+        "<li>DB_MIGRATION_NEEDED: database migration is required. DB migration can be started using WS /api/system/migrate_db.</li>" +
+        "<li>DB_MIGRATION_RUNNING: DB migration is running (refer to WS /api/system/migrate_db for details)</li>" +
+        "</ul>")
+      .setSince("5.2")
+      .setResponseExample(Resources.getResource(this.getClass(), "example-status.json"))
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter json = response.newJsonWriter();
+    writeJson(json);
+    json.close();
+  }
+
+  private void writeJson(JsonWriter json) {
+    Status status = computeStatus();
+
+    json.beginObject();
+    json.prop("id", server.getId());
+    json.prop("version", server.getVersion());
+    json.prop("status", status.toString());
+    json.endObject();
+  }
+
+  private Status computeStatus() {
+    if (!isConnectedToDB()) {
+      return Status.DOWN;
+    }
+
+    Platform.Status platformStatus = platform.status();
+    switch (platformStatus) {
+      case BOOTING:
+        // can not happen since there can not even exist an instance of the current class
+        // unless the Platform's status is UP or SAFEMODE
+        return Status.DOWN;
+      case UP:
+        return Status.UP;
+      case SAFEMODE:
+        return computeFromDbMigrationStatus();
+      default:
+        throw new IllegalArgumentException("Unsupported Platform.Status " + platformStatus);
+    }
+  }
+
+  private boolean isConnectedToDB() {
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      return dbSession.getMapper(IsAliveMapper.class).isAlive() == IsAliveMapper.IS_ALIVE_RETURNED_VALUE;
+    } catch (RuntimeException e) {
+      LOGGER.error("DB connection is down", e);
+      return false;
+    }
+  }
+
+  private Status computeFromDbMigrationStatus() {
+    DatabaseMigration.Status databaseMigrationStatus = databaseMigration.status();
+    switch (databaseMigrationStatus) {
+      case NONE:
+        return Status.DB_MIGRATION_NEEDED;
+      case RUNNING:
+        return Status.DB_MIGRATION_RUNNING;
+      case FAILED:
+        return Status.DOWN;
+      case SUCCEEDED:
+        // status of Platform is supposed to be UP _before_ DatabaseMigration status becomes UP too
+        // so, in theory, this case can not happen
+        return Status.UP;
+      default:
+        throw new IllegalArgumentException("Unsupported DatabaseMigration.Status " + databaseMigrationStatus);
+    }
+  }
+
+  private enum Status {
+    UP, DOWN, DB_MIGRATION_NEEDED, DB_MIGRATION_RUNNING
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemInfoWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemInfoWsAction.java
deleted file mode 100644 (file)
index a90d171..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.platform.ws;
-
-import java.util.Map;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.platform.monitoring.Monitor;
-import org.sonar.server.user.UserSession;
-
-/**
- * Implementation of the {@code info} action for the System WebService.
- */
-public class SystemInfoWsAction implements SystemWsAction {
-
-  private final Monitor[] monitors;
-  private final UserSession userSession;
-
-  public SystemInfoWsAction(UserSession userSession, Monitor... monitors) {
-    this.userSession = userSession;
-    this.monitors = monitors;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("info")
-      .setDescription("Detailed information about system configuration." +
-        "<br/>" +
-        "Requires user to be authenticated with Administer System permissions.")
-      .setSince("5.1")
-      .setResponseExample(getClass().getResource("/org/sonar/server/platform/ws/example-system-info.json"))
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
-    JsonWriter json = response.newJsonWriter();
-    writeJson(json);
-    json.close();
-  }
-
-  private void writeJson(JsonWriter json) {
-    json.beginObject();
-    for (Monitor monitor : monitors) {
-      json.name(monitor.name());
-      json.beginObject();
-      for (Map.Entry<String, Object> attribute : monitor.attributes().entrySet()) {
-        json.name(attribute.getKey()).valueObject(attribute.getValue());
-      }
-      json.endObject();
-    }
-    json.endObject();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemRestartWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemRestartWsAction.java
deleted file mode 100644 (file)
index 92665be..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.ws;
-
-import org.sonar.api.config.Settings;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.platform.Platform;
-
-/**
- * Implementation of the {@code restart} action for the System WebService.
- */
-public class SystemRestartWsAction implements SystemWsAction {
-
-  private static final Logger LOGGER = Loggers.get(SystemRestartWsAction.class);
-
-  private final Settings settings;
-  private final Platform platform;
-
-  public SystemRestartWsAction(Settings settings, Platform platform) {
-    this.settings = settings;
-    this.platform = platform;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("restart")
-      .setDescription("Restart server. Available only on development mode (sonar.web.dev=true). " +
-        "Ruby on Rails extensions are not reloaded.")
-      .setSince("4.3")
-      .setPost(true)
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    if (!settings.getBoolean("sonar.web.dev")) {
-      throw new ForbiddenException("Webservice available only in dev mode");
-    }
-
-    LOGGER.info("Restart server");
-    platform.restart();
-    LOGGER.info("Server restarted");
-    response.noContent();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemStatusWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemStatusWsAction.java
deleted file mode 100644 (file)
index 89e08b4..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.ws;
-
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.IsAliveMapper;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.db.migrations.DatabaseMigration;
-import org.sonar.server.platform.Platform;
-
-import com.google.common.io.Resources;
-
-/**
- * Implementation of the {@code status} action for the System WebService.
- */
-public class SystemStatusWsAction implements SystemWsAction {
-
-  private static final Logger LOGGER = Loggers.get(SystemStatusWsAction.class);
-
-  private final Server server;
-  private final DatabaseMigration databaseMigration;
-  private final Platform platform;
-  private final DbClient dbClient;
-
-  public SystemStatusWsAction(Server server, DatabaseMigration databaseMigration, Platform platform, DbClient dbClient) {
-    this.server = server;
-    this.databaseMigration = databaseMigration;
-    this.platform = platform;
-    this.dbClient = dbClient;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("status")
-      .setDescription("Get the server status:" +
-        "<ul>" +
-        "<li>UP: SonarQube instance is up and running</li>" +
-        "<li>DOWN: SonarQube instance is up but not running because SQ can not connect to database or " +
-        "migration has failed (refer to WS /api/system/migrate_db for details) or some other reason (check logs).</li>" +
-        "<li>DB_MIGRATION_NEEDED: database migration is required. DB migration can be started using WS /api/system/migrate_db.</li>" +
-        "<li>DB_MIGRATION_RUNNING: DB migration is running (refer to WS /api/system/migrate_db for details)</li>" +
-        "</ul>")
-      .setSince("5.2")
-      .setResponseExample(Resources.getResource(this.getClass(), "example-status.json"))
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter json = response.newJsonWriter();
-    writeJson(json);
-    json.close();
-  }
-
-  private void writeJson(JsonWriter json) {
-    Status status = computeStatus();
-
-    json.beginObject();
-    json.prop("id", server.getId());
-    json.prop("version", server.getVersion());
-    json.prop("status", status.toString());
-    json.endObject();
-  }
-
-  private Status computeStatus() {
-    if (!isConnectedToDB()) {
-      return Status.DOWN;
-    }
-
-    Platform.Status platformStatus = platform.status();
-    switch (platformStatus) {
-      case BOOTING:
-        // can not happen since there can not even exist an instance of the current class
-        // unless the Platform's status is UP or SAFEMODE
-        return Status.DOWN;
-      case UP:
-        return Status.UP;
-      case SAFEMODE:
-        return computeFromDbMigrationStatus();
-      default:
-        throw new IllegalArgumentException("Unsupported Platform.Status " + platformStatus);
-    }
-  }
-
-  private boolean isConnectedToDB() {
-    try (DbSession dbSession = dbClient.openSession(false)) {
-      return dbSession.getMapper(IsAliveMapper.class).isAlive() == IsAliveMapper.IS_ALIVE_RETURNED_VALUE;
-    } catch (RuntimeException e) {
-      LOGGER.error("DB connection is down", e);
-      return false;
-    }
-  }
-
-  private Status computeFromDbMigrationStatus() {
-    DatabaseMigration.Status databaseMigrationStatus = databaseMigration.status();
-    switch (databaseMigrationStatus) {
-      case NONE:
-        return Status.DB_MIGRATION_NEEDED;
-      case RUNNING:
-        return Status.DB_MIGRATION_RUNNING;
-      case FAILED:
-        return Status.DOWN;
-      case SUCCEEDED:
-        // status of Platform is supposed to be UP _before_ DatabaseMigration status becomes UP too
-        // so, in theory, this case can not happen
-        return Status.UP;
-      default:
-        throw new IllegalArgumentException("Unsupported DatabaseMigration.Status " + databaseMigrationStatus);
-    }
-  }
-
-  private enum Status {
-    UP, DOWN, DB_MIGRATION_NEEDED, DB_MIGRATION_RUNNING
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/UpgradesAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/UpgradesAction.java
new file mode 100644 (file)
index 0000000..3b7c0a8
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.ws.PluginWSCommons;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.Release;
+import org.sonar.updatecenter.common.SonarUpdate;
+import org.sonar.updatecenter.common.UpdateCenter;
+
+import java.util.List;
+
+/**
+ * Implementation of the {@code upgrades} action for the System WebService.
+ */
+public class UpgradesAction implements SystemWsAction {
+
+  private static final boolean DO_NOT_FORCE_REFRESH = false;
+
+  private static final String ARRAY_UPGRADES = "upgrades";
+  private static final String PROPERTY_UPDATE_CENTER_REFRESH = "updateCenterRefresh";
+  private static final String PROPERTY_VERSION = "version";
+  private static final String PROPERTY_DESCRIPTION = "description";
+  private static final String PROPERTY_RELEASE_DATE = "releaseDate";
+  private static final String PROPERTY_CHANGE_LOG_URL = "changeLogUrl";
+  private static final String PROPERTY_DOWNLOAD_URL = "downloadUrl";
+  private static final String OBJECT_PLUGINS = "plugins";
+  private static final String ARRAY_REQUIRE_UPDATE = "requireUpdate";
+  private static final String ARRAY_INCOMPATIBLE = "incompatible";
+
+  private final UpdateCenterMatrixFactory updateCenterFactory;
+  private final PluginWSCommons pluginWSCommons;
+
+  public UpgradesAction(UpdateCenterMatrixFactory updateCenterFactory, PluginWSCommons pluginWSCommons) {
+    this.updateCenterFactory = updateCenterFactory;
+    this.pluginWSCommons = pluginWSCommons;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("upgrades")
+      .setDescription("Lists available upgrades for the SonarQube instance (if any) and for each one, " +
+        "lists incompatible plugins and plugins requiring upgrade." +
+        "<br/>" +
+        "Plugin information is retrieved from Update Center. Date and time at which Update Center was last refreshed " +
+        "is provided in the response.")
+      .setHandler(this)
+      .setResponseExample(Resources.getResource(this.getClass(), "example-upgrades_plugins.json"));
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter jsonWriter = response.newJsonWriter().setSerializeEmptys(false);
+
+    writeResponse(jsonWriter);
+
+    jsonWriter.close();
+  }
+
+  private void writeResponse(JsonWriter jsonWriter) {
+    jsonWriter.beginObject();
+
+    UpdateCenter updateCenter = updateCenterFactory.getUpdateCenter(DO_NOT_FORCE_REFRESH);
+    writeUpgrades(jsonWriter, updateCenter);
+    jsonWriter.propDateTime(PROPERTY_UPDATE_CENTER_REFRESH, updateCenter.getDate());
+
+    jsonWriter.endObject();
+  }
+
+  private void writeUpgrades(JsonWriter jsonWriter, UpdateCenter updateCenter) {
+    jsonWriter.name(ARRAY_UPGRADES).beginArray();
+
+    for (SonarUpdate sonarUpdate : updateCenter.findSonarUpdates()) {
+      writeUpgrade(jsonWriter, sonarUpdate);
+    }
+
+    jsonWriter.endArray();
+  }
+
+  private void writeUpgrade(JsonWriter jsonWriter, SonarUpdate sonarUpdate) {
+    jsonWriter.beginObject();
+
+    writeMetadata(jsonWriter, sonarUpdate.getRelease());
+
+    writePlugins(jsonWriter, sonarUpdate);
+
+    jsonWriter.endObject();
+  }
+
+  private void writeMetadata(JsonWriter jsonWriter, Release release) {
+    jsonWriter.prop(PROPERTY_VERSION, release.getVersion().getName());
+    jsonWriter.prop(PROPERTY_DESCRIPTION, release.getDescription());
+    jsonWriter.propDate(PROPERTY_RELEASE_DATE, release.getDate());
+    jsonWriter.prop(PROPERTY_CHANGE_LOG_URL, release.getChangelogUrl());
+    jsonWriter.prop(PROPERTY_DOWNLOAD_URL, release.getDownloadUrl());
+  }
+
+  private void writePlugins(JsonWriter jsonWriter, SonarUpdate sonarUpdate) {
+    jsonWriter.name(OBJECT_PLUGINS).beginObject();
+
+    writePluginsToUpdate(jsonWriter, sonarUpdate.getPluginsToUpgrade());
+
+    writeIncompatiblePlugins(jsonWriter, sonarUpdate.getIncompatiblePlugins());
+
+    jsonWriter.endObject();
+  }
+
+  private void writePluginsToUpdate(JsonWriter jsonWriter, List<Release> pluginsToUpgrade) {
+    jsonWriter.name(ARRAY_REQUIRE_UPDATE).beginArray();
+    for (Release release : pluginsToUpgrade) {
+      jsonWriter.beginObject();
+
+      pluginWSCommons.writeMetadata(jsonWriter, (Plugin) release.getArtifact());
+      jsonWriter.prop(PROPERTY_VERSION, release.getVersion().toString());
+
+      jsonWriter.endObject();
+    }
+
+    jsonWriter.endArray();
+  }
+
+  private void writeIncompatiblePlugins(JsonWriter jsonWriter, List<Plugin> incompatiblePlugins) {
+    jsonWriter.name(ARRAY_INCOMPATIBLE).beginArray();
+
+    for (Plugin incompatiblePlugin : incompatiblePlugins) {
+      jsonWriter.beginObject();
+
+      pluginWSCommons.writeMetadata(jsonWriter, incompatiblePlugin);
+
+      jsonWriter.endObject();
+    }
+
+    jsonWriter.endArray();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/UpgradesSystemWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/UpgradesSystemWsAction.java
deleted file mode 100644 (file)
index 5e84555..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.ws;
-
-import java.util.List;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.plugins.ws.PluginWSCommons;
-import org.sonar.updatecenter.common.Plugin;
-import org.sonar.updatecenter.common.Release;
-import org.sonar.updatecenter.common.SonarUpdate;
-import org.sonar.updatecenter.common.UpdateCenter;
-
-import com.google.common.io.Resources;
-
-/**
- * Implementation of the {@code upgrades} action for the System WebService.
- */
-public class UpgradesSystemWsAction implements SystemWsAction {
-
-  private static final boolean DO_NOT_FORCE_REFRESH = false;
-
-  private static final String ARRAY_UPGRADES = "upgrades";
-  private static final String PROPERTY_UPDATE_CENTER_REFRESH = "updateCenterRefresh";
-  private static final String PROPERTY_VERSION = "version";
-  private static final String PROPERTY_DESCRIPTION = "description";
-  private static final String PROPERTY_RELEASE_DATE = "releaseDate";
-  private static final String PROPERTY_CHANGE_LOG_URL = "changeLogUrl";
-  private static final String PROPERTY_DOWNLOAD_URL = "downloadUrl";
-  private static final String OBJECT_PLUGINS = "plugins";
-  private static final String ARRAY_REQUIRE_UPDATE = "requireUpdate";
-  private static final String ARRAY_INCOMPATIBLE = "incompatible";
-
-  private final UpdateCenterMatrixFactory updateCenterFactory;
-  private final PluginWSCommons pluginWSCommons;
-
-  public UpgradesSystemWsAction(UpdateCenterMatrixFactory updateCenterFactory, PluginWSCommons pluginWSCommons) {
-    this.updateCenterFactory = updateCenterFactory;
-    this.pluginWSCommons = pluginWSCommons;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("upgrades")
-      .setDescription("Lists available upgrades for the SonarQube instance (if any) and for each one, " +
-        "lists incompatible plugins and plugins requiring upgrade." +
-        "<br/>" +
-        "Plugin information is retrieved from Update Center. Date and time at which Update Center was last refreshed " +
-        "is provided in the response.")
-      .setHandler(this)
-      .setResponseExample(Resources.getResource(this.getClass(), "example-upgrades_plugins.json"));
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter jsonWriter = response.newJsonWriter().setSerializeEmptys(false);
-
-    writeResponse(jsonWriter);
-
-    jsonWriter.close();
-  }
-
-  private void writeResponse(JsonWriter jsonWriter) {
-    jsonWriter.beginObject();
-
-    UpdateCenter updateCenter = updateCenterFactory.getUpdateCenter(DO_NOT_FORCE_REFRESH);
-    writeUpgrades(jsonWriter, updateCenter);
-    jsonWriter.propDateTime(PROPERTY_UPDATE_CENTER_REFRESH, updateCenter.getDate());
-
-    jsonWriter.endObject();
-  }
-
-  private void writeUpgrades(JsonWriter jsonWriter, UpdateCenter updateCenter) {
-    jsonWriter.name(ARRAY_UPGRADES).beginArray();
-
-    for (SonarUpdate sonarUpdate : updateCenter.findSonarUpdates()) {
-      writeUpgrade(jsonWriter, sonarUpdate);
-    }
-
-    jsonWriter.endArray();
-  }
-
-  private void writeUpgrade(JsonWriter jsonWriter, SonarUpdate sonarUpdate) {
-    jsonWriter.beginObject();
-
-    writeMetadata(jsonWriter, sonarUpdate.getRelease());
-
-    writePlugins(jsonWriter, sonarUpdate);
-
-    jsonWriter.endObject();
-  }
-
-  private void writeMetadata(JsonWriter jsonWriter, Release release) {
-    jsonWriter.prop(PROPERTY_VERSION, release.getVersion().getName());
-    jsonWriter.prop(PROPERTY_DESCRIPTION, release.getDescription());
-    jsonWriter.propDate(PROPERTY_RELEASE_DATE, release.getDate());
-    jsonWriter.prop(PROPERTY_CHANGE_LOG_URL, release.getChangelogUrl());
-    jsonWriter.prop(PROPERTY_DOWNLOAD_URL, release.getDownloadUrl());
-  }
-
-  private void writePlugins(JsonWriter jsonWriter, SonarUpdate sonarUpdate) {
-    jsonWriter.name(OBJECT_PLUGINS).beginObject();
-
-    writePluginsToUpdate(jsonWriter, sonarUpdate.getPluginsToUpgrade());
-
-    writeIncompatiblePlugins(jsonWriter, sonarUpdate.getIncompatiblePlugins());
-
-    jsonWriter.endObject();
-  }
-
-  private void writePluginsToUpdate(JsonWriter jsonWriter, List<Release> pluginsToUpgrade) {
-    jsonWriter.name(ARRAY_REQUIRE_UPDATE).beginArray();
-    for (Release release : pluginsToUpgrade) {
-      jsonWriter.beginObject();
-
-      pluginWSCommons.writeMetadata(jsonWriter, (Plugin) release.getArtifact());
-      jsonWriter.prop(PROPERTY_VERSION, release.getVersion().toString());
-
-      jsonWriter.endObject();
-    }
-
-    jsonWriter.endArray();
-  }
-
-  private void writeIncompatiblePlugins(JsonWriter jsonWriter, List<Plugin> incompatiblePlugins) {
-    jsonWriter.name(ARRAY_INCOMPATIBLE).beginArray();
-
-    for (Plugin incompatiblePlugin : incompatiblePlugins) {
-      jsonWriter.beginObject();
-
-      pluginWSCommons.writeMetadata(jsonWriter, incompatiblePlugin);
-
-      jsonWriter.endObject();
-    }
-
-    jsonWriter.endArray();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/AvailableAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/AvailableAction.java
new file mode 100644 (file)
index 0000000..4bb68ba
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.updatecenter.common.PluginUpdate;
+import org.sonar.updatecenter.common.UpdateCenter;
+
+import java.util.Collection;
+
+import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_PLUGIN_UPDATE_ORDERING;
+
+public class AvailableAction implements PluginsWsAction {
+
+  private static final boolean DO_NOT_FORCE_REFRESH = false;
+  private static final String ARRAY_PLUGINS = "plugins";
+
+  private final UpdateCenterMatrixFactory updateCenterFactory;
+  private final PluginWSCommons pluginWSCommons;
+
+  public AvailableAction(UpdateCenterMatrixFactory updateCenterFactory, PluginWSCommons pluginWSCommons) {
+    this.updateCenterFactory = updateCenterFactory;
+    this.pluginWSCommons = pluginWSCommons;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("available")
+      .setDescription("Get the list of all the plugins available for installation on the SonarQube instance, sorted by plugin name." +
+        "<br/>" +
+        "Plugin information is retrieved from Update Center. Date and time at which Update Center was last refreshed is provided in the response." +
+        "<br/>" +
+        "Update status values are: " +
+          "<ul>" +
+          "<li>COMPATIBLE: plugin is compatible with current SonarQube instance.</li>" +
+          "<li>INCOMPATIBLE: plugin is not compatible with current SonarQube instance.</li>" +
+          "<li>REQUIRES_SYSTEM_UPGRADE: plugin requires SonarQube to be upgraded before being installed.</li>" +
+          "<li>DEPS_REQUIRE_SYSTEM_UPGRADE: at least one plugin on which the plugin is dependent requires SonarQube to be upgraded.</li>" +
+          "</ul>")
+      .setSince("5.2")
+      .setHandler(this)
+      .setResponseExample(Resources.getResource(this.getClass(), "example-available_plugins.json"));
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter jsonWriter = response.newJsonWriter();
+    jsonWriter.beginObject();
+
+    UpdateCenter updateCenter = updateCenterFactory.getUpdateCenter(DO_NOT_FORCE_REFRESH);
+
+    writePlugins(jsonWriter, updateCenter);
+
+    pluginWSCommons.writeUpdateCenterProperties(jsonWriter, updateCenter);
+
+    jsonWriter.endObject();
+    jsonWriter.close();
+  }
+
+  private void writePlugins(JsonWriter jsonWriter, UpdateCenter updateCenter) {
+    jsonWriter.name(ARRAY_PLUGINS).beginArray();
+    for (PluginUpdate pluginUpdate : retrieveAvailablePlugins(updateCenter)) {
+      pluginWSCommons.writePluginUpdate(jsonWriter, pluginUpdate);
+    }
+    jsonWriter.endArray();
+  }
+
+  private Collection<PluginUpdate> retrieveAvailablePlugins(UpdateCenter updateCenter) {
+    return ImmutableSortedSet.copyOf(
+      NAME_KEY_PLUGIN_UPDATE_ORDERING,
+      updateCenter.findAvailablePlugins()
+      );
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/AvailablePluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/AvailablePluginsWsAction.java
deleted file mode 100644 (file)
index bb0d0ea..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.io.Resources;
-import java.util.Collection;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.updatecenter.common.PluginUpdate;
-import org.sonar.updatecenter.common.UpdateCenter;
-
-import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_PLUGIN_UPDATE_ORDERING;
-
-public class AvailablePluginsWsAction implements PluginsWsAction {
-
-  private static final boolean DO_NOT_FORCE_REFRESH = false;
-  private static final String ARRAY_PLUGINS = "plugins";
-
-  private final UpdateCenterMatrixFactory updateCenterFactory;
-  private final PluginWSCommons pluginWSCommons;
-
-  public AvailablePluginsWsAction(UpdateCenterMatrixFactory updateCenterFactory, PluginWSCommons pluginWSCommons) {
-    this.updateCenterFactory = updateCenterFactory;
-    this.pluginWSCommons = pluginWSCommons;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("available")
-      .setDescription("Get the list of all the plugins available for installation on the SonarQube instance, sorted by plugin name." +
-        "<br/>" +
-        "Plugin information is retrieved from Update Center. Date and time at which Update Center was last refreshed is provided in the response." +
-        "<br/>" +
-        "Update status values are: " +
-          "<ul>" +
-          "<li>COMPATIBLE: plugin is compatible with current SonarQube instance.</li>" +
-          "<li>INCOMPATIBLE: plugin is not compatible with current SonarQube instance.</li>" +
-          "<li>REQUIRES_SYSTEM_UPGRADE: plugin requires SonarQube to be upgraded before being installed.</li>" +
-          "<li>DEPS_REQUIRE_SYSTEM_UPGRADE: at least one plugin on which the plugin is dependent requires SonarQube to be upgraded.</li>" +
-          "</ul>")
-      .setSince("5.2")
-      .setHandler(this)
-      .setResponseExample(Resources.getResource(this.getClass(), "example-available_plugins.json"));
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter jsonWriter = response.newJsonWriter();
-    jsonWriter.beginObject();
-
-    UpdateCenter updateCenter = updateCenterFactory.getUpdateCenter(DO_NOT_FORCE_REFRESH);
-
-    writePlugins(jsonWriter, updateCenter);
-
-    pluginWSCommons.writeUpdateCenterProperties(jsonWriter, updateCenter);
-
-    jsonWriter.endObject();
-    jsonWriter.close();
-  }
-
-  private void writePlugins(JsonWriter jsonWriter, UpdateCenter updateCenter) {
-    jsonWriter.name(ARRAY_PLUGINS).beginArray();
-    for (PluginUpdate pluginUpdate : retrieveAvailablePlugins(updateCenter)) {
-      pluginWSCommons.writePluginUpdate(jsonWriter, pluginUpdate);
-    }
-    jsonWriter.endArray();
-  }
-
-  private Collection<PluginUpdate> retrieveAvailablePlugins(UpdateCenter updateCenter) {
-    return ImmutableSortedSet.copyOf(
-      NAME_KEY_PLUGIN_UPDATE_ORDERING,
-      updateCenter.findAvailablePlugins()
-      );
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllAction.java
new file mode 100644 (file)
index 0000000..2d10ce1
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.user.UserSession;
+
+public class CancelAllAction implements PluginsWsAction {
+
+  private final PluginDownloader pluginDownloader;
+  private final ServerPluginRepository pluginRepository;
+  private final UserSession userSession;
+
+  public CancelAllAction(PluginDownloader pluginDownloader, ServerPluginRepository pluginRepository, UserSession userSession) {
+    this.pluginDownloader = pluginDownloader;
+    this.pluginRepository = pluginRepository;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("cancel_all")
+      .setPost(true)
+      .setDescription("Cancels any operation pending on any plugin (install, update or uninstall)" +
+        "<br/>" +
+        "Requires user to be authenticated with Administer System permissions")
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+
+    pluginDownloader.cancelDownloads();
+    pluginRepository.cancelUninstalls();
+
+    response.noContent();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllPluginsWsAction.java
deleted file mode 100644 (file)
index 1812db2..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.user.UserSession;
-
-public class CancelAllPluginsWsAction implements PluginsWsAction {
-
-  private final PluginDownloader pluginDownloader;
-  private final ServerPluginRepository pluginRepository;
-  private final UserSession userSession;
-
-  public CancelAllPluginsWsAction(PluginDownloader pluginDownloader, ServerPluginRepository pluginRepository, UserSession userSession) {
-    this.pluginDownloader = pluginDownloader;
-    this.pluginRepository = pluginRepository;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("cancel_all")
-      .setPost(true)
-      .setDescription("Cancels any operation pending on any plugin (install, update or uninstall)" +
-        "<br/>" +
-        "Requires user to be authenticated with Administer System permissions")
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
-
-    pluginDownloader.cancelDownloads();
-    pluginRepository.cancelUninstalls();
-
-    response.noContent();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstallAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstallAction.java
new file mode 100644 (file)
index 0000000..e69f4d6
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.user.UserSession;
+import org.sonar.updatecenter.common.PluginUpdate;
+
+import javax.annotation.Nullable;
+
+import static java.lang.String.format;
+
+/**
+ * Implementation of the {@code install} action for the Plugins WebService.
+ */
+public class InstallAction implements PluginsWsAction {
+
+  private static final String PARAM_KEY = "key";
+  private static final PluginUpdate MISSING_PLUGIN = null;
+
+  private final UpdateCenterMatrixFactory updateCenterFactory;
+  private final PluginDownloader pluginDownloader;
+  private final UserSession userSession;
+
+  public InstallAction(UpdateCenterMatrixFactory updateCenterFactory,
+                       PluginDownloader pluginDownloader, UserSession userSession) {
+    this.updateCenterFactory = updateCenterFactory;
+    this.pluginDownloader = pluginDownloader;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("install")
+      .setPost(true)
+      .setDescription("Installs the latest version of a plugin specified by its key." +
+        "<br/>" +
+        "Plugin information is retrieved from Update Center." +
+        "<br/>" +
+        "Requires user to be authenticated with Administer System permissions")
+      .setHandler(this);
+
+    action.createParam(PARAM_KEY).setRequired(true)
+      .setDescription("The key identifying the plugin to install");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+    String key = request.mandatoryParam(PARAM_KEY);
+    PluginUpdate pluginUpdate = findAvailablePluginByKey(key);
+    pluginDownloader.download(key, pluginUpdate.getRelease().getVersion());
+    response.noContent();
+  }
+
+  private PluginUpdate findAvailablePluginByKey(String key) {
+    PluginUpdate pluginUpdate = Iterables.find(
+      updateCenterFactory.getUpdateCenter(false).findAvailablePlugins(),
+      hasKey(key),
+      MISSING_PLUGIN
+      );
+    if (pluginUpdate == MISSING_PLUGIN) {
+      throw new IllegalArgumentException(
+        format("No plugin with key '%s' or plugin '%s' is already installed in latest version", key, key));
+    }
+    return pluginUpdate;
+  }
+
+  private static PluginKeyPredicate hasKey(String key) {
+    return new PluginKeyPredicate(key);
+  }
+
+  private static class PluginKeyPredicate implements Predicate<PluginUpdate> {
+    private final String key;
+
+    public PluginKeyPredicate(String key) {
+      this.key = key;
+    }
+
+    @Override
+    public boolean apply(@Nullable PluginUpdate input) {
+      return input != null && key.equals(input.getPlugin().getKey());
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstallPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstallPluginsWsAction.java
deleted file mode 100644 (file)
index 3a55f4a..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import javax.annotation.Nullable;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.user.UserSession;
-import org.sonar.updatecenter.common.PluginUpdate;
-
-import static java.lang.String.format;
-
-/**
- * Implementation of the {@code install} action for the Plugins WebService.
- */
-public class InstallPluginsWsAction implements PluginsWsAction {
-
-  private static final String PARAM_KEY = "key";
-  private static final PluginUpdate MISSING_PLUGIN = null;
-
-  private final UpdateCenterMatrixFactory updateCenterFactory;
-  private final PluginDownloader pluginDownloader;
-  private final UserSession userSession;
-
-  public InstallPluginsWsAction(UpdateCenterMatrixFactory updateCenterFactory,
-                                PluginDownloader pluginDownloader, UserSession userSession) {
-    this.updateCenterFactory = updateCenterFactory;
-    this.pluginDownloader = pluginDownloader;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("install")
-      .setPost(true)
-      .setDescription("Installs the latest version of a plugin specified by its key." +
-        "<br/>" +
-        "Plugin information is retrieved from Update Center." +
-        "<br/>" +
-        "Requires user to be authenticated with Administer System permissions")
-      .setHandler(this);
-
-    action.createParam(PARAM_KEY).setRequired(true)
-      .setDescription("The key identifying the plugin to install");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
-    String key = request.mandatoryParam(PARAM_KEY);
-    PluginUpdate pluginUpdate = findAvailablePluginByKey(key);
-    pluginDownloader.download(key, pluginUpdate.getRelease().getVersion());
-    response.noContent();
-  }
-
-  private PluginUpdate findAvailablePluginByKey(String key) {
-    PluginUpdate pluginUpdate = Iterables.find(
-      updateCenterFactory.getUpdateCenter(false).findAvailablePlugins(),
-      hasKey(key),
-      MISSING_PLUGIN
-      );
-    if (pluginUpdate == MISSING_PLUGIN) {
-      throw new IllegalArgumentException(
-        format("No plugin with key '%s' or plugin '%s' is already installed in latest version", key, key));
-    }
-    return pluginUpdate;
-  }
-
-  private static PluginKeyPredicate hasKey(String key) {
-    return new PluginKeyPredicate(key);
-  }
-
-  private static class PluginKeyPredicate implements Predicate<PluginUpdate> {
-    private final String key;
-
-    public PluginKeyPredicate(String key) {
-      this.key = key;
-    }
-
-    @Override
-    public boolean apply(@Nullable PluginUpdate input) {
-      return input != null && key.equals(input.getPlugin().getKey());
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java
new file mode 100644 (file)
index 0000000..bd0adda
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.server.plugins.ServerPluginRepository;
+
+import javax.annotation.Nullable;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import static com.google.common.collect.Iterables.filter;
+import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_PLUGIN_METADATA_COMPARATOR;
+
+/**
+ * Implementation of the {@code installed} action for the Plugins WebService.
+ */
+public class InstalledAction implements PluginsWsAction {
+  private static final String ARRAY_PLUGINS = "plugins";
+
+  private final ServerPluginRepository pluginRepository;
+  private final PluginWSCommons pluginWSCommons;
+
+  public InstalledAction(ServerPluginRepository pluginRepository,
+                         PluginWSCommons pluginWSCommons) {
+    this.pluginRepository = pluginRepository;
+    this.pluginWSCommons = pluginWSCommons;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("installed")
+      .setDescription("Get the list of all the plugins installed on the SonarQube instance, sorted by plugin name")
+      .setSince("5.2")
+      .setHandler(this)
+      .setResponseExample(Resources.getResource(this.getClass(), "example-installed_plugins.json"));
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    Collection<PluginInfo> infos = retrieveAndSortPluginMetadata();
+
+    JsonWriter jsonWriter = response.newJsonWriter();
+    jsonWriter.setSerializeEmptys(false);
+    jsonWriter.beginObject();
+
+    writeMetadataList(jsonWriter, infos);
+
+    jsonWriter.endObject();
+    jsonWriter.close();
+  }
+
+  private SortedSet<PluginInfo> retrieveAndSortPluginMetadata() {
+    return ImmutableSortedSet.copyOf(
+      NAME_KEY_PLUGIN_METADATA_COMPARATOR,
+      filter(pluginRepository.getPluginInfos(), NotCorePluginsPredicate.INSTANCE)
+      );
+  }
+
+  private void writeMetadataList(JsonWriter jsonWriter, Collection<PluginInfo> pluginMetadatas) {
+    jsonWriter.name(ARRAY_PLUGINS);
+    jsonWriter.beginArray();
+    for (PluginInfo pluginMetadata : pluginMetadatas) {
+      pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
+    }
+    jsonWriter.endArray();
+  }
+
+  private enum NotCorePluginsPredicate implements Predicate<PluginInfo> {
+    INSTANCE;
+
+    @Override
+    public boolean apply(@Nullable PluginInfo input) {
+      return input != null && !input.isCore();
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java
deleted file mode 100644 (file)
index dc2f3ff..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.platform.PluginInfo;
-import org.sonar.server.plugins.ServerPluginRepository;
-
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-import java.util.SortedSet;
-
-import static com.google.common.collect.Iterables.filter;
-import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_PLUGIN_METADATA_COMPARATOR;
-
-/**
- * Implementation of the {@code installed} action for the Plugins WebService.
- */
-public class InstalledPluginsWsAction implements PluginsWsAction {
-  private static final String ARRAY_PLUGINS = "plugins";
-
-  private final ServerPluginRepository pluginRepository;
-  private final PluginWSCommons pluginWSCommons;
-
-  public InstalledPluginsWsAction(ServerPluginRepository pluginRepository,
-    PluginWSCommons pluginWSCommons) {
-    this.pluginRepository = pluginRepository;
-    this.pluginWSCommons = pluginWSCommons;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("installed")
-      .setDescription("Get the list of all the plugins installed on the SonarQube instance, sorted by plugin name")
-      .setSince("5.2")
-      .setHandler(this)
-      .setResponseExample(Resources.getResource(this.getClass(), "example-installed_plugins.json"));
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    Collection<PluginInfo> infos = retrieveAndSortPluginMetadata();
-
-    JsonWriter jsonWriter = response.newJsonWriter();
-    jsonWriter.setSerializeEmptys(false);
-    jsonWriter.beginObject();
-
-    writeMetadataList(jsonWriter, infos);
-
-    jsonWriter.endObject();
-    jsonWriter.close();
-  }
-
-  private SortedSet<PluginInfo> retrieveAndSortPluginMetadata() {
-    return ImmutableSortedSet.copyOf(
-      NAME_KEY_PLUGIN_METADATA_COMPARATOR,
-      filter(pluginRepository.getPluginInfos(), NotCorePluginsPredicate.INSTANCE)
-      );
-  }
-
-  private void writeMetadataList(JsonWriter jsonWriter, Collection<PluginInfo> pluginMetadatas) {
-    jsonWriter.name(ARRAY_PLUGINS);
-    jsonWriter.beginArray();
-    for (PluginInfo pluginMetadata : pluginMetadatas) {
-      pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
-    }
-    jsonWriter.endArray();
-  }
-
-  private enum NotCorePluginsPredicate implements Predicate<PluginInfo> {
-    INSTANCE;
-
-    @Override
-    public boolean apply(@Nullable PluginInfo input) {
-      return input != null && !input.isCore();
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingAction.java
new file mode 100644 (file)
index 0000000..86293e7
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerPluginRepository;
+
+import java.util.Collection;
+
+import static com.google.common.collect.ImmutableSortedSet.copyOf;
+import static com.google.common.io.Resources.getResource;
+import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_PLUGIN_METADATA_COMPARATOR;
+
+/**
+ * Implementation of the {@code pending} action for the Plugins WebService.
+ */
+public class PendingAction implements PluginsWsAction {
+
+  private static final String ARRAY_INSTALLING = "installing";
+  private static final String ARRAY_REMOVING = "removing";
+
+  private final PluginDownloader pluginDownloader;
+  private final ServerPluginRepository installer;
+  private final PluginWSCommons pluginWSCommons;
+
+  public PendingAction(PluginDownloader pluginDownloader,
+                       ServerPluginRepository installer,
+                       PluginWSCommons pluginWSCommons) {
+    this.pluginDownloader = pluginDownloader;
+    this.installer = installer;
+    this.pluginWSCommons = pluginWSCommons;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("pending")
+      .setDescription("Get the list of plugins which will either be installed or removed at the next startup of the SonarQube instance, sorted by plugin name")
+      .setSince("5.2")
+      .setHandler(this)
+      .setResponseExample(getResource(this.getClass(), "example-pending_plugins.json"));
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter jsonWriter = response.newJsonWriter();
+
+    jsonWriter.beginObject();
+
+    writeInstalling(jsonWriter);
+
+    writeRemoving(jsonWriter);
+
+    jsonWriter.endObject();
+    jsonWriter.close();
+  }
+
+  private void writeInstalling(JsonWriter jsonWriter) {
+    jsonWriter.name(ARRAY_INSTALLING);
+    jsonWriter.beginArray();
+    Collection<PluginInfo> plugins = pluginDownloader.getDownloadedPlugins();
+    for (PluginInfo pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
+      pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
+    }
+    jsonWriter.endArray();
+  }
+
+  private void writeRemoving(JsonWriter jsonWriter) {
+    jsonWriter.name(ARRAY_REMOVING);
+    jsonWriter.beginArray();
+    Collection<PluginInfo> plugins = installer.getUninstalledPlugins();
+    for (PluginInfo pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
+      pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
+    }
+    jsonWriter.endArray();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java
deleted file mode 100644 (file)
index 29eb3cc..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.platform.PluginInfo;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginRepository;
-
-import java.util.Collection;
-
-import static com.google.common.collect.ImmutableSortedSet.copyOf;
-import static com.google.common.io.Resources.getResource;
-import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_PLUGIN_METADATA_COMPARATOR;
-
-/**
- * Implementation of the {@code pending} action for the Plugins WebService.
- */
-public class PendingPluginsWsAction implements PluginsWsAction {
-
-  private static final String ARRAY_INSTALLING = "installing";
-  private static final String ARRAY_REMOVING = "removing";
-
-  private final PluginDownloader pluginDownloader;
-  private final ServerPluginRepository installer;
-  private final PluginWSCommons pluginWSCommons;
-
-  public PendingPluginsWsAction(PluginDownloader pluginDownloader,
-    ServerPluginRepository installer,
-    PluginWSCommons pluginWSCommons) {
-    this.pluginDownloader = pluginDownloader;
-    this.installer = installer;
-    this.pluginWSCommons = pluginWSCommons;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("pending")
-      .setDescription("Get the list of plugins which will either be installed or removed at the next startup of the SonarQube instance, sorted by plugin name")
-      .setSince("5.2")
-      .setHandler(this)
-      .setResponseExample(getResource(this.getClass(), "example-pending_plugins.json"));
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter jsonWriter = response.newJsonWriter();
-
-    jsonWriter.beginObject();
-
-    writeInstalling(jsonWriter);
-
-    writeRemoving(jsonWriter);
-
-    jsonWriter.endObject();
-    jsonWriter.close();
-  }
-
-  private void writeInstalling(JsonWriter jsonWriter) {
-    jsonWriter.name(ARRAY_INSTALLING);
-    jsonWriter.beginArray();
-    Collection<PluginInfo> plugins = pluginDownloader.getDownloadedPlugins();
-    for (PluginInfo pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
-      pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
-    }
-    jsonWriter.endArray();
-  }
-
-  private void writeRemoving(JsonWriter jsonWriter) {
-    jsonWriter.name(ARRAY_REMOVING);
-    jsonWriter.beginArray();
-    Collection<PluginInfo> plugins = installer.getUninstalledPlugins();
-    for (PluginInfo pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
-      pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
-    }
-    jsonWriter.endArray();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallAction.java
new file mode 100644 (file)
index 0000000..5e465fc
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.user.UserSession;
+
+import static java.lang.String.format;
+
+/**
+ * Implementation of the {@code uninstall} action for the Plugins WebService.
+ */
+public class UninstallAction implements PluginsWsAction {
+  private static final String PARAM_KEY = "key";
+
+  private final ServerPluginRepository pluginRepository;
+  private final UserSession userSession;
+
+  public UninstallAction(ServerPluginRepository pluginRepository, UserSession userSession) {
+    this.pluginRepository = pluginRepository;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("uninstall")
+      .setPost(true)
+      .setDescription("Uninstalls the plugin specified by its key." +
+        "<br/>" +
+        "Requires user to be authenticated with Administer System permissions.")
+      .setHandler(this);
+
+    action.createParam(PARAM_KEY)
+      .setDescription("The key identifying the plugin to uninstall")
+      .setRequired(true);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+    String key = request.mandatoryParam(PARAM_KEY);
+    ensurePluginIsInstalled(key);
+    pluginRepository.uninstall(key);
+    response.noContent();
+  }
+
+  // FIXME should be moved to ServerPluginRepository#uninstall(String)
+  private void ensurePluginIsInstalled(String key) {
+    if (!pluginRepository.hasPlugin(key)) {
+      throw new IllegalArgumentException(format("Plugin [%s] is not installed", key));
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallPluginsWsAction.java
deleted file mode 100644 (file)
index a4583e3..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.user.UserSession;
-
-import static java.lang.String.format;
-
-/**
- * Implementation of the {@code uninstall} action for the Plugins WebService.
- */
-public class UninstallPluginsWsAction implements PluginsWsAction {
-  private static final String PARAM_KEY = "key";
-
-  private final ServerPluginRepository pluginRepository;
-  private final UserSession userSession;
-
-  public UninstallPluginsWsAction(ServerPluginRepository pluginRepository, UserSession userSession) {
-    this.pluginRepository = pluginRepository;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("uninstall")
-      .setPost(true)
-      .setDescription("Uninstalls the plugin specified by its key." +
-        "<br/>" +
-        "Requires user to be authenticated with Administer System permissions.")
-      .setHandler(this);
-
-    action.createParam(PARAM_KEY)
-      .setDescription("The key identifying the plugin to uninstall")
-      .setRequired(true);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
-    String key = request.mandatoryParam(PARAM_KEY);
-    ensurePluginIsInstalled(key);
-    pluginRepository.uninstall(key);
-    response.noContent();
-  }
-
-  // FIXME should be moved to ServerPluginRepository#uninstall(String)
-  private void ensurePluginIsInstalled(String key) {
-    if (!pluginRepository.hasPlugin(key)) {
-      throw new IllegalArgumentException(format("Plugin [%s] is not installed", key));
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdateAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdateAction.java
new file mode 100644 (file)
index 0000000..1a8a3bc
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.user.UserSession;
+import org.sonar.updatecenter.common.PluginUpdate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import static java.lang.String.format;
+
+/**
+ * Implementation of the {@code update} action for the Plugins WebService.
+ */
+public class UpdateAction implements PluginsWsAction {
+
+  public static final String PARAM_KEY = "key";
+  public static final PluginUpdate MISSING_PLUGIN = null;
+
+  private final UpdateCenterMatrixFactory updateCenterFactory;
+  private final PluginDownloader pluginDownloader;
+  private final UserSession userSession;
+
+  public UpdateAction(UpdateCenterMatrixFactory updateCenterFactory, PluginDownloader pluginDownloader, UserSession userSession) {
+    this.updateCenterFactory = updateCenterFactory;
+    this.pluginDownloader = pluginDownloader;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("update")
+      .setPost(true)
+      .setDescription("Updates a plugin specified by its key to the latest version compatible with the SonarQube instance." +
+        "<br/>" +
+        "Plugin information is retrieved from Update Center." +
+        "<br/>" +
+        "Requires user to be authenticated with Administer System permissions")
+      .setHandler(this);
+
+    action.createParam(PARAM_KEY)
+      .setRequired(true)
+      .setDescription("The key identifying the plugin to update");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+    String key = request.mandatoryParam(PARAM_KEY);
+    PluginUpdate pluginUpdate = findPluginUpdateByKey(key);
+    pluginDownloader.download(key, pluginUpdate.getRelease().getVersion());
+    response.noContent();
+  }
+
+  @Nonnull
+  private PluginUpdate findPluginUpdateByKey(String key) {
+    PluginUpdate pluginUpdate = Iterables.find(
+      updateCenterFactory.getUpdateCenter(false).findPluginUpdates(),
+      new PluginKeyPredicate(key),
+      MISSING_PLUGIN
+      );
+    if (pluginUpdate == MISSING_PLUGIN) {
+      throw new IllegalArgumentException(
+        format("No plugin with key '%s' or plugin '%s' is already in latest compatible version", key, key));
+    }
+    return pluginUpdate;
+  }
+
+  private static class PluginKeyPredicate implements Predicate<PluginUpdate> {
+    private final String key;
+
+    public PluginKeyPredicate(String key) {
+      this.key = key;
+    }
+
+    @Override
+    public boolean apply(@Nullable PluginUpdate input) {
+      return input != null && key.equals(input.getPlugin().getKey());
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatePluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatePluginsWsAction.java
deleted file mode 100644 (file)
index 3738273..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.user.UserSession;
-import org.sonar.updatecenter.common.PluginUpdate;
-
-import static java.lang.String.format;
-
-/**
- * Implementation of the {@code update} action for the Plugins WebService.
- */
-public class UpdatePluginsWsAction implements PluginsWsAction {
-
-  public static final String PARAM_KEY = "key";
-  public static final PluginUpdate MISSING_PLUGIN = null;
-
-  private final UpdateCenterMatrixFactory updateCenterFactory;
-  private final PluginDownloader pluginDownloader;
-  private final UserSession userSession;
-
-  public UpdatePluginsWsAction(UpdateCenterMatrixFactory updateCenterFactory, PluginDownloader pluginDownloader, UserSession userSession) {
-    this.updateCenterFactory = updateCenterFactory;
-    this.pluginDownloader = pluginDownloader;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("update")
-      .setPost(true)
-      .setDescription("Updates a plugin specified by its key to the latest version compatible with the SonarQube instance." +
-        "<br/>" +
-        "Plugin information is retrieved from Update Center." +
-        "<br/>" +
-        "Requires user to be authenticated with Administer System permissions")
-      .setHandler(this);
-
-    action.createParam(PARAM_KEY)
-      .setRequired(true)
-      .setDescription("The key identifying the plugin to update");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
-    String key = request.mandatoryParam(PARAM_KEY);
-    PluginUpdate pluginUpdate = findPluginUpdateByKey(key);
-    pluginDownloader.download(key, pluginUpdate.getRelease().getVersion());
-    response.noContent();
-  }
-
-  @Nonnull
-  private PluginUpdate findPluginUpdateByKey(String key) {
-    PluginUpdate pluginUpdate = Iterables.find(
-      updateCenterFactory.getUpdateCenter(false).findPluginUpdates(),
-      new PluginKeyPredicate(key),
-      MISSING_PLUGIN
-      );
-    if (pluginUpdate == MISSING_PLUGIN) {
-      throw new IllegalArgumentException(
-        format("No plugin with key '%s' or plugin '%s' is already in latest compatible version", key, key));
-    }
-    return pluginUpdate;
-  }
-
-  private static class PluginKeyPredicate implements Predicate<PluginUpdate> {
-    private final String key;
-
-    public PluginKeyPredicate(String key) {
-      this.key = key;
-    }
-
-    @Override
-    public boolean apply(@Nullable PluginUpdate input) {
-      return input != null && key.equals(input.getPlugin().getKey());
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatesAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatesAction.java
new file mode 100644 (file)
index 0000000..1e60143
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Ordering;
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.ws.PluginUpdateAggregator.PluginUpdateAggregate;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.PluginUpdate;
+import org.sonar.updatecenter.common.UpdateCenter;
+
+import javax.annotation.Nonnull;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Implementation of the {@code updates} action for the Plugins WebService.
+ */
+public class UpdatesAction implements PluginsWsAction {
+
+  private static final boolean DO_NOT_FORCE_REFRESH = false;
+  private static final String ARRAY_PLUGINS = "plugins";
+  private static final String ARRAY_UPDATES = "updates";
+
+  private static final Ordering<PluginUpdateAggregate> NAME_KEY_PLUGIN_UPGRADE_AGGREGATE_ORDERING =
+    Ordering.from(PluginWSCommons.NAME_KEY_PLUGIN_ORDERING).onResultOf(PluginUpdateAggregateToPlugin.INSTANCE);
+  private static final Ordering<PluginUpdate> PLUGIN_UPDATE_BY_VERSION_ORDERING = Ordering.natural().onResultOf(new Function<PluginUpdate, String>() {
+    @Override
+    public String apply(@Nonnull PluginUpdate input) {
+      return input.getRelease().getVersion().toString();
+    }
+  });
+
+  private final UpdateCenterMatrixFactory updateCenterMatrixFactory;
+  private final PluginWSCommons pluginWSCommons;
+  private final PluginUpdateAggregator aggregator;
+
+  public UpdatesAction(UpdateCenterMatrixFactory updateCenterMatrixFactory,
+                       PluginWSCommons pluginWSCommons,
+                       PluginUpdateAggregator aggregator) {
+    this.updateCenterMatrixFactory = updateCenterMatrixFactory;
+    this.pluginWSCommons = pluginWSCommons;
+    this.aggregator = aggregator;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("updates")
+      .setDescription("Lists plugins installed on the SonarQube instance for which at least one newer version is available, sorted by plugin name." +
+        "<br/>" +
+        "Each newer version is listed, ordered from the oldest to the newest, with its own update/compatibility status." +
+        "<br/>" +
+        "Plugin information is retrieved from Update Center. Date and time at which Update Center was last refreshed is provided in the response." +
+        "<br/>" +
+        "Update status values are: [COMPATIBLE, INCOMPATIBLE, REQUIRES_UPGRADE, DEPS_REQUIRE_UPGRADE]")
+      .setSince("5.2")
+      .setHandler(this)
+      .setResponseExample(Resources.getResource(this.getClass(), "example-updates_plugins.json"));
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter jsonWriter = response.newJsonWriter();
+    jsonWriter.beginObject();
+
+    UpdateCenter updateCenter = updateCenterMatrixFactory.getUpdateCenter(DO_NOT_FORCE_REFRESH);
+
+    writePlugins(jsonWriter, updateCenter);
+
+    pluginWSCommons.writeUpdateCenterProperties(jsonWriter, updateCenter);
+
+    jsonWriter.endObject();
+    jsonWriter.close();
+  }
+
+  private void writePlugins(JsonWriter jsonWriter, UpdateCenter updateCenter) {
+    jsonWriter.name(ARRAY_PLUGINS);
+    jsonWriter.beginArray();
+    for (PluginUpdateAggregate aggregate : retrieveUpdatablePlugins(updateCenter)) {
+      writePluginUpdateAggregate(jsonWriter, aggregate);
+    }
+    jsonWriter.endArray();
+  }
+
+  private void writePluginUpdateAggregate(JsonWriter jsonWriter, PluginUpdateAggregate aggregate) {
+    jsonWriter.beginObject();
+    Plugin plugin = aggregate.getPlugin();
+
+    pluginWSCommons.writeMetadata(jsonWriter, plugin);
+
+    writeUpdates(jsonWriter, aggregate.getUpdates());
+
+    jsonWriter.endObject();
+  }
+
+  private void writeUpdates(JsonWriter jsonWriter, Collection<PluginUpdate> pluginUpdates) {
+    jsonWriter.name(ARRAY_UPDATES).beginArray();
+    for (PluginUpdate pluginUpdate : ImmutableSortedSet.copyOf(PLUGIN_UPDATE_BY_VERSION_ORDERING, pluginUpdates)) {
+      jsonWriter.beginObject();
+      pluginWSCommons.writeRelease(jsonWriter, pluginUpdate.getRelease());
+      pluginWSCommons.writeUpdateProperties(jsonWriter, pluginUpdate);
+      jsonWriter.endObject();
+    }
+    jsonWriter.endArray();
+  }
+
+  private Collection<PluginUpdateAggregate> retrieveUpdatablePlugins(UpdateCenter updateCenter) {
+    List<PluginUpdate> pluginUpdates = updateCenter.findPluginUpdates();
+    // aggregates updates of the same plugin to a single object and sort these objects by plugin name then key
+    return ImmutableSortedSet.copyOf(
+      NAME_KEY_PLUGIN_UPGRADE_AGGREGATE_ORDERING,
+      aggregator.aggregate(pluginUpdates)
+      );
+  }
+
+  private enum PluginUpdateAggregateToPlugin implements Function<PluginUpdateAggregate, Plugin> {
+    INSTANCE;
+
+    @Override
+    public Plugin apply(@Nonnull PluginUpdateAggregate input) {
+      return input.getPlugin();
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatesPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatesPluginsWsAction.java
deleted file mode 100644 (file)
index 0aedfd3..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import java.util.Collection;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.plugins.ws.PluginUpdateAggregator.PluginUpdateAggregate;
-import org.sonar.updatecenter.common.Plugin;
-import org.sonar.updatecenter.common.PluginUpdate;
-import org.sonar.updatecenter.common.UpdateCenter;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Ordering;
-import com.google.common.io.Resources;
-
-/**
- * Implementation of the {@code updates} action for the Plugins WebService.
- */
-public class UpdatesPluginsWsAction implements PluginsWsAction {
-
-  private static final boolean DO_NOT_FORCE_REFRESH = false;
-  private static final String ARRAY_PLUGINS = "plugins";
-  private static final String ARRAY_UPDATES = "updates";
-
-  private static final Ordering<PluginUpdateAggregate> NAME_KEY_PLUGIN_UPGRADE_AGGREGATE_ORDERING =
-    Ordering.from(PluginWSCommons.NAME_KEY_PLUGIN_ORDERING).onResultOf(PluginUpdateAggregateToPlugin.INSTANCE);
-  private static final Ordering<PluginUpdate> PLUGIN_UPDATE_BY_VERSION_ORDERING = Ordering.natural().onResultOf(new Function<PluginUpdate, String>() {
-    @Override
-    public String apply(@Nonnull PluginUpdate input) {
-      return input.getRelease().getVersion().toString();
-    }
-  });
-
-  private final UpdateCenterMatrixFactory updateCenterMatrixFactory;
-  private final PluginWSCommons pluginWSCommons;
-  private final PluginUpdateAggregator aggregator;
-
-  public UpdatesPluginsWsAction(UpdateCenterMatrixFactory updateCenterMatrixFactory,
-    PluginWSCommons pluginWSCommons,
-    PluginUpdateAggregator aggregator) {
-    this.updateCenterMatrixFactory = updateCenterMatrixFactory;
-    this.pluginWSCommons = pluginWSCommons;
-    this.aggregator = aggregator;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("updates")
-      .setDescription("Lists plugins installed on the SonarQube instance for which at least one newer version is available, sorted by plugin name." +
-        "<br/>" +
-        "Each newer version is listed, ordered from the oldest to the newest, with its own update/compatibility status." +
-        "<br/>" +
-        "Plugin information is retrieved from Update Center. Date and time at which Update Center was last refreshed is provided in the response." +
-        "<br/>" +
-        "Update status values are: [COMPATIBLE, INCOMPATIBLE, REQUIRES_UPGRADE, DEPS_REQUIRE_UPGRADE]")
-      .setSince("5.2")
-      .setHandler(this)
-      .setResponseExample(Resources.getResource(this.getClass(), "example-updates_plugins.json"));
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter jsonWriter = response.newJsonWriter();
-    jsonWriter.beginObject();
-
-    UpdateCenter updateCenter = updateCenterMatrixFactory.getUpdateCenter(DO_NOT_FORCE_REFRESH);
-
-    writePlugins(jsonWriter, updateCenter);
-
-    pluginWSCommons.writeUpdateCenterProperties(jsonWriter, updateCenter);
-
-    jsonWriter.endObject();
-    jsonWriter.close();
-  }
-
-  private void writePlugins(JsonWriter jsonWriter, UpdateCenter updateCenter) {
-    jsonWriter.name(ARRAY_PLUGINS);
-    jsonWriter.beginArray();
-    for (PluginUpdateAggregate aggregate : retrieveUpdatablePlugins(updateCenter)) {
-      writePluginUpdateAggregate(jsonWriter, aggregate);
-    }
-    jsonWriter.endArray();
-  }
-
-  private void writePluginUpdateAggregate(JsonWriter jsonWriter, PluginUpdateAggregate aggregate) {
-    jsonWriter.beginObject();
-    Plugin plugin = aggregate.getPlugin();
-
-    pluginWSCommons.writeMetadata(jsonWriter, plugin);
-
-    writeUpdates(jsonWriter, aggregate.getUpdates());
-
-    jsonWriter.endObject();
-  }
-
-  private void writeUpdates(JsonWriter jsonWriter, Collection<PluginUpdate> pluginUpdates) {
-    jsonWriter.name(ARRAY_UPDATES).beginArray();
-    for (PluginUpdate pluginUpdate : ImmutableSortedSet.copyOf(PLUGIN_UPDATE_BY_VERSION_ORDERING, pluginUpdates)) {
-      jsonWriter.beginObject();
-      pluginWSCommons.writeRelease(jsonWriter, pluginUpdate.getRelease());
-      pluginWSCommons.writeUpdateProperties(jsonWriter, pluginUpdate);
-      jsonWriter.endObject();
-    }
-    jsonWriter.endArray();
-  }
-
-  private Collection<PluginUpdateAggregate> retrieveUpdatablePlugins(UpdateCenter updateCenter) {
-    List<PluginUpdate> pluginUpdates = updateCenter.findPluginUpdates();
-    // aggregates updates of the same plugin to a single object and sort these objects by plugin name then key
-    return ImmutableSortedSet.copyOf(
-      NAME_KEY_PLUGIN_UPGRADE_AGGREGATE_ORDERING,
-      aggregator.aggregate(pluginUpdates)
-      );
-  }
-
-  private enum PluginUpdateAggregateToPlugin implements Function<PluginUpdateAggregate, Plugin> {
-    INSTANCE;
-
-    @Override
-    public Plugin apply(@Nonnull PluginUpdateAggregate input) {
-      return input.getPlugin();
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/DeleteAction.java
new file mode 100644 (file)
index 0000000..9596c36
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.component.ComponentCleanerService;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+public class DeleteAction implements ProjectsWsAction {
+  private static final String ACTION = "delete";
+  private static final String PARAM_UUIDS = "uuids";
+  private static final String PARAM_KEYS = "keys";
+
+  private final ComponentCleanerService componentCleanerService;
+  private final DbClient dbClient;
+  private final UserSession userSession;
+
+  public DeleteAction(ComponentCleanerService componentCleanerService, DbClient dbClient, UserSession userSession) {
+    this.componentCleanerService = componentCleanerService;
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context
+      .createAction(ACTION)
+      .setDescription("Delete one or several projects.<br /> Requires Admin permission.")
+      .setSince("5.2")
+      .setHandler(this);
+
+    action
+      .createParam(PARAM_UUIDS)
+      .setDescription("List of project UUIDs to delete")
+      .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d,c526ef20-131b-4486-9357-063fa64b5079");
+
+    action
+      .createParam(PARAM_KEYS)
+      .setDescription("List of project keys to delete")
+      .setExampleValue("org.apache.hbas:hbase,com.microsoft.roslyn:roslyn");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkGlobalPermission(UserRole.ADMIN);
+    List<String> uuids = request.paramAsStrings(PARAM_UUIDS);
+    List<String> keys = request.paramAsStrings(PARAM_KEYS);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      List<ComponentDto> projects = searchProjects(dbSession, uuids, keys);
+      componentCleanerService.delete(dbSession, projects);
+    } finally {
+      MyBatis.closeQuietly(dbSession);
+    }
+
+    response.noContent();
+  }
+
+  private List<ComponentDto> searchProjects(DbSession dbSession, @Nullable List<String> uuids, @Nullable List<String> keys) {
+    if (uuids != null) {
+      return dbClient.componentDao().selectByUuids(dbSession, uuids);
+    }
+    if (keys != null) {
+      return dbClient.componentDao().selectByKeys(dbSession, keys);
+    }
+
+    throw new IllegalArgumentException("UUIDs or keys must be provided");
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/GhostsAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/GhostsAction.java
new file mode 100644 (file)
index 0000000..b80814d
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+public class GhostsAction implements ProjectsWsAction {
+  public static final String ACTION = "ghosts";
+  private static final Set<String> POSSIBLE_FIELDS = newHashSet("uuid", "key", "name", "creationDate");
+
+  private final DbClient dbClient;
+  private final UserSession userSession;
+
+  public GhostsAction(DbClient dbClient, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    context
+      .createAction(ACTION)
+      .setDescription("List ghost projects.<br /> Requires 'Administer System' permission.")
+      .setResponseExample(Resources.getResource(getClass(), "projects-example-ghosts.json"))
+      .setSince("5.2")
+      .addPagingParams(100)
+      .addFieldsParam(POSSIBLE_FIELDS)
+      .addSearchQuery("sonar", "names", "keys")
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkGlobalPermission(UserRole.ADMIN);
+    DbSession dbSession = dbClient.openSession(false);
+    SearchOptions searchOptions = new SearchOptions()
+      .setPage(request.mandatoryParamAsInt(Param.PAGE),
+        request.mandatoryParamAsInt(Param.PAGE_SIZE));
+    Set<String> desiredFields = fieldsToReturn(request.paramAsStrings(Param.FIELDS));
+    String query = request.param(Param.TEXT_QUERY);
+
+    try {
+      long nbOfProjects = dbClient.componentDao().countGhostProjects(dbSession, query);
+      List<ComponentDto> projects = dbClient.componentDao().selectGhostProjects(dbSession, query, searchOptions);
+      JsonWriter json = response.newJsonWriter().beginObject();
+      writeProjects(json, projects, desiredFields);
+      searchOptions.writeJson(json, nbOfProjects);
+      json.endObject().close();
+    } finally {
+      MyBatis.closeQuietly(dbSession);
+    }
+  }
+
+  private void writeProjects(JsonWriter json, List<ComponentDto> projects, Set<String> fieldsToReturn) {
+    json.name("projects");
+    json.beginArray();
+    for (ComponentDto project : projects) {
+      json.beginObject();
+      json.prop("uuid", project.uuid());
+      writeIfWished(json, "key", project.key(), fieldsToReturn);
+      writeIfWished(json, "name", project.name(), fieldsToReturn);
+      writeIfWished(json, "creationDate", project.getCreatedAt(), fieldsToReturn);
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+  private void writeIfWished(JsonWriter json, String key, String value, Set<String> fieldsToReturn) {
+    if (fieldsToReturn.contains(key)) {
+      json.prop(key, value);
+    }
+  }
+
+  private void writeIfWished(JsonWriter json, String key, Date value, Set<String> desiredFields) {
+    if (desiredFields.contains(key)) {
+      json.propDateTime(key, value);
+    }
+  }
+
+  private Set<String> fieldsToReturn(@Nullable List<String> desiredFieldsFromRequest) {
+    if (desiredFieldsFromRequest == null) {
+      return POSSIBLE_FIELDS;
+    }
+
+    return newHashSet(desiredFieldsFromRequest);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java
new file mode 100644 (file)
index 0000000..8c70d26
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.RailsHandler;
+import org.sonar.api.server.ws.WebService;
+
+public class ProjectsWs implements WebService {
+  private static final String ENDPOINT = "api/projects";
+
+  private final ProjectsWsAction[] actions;
+
+  public ProjectsWs(ProjectsWsAction... actions) {
+    this.actions = actions;
+  }
+
+  @Override
+  public void define(Context context) {
+    NewController controller = context.createController(ENDPOINT)
+      .setSince("2.10")
+      .setDescription("Projects management");
+
+    defineIndexAction(controller);
+    defineCreateAction(controller);
+    defineDestroyAction(controller);
+
+    for (ProjectsWsAction action : actions) {
+      action.define(controller);
+    }
+
+    controller.done();
+  }
+
+  private void defineIndexAction(NewController controller) {
+    WebService.NewAction action = controller.createAction("index")
+      .setDescription("Search for projects")
+      .setSince("2.10")
+      .setHandler(RailsHandler.INSTANCE)
+      .setResponseExample(Resources.getResource(this.getClass(), "projects-example-index.json"));
+
+    action.createParam("key")
+      .setDescription("id or key of the project")
+      .setExampleValue("org.codehaus.sonar:sonar");
+
+    action.createParam("search")
+      .setDescription("Substring of project name, case insensitive")
+      .setExampleValue("Sonar");
+
+    action.createParam("desc")
+      .setDescription("Load project description")
+      .setDefaultValue("true")
+      .setPossibleValues("true", "false");
+
+    action.createParam("subprojects")
+      .setDescription("Load sub-projects. Ignored if the parameter key is set")
+      .setDefaultValue("false")
+      .setPossibleValues("true", "false");
+
+    action.createParam("views")
+      .setDescription("Load views and sub-views. Ignored if the parameter key is set")
+      .setDefaultValue("false")
+      .setPossibleValues("true", "false");
+
+    action.createParam("libs")
+      .setDescription("Load libraries. Ignored if the parameter key is set")
+      .setDefaultValue("false")
+      .setPossibleValues("true", "false");
+
+    action.createParam("versions")
+      .setDescription("Load version")
+      .setDefaultValue("false")
+      .setPossibleValues("true", "false", "last");
+
+    RailsHandler.addFormatParam(action);
+  }
+
+  private void defineCreateAction(NewController controller) {
+    WebService.NewAction action = controller.createAction("create")
+      .setDescription("Provision a project. Requires Provision Projects permission")
+      .setSince("4.0")
+      .setPost(true)
+      .setHandler(RailsHandler.INSTANCE)
+      .setResponseExample(Resources.getResource(this.getClass(), "projects-example-create.json"));
+
+    action.createParam("key")
+      .setDescription("Key of the project")
+      .setRequired(true)
+      .setExampleValue("org.codehaus.sonar:sonar");
+
+    action.createParam("name")
+      .setDescription("Name of the project")
+      .setRequired(true)
+      .setExampleValue("SonarQube");
+
+    action.createParam("branch")
+      .setDescription("SCM Branch of the project. The key of the project will become key:branch, for instance 'SonarQube:branch-5.0'")
+      .setRequired(false)
+      .setExampleValue("branch-5.0");
+
+    RailsHandler.addFormatParam(action);
+  }
+
+  private void defineDestroyAction(NewController controller) {
+    WebService.NewAction action = controller.createAction("destroy")
+      .setDescription("Delete a project. Requires Administer System permission")
+      .setSince("2.11")
+      .setPost(true)
+      .setHandler(RailsHandler.INSTANCE);
+
+    action.createParam("id")
+      .setDescription("id or key of the resource (ie: component)")
+      .setRequired(true)
+      .setExampleValue("org.codehaus.sonar:sonar");
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsAction.java
new file mode 100644 (file)
index 0000000..5792d51
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import org.sonar.server.ws.WsAction;
+
+public interface ProjectsWsAction extends WsAction {
+  // marker interface
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProvisionedAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProvisionedAction.java
new file mode 100644 (file)
index 0000000..8825707
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.user.UserSession;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+public class ProvisionedAction implements ProjectsWsAction {
+  private static final Set<String> POSSIBLE_FIELDS = newHashSet("uuid", "key", "name", "creationDate");
+
+  private final DbClient dbClient;
+  private final UserSession userSession;
+
+  public ProvisionedAction(DbClient dbClient, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller
+      .createAction("provisioned")
+      .setDescription(
+        "Get the list of provisioned projects.<br /> " +
+          "Require 'Provision Projects' permission.")
+      .setSince("5.2")
+      .setResponseExample(Resources.getResource(getClass(), "projects-example-provisioned.json"))
+      .setHandler(this)
+      .addPagingParams(100)
+      .addSearchQuery("sonar", "names", "keys")
+      .addFieldsParam(POSSIBLE_FIELDS);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkGlobalPermission(GlobalPermissions.PROVISIONING);
+    SearchOptions options = new SearchOptions().setPage(
+      request.mandatoryParamAsInt(Param.PAGE),
+      request.mandatoryParamAsInt(Param.PAGE_SIZE)
+      );
+    Set<String> desiredFields = desiredFields(request);
+    String query = request.param(Param.TEXT_QUERY);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      List<ComponentDto> projects = dbClient.componentDao().selectProvisionedProjects(dbSession, options, query);
+      int nbOfProjects = dbClient.componentDao().countProvisionedProjects(dbSession, query);
+      JsonWriter json = response.newJsonWriter().beginObject();
+      writeProjects(projects, json, desiredFields);
+      options.writeJson(json, nbOfProjects);
+      json.endObject().close();
+    } finally {
+      MyBatis.closeQuietly(dbSession);
+    }
+  }
+
+  private void writeProjects(List<ComponentDto> projects, JsonWriter json, Set<String> desiredFields) {
+    json.name("projects");
+    json.beginArray();
+    for (ComponentDto project : projects) {
+      json.beginObject();
+      json.prop("uuid", project.uuid());
+      writeIfNeeded(json, "key", project.key(), desiredFields);
+      writeIfNeeded(json, "name", project.name(), desiredFields);
+      writeIfNeeded(json, "creationDate", project.getCreatedAt(), desiredFields);
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+  private void writeIfNeeded(JsonWriter json, String fieldName, String value, Set<String> desiredFields) {
+    if (desiredFields.contains(fieldName)) {
+      json.prop(fieldName, value);
+    }
+  }
+
+  private void writeIfNeeded(JsonWriter json, String fieldName, Date date, Set<String> desiredFields) {
+    if (desiredFields.contains(fieldName)) {
+      json.propDateTime(fieldName, date);
+    }
+  }
+
+  private Set<String> desiredFields(Request request) {
+    List<String> desiredFields = request.paramAsStrings(Param.FIELDS);
+    if (desiredFields == null) {
+      return POSSIBLE_FIELDS;
+    }
+
+    return newHashSet(desiredFields);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/package-info.java
new file mode 100644 (file)
index 0000000..b02c9e3
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.project.ws;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/AppAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/AppAction.java
new file mode 100644 (file)
index 0000000..a0e0c40
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualitygate.ws;
+
+import org.apache.commons.lang.BooleanUtils;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.timemachine.Periods;
+import org.sonar.server.qualitygate.QualityGates;
+
+import java.util.Locale;
+
+public class AppAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  private final Periods periods;
+
+  private final I18n i18n;
+
+  public AppAction(QualityGates qualityGates, Periods periods, I18n i18n) {
+    this.qualityGates = qualityGates;
+    this.periods = periods;
+    this.i18n = i18n;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("app")
+      .setInternal(true)
+      .setDescription("Get initialization items for the admin UI. For internal use")
+      .setSince("4.3")
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    JsonWriter writer = response.newJsonWriter().beginObject();
+    addPermissions(writer);
+    addPeriods(writer);
+    addMetrics(writer);
+    writer.endObject().close();
+  }
+
+  private void addPermissions(JsonWriter writer) {
+    writer.prop("edit", qualityGates.currentUserHasWritePermission());
+  }
+
+  private void addPeriods(JsonWriter writer) {
+    writer.name("periods").beginArray();
+    for (int i = 0; i < 3; i++) {
+      writer.beginObject().prop("key", (long) i + 1).prop("text", periods.label(i + 1)).endObject();
+    }
+    addProjectPeriod(4, writer);
+    addProjectPeriod(5, writer);
+    writer.endArray();
+  }
+
+  private void addProjectPeriod(int periodIndex, JsonWriter writer) {
+    writer.beginObject().prop("key", periodIndex).prop("text",
+      i18n.message(Locale.getDefault(), "quality_gates.project_period", "Period " + periodIndex, periodIndex)
+      ).endObject();
+  }
+
+  private void addMetrics(JsonWriter writer) {
+    writer.name("metrics").beginArray();
+    for (Metric metric : qualityGates.gateMetrics()) {
+      writer.beginObject()
+        .prop("id", metric.getId())
+        .prop("key", metric.getKey())
+        .prop("name", metric.getName())
+        .prop("type", metric.getType().toString())
+        .prop("domain", metric.getDomain())
+        .prop("hidden", BooleanUtils.isNotFalse(metric.isHidden()))
+        .endObject();
+    }
+    writer.endArray();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java
new file mode 100644 (file)
index 0000000..8c93072
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.qualitygate.db.QualityGateDto;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class CopyAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public CopyAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("copy")
+      .setDescription("Copy a Quality Gate. Require Administer Quality Profiles and Gates permission")
+      .setPost(true)
+      .setSince("4.3")
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_ID)
+      .setDescription("The ID of the source quality gate")
+      .setRequired(true)
+      .setExampleValue("1");
+
+    action.createParam(QGatesWs.PARAM_NAME)
+      .setDescription("The name of the quality gate to create")
+      .setRequired(true)
+      .setExampleValue("My Quality Gate");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    QualityGateDto newQualityGate = qualityGates.copy(QGatesWs.parseId(request, QGatesWs.PARAM_ID), request.mandatoryParam(QGatesWs.PARAM_NAME));
+    JsonWriter writer = response.newJsonWriter();
+    QGatesWs.writeQualityGate(newQualityGate, writer).close();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java
new file mode 100644 (file)
index 0000000..d83aae3
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.qualitygate.db.QualityGateDto;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class CreateAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public CreateAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("create")
+      .setDescription("Create a Quality Gate. Require Administer Quality Profiles and Gates permission")
+      .setSince("4.3")
+      .setPost(true)
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_NAME)
+      .setDescription("The name of the quality gate to create")
+      .setRequired(true)
+      .setExampleValue("My Quality Gate");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    QualityGateDto newQualityGate = qualityGates.create(request.mandatoryParam(QGatesWs.PARAM_NAME));
+    JsonWriter writer = response.newJsonWriter();
+    QGatesWs.writeQualityGate(newQualityGate, writer).close();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java
new file mode 100644 (file)
index 0000000..69a796d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class CreateConditionAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public CreateConditionAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction createCondition = controller.createAction("create_condition")
+      .setDescription("Add a new condition to a quality gate. Require Administer Quality Profiles and Gates permission")
+      .setPost(true)
+      .setSince("4.3")
+      .setHandler(this);
+
+    createCondition
+      .createParam(QGatesWs.PARAM_GATE_ID)
+      .setDescription("ID of the quality gate")
+      .setRequired(true)
+      .setExampleValue("1");
+
+    QGatesWs.addConditionParams(createCondition);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    QGatesWs.writeQualityGateCondition(
+      qualityGates.createCondition(
+        QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID),
+        request.mandatoryParam(QGatesWs.PARAM_METRIC),
+        request.mandatoryParam(QGatesWs.PARAM_OPERATOR),
+        request.param(QGatesWs.PARAM_WARNING),
+        request.param(QGatesWs.PARAM_ERROR),
+        request.paramAsInt(QGatesWs.PARAM_PERIOD)
+        ), response.newJsonWriter()
+      ).close();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java
new file mode 100644 (file)
index 0000000..f7d1d07
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class DeleteConditionAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public DeleteConditionAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction createCondition = controller.createAction("delete_condition")
+      .setDescription("Delete a condition from a quality gate. Require Administer Quality Profiles and Gates permission")
+      .setPost(true)
+      .setSince("4.3")
+      .setHandler(this);
+
+    createCondition
+      .createParam(QGatesWs.PARAM_ID)
+      .setRequired(true)
+      .setDescription("Condition ID")
+      .setExampleValue("2");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    qualityGates.deleteCondition(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
+    response.noContent();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java
new file mode 100644 (file)
index 0000000..941efa1
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class DeselectAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public DeselectAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("deselect")
+      .setDescription("Remove the association of a project from a quality gate. Require Administer Quality Profiles and Gates permission")
+      .setPost(true)
+      .setSince("4.3")
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_GATE_ID)
+      .setDescription("Quality Gate ID")
+      .setRequired(true)
+      .setExampleValue("1");
+
+    action.createParam(QGatesWs.PARAM_PROJECT_ID)
+      .setDescription("Project ID")
+      .setRequired(true)
+      .setExampleValue("12");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    qualityGates.dissociateProject(QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID), QGatesWs.parseId(request, QGatesWs.PARAM_PROJECT_ID));
+    response.noContent();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java
new file mode 100644 (file)
index 0000000..85b706c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class DestroyAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public DestroyAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("destroy")
+      .setDescription("Delete a Quality Gate. Require Administer Quality Profiles and Gates permission")
+      .setSince("4.3")
+      .setPost(true)
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_ID)
+      .setDescription("ID of the quality gate to delete")
+      .setRequired(true)
+      .setExampleValue("1");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    qualityGates.delete(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
+    response.noContent();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ListAction.java
new file mode 100644 (file)
index 0000000..a185621
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.qualitygate.db.QualityGateDto;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class ListAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public ListAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("list")
+      .setDescription("Get a list of quality gates")
+      .setSince("4.3")
+      .setResponseExample(Resources.getResource(this.getClass(), "example-list.json"))
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    JsonWriter writer = response.newJsonWriter().beginObject().name("qualitygates").beginArray();
+    for (QualityGateDto qgate : qualityGates.list()) {
+      QGatesWs.writeQualityGate(qgate, writer);
+    }
+    writer.endArray();
+    QualityGateDto defaultQgate = qualityGates.getDefault();
+    if (defaultQgate != null) {
+      writer.prop("default", defaultQgate.getId());
+    }
+    writer.endObject().close();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesAppAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesAppAction.java
deleted file mode 100644 (file)
index 1996e96..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualitygate.ws;
-
-import org.apache.commons.lang.BooleanUtils;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.timemachine.Periods;
-import org.sonar.server.qualitygate.QualityGates;
-
-import java.util.Locale;
-
-public class QGatesAppAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  private final Periods periods;
-
-  private final I18n i18n;
-
-  public QGatesAppAction(QualityGates qualityGates, Periods periods, I18n i18n) {
-    this.qualityGates = qualityGates;
-    this.periods = periods;
-    this.i18n = i18n;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("app")
-      .setInternal(true)
-      .setDescription("Get initialization items for the admin UI. For internal use")
-      .setSince("4.3")
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    JsonWriter writer = response.newJsonWriter().beginObject();
-    addPermissions(writer);
-    addPeriods(writer);
-    addMetrics(writer);
-    writer.endObject().close();
-  }
-
-  private void addPermissions(JsonWriter writer) {
-    writer.prop("edit", qualityGates.currentUserHasWritePermission());
-  }
-
-  private void addPeriods(JsonWriter writer) {
-    writer.name("periods").beginArray();
-    for (int i = 0; i < 3; i++) {
-      writer.beginObject().prop("key", (long) i + 1).prop("text", periods.label(i + 1)).endObject();
-    }
-    addProjectPeriod(4, writer);
-    addProjectPeriod(5, writer);
-    writer.endArray();
-  }
-
-  private void addProjectPeriod(int periodIndex, JsonWriter writer) {
-    writer.beginObject().prop("key", periodIndex).prop("text",
-      i18n.message(Locale.getDefault(), "quality_gates.project_period", "Period " + periodIndex, periodIndex)
-      ).endObject();
-  }
-
-  private void addMetrics(JsonWriter writer) {
-    writer.name("metrics").beginArray();
-    for (Metric metric : qualityGates.gateMetrics()) {
-      writer.beginObject()
-        .prop("id", metric.getId())
-        .prop("key", metric.getKey())
-        .prop("name", metric.getName())
-        .prop("type", metric.getType().toString())
-        .prop("domain", metric.getDomain())
-        .prop("hidden", BooleanUtils.isNotFalse(metric.isHidden()))
-        .endObject();
-    }
-    writer.endArray();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCopyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCopyAction.java
deleted file mode 100644 (file)
index c61f2a2..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.qualitygate.db.QualityGateDto;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesCopyAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesCopyAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("copy")
-      .setDescription("Copy a Quality Gate. Require Administer Quality Profiles and Gates permission")
-      .setPost(true)
-      .setSince("4.3")
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_ID)
-      .setDescription("The ID of the source quality gate")
-      .setRequired(true)
-      .setExampleValue("1");
-
-    action.createParam(QGatesWs.PARAM_NAME)
-      .setDescription("The name of the quality gate to create")
-      .setRequired(true)
-      .setExampleValue("My Quality Gate");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    QualityGateDto newQualityGate = qualityGates.copy(QGatesWs.parseId(request, QGatesWs.PARAM_ID), request.mandatoryParam(QGatesWs.PARAM_NAME));
-    JsonWriter writer = response.newJsonWriter();
-    QGatesWs.writeQualityGate(newQualityGate, writer).close();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCreateAction.java
deleted file mode 100644 (file)
index d311489..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.qualitygate.db.QualityGateDto;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesCreateAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesCreateAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("create")
-      .setDescription("Create a Quality Gate. Require Administer Quality Profiles and Gates permission")
-      .setSince("4.3")
-      .setPost(true)
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_NAME)
-      .setDescription("The name of the quality gate to create")
-      .setRequired(true)
-      .setExampleValue("My Quality Gate");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    QualityGateDto newQualityGate = qualityGates.create(request.mandatoryParam(QGatesWs.PARAM_NAME));
-    JsonWriter writer = response.newJsonWriter();
-    QGatesWs.writeQualityGate(newQualityGate, writer).close();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCreateConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesCreateConditionAction.java
deleted file mode 100644 (file)
index 927622e..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesCreateConditionAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesCreateConditionAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction createCondition = controller.createAction("create_condition")
-      .setDescription("Add a new condition to a quality gate. Require Administer Quality Profiles and Gates permission")
-      .setPost(true)
-      .setSince("4.3")
-      .setHandler(this);
-
-    createCondition
-      .createParam(QGatesWs.PARAM_GATE_ID)
-      .setDescription("ID of the quality gate")
-      .setRequired(true)
-      .setExampleValue("1");
-
-    QGatesWs.addConditionParams(createCondition);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    QGatesWs.writeQualityGateCondition(
-      qualityGates.createCondition(
-        QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID),
-        request.mandatoryParam(QGatesWs.PARAM_METRIC),
-        request.mandatoryParam(QGatesWs.PARAM_OPERATOR),
-        request.param(QGatesWs.PARAM_WARNING),
-        request.param(QGatesWs.PARAM_ERROR),
-        request.paramAsInt(QGatesWs.PARAM_PERIOD)
-        ), response.newJsonWriter()
-      ).close();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDeleteConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDeleteConditionAction.java
deleted file mode 100644 (file)
index 2edfc8d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesDeleteConditionAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesDeleteConditionAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction createCondition = controller.createAction("delete_condition")
-      .setDescription("Delete a condition from a quality gate. Require Administer Quality Profiles and Gates permission")
-      .setPost(true)
-      .setSince("4.3")
-      .setHandler(this);
-
-    createCondition
-      .createParam(QGatesWs.PARAM_ID)
-      .setRequired(true)
-      .setDescription("Condition ID")
-      .setExampleValue("2");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    qualityGates.deleteCondition(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
-    response.noContent();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDeselectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDeselectAction.java
deleted file mode 100644 (file)
index 8bdcb84..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesDeselectAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesDeselectAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("deselect")
-      .setDescription("Remove the association of a project from a quality gate. Require Administer Quality Profiles and Gates permission")
-      .setPost(true)
-      .setSince("4.3")
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_GATE_ID)
-      .setDescription("Quality Gate ID")
-      .setRequired(true)
-      .setExampleValue("1");
-
-    action.createParam(QGatesWs.PARAM_PROJECT_ID)
-      .setDescription("Project ID")
-      .setRequired(true)
-      .setExampleValue("12");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    qualityGates.dissociateProject(QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID), QGatesWs.parseId(request, QGatesWs.PARAM_PROJECT_ID));
-    response.noContent();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDestroyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesDestroyAction.java
deleted file mode 100644 (file)
index e8aa787..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesDestroyAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesDestroyAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("destroy")
-      .setDescription("Delete a Quality Gate. Require Administer Quality Profiles and Gates permission")
-      .setSince("4.3")
-      .setPost(true)
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_ID)
-      .setDescription("ID of the quality gate to delete")
-      .setRequired(true)
-      .setExampleValue("1");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    qualityGates.delete(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
-    response.noContent();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesListAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesListAction.java
deleted file mode 100644 (file)
index d7f5d37..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.qualitygate.db.QualityGateDto;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesListAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesListAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("list")
-      .setDescription("Get a list of quality gates")
-      .setSince("4.3")
-      .setResponseExample(Resources.getResource(this.getClass(), "example-list.json"))
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    JsonWriter writer = response.newJsonWriter().beginObject().name("qualitygates").beginArray();
-    for (QualityGateDto qgate : qualityGates.list()) {
-      QGatesWs.writeQualityGate(qgate, writer);
-    }
-    writer.endArray();
-    QualityGateDto defaultQgate = qualityGates.getDefault();
-    if (defaultQgate != null) {
-      writer.prop("default", defaultQgate.getId());
-    }
-    writer.endObject().close();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesRenameAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesRenameAction.java
deleted file mode 100644 (file)
index 8491c29..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.qualitygate.db.QualityGateDto;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesRenameAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesRenameAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("rename")
-      .setDescription("Rename a Quality Gate. Require Administer Quality Profiles and Gates permission")
-      .setPost(true)
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_ID)
-      .setDescription("ID of the quality gate to rename")
-      .setRequired(true)
-      .setExampleValue("1");
-
-    action.createParam(QGatesWs.PARAM_NAME)
-      .setDescription("New name of the quality gate")
-      .setRequired(true)
-      .setExampleValue("My Quality Gate");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    long idToRename = QGatesWs.parseId(request, QGatesWs.PARAM_ID);
-    QualityGateDto renamedQualityGate = qualityGates.rename(idToRename, request.mandatoryParam(QGatesWs.PARAM_NAME));
-    JsonWriter writer = response.newJsonWriter();
-    QGatesWs.writeQualityGate(renamedQualityGate, writer).close();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSearchAction.java
deleted file mode 100644 (file)
index e21973c..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.qualitygate.db.ProjectQgateAssociation;
-import org.sonar.core.qualitygate.db.ProjectQgateAssociationQuery;
-import org.sonar.server.qualitygate.QgateProjectFinder;
-
-public class QGatesSearchAction implements QGateWsAction {
-
-  private final QgateProjectFinder projectFinder;
-
-  public QGatesSearchAction(QgateProjectFinder projectFinder) {
-    this.projectFinder = projectFinder;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("search")
-      .setDescription("Search for projects associated (or not) to a quality gate")
-      .setSince("4.3")
-      .setResponseExample(Resources.getResource(this.getClass(), "example-search.json"))
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_GATE_ID)
-      .setDescription("Quality Gate ID")
-      .setRequired(true)
-      .setExampleValue("1");
-
-    action.createParam(QGatesWs.PARAM_QUERY)
-      .setDescription("To search for projects containing this string. If this parameter is set, \"selected\" is set to \"all\".")
-      .setExampleValue("abc");
-
-    action.createParam(QGatesWs.PARAM_SELECTED)
-      .setDescription("If \"selected\", search for projects associated to the quality gate")
-      .setDefaultValue(ProjectQgateAssociationQuery.IN)
-      .setPossibleValues(ProjectQgateAssociationQuery.AVAILABLE_MEMBERSHIP)
-      .setExampleValue(ProjectQgateAssociationQuery.OUT);
-
-    action.createParam(QGatesWs.PARAM_PAGE)
-      .setDescription("Page number")
-      .setDefaultValue("1")
-      .setExampleValue("2");
-
-    action.createParam(QGatesWs.PARAM_PAGE_SIZE)
-      .setDescription("Page size")
-      .setExampleValue("10");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    QgateProjectFinder.Association associations = projectFinder.find(ProjectQgateAssociationQuery.builder()
-      .gateId(request.mandatoryParam(QGatesWs.PARAM_GATE_ID))
-      .membership(request.param(QGatesWs.PARAM_QUERY) == null ? request.param(QGatesWs.PARAM_SELECTED) : ProjectQgateAssociationQuery.ANY)
-      .projectSearch(request.param(QGatesWs.PARAM_QUERY))
-      .pageIndex(request.paramAsInt(QGatesWs.PARAM_PAGE))
-      .pageSize(request.paramAsInt(QGatesWs.PARAM_PAGE_SIZE))
-      .build());
-    JsonWriter writer = response.newJsonWriter();
-    writer.beginObject().prop("more", associations.hasMoreResults());
-    writer.name("results").beginArray();
-    for (ProjectQgateAssociation project : associations.projects()) {
-      writer.beginObject().prop("id", project.id()).prop("name", project.name()).prop(QGatesWs.PARAM_SELECTED, project.isMember()).endObject();
-    }
-    writer.endArray().endObject().close();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSelectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSelectAction.java
deleted file mode 100644 (file)
index ce76011..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesSelectAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesSelectAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("select")
-      .setDescription("Associate a project to a quality gate. Require Administer Quality Profiles and Gates permission")
-      .setPost(true)
-      .setSince("4.3")
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_GATE_ID)
-      .setDescription("Quality Gate ID")
-      .setRequired(true)
-      .setExampleValue("1");
-
-    action.createParam(QGatesWs.PARAM_PROJECT_ID)
-      .setDescription("Project ID")
-      .setRequired(true)
-      .setExampleValue("12");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    qualityGates.associateProject(QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID), QGatesWs.parseId(request, QGatesWs.PARAM_PROJECT_ID));
-    response.noContent();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSetAsDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesSetAsDefaultAction.java
deleted file mode 100644 (file)
index 18fc05e..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesSetAsDefaultAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesSetAsDefaultAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("set_as_default")
-      .setDescription("Set a quality gate as the default quality gate. Require Administer Quality Profiles and Gates permission")
-      .setSince("4.3")
-      .setPost(true)
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_ID)
-      .setDescription("ID of the quality gate to set as default")
-      .setRequired(true)
-      .setExampleValue("1");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    qualityGates.setDefault(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
-    response.noContent();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesShowAction.java
deleted file mode 100644 (file)
index 74710fa..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.qualitygate.db.QualityGateConditionDto;
-import org.sonar.core.qualitygate.db.QualityGateDto;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.qualitygate.QualityGates;
-
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-
-public class QGatesShowAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesShowAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("show")
-      .setDescription("Display the details of a quality gate")
-      .setSince("4.3")
-      .setResponseExample(Resources.getResource(this.getClass(), "example-show.json"))
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_ID)
-      .setDescription("ID of the quality gate. Either id or name must be set")
-      .setExampleValue("1");
-
-    action.createParam(QGatesWs.PARAM_NAME)
-      .setDescription("Name of the quality gate. Either id or name must be set")
-      .setExampleValue("My Quality Gate");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    Long qGateId = request.paramAsLong(QGatesWs.PARAM_ID);
-    String qGateName = request.param(QGatesWs.PARAM_NAME);
-    checkOneOfIdOrNamePresent(qGateId, qGateName);
-
-    QualityGateDto qGate = qGateId == null ? qualityGates.get(qGateName) : qualityGates.get(qGateId);
-    qGateId = qGate.getId();
-
-    JsonWriter writer = response.newJsonWriter().beginObject()
-      .prop(QGatesWs.PARAM_ID, qGate.getId())
-      .prop(QGatesWs.PARAM_NAME, qGate.getName());
-    Collection<QualityGateConditionDto> conditions = qualityGates.listConditions(qGateId);
-    if (!conditions.isEmpty()) {
-      writer.name("conditions").beginArray();
-      for (QualityGateConditionDto condition : conditions) {
-        QGatesWs.writeQualityGateCondition(condition, writer);
-      }
-      writer.endArray();
-    }
-    writer.endObject().close();
-  }
-
-  private void checkOneOfIdOrNamePresent(@Nullable Long qGateId, @Nullable String qGateName) {
-    if (qGateId == null && qGateName == null) {
-      throw new BadRequestException("Either one of 'id' or 'name' is required.");
-    } else if (qGateId != null && qGateName != null) {
-      throw new BadRequestException("Only one of 'id' or 'name' must be provided.");
-    }
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesUnsetDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesUnsetDefaultAction.java
deleted file mode 100644 (file)
index ab76b7e..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesUnsetDefaultAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesUnsetDefaultAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("unset_default")
-      .setDescription("Unset a quality gate as the default quality gate. Require Administer Quality Profiles and Gates permission")
-      .setSince("4.3")
-      .setPost(true)
-      .setHandler(this);
-
-    action.createParam(QGatesWs.PARAM_ID)
-      .setDescription("ID of the quality gate to unset as default")
-      .setRequired(true)
-      .setExampleValue("1");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    qualityGates.setDefault(null);
-    response.noContent();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesUpdateConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesUpdateConditionAction.java
deleted file mode 100644 (file)
index 1a5d8bf..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-
-public class QGatesUpdateConditionAction implements QGateWsAction {
-
-  private final QualityGates qualityGates;
-
-  public QGatesUpdateConditionAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction createCondition = controller.createAction("update_condition")
-      .setDescription("Update a condition attached to a quality gate. Require Administer Quality Profiles and Gates permission")
-      .setPost(true)
-      .setSince("4.3")
-      .setHandler(this);
-
-    createCondition
-      .createParam(QGatesWs.PARAM_ID)
-      .setDescription("Condition ID")
-      .setRequired(true)
-      .setExampleValue("10");
-
-    QGatesWs.addConditionParams(createCondition);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    QGatesWs.writeQualityGateCondition(
-      qualityGates.updateCondition(
-        QGatesWs.parseId(request, QGatesWs.PARAM_ID),
-        request.mandatoryParam(QGatesWs.PARAM_METRIC),
-        request.mandatoryParam(QGatesWs.PARAM_OPERATOR),
-        request.param(QGatesWs.PARAM_WARNING),
-        request.param(QGatesWs.PARAM_ERROR),
-        request.paramAsInt(QGatesWs.PARAM_PERIOD)
-        ), response.newJsonWriter()
-      ).close();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java
new file mode 100644 (file)
index 0000000..42901fa
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.qualitygate.db.QualityGateDto;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class RenameAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public RenameAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("rename")
+      .setDescription("Rename a Quality Gate. Require Administer Quality Profiles and Gates permission")
+      .setPost(true)
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_ID)
+      .setDescription("ID of the quality gate to rename")
+      .setRequired(true)
+      .setExampleValue("1");
+
+    action.createParam(QGatesWs.PARAM_NAME)
+      .setDescription("New name of the quality gate")
+      .setRequired(true)
+      .setExampleValue("My Quality Gate");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    long idToRename = QGatesWs.parseId(request, QGatesWs.PARAM_ID);
+    QualityGateDto renamedQualityGate = qualityGates.rename(idToRename, request.mandatoryParam(QGatesWs.PARAM_NAME));
+    JsonWriter writer = response.newJsonWriter();
+    QGatesWs.writeQualityGate(renamedQualityGate, writer).close();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java
new file mode 100644 (file)
index 0000000..24ccf06
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.qualitygate.db.ProjectQgateAssociation;
+import org.sonar.core.qualitygate.db.ProjectQgateAssociationQuery;
+import org.sonar.server.qualitygate.QgateProjectFinder;
+
+public class SearchAction implements QGateWsAction {
+
+  private final QgateProjectFinder projectFinder;
+
+  public SearchAction(QgateProjectFinder projectFinder) {
+    this.projectFinder = projectFinder;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("search")
+      .setDescription("Search for projects associated (or not) to a quality gate")
+      .setSince("4.3")
+      .setResponseExample(Resources.getResource(this.getClass(), "example-search.json"))
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_GATE_ID)
+      .setDescription("Quality Gate ID")
+      .setRequired(true)
+      .setExampleValue("1");
+
+    action.createParam(QGatesWs.PARAM_QUERY)
+      .setDescription("To search for projects containing this string. If this parameter is set, \"selected\" is set to \"all\".")
+      .setExampleValue("abc");
+
+    action.createParam(QGatesWs.PARAM_SELECTED)
+      .setDescription("If \"selected\", search for projects associated to the quality gate")
+      .setDefaultValue(ProjectQgateAssociationQuery.IN)
+      .setPossibleValues(ProjectQgateAssociationQuery.AVAILABLE_MEMBERSHIP)
+      .setExampleValue(ProjectQgateAssociationQuery.OUT);
+
+    action.createParam(QGatesWs.PARAM_PAGE)
+      .setDescription("Page number")
+      .setDefaultValue("1")
+      .setExampleValue("2");
+
+    action.createParam(QGatesWs.PARAM_PAGE_SIZE)
+      .setDescription("Page size")
+      .setExampleValue("10");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    QgateProjectFinder.Association associations = projectFinder.find(ProjectQgateAssociationQuery.builder()
+      .gateId(request.mandatoryParam(QGatesWs.PARAM_GATE_ID))
+      .membership(request.param(QGatesWs.PARAM_QUERY) == null ? request.param(QGatesWs.PARAM_SELECTED) : ProjectQgateAssociationQuery.ANY)
+      .projectSearch(request.param(QGatesWs.PARAM_QUERY))
+      .pageIndex(request.paramAsInt(QGatesWs.PARAM_PAGE))
+      .pageSize(request.paramAsInt(QGatesWs.PARAM_PAGE_SIZE))
+      .build());
+    JsonWriter writer = response.newJsonWriter();
+    writer.beginObject().prop("more", associations.hasMoreResults());
+    writer.name("results").beginArray();
+    for (ProjectQgateAssociation project : associations.projects()) {
+      writer.beginObject().prop("id", project.id()).prop("name", project.name()).prop(QGatesWs.PARAM_SELECTED, project.isMember()).endObject();
+    }
+    writer.endArray().endObject().close();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java
new file mode 100644 (file)
index 0000000..f2f2b5b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class SelectAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public SelectAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("select")
+      .setDescription("Associate a project to a quality gate. Require Administer Quality Profiles and Gates permission")
+      .setPost(true)
+      .setSince("4.3")
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_GATE_ID)
+      .setDescription("Quality Gate ID")
+      .setRequired(true)
+      .setExampleValue("1");
+
+    action.createParam(QGatesWs.PARAM_PROJECT_ID)
+      .setDescription("Project ID")
+      .setRequired(true)
+      .setExampleValue("12");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    qualityGates.associateProject(QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID), QGatesWs.parseId(request, QGatesWs.PARAM_PROJECT_ID));
+    response.noContent();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java
new file mode 100644 (file)
index 0000000..828186c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class SetAsDefaultAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public SetAsDefaultAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("set_as_default")
+      .setDescription("Set a quality gate as the default quality gate. Require Administer Quality Profiles and Gates permission")
+      .setSince("4.3")
+      .setPost(true)
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_ID)
+      .setDescription("ID of the quality gate to set as default")
+      .setRequired(true)
+      .setExampleValue("1");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    qualityGates.setDefault(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
+    response.noContent();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java
new file mode 100644 (file)
index 0000000..9b53247
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.qualitygate.db.QualityGateConditionDto;
+import org.sonar.core.qualitygate.db.QualityGateDto;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.qualitygate.QualityGates;
+
+import javax.annotation.Nullable;
+
+import java.util.Collection;
+
+public class ShowAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public ShowAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("show")
+      .setDescription("Display the details of a quality gate")
+      .setSince("4.3")
+      .setResponseExample(Resources.getResource(this.getClass(), "example-show.json"))
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_ID)
+      .setDescription("ID of the quality gate. Either id or name must be set")
+      .setExampleValue("1");
+
+    action.createParam(QGatesWs.PARAM_NAME)
+      .setDescription("Name of the quality gate. Either id or name must be set")
+      .setExampleValue("My Quality Gate");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    Long qGateId = request.paramAsLong(QGatesWs.PARAM_ID);
+    String qGateName = request.param(QGatesWs.PARAM_NAME);
+    checkOneOfIdOrNamePresent(qGateId, qGateName);
+
+    QualityGateDto qGate = qGateId == null ? qualityGates.get(qGateName) : qualityGates.get(qGateId);
+    qGateId = qGate.getId();
+
+    JsonWriter writer = response.newJsonWriter().beginObject()
+      .prop(QGatesWs.PARAM_ID, qGate.getId())
+      .prop(QGatesWs.PARAM_NAME, qGate.getName());
+    Collection<QualityGateConditionDto> conditions = qualityGates.listConditions(qGateId);
+    if (!conditions.isEmpty()) {
+      writer.name("conditions").beginArray();
+      for (QualityGateConditionDto condition : conditions) {
+        QGatesWs.writeQualityGateCondition(condition, writer);
+      }
+      writer.endArray();
+    }
+    writer.endObject().close();
+  }
+
+  private void checkOneOfIdOrNamePresent(@Nullable Long qGateId, @Nullable String qGateName) {
+    if (qGateId == null && qGateName == null) {
+      throw new BadRequestException("Either one of 'id' or 'name' is required.");
+    } else if (qGateId != null && qGateName != null) {
+      throw new BadRequestException("Only one of 'id' or 'name' must be provided.");
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java
new file mode 100644 (file)
index 0000000..b2210ad
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class UnsetDefaultAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public UnsetDefaultAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("unset_default")
+      .setDescription("Unset a quality gate as the default quality gate. Require Administer Quality Profiles and Gates permission")
+      .setSince("4.3")
+      .setPost(true)
+      .setHandler(this);
+
+    action.createParam(QGatesWs.PARAM_ID)
+      .setDescription("ID of the quality gate to unset as default")
+      .setRequired(true)
+      .setExampleValue("1");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    qualityGates.setDefault(null);
+    response.noContent();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java
new file mode 100644 (file)
index 0000000..cb844e0
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualitygate.QualityGates;
+
+public class UpdateConditionAction implements QGateWsAction {
+
+  private final QualityGates qualityGates;
+
+  public UpdateConditionAction(QualityGates qualityGates) {
+    this.qualityGates = qualityGates;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction createCondition = controller.createAction("update_condition")
+      .setDescription("Update a condition attached to a quality gate. Require Administer Quality Profiles and Gates permission")
+      .setPost(true)
+      .setSince("4.3")
+      .setHandler(this);
+
+    createCondition
+      .createParam(QGatesWs.PARAM_ID)
+      .setDescription("Condition ID")
+      .setRequired(true)
+      .setExampleValue("10");
+
+    QGatesWs.addConditionParams(createCondition);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    QGatesWs.writeQualityGateCondition(
+      qualityGates.updateCondition(
+        QGatesWs.parseId(request, QGatesWs.PARAM_ID),
+        request.mandatoryParam(QGatesWs.PARAM_METRIC),
+        request.mandatoryParam(QGatesWs.PARAM_OPERATOR),
+        request.param(QGatesWs.PARAM_WARNING),
+        request.param(QGatesWs.PARAM_ERROR),
+        request.paramAsInt(QGatesWs.PARAM_PERIOD)
+        ), response.newJsonWriter()
+      ).close();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BackupAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BackupAction.java
new file mode 100644 (file)
index 0000000..69e320d
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.Response.Stream;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.plugins.MimeTypes;
+import org.sonar.server.qualityprofile.QProfileBackuper;
+import org.sonar.server.qualityprofile.QProfileFactory;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+
+public class BackupAction implements QProfileWsAction {
+
+  private final QProfileBackuper backuper;
+
+  private final DbClient dbClient;
+
+  private QProfileFactory profileFactory;
+
+  private final Languages languages;
+
+  public BackupAction(QProfileBackuper backuper, DbClient dbClient, QProfileFactory profileFactory, Languages languages) {
+    this.backuper = backuper;
+    this.dbClient = dbClient;
+    this.profileFactory = profileFactory;
+    this.languages = languages;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction backup = controller.createAction("backup")
+      .setSince("5.2")
+      .setDescription("Backup a quality profile in XML form. The exported profile can be restored through api/qualityprofiles/restore.")
+      .setHandler(this);
+
+    QProfileIdentificationParamUtils.defineProfileParams(backup, languages);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    Stream stream = response.stream();
+    stream.setMediaType(MimeTypes.XML);
+    OutputStreamWriter writer = new OutputStreamWriter(stream.output(), StandardCharsets.UTF_8);
+    DbSession session = dbClient.openSession(false);
+    try {
+      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
+      backuper.backup(profileKey, writer);
+    } finally {
+      session.close();
+      IOUtils.closeQuietly(writer);
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangeParentAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangeParentAction.java
new file mode 100644 (file)
index 0000000..002ac94
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.base.Preconditions;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.RuleActivator;
+import org.sonar.server.user.UserSession;
+
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
+public class ChangeParentAction implements QProfileWsAction {
+
+  private static final String PARAM_PARENT_KEY = "parentKey";
+
+  private static final String PARAM_PARENT_NAME = "parentName";
+
+  private final DbClient dbClient;
+
+  private final RuleActivator ruleActivator;
+
+  private final QProfileFactory profileFactory;
+
+  private final Languages languages;
+  private final UserSession userSession;
+
+  public ChangeParentAction(DbClient dbClient, RuleActivator ruleActivator, QProfileFactory profileFactory, Languages languages, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.ruleActivator = ruleActivator;
+    this.profileFactory = profileFactory;
+    this.languages = languages;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(NewController context) {
+    NewAction inheritance = context.createAction("change_parent")
+      .setSince("5.2")
+      .setPost(true)
+      .setDescription("Change a quality profile's parent.")
+      .setHandler(this);
+
+    QProfileIdentificationParamUtils.defineProfileParams(inheritance, languages);
+
+    inheritance.createParam(PARAM_PARENT_KEY)
+      .setDescription("The key of the new parent profile. If this parameter is set, parentName must not be set. " +
+        "If both are left empty, the inheritance link with current parent profile (if any) is broken, which deactivates all rules " +
+        "which come from the parent and are not overridden.")
+      .setExampleValue("sonar-way-java-12345");
+    inheritance.createParam(PARAM_PARENT_NAME)
+      .setDescription("A quality profile name. If this parameter is set, profileKey must not be set and language must be set to disambiguate.")
+      .setExampleValue("Sonar way");
+
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    DbSession session = dbClient.openSession(false);
+    try {
+      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
+      String parentKey = getParentKeyFromParameters(request, profileFactory, session);
+
+      ruleActivator.setParent(profileKey, parentKey);
+
+      response.noContent();
+    } finally {
+      session.close();
+    }
+  }
+
+  private static String getParentKeyFromParameters(Request request, QProfileFactory profileFactory, DbSession session) {
+    String language = request.param(QProfileIdentificationParamUtils.PARAM_LANGUAGE);
+    String parentName = request.param(PARAM_PARENT_NAME);
+    String parentKey = request.param(PARAM_PARENT_KEY);
+
+    Preconditions.checkArgument(
+      isEmpty(parentName) || isEmpty(parentKey), "parentKey and parentName cannot be used simultaneously");
+
+    if (isEmpty(parentKey)) {
+      if (!isEmpty(parentName)) {
+        parentKey = QProfileIdentificationParamUtils.getProfileKeyFromLanguageAndName(language, parentName, profileFactory, session);
+      } else {
+        // Empty parent key is treated as "no more parent"
+        parentKey = null;
+      }
+    }
+
+    return parentKey;
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java
new file mode 100644 (file)
index 0000000..af462f7
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.search.SearchHit;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.*;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.Paging;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfileActivity;
+import org.sonar.server.qualityprofile.QProfileActivityQuery;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.search.Result;
+
+import java.util.Date;
+import java.util.Map.Entry;
+
+public class ChangelogAction implements QProfileWsAction {
+
+  private static final String PARAM_SINCE = "since";
+  private static final String PARAM_TO = "to";
+
+  private DbClient dbClient;
+  private ActivityIndex activityIndex;
+  private QProfileFactory profileFactory;
+  private Languages languages;
+
+  public ChangelogAction(DbClient dbClient, ActivityIndex activityIndex, QProfileFactory profileFactory, Languages languages) {
+    this.dbClient = dbClient;
+    this.activityIndex = activityIndex;
+    this.profileFactory = profileFactory;
+    this.languages = languages;
+  }
+
+  @Override
+  public void define(NewController context) {
+    NewAction changelog = context.createAction("changelog")
+      .setSince("5.2")
+      .setDescription("Get the history of changes on a quality profile: rule activation/deactivation, change in parameters/severity. " +
+        "Events are ordered by date in descending order (most recent first).")
+      .setHandler(this)
+      .setResponseExample(getClass().getResource("example-changelog.json"));
+
+    QProfileIdentificationParamUtils.defineProfileParams(changelog, languages);
+
+    changelog.addPagingParams(50);
+
+    changelog.createParam(PARAM_SINCE)
+      .setDescription("Start date for the changelog.")
+      .setExampleValue("2011-04-25T01:15:42+0100");
+
+    changelog.createParam(PARAM_TO)
+      .setDescription("End date for the changelog.")
+      .setExampleValue("2013-07-25T07:35:42+0200");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    DbSession session = dbClient.openSession(false);
+    try {
+      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
+      if (dbClient.qualityProfileDao().getByKey(session, profileKey) == null) {
+        throw new NotFoundException(String.format("Could not find a profile with key '%s'", profileKey));
+      }
+
+      QProfileActivityQuery query = new QProfileActivityQuery().setQprofileKey(profileKey);
+      Date since = request.paramAsDateTime(PARAM_SINCE);
+      if (since != null) {
+        query.setSince(since);
+      }
+      Date to = request.paramAsDateTime(PARAM_TO);
+      if (to != null) {
+        query.setTo(to);
+      }
+      SearchOptions options = new SearchOptions();
+
+      int page = request.mandatoryParamAsInt(Param.PAGE);
+      options.setPage(page, request.mandatoryParamAsInt(Param.PAGE_SIZE));
+
+      Result<QProfileActivity> result = searchActivities(query, options);
+      writeResponse(response.newJsonWriter(), result, Paging.create(options.getLimit(), page, (int) result.getTotal()));
+    } finally {
+      session.close();
+    }
+  }
+
+  private Result<QProfileActivity> searchActivities(QProfileActivityQuery query, SearchOptions options) {
+    DbSession session = dbClient.openSession(false);
+    try {
+      SearchResponse response = activityIndex.doSearch(query, options);
+      Result<QProfileActivity> result = new Result<>(response);
+      for (SearchHit hit : response.getHits().getHits()) {
+        QProfileActivity profileActivity = new QProfileActivity(hit.getSource());
+        RuleDto ruleDto = dbClient.ruleDao().getNullableByKey(session, profileActivity.ruleKey());
+        profileActivity.ruleName(ruleDto != null ? ruleDto.getName() : null);
+
+        String login = profileActivity.getLogin();
+        if (login != null) {
+          UserDto user = dbClient.userDao().selectActiveUserByLogin(session, login);
+          profileActivity.authorName(user != null ? user.getName() : null);
+        }
+        result.getHits().add(profileActivity);
+      }
+      return result;
+    } finally {
+      session.close();
+    }
+  }
+
+  private void writeResponse(JsonWriter json, Result<QProfileActivity> result, Paging paging) {
+    json.beginObject();
+    json.prop("total", result.getTotal());
+    json.prop(Param.PAGE, paging.pageIndex());
+    json.prop(Param.PAGE_SIZE, paging.pageSize());
+    json.name("events").beginArray();
+    for (QProfileActivity event : result.getHits()) {
+      json.beginObject()
+        .prop("date", DateUtils.formatDateTime(event.getCreatedAt()))
+        .prop("authorLogin", event.getLogin())
+        .prop("authorName", event.authorName())
+        .prop("action", event.getAction())
+        .prop("ruleKey", event.ruleKey().toString())
+        .prop("ruleName", event.ruleName());
+      writeParameters(json, event);
+      json.endObject();
+    }
+    json.endArray();
+    json.endObject().close();
+  }
+
+  private void writeParameters(JsonWriter json, QProfileActivity event) {
+    json.name("params").beginObject()
+      .prop("severity", event.severity());
+    for (Entry<String, String> param : event.parameters().entrySet()) {
+      json.prop(param.getKey(), param.getValue());
+    }
+    json.endObject();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CompareAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CompareAction.java
new file mode 100644 (file)
index 0000000..6659583
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.collect.MapDifference.ValueDifference;
+import com.google.common.collect.Maps;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.util.NonNullInputFunction;
+import org.sonar.server.qualityprofile.ActiveRule;
+import org.sonar.server.qualityprofile.QProfileComparison;
+import org.sonar.server.qualityprofile.QProfileComparison.ActiveRuleDiff;
+import org.sonar.server.qualityprofile.QProfileComparison.QProfileComparisonResult;
+import org.sonar.server.rule.Rule;
+import org.sonar.server.rule.RuleRepositories;
+import org.sonar.server.rule.RuleRepositories.Repository;
+import org.sonar.server.rule.RuleService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class CompareAction implements QProfileWsAction {
+
+  private static final String ATTRIBUTE_LEFT = "left";
+  private static final String ATTRIBUTE_RIGHT = "right";
+  private static final String ATTRIBUTE_IN_LEFT = "inLeft";
+  private static final String ATTRIBUTE_IN_RIGHT = "inRight";
+  private static final String ATTRIBUTE_MODIFIED = "modified";
+  private static final String ATTRIBUTE_SAME = "same";
+  private static final String ATTRIBUTE_KEY = "key";
+  private static final String ATTRIBUTE_NAME = "name";
+  private static final String ATTRIBUTE_SEVERITY = "severity";
+  private static final String ATTRIBUTE_PLUGIN_KEY = "pluginKey";
+  private static final String ATTRIBUTE_PLUGIN_NAME = "pluginName";
+  private static final String ATTRIBUTE_LANGUAGE_KEY = "languageKey";
+  private static final String ATTRIBUTE_LANGUAGE_NAME = "languageName";
+  private static final String ATTRIBUTE_PARAMS = "params";
+
+  private static final String PARAM_LEFT_KEY = "leftKey";
+  private static final String PARAM_RIGHT_KEY = "rightKey";
+
+  private final QProfileComparison comparator;
+  private final RuleService ruleService;
+  private final RuleRepositories ruleRepositories;
+  private final Languages languages;
+
+  public CompareAction(QProfileComparison comparator, RuleService ruleService, RuleRepositories ruleRepositories, Languages languages) {
+    this.comparator = comparator;
+    this.ruleService = ruleService;
+    this.ruleRepositories = ruleRepositories;
+    this.languages = languages;
+  }
+
+  @Override
+  public void define(NewController context) {
+    NewAction compare = context.createAction("compare")
+      .setDescription("Compare two quality profiles.")
+      .setHandler(this)
+      .setInternal(true)
+      .setResponseExample(getClass().getResource("example-compare.json"))
+      .setSince("5.2");
+
+    compare.createParam(PARAM_LEFT_KEY)
+      .setDescription("A profile key.")
+      .setExampleValue("java-sonar-way-12345")
+      .setRequired(true);
+
+    compare.createParam(PARAM_RIGHT_KEY)
+      .setDescription("Another profile key.")
+      .setExampleValue("java-sonar-way-with-findbugs-23456")
+      .setRequired(true);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    String leftKey = request.mandatoryParam(PARAM_LEFT_KEY);
+    String rightKey = request.mandatoryParam(PARAM_RIGHT_KEY);
+
+    QProfileComparisonResult result = comparator.compare(leftKey, rightKey);
+
+    List<Rule> referencedRules = ruleService.getByKeys(result.collectRuleKeys());
+    Map<RuleKey, Rule> rulesByKey = Maps.uniqueIndex(referencedRules, new NonNullInputFunction<Rule, RuleKey>() {
+      @Override
+      protected RuleKey doApply(Rule input) {
+        return input.key();
+      }
+    });
+
+    writeResult(response.newJsonWriter(), result, rulesByKey);
+  }
+
+  private void writeResult(JsonWriter json, QProfileComparisonResult result, Map<RuleKey, Rule> rulesByKey) {
+    json.beginObject();
+
+    json.name(ATTRIBUTE_LEFT).beginObject();
+    writeProfile(json, result.left());
+    json.endObject();
+
+    json.name(ATTRIBUTE_RIGHT).beginObject();
+    writeProfile(json, result.right());
+    json.endObject();
+
+    json.name(ATTRIBUTE_IN_LEFT);
+    writeRules(json, result.inLeft(), rulesByKey);
+
+    json.name(ATTRIBUTE_IN_RIGHT);
+    writeRules(json, result.inRight(), rulesByKey);
+
+    json.name(ATTRIBUTE_MODIFIED);
+    writeDifferences(json, result.modified(), rulesByKey);
+
+    json.name(ATTRIBUTE_SAME);
+    writeRules(json, result.same(), rulesByKey);
+
+    json.endObject().close();
+  }
+
+  private void writeProfile(JsonWriter json, QualityProfileDto profile) {
+    json.prop(ATTRIBUTE_KEY, profile.getKey())
+      .prop(ATTRIBUTE_NAME, profile.getName());
+  }
+
+  private void writeRules(JsonWriter json, Map<RuleKey, ActiveRule> activeRules, Map<RuleKey, Rule> rulesByKey) {
+    json.beginArray();
+    for (Entry<RuleKey, ActiveRule> activeRule : activeRules.entrySet()) {
+      RuleKey key = activeRule.getKey();
+      ActiveRule value = activeRule.getValue();
+
+      json.beginObject();
+      writeRule(json, key, rulesByKey);
+      json.prop(ATTRIBUTE_SEVERITY, value.severity());
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+  private void writeRule(JsonWriter json, RuleKey key, Map<RuleKey, Rule> rulesByKey) {
+    String repositoryKey = key.repository();
+    json.prop(ATTRIBUTE_KEY, key.toString())
+      .prop(ATTRIBUTE_NAME, rulesByKey.get(key).name())
+      .prop(ATTRIBUTE_PLUGIN_KEY, repositoryKey);
+
+    Repository repo = ruleRepositories.repository(repositoryKey);
+    if (repo != null) {
+      String languageKey = repo.getLanguage();
+      Language language = languages.get(languageKey);
+
+      json.prop(ATTRIBUTE_PLUGIN_NAME, repo.getName());
+      json.prop(ATTRIBUTE_LANGUAGE_KEY, languageKey);
+      json.prop(ATTRIBUTE_LANGUAGE_NAME, language == null ? null : language.getName());
+    }
+  }
+
+  private void writeDifferences(JsonWriter json, Map<RuleKey, ActiveRuleDiff> modified, Map<RuleKey, Rule> rulesByKey) {
+    json.beginArray();
+    for (Entry<RuleKey, ActiveRuleDiff> diffEntry : modified.entrySet()) {
+      RuleKey key = diffEntry.getKey();
+      ActiveRuleDiff value = diffEntry.getValue();
+      json.beginObject();
+      writeRule(json, key, rulesByKey);
+
+      json.name(ATTRIBUTE_LEFT).beginObject();
+      json.prop(ATTRIBUTE_SEVERITY, value.leftSeverity());
+      json.name(ATTRIBUTE_PARAMS).beginObject();
+      for (Entry<String, ValueDifference<String>> valueDiff : value.paramDifference().entriesDiffering().entrySet()) {
+        json.prop(valueDiff.getKey(), valueDiff.getValue().leftValue());
+      }
+      for (Entry<String, String> valueDiff : value.paramDifference().entriesOnlyOnLeft().entrySet()) {
+        json.prop(valueDiff.getKey(), valueDiff.getValue());
+      }
+      // params
+      json.endObject();
+      // left
+      json.endObject();
+
+      json.name(ATTRIBUTE_RIGHT).beginObject();
+      json.prop(ATTRIBUTE_SEVERITY, value.rightSeverity());
+      json.name(ATTRIBUTE_PARAMS).beginObject();
+      for (Entry<String, ValueDifference<String>> valueDiff : value.paramDifference().entriesDiffering().entrySet()) {
+        json.prop(valueDiff.getKey(), valueDiff.getValue().rightValue());
+      }
+      for (Entry<String, String> valueDiff : value.paramDifference().entriesOnlyOnRight().entrySet()) {
+        json.prop(valueDiff.getKey(), valueDiff.getValue());
+      }
+      // params
+      json.endObject();
+      // right
+      json.endObject();
+
+      // rule
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CopyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CopyAction.java
new file mode 100644 (file)
index 0000000..f02a071
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.qualityprofile.QProfileCopier;
+import org.sonar.server.user.UserSession;
+
+public class CopyAction implements QProfileWsAction {
+
+  private static final String PARAM_PROFILE_NAME = "toName";
+  private static final String PARAM_PROFILE_KEY = "fromKey";
+
+  private final QProfileCopier profileCopier;
+  private final Languages languages;
+  private final UserSession userSession;
+
+  public CopyAction(QProfileCopier profileCopier, Languages languages, UserSession userSession) {
+    this.profileCopier = profileCopier;
+    this.languages = languages;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction setDefault = controller.createAction("copy")
+      .setSince("5.2")
+      .setDescription("Copy a quality profile.")
+      .setPost(true)
+      .setHandler(this);
+
+    setDefault.createParam(PARAM_PROFILE_NAME)
+      .setDescription("The name for the new quality profile.")
+      .setExampleValue("My Sonar way")
+      .setRequired(true);
+
+    setDefault.createParam(PARAM_PROFILE_KEY)
+      .setDescription("The key of a quality profile.")
+      .setExampleValue("sonar-way-js-12345")
+      .setRequired(true);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    String newName = request.mandatoryParam(PARAM_PROFILE_NAME);
+    String profileKey = request.mandatoryParam(PARAM_PROFILE_KEY);
+
+    QualityProfileDto copiedProfile = profileCopier.copyToName(profileKey, newName);
+
+    String languageKey = copiedProfile.getLanguage();
+    Language language = languages.get(copiedProfile.getLanguage());
+    String parentKey = copiedProfile.getParentKee();
+    response.newJsonWriter()
+      .beginObject()
+      .prop("key", copiedProfile.getKey())
+      .prop("name", copiedProfile.getName())
+      .prop("language", languageKey)
+      .prop("languageName", language == null ? null : language.getName())
+      .prop("isDefault", copiedProfile.isDefault())
+      .prop("isInherited", parentKey != null)
+      .prop("parentKey", parentKey)
+      .endObject().close();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java
new file mode 100644 (file)
index 0000000..b41ab30
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.sonar.api.profiles.ProfileImporter;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.QProfileExporters;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.qualityprofile.QProfileResult;
+import org.sonar.server.user.UserSession;
+
+import java.io.InputStream;
+
+public class CreateAction implements QProfileWsAction {
+
+  private static final String PARAM_PROFILE_NAME = "name";
+  private static final String PARAM_LANGUAGE = "language";
+  private static final String PARAM_BACKUP_FORMAT = "backup_%s";
+
+  private final DbClient dbClient;
+
+  private final QProfileFactory profileFactory;
+
+  private final QProfileExporters exporters;
+
+  private final Languages languages;
+
+  private final ProfileImporter[] importers;
+  private final UserSession userSession;
+
+  public CreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters,
+                      Languages languages, ProfileImporter[] importers, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.profileFactory = profileFactory;
+    this.exporters = exporters;
+    this.languages = languages;
+    this.importers = importers;
+    this.userSession = userSession;
+  }
+
+  public CreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters, Languages languages, UserSession userSession) {
+    this(dbClient, profileFactory, exporters, languages, new ProfileImporter[0], userSession);
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction create = controller.createAction("create")
+      .setSince("5.2")
+      .setDescription("Create a quality profile.")
+      .setPost(true)
+      .setResponseExample(getClass().getResource("example-create.json"))
+      .setHandler(this);
+
+    create.createParam(PARAM_PROFILE_NAME)
+      .setDescription("The name for the new quality profile.")
+      .setExampleValue("My Sonar way")
+      .setRequired(true);
+
+    create.createParam(PARAM_LANGUAGE)
+      .setDescription("The language for the quality profile.")
+      .setExampleValue("js")
+      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
+      .setRequired(true);
+
+    for (ProfileImporter importer : importers) {
+      create.createParam(getBackupParamName(importer.getKey()))
+        .setDescription(String.format("A configuration file for %s.", importer.getName()));
+    }
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    String name = request.mandatoryParam(PARAM_PROFILE_NAME);
+    String language = request.mandatoryParam(PARAM_LANGUAGE);
+
+    DbSession dbSession = dbClient.openSession(false);
+
+    try {
+      QProfileResult result = new QProfileResult();
+      QualityProfileDto profile = profileFactory.create(dbSession, QProfileName.createFor(language, name));
+      result.setProfile(profile);
+      for (ProfileImporter importer : importers) {
+        InputStream contentToImport = request.paramAsInputStream(getBackupParamName(importer.getKey()));
+        if (contentToImport != null) {
+          result.add(exporters.importXml(profile, importer.getKey(), contentToImport, dbSession));
+        }
+      }
+      dbSession.commit();
+      writeResult(response.newJsonWriter(), result);
+    } finally {
+      dbSession.close();
+    }
+  }
+
+  private void writeResult(JsonWriter json, QProfileResult result) {
+    String language = result.profile().getLanguage();
+    json.beginObject().name("profile").beginObject()
+      .prop("key", result.profile().getKey())
+      .prop("name", result.profile().getName())
+      .prop("language", language)
+      .prop("languageName", languages.get(result.profile().getLanguage()).getName())
+      .prop("isDefault", false)
+      .prop("isInherited", false)
+      .endObject();
+
+    if (!result.infos().isEmpty()) {
+      json.name("infos").beginArray();
+      for (String info : result.infos()) {
+        json.value(info);
+      }
+      json.endArray();
+    }
+
+    if (!result.warnings().isEmpty()) {
+      json.name("warnings").beginArray();
+      for (String warning : result.warnings()) {
+        json.value(warning);
+      }
+      json.endArray();
+    }
+
+    json.endObject().close();
+  }
+
+  private String getBackupParamName(String importerKey) {
+    return String.format(PARAM_BACKUP_FORMAT, importerKey);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeleteAction.java
new file mode 100644 (file)
index 0000000..0af30ba
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.user.UserSession;
+
+public class DeleteAction implements QProfileWsAction {
+
+  private final Languages languages;
+  private final QProfileFactory profileFactory;
+  private final DbClient dbClient;
+  private final UserSession userSession;
+
+  public DeleteAction(Languages languages, QProfileFactory profileFactory, DbClient dbClient, UserSession userSession) {
+    this.languages = languages;
+    this.profileFactory = profileFactory;
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(NewController controller) {
+    NewAction action = controller.createAction("delete")
+      .setDescription("Delete a quality profile and all its descendants. The default quality profile cannot be deleted.")
+      .setSince("5.2")
+      .setPost(true)
+      .setHandler(this);
+
+    QProfileIdentificationParamUtils.defineProfileParams(action, languages);
+  }
+
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkLoggedIn();
+    userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+
+    DbSession session = dbClient.openSession(false);
+    try {
+      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
+      profileFactory.delete(session, profileKey, false);
+
+      session.commit();
+    } finally {
+      session.close();
+    }
+
+    response.noContent();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java
new file mode 100644 (file)
index 0000000..38f97c7
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.Response.Stream;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.plugins.MimeTypes;
+import org.sonar.server.qualityprofile.QProfileBackuper;
+import org.sonar.server.qualityprofile.QProfileExporters;
+import org.sonar.server.qualityprofile.QProfileFactory;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+public class ExportAction implements QProfileWsAction {
+
+  private static final String PARAM_PROFILE_NAME = "name";
+  private static final String PARAM_LANGUAGE = "language";
+  private static final String PARAM_FORMAT = "exporterKey";
+
+  private final DbClient dbClient;
+
+  private final QProfileFactory profileFactory;
+
+  private final QProfileBackuper backuper;
+
+  private final QProfileExporters exporters;
+
+  private final Languages languages;
+
+  public ExportAction(DbClient dbClient, QProfileFactory profileFactory, QProfileBackuper backuper, QProfileExporters exporters, Languages languages) {
+    this.dbClient = dbClient;
+    this.profileFactory = profileFactory;
+    this.backuper = backuper;
+    this.exporters = exporters;
+    this.languages = languages;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction create = controller.createAction("export")
+      .setSince("5.2")
+      .setDescription("Export a quality profile.")
+      .setHandler(this);
+
+    create.createParam(PARAM_PROFILE_NAME)
+      .setDescription("The name of the quality profile to export. If left empty, will export the default profile for the language.")
+      .setExampleValue("My Sonar way");
+
+    create.createParam(PARAM_LANGUAGE)
+      .setDescription("The language for the quality profile.")
+      .setExampleValue(LanguageParamUtils.getExampleValue(languages))
+      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
+      .setRequired(true);
+
+    List<String> exporterKeys = Lists.newArrayList();
+    for (Language lang : languages.all()) {
+      for (ProfileExporter exporter : exporters.exportersForLanguage(lang.getKey())) {
+        exporterKeys.add(exporter.getKey());
+      }
+    }
+    if (!exporterKeys.isEmpty()) {
+      create.createParam(PARAM_FORMAT)
+        .setDescription("Output format. If left empty, the same format as api/qualityprofiles/backup is used. " +
+          "Possible values are described by api/qualityprofiles/exporters.")
+        .setPossibleValues(exporterKeys);
+    }
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    String name = request.param(PARAM_PROFILE_NAME);
+    String language = request.mandatoryParam(PARAM_LANGUAGE);
+    String format = null;
+    if (!exporters.exportersForLanguage(language).isEmpty()) {
+      format = request.param(PARAM_FORMAT);
+    }
+
+    DbSession dbSession = dbClient.openSession(false);
+    Stream stream = response.stream();
+    OutputStream output = stream.output();
+    Writer writer = new OutputStreamWriter(output, StandardCharsets.UTF_8);
+
+    try {
+      QualityProfileDto profile;
+      if (name == null) {
+        profile = profileFactory.getDefault(dbSession, language);
+      } else {
+        profile = profileFactory.getByNameAndLanguage(dbSession, name, language);
+      }
+      if (profile == null) {
+        throw new NotFoundException(String.format("Could not find profile with name '%s' for language '%s'", name, language));
+      }
+
+      String profileKey = profile.getKey();
+      if (format == null) {
+        stream.setMediaType(MimeTypes.XML);
+        backuper.backup(profileKey, writer);
+      } else {
+        stream.setMediaType(exporters.mimeType(format));
+        exporters.export(profileKey, format, writer);
+      }
+    } finally {
+      IOUtils.closeQuietly(writer);
+      IOUtils.closeQuietly(output);
+      dbSession.close();
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportersAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportersAction.java
new file mode 100644 (file)
index 0000000..0196729
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.utils.text.JsonWriter;
+
+public class ExportersAction implements QProfileWsAction {
+
+  private ProfileExporter[] exporters;
+
+  public ExportersAction(ProfileExporter[] exporters) {
+    this.exporters = exporters;
+  }
+
+  public ExportersAction() {
+    this(new ProfileExporter[0]);
+  }
+
+  @Override
+  public void define(NewController context) {
+    context.createAction("exporters")
+      .setDescription("Lists available profile export formats.")
+      .setHandler(this)
+      .setResponseExample(getClass().getResource("example-exporters.json"))
+      .setSince("5.2");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter json = response.newJsonWriter().beginObject().name("exporters").beginArray();
+    for (ProfileExporter exporter : exporters) {
+      json.beginObject()
+        .prop("key", exporter.getKey())
+        .prop("name", exporter.getName());
+      json.name("languages").beginArray();
+      for (String language : exporter.getSupportedLanguages()) {
+        json.value(language);
+      }
+      json.endArray().endObject();
+    }
+    json.endArray().endObject().close();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ImportersAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ImportersAction.java
new file mode 100644 (file)
index 0000000..6911be1
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.sonar.api.profiles.ProfileImporter;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+
+public class ImportersAction implements QProfileWsAction {
+
+  private final ProfileImporter[] importers;
+
+  public ImportersAction(ProfileImporter[] importers) {
+    this.importers = importers;
+  }
+
+  public ImportersAction() {
+    this(new ProfileImporter[0]);
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("importers")
+      .setSince("5.2")
+      .setDescription("List supported importers.")
+      .setResponseExample(getClass().getResource("example-importers.json"))
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter json = response.newJsonWriter().beginObject().name("importers").beginArray();
+    for (ProfileImporter importer : importers) {
+      json.beginObject()
+        .prop("key", importer.getKey())
+        .prop("name", importer.getName())
+        .name("languages").beginArray();
+      for (String languageKey : importer.getSupportedLanguages()) {
+        json.value(languageKey);
+      }
+      json.endArray().endObject();
+    }
+    json.endArray().endObject().close();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/InheritanceAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/InheritanceAction.java
new file mode 100644 (file)
index 0000000..5cf4062
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.collect.Multimap;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfile;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLoader;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
+import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
+import org.sonar.server.search.FacetValue;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+import java.util.Map;
+
+public class InheritanceAction implements QProfileWsAction {
+
+  private final DbClient dbClient;
+
+  private final QProfileLookup profileLookup;
+
+  private final QProfileLoader profileLoader;
+
+  private final QProfileFactory profileFactory;
+
+  private final Languages languages;
+
+  public InheritanceAction(DbClient dbClient, QProfileLookup profileLookup, QProfileLoader profileLoader, QProfileFactory profileFactory, Languages languages) {
+    this.dbClient = dbClient;
+    this.profileLookup = profileLookup;
+    this.profileLoader = profileLoader;
+    this.profileFactory = profileFactory;
+    this.languages = languages;
+  }
+
+  @Override
+  public void define(NewController context) {
+    NewAction inheritance = context.createAction("inheritance")
+      .setSince("5.2")
+      .setDescription("Show a quality profile's ancestors and children.")
+      .setHandler(this)
+      .setResponseExample(getClass().getResource("example-inheritance.json"));
+
+    QProfileIdentificationParamUtils.defineProfileParams(inheritance, languages);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    DbSession session = dbClient.openSession(false);
+    try {
+      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
+      QualityProfileDto profile = dbClient.qualityProfileDao().getByKey(session, profileKey);
+      if (profile == null) {
+        throw new NotFoundException(String.format("Could not find a quality profile with key %s", profileKey));
+      }
+
+      List<QProfile> ancestors = profileLookup.ancestors(profile, session);
+      List<QualityProfileDto> children = dbClient.qualityProfileDao().findChildren(session, profileKey);
+      Map<String, Multimap<String, FacetValue>> profileStats = profileLoader.getAllProfileStats();
+
+      writeResponse(response.newJsonWriter(), profile, ancestors, children, profileStats);
+    } finally {
+      session.close();
+    }
+  }
+
+  private void writeResponse(JsonWriter json, QualityProfileDto profile, List<QProfile> ancestors, List<QualityProfileDto> children,
+    Map<String, Multimap<String, FacetValue>> profileStats) {
+    json.beginObject();
+    writeProfile(json, profile, profileStats);
+    writeAncestors(json, ancestors, profileStats);
+    writeChildren(json, children, profileStats);
+    json.endObject().close();
+  }
+
+  private void writeProfile(JsonWriter json, QualityProfileDto profile, Map<String, Multimap<String, FacetValue>> profileStats) {
+    String profileKey = profile.getKey();
+    json.name("profile");
+    writeProfileAttributes(json, profileKey, profile.getName(), profile.getParentKee(), profileStats);
+  }
+
+  private void writeAncestors(JsonWriter json, List<QProfile> ancestors, Map<String, Multimap<String, FacetValue>> profileStats) {
+    json.name("ancestors").beginArray();
+    for (QProfile ancestor : ancestors) {
+      String ancestorKey = ancestor.key();
+      writeProfileAttributes(json, ancestorKey, ancestor.name(), ancestor.parent(), profileStats);
+    }
+    json.endArray();
+  }
+
+  private void writeChildren(JsonWriter json, List<QualityProfileDto> children, Map<String, Multimap<String, FacetValue>> profileStats) {
+    json.name("children").beginArray();
+    for (QualityProfileDto child : children) {
+      String childKey = child.getKey();
+      writeProfileAttributes(json, childKey, child.getName(), null, profileStats);
+    }
+    json.endArray();
+  }
+
+  private void writeProfileAttributes(JsonWriter json, String key, String name, @Nullable String parentKey, Map<String, Multimap<String, FacetValue>> profileStats) {
+    json.beginObject();
+    json.prop("key", key)
+      .prop("name", name)
+      .prop("parent", parentKey);
+    writeStats(json, key, profileStats);
+    json.endObject();
+  }
+
+  private void writeStats(JsonWriter json, String profileKey, Map<String, Multimap<String, FacetValue>> profileStats) {
+    if (profileStats.containsKey(profileKey)) {
+      Multimap<String, FacetValue> ancestorStats = profileStats.get(profileKey);
+      json.prop("activeRuleCount", getActiveRuleCount(ancestorStats));
+      json.prop("overridingRuleCount", getOverridingRuleCount(ancestorStats));
+    } else {
+      json.prop("activeRuleCount", 0);
+    }
+  }
+
+  private Long getActiveRuleCount(Multimap<String, FacetValue> profileStats) {
+    Long result = null;
+    if (profileStats.containsKey(ActiveRuleIndex.COUNT_ACTIVE_RULES)) {
+      result = profileStats.get(ActiveRuleIndex.COUNT_ACTIVE_RULES).iterator().next().getValue();
+    }
+    return result;
+  }
+
+  private Long getOverridingRuleCount(Multimap<String, FacetValue> profileStats) {
+    Long result = null;
+    if (profileStats.containsKey(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())) {
+      for (FacetValue value : profileStats.get(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())) {
+        if ("OVERRIDES".equals(value.getKey())) {
+          result = value.getValue();
+        }
+      }
+    }
+    return result;
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectsAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectsAction.java
new file mode 100644 (file)
index 0000000..f4b3bc9
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.builder.CompareToBuilder;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.utils.Paging;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ProjectQprofileAssociationDto;
+import org.sonar.core.util.NonNullInputFunction;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class ProjectsAction implements QProfileWsAction {
+
+  private static final String PARAM_KEY = "key";
+  private static final String PARAM_SELECTED = "selected";
+  private static final String PARAM_QUERY = "query";
+  private static final String PARAM_PAGE_SIZE = "pageSize";
+  private static final String PARAM_PAGE = "page";
+
+  private static final String SELECTION_ALL = "all";
+  private static final String SELECTION_SELECTED = "selected";
+  private static final String SELECTION_DESELECTED = "deselected";
+
+  private final DbClient dbClient;
+  private final UserSession userSession;
+
+  public ProjectsAction(DbClient dbClient, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(NewController controller) {
+    NewAction projects = controller.createAction("projects")
+      .setSince("5.2")
+      .setHandler(this)
+      .setDescription("List projects with their association status regarding a quality profile.")
+      .setResponseExample(getClass().getResource("example-projects.json"));
+    projects.createParam(PARAM_KEY)
+      .setDescription("A quality profile key.")
+      .setRequired(true)
+      .setExampleValue("sonar-way-java-12345");
+    projects.createParam(PARAM_SELECTED)
+      .setDescription("If specified, return only selected or deselected projects.")
+      .setPossibleValues(SELECTION_SELECTED, SELECTION_DESELECTED, SELECTION_ALL)
+      .setDefaultValue(SELECTION_ALL);
+    projects.createParam(PARAM_QUERY)
+      .setDescription("If specified, return only projects whose name match the query.");
+    projects.createParam(PARAM_PAGE_SIZE)
+      .setDescription("Size for the paging to apply.").setDefaultValue(100);
+    projects.createParam(PARAM_PAGE)
+      .setDescription("Index of the page to display.").setDefaultValue(1);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    String profileKey = request.mandatoryParam(PARAM_KEY);
+
+    DbSession session = dbClient.openSession(false);
+
+    try {
+      checkProfileExists(profileKey, session);
+      String selected = request.param(PARAM_SELECTED);
+      String query = request.param(PARAM_QUERY);
+      int pageSize = request.mandatoryParamAsInt(PARAM_PAGE_SIZE);
+      int page = request.mandatoryParamAsInt(PARAM_PAGE);
+
+      List<ProjectQprofileAssociationDto> projects = loadProjects(profileKey, session, selected, query);
+      Collections.sort(projects, new Comparator<ProjectQprofileAssociationDto>() {
+        @Override
+        public int compare(ProjectQprofileAssociationDto o1, ProjectQprofileAssociationDto o2) {
+          return new CompareToBuilder()
+            // First, sort by name
+            .append(o1.getProjectName(), o2.getProjectName())
+            // Then by UUID to disambiguate
+            .append(o1.getProjectUuid(), o2.getProjectUuid())
+            .toComparison();
+        }
+      });
+
+      Collection<Long> projectIds = Collections2.transform(projects, new NonNullInputFunction<ProjectQprofileAssociationDto, Long>() {
+        @Override
+        protected Long doApply(ProjectQprofileAssociationDto input) {
+          return input.getProjectId();
+        }
+      });
+
+      final Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(session, projectIds, userSession.getUserId(), UserRole.USER);
+      Iterable<ProjectQprofileAssociationDto> authorizedProjects = Iterables.filter(projects, new Predicate<ProjectQprofileAssociationDto>() {
+        @Override
+        public boolean apply(ProjectQprofileAssociationDto input) {
+          return authorizedProjectIds.contains(input.getProjectId());
+        }
+      });
+
+      Paging paging = Paging.create(pageSize, page, authorizedProjectIds.size());
+
+      List<ProjectQprofileAssociationDto> pagedAuthorizedProjects = Lists.newArrayList(authorizedProjects);
+      if (pagedAuthorizedProjects.size() <= paging.offset()) {
+        pagedAuthorizedProjects = Lists.newArrayList();
+      } else if (pagedAuthorizedProjects.size() > paging.pageSize()) {
+        int endIndex = Math.min(paging.offset() + pageSize, pagedAuthorizedProjects.size());
+        pagedAuthorizedProjects = pagedAuthorizedProjects.subList(paging.offset(), endIndex);
+      }
+
+      writeProjects(response.newJsonWriter(), pagedAuthorizedProjects, paging);
+    } finally {
+      session.close();
+    }
+  }
+
+  private void checkProfileExists(String profileKey, DbSession session) {
+    if (dbClient.qualityProfileDao().getByKey(session, profileKey) == null) {
+      throw new NotFoundException(String.format("Could not find a quality profile with key '%s'", profileKey));
+    }
+  }
+
+  private List<ProjectQprofileAssociationDto> loadProjects(String profileKey, DbSession session, String selected, String query) {
+    List<ProjectQprofileAssociationDto> projects = Lists.newArrayList();
+    if (SELECTION_SELECTED.equals(selected)) {
+      projects.addAll(dbClient.qualityProfileDao().selectSelectedProjects(profileKey, query, session));
+    } else if (SELECTION_DESELECTED.equals(selected)) {
+      projects.addAll(dbClient.qualityProfileDao().selectDeselectedProjects(profileKey, query, session));
+    } else {
+      projects.addAll(dbClient.qualityProfileDao().selectProjectAssociations(profileKey, query, session));
+    }
+    return projects;
+  }
+
+  private void writeProjects(JsonWriter json, List<ProjectQprofileAssociationDto> projects, Paging paging) {
+    json.beginObject();
+    json.name("results").beginArray();
+    for (ProjectQprofileAssociationDto project : projects) {
+      json.beginObject()
+        .prop("uuid", project.getProjectUuid())
+        .prop("name", project.getProjectName())
+        .prop("selected", project.isAssociated())
+        .endObject();
+    }
+    json.endArray();
+    json.prop("more", paging.hasNextPage());
+    json.endObject().close();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileBackupAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileBackupAction.java
deleted file mode 100644 (file)
index 0bca14c..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.Response.Stream;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.plugins.MimeTypes;
-import org.sonar.server.qualityprofile.QProfileBackuper;
-import org.sonar.server.qualityprofile.QProfileFactory;
-
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
-
-public class QProfileBackupAction implements QProfileWsAction {
-
-  private final QProfileBackuper backuper;
-
-  private final DbClient dbClient;
-
-  private QProfileFactory profileFactory;
-
-  private final Languages languages;
-
-  public QProfileBackupAction(QProfileBackuper backuper, DbClient dbClient, QProfileFactory profileFactory, Languages languages) {
-    this.backuper = backuper;
-    this.dbClient = dbClient;
-    this.profileFactory = profileFactory;
-    this.languages = languages;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    NewAction backup = controller.createAction("backup")
-      .setSince("5.2")
-      .setDescription("Backup a quality profile in XML form. The exported profile can be restored through api/qualityprofiles/restore.")
-      .setHandler(this);
-
-    QProfileIdentificationParamUtils.defineProfileParams(backup, languages);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    Stream stream = response.stream();
-    stream.setMediaType(MimeTypes.XML);
-    OutputStreamWriter writer = new OutputStreamWriter(stream.output(), StandardCharsets.UTF_8);
-    DbSession session = dbClient.openSession(false);
-    try {
-      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
-      backuper.backup(profileKey, writer);
-    } finally {
-      session.close();
-      IOUtils.closeQuietly(writer);
-    }
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentAction.java
deleted file mode 100644 (file)
index 034cddd..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.base.Preconditions;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.RuleActivator;
-import org.sonar.server.user.UserSession;
-
-import static org.apache.commons.lang.StringUtils.isEmpty;
-
-public class QProfileChangeParentAction implements QProfileWsAction {
-
-  private static final String PARAM_PARENT_KEY = "parentKey";
-
-  private static final String PARAM_PARENT_NAME = "parentName";
-
-  private final DbClient dbClient;
-
-  private final RuleActivator ruleActivator;
-
-  private final QProfileFactory profileFactory;
-
-  private final Languages languages;
-  private final UserSession userSession;
-
-  public QProfileChangeParentAction(DbClient dbClient, RuleActivator ruleActivator, QProfileFactory profileFactory, Languages languages, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.ruleActivator = ruleActivator;
-    this.profileFactory = profileFactory;
-    this.languages = languages;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(NewController context) {
-    NewAction inheritance = context.createAction("change_parent")
-      .setSince("5.2")
-      .setPost(true)
-      .setDescription("Change a quality profile's parent.")
-      .setHandler(this);
-
-    QProfileIdentificationParamUtils.defineProfileParams(inheritance, languages);
-
-    inheritance.createParam(PARAM_PARENT_KEY)
-      .setDescription("The key of the new parent profile. If this parameter is set, parentName must not be set. " +
-        "If both are left empty, the inheritance link with current parent profile (if any) is broken, which deactivates all rules " +
-        "which come from the parent and are not overridden.")
-      .setExampleValue("sonar-way-java-12345");
-    inheritance.createParam(PARAM_PARENT_NAME)
-      .setDescription("A quality profile name. If this parameter is set, profileKey must not be set and language must be set to disambiguate.")
-      .setExampleValue("Sonar way");
-
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    DbSession session = dbClient.openSession(false);
-    try {
-      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
-      String parentKey = getParentKeyFromParameters(request, profileFactory, session);
-
-      ruleActivator.setParent(profileKey, parentKey);
-
-      response.noContent();
-    } finally {
-      session.close();
-    }
-  }
-
-  private static String getParentKeyFromParameters(Request request, QProfileFactory profileFactory, DbSession session) {
-    String language = request.param(QProfileIdentificationParamUtils.PARAM_LANGUAGE);
-    String parentName = request.param(PARAM_PARENT_NAME);
-    String parentKey = request.param(PARAM_PARENT_KEY);
-
-    Preconditions.checkArgument(
-      isEmpty(parentName) || isEmpty(parentKey), "parentKey and parentName cannot be used simultaneously");
-
-    if (isEmpty(parentKey)) {
-      if (!isEmpty(parentName)) {
-        parentKey = QProfileIdentificationParamUtils.getProfileKeyFromLanguageAndName(language, parentName, profileFactory, session);
-      } else {
-        // Empty parent key is treated as "no more parent"
-        parentKey = null;
-      }
-    }
-
-    return parentKey;
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangelogAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangelogAction.java
deleted file mode 100644 (file)
index 6ad1992..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.search.SearchHit;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.*;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.Paging;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.core.user.UserDto;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfileActivity;
-import org.sonar.server.qualityprofile.QProfileActivityQuery;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.search.Result;
-
-import java.util.Date;
-import java.util.Map.Entry;
-
-public class QProfileChangelogAction implements QProfileWsAction {
-
-  private static final String PARAM_SINCE = "since";
-  private static final String PARAM_TO = "to";
-
-  private DbClient dbClient;
-  private ActivityIndex activityIndex;
-  private QProfileFactory profileFactory;
-  private Languages languages;
-
-  public QProfileChangelogAction(DbClient dbClient, ActivityIndex activityIndex, QProfileFactory profileFactory, Languages languages) {
-    this.dbClient = dbClient;
-    this.activityIndex = activityIndex;
-    this.profileFactory = profileFactory;
-    this.languages = languages;
-  }
-
-  @Override
-  public void define(NewController context) {
-    NewAction changelog = context.createAction("changelog")
-      .setSince("5.2")
-      .setDescription("Get the history of changes on a quality profile: rule activation/deactivation, change in parameters/severity. " +
-        "Events are ordered by date in descending order (most recent first).")
-      .setHandler(this)
-      .setResponseExample(getClass().getResource("example-changelog.json"));
-
-    QProfileIdentificationParamUtils.defineProfileParams(changelog, languages);
-
-    changelog.addPagingParams(50);
-
-    changelog.createParam(PARAM_SINCE)
-      .setDescription("Start date for the changelog.")
-      .setExampleValue("2011-04-25T01:15:42+0100");
-
-    changelog.createParam(PARAM_TO)
-      .setDescription("End date for the changelog.")
-      .setExampleValue("2013-07-25T07:35:42+0200");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    DbSession session = dbClient.openSession(false);
-    try {
-      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
-      if (dbClient.qualityProfileDao().getByKey(session, profileKey) == null) {
-        throw new NotFoundException(String.format("Could not find a profile with key '%s'", profileKey));
-      }
-
-      QProfileActivityQuery query = new QProfileActivityQuery().setQprofileKey(profileKey);
-      Date since = request.paramAsDateTime(PARAM_SINCE);
-      if (since != null) {
-        query.setSince(since);
-      }
-      Date to = request.paramAsDateTime(PARAM_TO);
-      if (to != null) {
-        query.setTo(to);
-      }
-      SearchOptions options = new SearchOptions();
-
-      int page = request.mandatoryParamAsInt(Param.PAGE);
-      options.setPage(page, request.mandatoryParamAsInt(Param.PAGE_SIZE));
-
-      Result<QProfileActivity> result = searchActivities(query, options);
-      writeResponse(response.newJsonWriter(), result, Paging.create(options.getLimit(), page, (int) result.getTotal()));
-    } finally {
-      session.close();
-    }
-  }
-
-  private Result<QProfileActivity> searchActivities(QProfileActivityQuery query, SearchOptions options) {
-    DbSession session = dbClient.openSession(false);
-    try {
-      SearchResponse response = activityIndex.doSearch(query, options);
-      Result<QProfileActivity> result = new Result<>(response);
-      for (SearchHit hit : response.getHits().getHits()) {
-        QProfileActivity profileActivity = new QProfileActivity(hit.getSource());
-        RuleDto ruleDto = dbClient.ruleDao().getNullableByKey(session, profileActivity.ruleKey());
-        profileActivity.ruleName(ruleDto != null ? ruleDto.getName() : null);
-
-        String login = profileActivity.getLogin();
-        if (login != null) {
-          UserDto user = dbClient.userDao().selectActiveUserByLogin(session, login);
-          profileActivity.authorName(user != null ? user.getName() : null);
-        }
-        result.getHits().add(profileActivity);
-      }
-      return result;
-    } finally {
-      session.close();
-    }
-  }
-
-  private void writeResponse(JsonWriter json, Result<QProfileActivity> result, Paging paging) {
-    json.beginObject();
-    json.prop("total", result.getTotal());
-    json.prop(Param.PAGE, paging.pageIndex());
-    json.prop(Param.PAGE_SIZE, paging.pageSize());
-    json.name("events").beginArray();
-    for (QProfileActivity event : result.getHits()) {
-      json.beginObject()
-        .prop("date", DateUtils.formatDateTime(event.getCreatedAt()))
-        .prop("authorLogin", event.getLogin())
-        .prop("authorName", event.authorName())
-        .prop("action", event.getAction())
-        .prop("ruleKey", event.ruleKey().toString())
-        .prop("ruleName", event.ruleName());
-      writeParameters(json, event);
-      json.endObject();
-    }
-    json.endArray();
-    json.endObject().close();
-  }
-
-  private void writeParameters(JsonWriter json, QProfileActivity event) {
-    json.name("params").beginObject()
-      .prop("severity", event.severity());
-    for (Entry<String, String> param : event.parameters().entrySet()) {
-      json.prop(param.getKey(), param.getValue());
-    }
-    json.endObject();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCompareAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCompareAction.java
deleted file mode 100644 (file)
index b455ab5..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.collect.MapDifference.ValueDifference;
-import com.google.common.collect.Maps;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.core.util.NonNullInputFunction;
-import org.sonar.server.qualityprofile.ActiveRule;
-import org.sonar.server.qualityprofile.QProfileComparison;
-import org.sonar.server.qualityprofile.QProfileComparison.ActiveRuleDiff;
-import org.sonar.server.qualityprofile.QProfileComparison.QProfileComparisonResult;
-import org.sonar.server.rule.Rule;
-import org.sonar.server.rule.RuleRepositories;
-import org.sonar.server.rule.RuleRepositories.Repository;
-import org.sonar.server.rule.RuleService;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-public class QProfileCompareAction implements QProfileWsAction {
-
-  private static final String ATTRIBUTE_LEFT = "left";
-  private static final String ATTRIBUTE_RIGHT = "right";
-  private static final String ATTRIBUTE_IN_LEFT = "inLeft";
-  private static final String ATTRIBUTE_IN_RIGHT = "inRight";
-  private static final String ATTRIBUTE_MODIFIED = "modified";
-  private static final String ATTRIBUTE_SAME = "same";
-  private static final String ATTRIBUTE_KEY = "key";
-  private static final String ATTRIBUTE_NAME = "name";
-  private static final String ATTRIBUTE_SEVERITY = "severity";
-  private static final String ATTRIBUTE_PLUGIN_KEY = "pluginKey";
-  private static final String ATTRIBUTE_PLUGIN_NAME = "pluginName";
-  private static final String ATTRIBUTE_LANGUAGE_KEY = "languageKey";
-  private static final String ATTRIBUTE_LANGUAGE_NAME = "languageName";
-  private static final String ATTRIBUTE_PARAMS = "params";
-
-  private static final String PARAM_LEFT_KEY = "leftKey";
-  private static final String PARAM_RIGHT_KEY = "rightKey";
-
-  private final QProfileComparison comparator;
-  private final RuleService ruleService;
-  private final RuleRepositories ruleRepositories;
-  private final Languages languages;
-
-  public QProfileCompareAction(QProfileComparison comparator, RuleService ruleService, RuleRepositories ruleRepositories, Languages languages) {
-    this.comparator = comparator;
-    this.ruleService = ruleService;
-    this.ruleRepositories = ruleRepositories;
-    this.languages = languages;
-  }
-
-  @Override
-  public void define(NewController context) {
-    NewAction compare = context.createAction("compare")
-      .setDescription("Compare two quality profiles.")
-      .setHandler(this)
-      .setInternal(true)
-      .setResponseExample(getClass().getResource("example-compare.json"))
-      .setSince("5.2");
-
-    compare.createParam(PARAM_LEFT_KEY)
-      .setDescription("A profile key.")
-      .setExampleValue("java-sonar-way-12345")
-      .setRequired(true);
-
-    compare.createParam(PARAM_RIGHT_KEY)
-      .setDescription("Another profile key.")
-      .setExampleValue("java-sonar-way-with-findbugs-23456")
-      .setRequired(true);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    String leftKey = request.mandatoryParam(PARAM_LEFT_KEY);
-    String rightKey = request.mandatoryParam(PARAM_RIGHT_KEY);
-
-    QProfileComparisonResult result = comparator.compare(leftKey, rightKey);
-
-    List<Rule> referencedRules = ruleService.getByKeys(result.collectRuleKeys());
-    Map<RuleKey, Rule> rulesByKey = Maps.uniqueIndex(referencedRules, new NonNullInputFunction<Rule, RuleKey>() {
-      @Override
-      protected RuleKey doApply(Rule input) {
-        return input.key();
-      }
-    });
-
-    writeResult(response.newJsonWriter(), result, rulesByKey);
-  }
-
-  private void writeResult(JsonWriter json, QProfileComparisonResult result, Map<RuleKey, Rule> rulesByKey) {
-    json.beginObject();
-
-    json.name(ATTRIBUTE_LEFT).beginObject();
-    writeProfile(json, result.left());
-    json.endObject();
-
-    json.name(ATTRIBUTE_RIGHT).beginObject();
-    writeProfile(json, result.right());
-    json.endObject();
-
-    json.name(ATTRIBUTE_IN_LEFT);
-    writeRules(json, result.inLeft(), rulesByKey);
-
-    json.name(ATTRIBUTE_IN_RIGHT);
-    writeRules(json, result.inRight(), rulesByKey);
-
-    json.name(ATTRIBUTE_MODIFIED);
-    writeDifferences(json, result.modified(), rulesByKey);
-
-    json.name(ATTRIBUTE_SAME);
-    writeRules(json, result.same(), rulesByKey);
-
-    json.endObject().close();
-  }
-
-  private void writeProfile(JsonWriter json, QualityProfileDto profile) {
-    json.prop(ATTRIBUTE_KEY, profile.getKey())
-      .prop(ATTRIBUTE_NAME, profile.getName());
-  }
-
-  private void writeRules(JsonWriter json, Map<RuleKey, ActiveRule> activeRules, Map<RuleKey, Rule> rulesByKey) {
-    json.beginArray();
-    for (Entry<RuleKey, ActiveRule> activeRule : activeRules.entrySet()) {
-      RuleKey key = activeRule.getKey();
-      ActiveRule value = activeRule.getValue();
-
-      json.beginObject();
-      writeRule(json, key, rulesByKey);
-      json.prop(ATTRIBUTE_SEVERITY, value.severity());
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-  private void writeRule(JsonWriter json, RuleKey key, Map<RuleKey, Rule> rulesByKey) {
-    String repositoryKey = key.repository();
-    json.prop(ATTRIBUTE_KEY, key.toString())
-      .prop(ATTRIBUTE_NAME, rulesByKey.get(key).name())
-      .prop(ATTRIBUTE_PLUGIN_KEY, repositoryKey);
-
-    Repository repo = ruleRepositories.repository(repositoryKey);
-    if (repo != null) {
-      String languageKey = repo.getLanguage();
-      Language language = languages.get(languageKey);
-
-      json.prop(ATTRIBUTE_PLUGIN_NAME, repo.getName());
-      json.prop(ATTRIBUTE_LANGUAGE_KEY, languageKey);
-      json.prop(ATTRIBUTE_LANGUAGE_NAME, language == null ? null : language.getName());
-    }
-  }
-
-  private void writeDifferences(JsonWriter json, Map<RuleKey, ActiveRuleDiff> modified, Map<RuleKey, Rule> rulesByKey) {
-    json.beginArray();
-    for (Entry<RuleKey, ActiveRuleDiff> diffEntry : modified.entrySet()) {
-      RuleKey key = diffEntry.getKey();
-      ActiveRuleDiff value = diffEntry.getValue();
-      json.beginObject();
-      writeRule(json, key, rulesByKey);
-
-      json.name(ATTRIBUTE_LEFT).beginObject();
-      json.prop(ATTRIBUTE_SEVERITY, value.leftSeverity());
-      json.name(ATTRIBUTE_PARAMS).beginObject();
-      for (Entry<String, ValueDifference<String>> valueDiff : value.paramDifference().entriesDiffering().entrySet()) {
-        json.prop(valueDiff.getKey(), valueDiff.getValue().leftValue());
-      }
-      for (Entry<String, String> valueDiff : value.paramDifference().entriesOnlyOnLeft().entrySet()) {
-        json.prop(valueDiff.getKey(), valueDiff.getValue());
-      }
-      // params
-      json.endObject();
-      // left
-      json.endObject();
-
-      json.name(ATTRIBUTE_RIGHT).beginObject();
-      json.prop(ATTRIBUTE_SEVERITY, value.rightSeverity());
-      json.name(ATTRIBUTE_PARAMS).beginObject();
-      for (Entry<String, ValueDifference<String>> valueDiff : value.paramDifference().entriesDiffering().entrySet()) {
-        json.prop(valueDiff.getKey(), valueDiff.getValue().rightValue());
-      }
-      for (Entry<String, String> valueDiff : value.paramDifference().entriesOnlyOnRight().entrySet()) {
-        json.prop(valueDiff.getKey(), valueDiff.getValue());
-      }
-      // params
-      json.endObject();
-      // right
-      json.endObject();
-
-      // rule
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCopyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCopyAction.java
deleted file mode 100644 (file)
index 99b0a5c..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.qualityprofile.QProfileCopier;
-import org.sonar.server.user.UserSession;
-
-public class QProfileCopyAction implements QProfileWsAction {
-
-  private static final String PARAM_PROFILE_NAME = "toName";
-  private static final String PARAM_PROFILE_KEY = "fromKey";
-
-  private final QProfileCopier profileCopier;
-  private final Languages languages;
-  private final UserSession userSession;
-
-  public QProfileCopyAction(QProfileCopier profileCopier, Languages languages, UserSession userSession) {
-    this.profileCopier = profileCopier;
-    this.languages = languages;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    NewAction setDefault = controller.createAction("copy")
-      .setSince("5.2")
-      .setDescription("Copy a quality profile.")
-      .setPost(true)
-      .setHandler(this);
-
-    setDefault.createParam(PARAM_PROFILE_NAME)
-      .setDescription("The name for the new quality profile.")
-      .setExampleValue("My Sonar way")
-      .setRequired(true);
-
-    setDefault.createParam(PARAM_PROFILE_KEY)
-      .setDescription("The key of a quality profile.")
-      .setExampleValue("sonar-way-js-12345")
-      .setRequired(true);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    String newName = request.mandatoryParam(PARAM_PROFILE_NAME);
-    String profileKey = request.mandatoryParam(PARAM_PROFILE_KEY);
-
-    QualityProfileDto copiedProfile = profileCopier.copyToName(profileKey, newName);
-
-    String languageKey = copiedProfile.getLanguage();
-    Language language = languages.get(copiedProfile.getLanguage());
-    String parentKey = copiedProfile.getParentKee();
-    response.newJsonWriter()
-      .beginObject()
-      .prop("key", copiedProfile.getKey())
-      .prop("name", copiedProfile.getName())
-      .prop("language", languageKey)
-      .prop("languageName", language == null ? null : language.getName())
-      .prop("isDefault", copiedProfile.isDefault())
-      .prop("isInherited", parentKey != null)
-      .prop("parentKey", parentKey)
-      .endObject().close();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCreateAction.java
deleted file mode 100644 (file)
index 18b7b82..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.sonar.api.profiles.ProfileImporter;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.qualityprofile.QProfileExporters;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.qualityprofile.QProfileResult;
-
-import java.io.InputStream;
-import org.sonar.server.user.UserSession;
-
-public class QProfileCreateAction implements QProfileWsAction {
-
-  private static final String PARAM_PROFILE_NAME = "name";
-  private static final String PARAM_LANGUAGE = "language";
-  private static final String PARAM_BACKUP_FORMAT = "backup_%s";
-
-  private final DbClient dbClient;
-
-  private final QProfileFactory profileFactory;
-
-  private final QProfileExporters exporters;
-
-  private final Languages languages;
-
-  private final ProfileImporter[] importers;
-  private final UserSession userSession;
-
-  public QProfileCreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters,
-    Languages languages, ProfileImporter[] importers, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.profileFactory = profileFactory;
-    this.exporters = exporters;
-    this.languages = languages;
-    this.importers = importers;
-    this.userSession = userSession;
-  }
-
-  public QProfileCreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters, Languages languages, UserSession userSession) {
-    this(dbClient, profileFactory, exporters, languages, new ProfileImporter[0], userSession);
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    NewAction create = controller.createAction("create")
-      .setSince("5.2")
-      .setDescription("Create a quality profile.")
-      .setPost(true)
-      .setResponseExample(getClass().getResource("example-create.json"))
-      .setHandler(this);
-
-    create.createParam(PARAM_PROFILE_NAME)
-      .setDescription("The name for the new quality profile.")
-      .setExampleValue("My Sonar way")
-      .setRequired(true);
-
-    create.createParam(PARAM_LANGUAGE)
-      .setDescription("The language for the quality profile.")
-      .setExampleValue("js")
-      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
-      .setRequired(true);
-
-    for (ProfileImporter importer : importers) {
-      create.createParam(getBackupParamName(importer.getKey()))
-        .setDescription(String.format("A configuration file for %s.", importer.getName()));
-    }
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    String name = request.mandatoryParam(PARAM_PROFILE_NAME);
-    String language = request.mandatoryParam(PARAM_LANGUAGE);
-
-    DbSession dbSession = dbClient.openSession(false);
-
-    try {
-      QProfileResult result = new QProfileResult();
-      QualityProfileDto profile = profileFactory.create(dbSession, QProfileName.createFor(language, name));
-      result.setProfile(profile);
-      for (ProfileImporter importer : importers) {
-        InputStream contentToImport = request.paramAsInputStream(getBackupParamName(importer.getKey()));
-        if (contentToImport != null) {
-          result.add(exporters.importXml(profile, importer.getKey(), contentToImport, dbSession));
-        }
-      }
-      dbSession.commit();
-      writeResult(response.newJsonWriter(), result);
-    } finally {
-      dbSession.close();
-    }
-  }
-
-  private void writeResult(JsonWriter json, QProfileResult result) {
-    String language = result.profile().getLanguage();
-    json.beginObject().name("profile").beginObject()
-      .prop("key", result.profile().getKey())
-      .prop("name", result.profile().getName())
-      .prop("language", language)
-      .prop("languageName", languages.get(result.profile().getLanguage()).getName())
-      .prop("isDefault", false)
-      .prop("isInherited", false)
-      .endObject();
-
-    if (!result.infos().isEmpty()) {
-      json.name("infos").beginArray();
-      for (String info : result.infos()) {
-        json.value(info);
-      }
-      json.endArray();
-    }
-
-    if (!result.warnings().isEmpty()) {
-      json.name("warnings").beginArray();
-      for (String warning : result.warnings()) {
-        json.value(warning);
-      }
-      json.endArray();
-    }
-
-    json.endObject().close();
-  }
-
-  private String getBackupParamName(String importerKey) {
-    return String.format(PARAM_BACKUP_FORMAT, importerKey);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileDeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileDeleteAction.java
deleted file mode 100644 (file)
index 800031e..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.user.UserSession;
-
-public class QProfileDeleteAction implements QProfileWsAction {
-
-  private final Languages languages;
-  private final QProfileFactory profileFactory;
-  private final DbClient dbClient;
-  private final UserSession userSession;
-
-  public QProfileDeleteAction(Languages languages, QProfileFactory profileFactory, DbClient dbClient, UserSession userSession) {
-    this.languages = languages;
-    this.profileFactory = profileFactory;
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(NewController controller) {
-    NewAction action = controller.createAction("delete")
-      .setDescription("Delete a quality profile and all its descendants. The default quality profile cannot be deleted.")
-      .setSince("5.2")
-      .setPost(true)
-      .setHandler(this);
-
-    QProfileIdentificationParamUtils.defineProfileParams(action, languages);
-  }
-
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkLoggedIn();
-    userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-
-    DbSession session = dbClient.openSession(false);
-    try {
-      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
-      profileFactory.delete(session, profileKey, false);
-
-      session.commit();
-    } finally {
-      session.close();
-    }
-
-    response.noContent();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileExportAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileExportAction.java
deleted file mode 100644 (file)
index 1750393..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.profiles.ProfileExporter;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.Response.Stream;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.plugins.MimeTypes;
-import org.sonar.server.qualityprofile.QProfileBackuper;
-import org.sonar.server.qualityprofile.QProfileExporters;
-import org.sonar.server.qualityprofile.QProfileFactory;
-
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
-public class QProfileExportAction implements QProfileWsAction {
-
-  private static final String PARAM_PROFILE_NAME = "name";
-  private static final String PARAM_LANGUAGE = "language";
-  private static final String PARAM_FORMAT = "exporterKey";
-
-  private final DbClient dbClient;
-
-  private final QProfileFactory profileFactory;
-
-  private final QProfileBackuper backuper;
-
-  private final QProfileExporters exporters;
-
-  private final Languages languages;
-
-  public QProfileExportAction(DbClient dbClient, QProfileFactory profileFactory, QProfileBackuper backuper, QProfileExporters exporters, Languages languages) {
-    this.dbClient = dbClient;
-    this.profileFactory = profileFactory;
-    this.backuper = backuper;
-    this.exporters = exporters;
-    this.languages = languages;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    NewAction create = controller.createAction("export")
-      .setSince("5.2")
-      .setDescription("Export a quality profile.")
-      .setHandler(this);
-
-    create.createParam(PARAM_PROFILE_NAME)
-      .setDescription("The name of the quality profile to export. If left empty, will export the default profile for the language.")
-      .setExampleValue("My Sonar way");
-
-    create.createParam(PARAM_LANGUAGE)
-      .setDescription("The language for the quality profile.")
-      .setExampleValue(LanguageParamUtils.getExampleValue(languages))
-      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
-      .setRequired(true);
-
-    List<String> exporterKeys = Lists.newArrayList();
-    for (Language lang : languages.all()) {
-      for (ProfileExporter exporter : exporters.exportersForLanguage(lang.getKey())) {
-        exporterKeys.add(exporter.getKey());
-      }
-    }
-    if (!exporterKeys.isEmpty()) {
-      create.createParam(PARAM_FORMAT)
-        .setDescription("Output format. If left empty, the same format as api/qualityprofiles/backup is used. " +
-          "Possible values are described by api/qualityprofiles/exporters.")
-        .setPossibleValues(exporterKeys);
-    }
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    String name = request.param(PARAM_PROFILE_NAME);
-    String language = request.mandatoryParam(PARAM_LANGUAGE);
-    String format = null;
-    if (!exporters.exportersForLanguage(language).isEmpty()) {
-      format = request.param(PARAM_FORMAT);
-    }
-
-    DbSession dbSession = dbClient.openSession(false);
-    Stream stream = response.stream();
-    OutputStream output = stream.output();
-    Writer writer = new OutputStreamWriter(output, StandardCharsets.UTF_8);
-
-    try {
-      QualityProfileDto profile;
-      if (name == null) {
-        profile = profileFactory.getDefault(dbSession, language);
-      } else {
-        profile = profileFactory.getByNameAndLanguage(dbSession, name, language);
-      }
-      if (profile == null) {
-        throw new NotFoundException(String.format("Could not find profile with name '%s' for language '%s'", name, language));
-      }
-
-      String profileKey = profile.getKey();
-      if (format == null) {
-        stream.setMediaType(MimeTypes.XML);
-        backuper.backup(profileKey, writer);
-      } else {
-        stream.setMediaType(exporters.mimeType(format));
-        exporters.export(profileKey, format, writer);
-      }
-    } finally {
-      IOUtils.closeQuietly(writer);
-      IOUtils.closeQuietly(output);
-      dbSession.close();
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileExportersAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileExportersAction.java
deleted file mode 100644 (file)
index fff90fc..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.sonar.api.profiles.ProfileExporter;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.api.utils.text.JsonWriter;
-
-public class QProfileExportersAction implements QProfileWsAction {
-
-  private ProfileExporter[] exporters;
-
-  public QProfileExportersAction(ProfileExporter[] exporters) {
-    this.exporters = exporters;
-  }
-
-  public QProfileExportersAction() {
-    this(new ProfileExporter[0]);
-  }
-
-  @Override
-  public void define(NewController context) {
-    context.createAction("exporters")
-      .setDescription("Lists available profile export formats.")
-      .setHandler(this)
-      .setResponseExample(getClass().getResource("example-exporters.json"))
-      .setSince("5.2");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter json = response.newJsonWriter().beginObject().name("exporters").beginArray();
-    for (ProfileExporter exporter : exporters) {
-      json.beginObject()
-        .prop("key", exporter.getKey())
-        .prop("name", exporter.getName());
-      json.name("languages").beginArray();
-      for (String language : exporter.getSupportedLanguages()) {
-        json.value(language);
-      }
-      json.endArray().endObject();
-    }
-    json.endArray().endObject().close();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileImportersAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileImportersAction.java
deleted file mode 100644 (file)
index dba30bf..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.sonar.api.profiles.ProfileImporter;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-
-public class QProfileImportersAction implements QProfileWsAction {
-
-  private final ProfileImporter[] importers;
-
-  public QProfileImportersAction(ProfileImporter[] importers) {
-    this.importers = importers;
-  }
-
-  public QProfileImportersAction() {
-    this(new ProfileImporter[0]);
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("importers")
-      .setSince("5.2")
-      .setDescription("List supported importers.")
-      .setResponseExample(getClass().getResource("example-importers.json"))
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter json = response.newJsonWriter().beginObject().name("importers").beginArray();
-    for (ProfileImporter importer : importers) {
-      json.beginObject()
-        .prop("key", importer.getKey())
-        .prop("name", importer.getName())
-        .name("languages").beginArray();
-      for (String languageKey : importer.getSupportedLanguages()) {
-        json.value(languageKey);
-      }
-      json.endArray().endObject();
-    }
-    json.endArray().endObject().close();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java
deleted file mode 100644 (file)
index fd1790e..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.collect.Multimap;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfile;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileLoader;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
-import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
-import org.sonar.server.search.FacetValue;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-import java.util.Map;
-
-public class QProfileInheritanceAction implements QProfileWsAction {
-
-  private final DbClient dbClient;
-
-  private final QProfileLookup profileLookup;
-
-  private final QProfileLoader profileLoader;
-
-  private final QProfileFactory profileFactory;
-
-  private final Languages languages;
-
-  public QProfileInheritanceAction(DbClient dbClient, QProfileLookup profileLookup, QProfileLoader profileLoader, QProfileFactory profileFactory, Languages languages) {
-    this.dbClient = dbClient;
-    this.profileLookup = profileLookup;
-    this.profileLoader = profileLoader;
-    this.profileFactory = profileFactory;
-    this.languages = languages;
-  }
-
-  @Override
-  public void define(NewController context) {
-    NewAction inheritance = context.createAction("inheritance")
-      .setSince("5.2")
-      .setDescription("Show a quality profile's ancestors and children.")
-      .setHandler(this)
-      .setResponseExample(getClass().getResource("example-inheritance.json"));
-
-    QProfileIdentificationParamUtils.defineProfileParams(inheritance, languages);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    DbSession session = dbClient.openSession(false);
-    try {
-      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
-      QualityProfileDto profile = dbClient.qualityProfileDao().getByKey(session, profileKey);
-      if (profile == null) {
-        throw new NotFoundException(String.format("Could not find a quality profile with key %s", profileKey));
-      }
-
-      List<QProfile> ancestors = profileLookup.ancestors(profile, session);
-      List<QualityProfileDto> children = dbClient.qualityProfileDao().findChildren(session, profileKey);
-      Map<String, Multimap<String, FacetValue>> profileStats = profileLoader.getAllProfileStats();
-
-      writeResponse(response.newJsonWriter(), profile, ancestors, children, profileStats);
-    } finally {
-      session.close();
-    }
-  }
-
-  private void writeResponse(JsonWriter json, QualityProfileDto profile, List<QProfile> ancestors, List<QualityProfileDto> children,
-    Map<String, Multimap<String, FacetValue>> profileStats) {
-    json.beginObject();
-    writeProfile(json, profile, profileStats);
-    writeAncestors(json, ancestors, profileStats);
-    writeChildren(json, children, profileStats);
-    json.endObject().close();
-  }
-
-  private void writeProfile(JsonWriter json, QualityProfileDto profile, Map<String, Multimap<String, FacetValue>> profileStats) {
-    String profileKey = profile.getKey();
-    json.name("profile");
-    writeProfileAttributes(json, profileKey, profile.getName(), profile.getParentKee(), profileStats);
-  }
-
-  private void writeAncestors(JsonWriter json, List<QProfile> ancestors, Map<String, Multimap<String, FacetValue>> profileStats) {
-    json.name("ancestors").beginArray();
-    for (QProfile ancestor : ancestors) {
-      String ancestorKey = ancestor.key();
-      writeProfileAttributes(json, ancestorKey, ancestor.name(), ancestor.parent(), profileStats);
-    }
-    json.endArray();
-  }
-
-  private void writeChildren(JsonWriter json, List<QualityProfileDto> children, Map<String, Multimap<String, FacetValue>> profileStats) {
-    json.name("children").beginArray();
-    for (QualityProfileDto child : children) {
-      String childKey = child.getKey();
-      writeProfileAttributes(json, childKey, child.getName(), null, profileStats);
-    }
-    json.endArray();
-  }
-
-  private void writeProfileAttributes(JsonWriter json, String key, String name, @Nullable String parentKey, Map<String, Multimap<String, FacetValue>> profileStats) {
-    json.beginObject();
-    json.prop("key", key)
-      .prop("name", name)
-      .prop("parent", parentKey);
-    writeStats(json, key, profileStats);
-    json.endObject();
-  }
-
-  private void writeStats(JsonWriter json, String profileKey, Map<String, Multimap<String, FacetValue>> profileStats) {
-    if (profileStats.containsKey(profileKey)) {
-      Multimap<String, FacetValue> ancestorStats = profileStats.get(profileKey);
-      json.prop("activeRuleCount", getActiveRuleCount(ancestorStats));
-      json.prop("overridingRuleCount", getOverridingRuleCount(ancestorStats));
-    } else {
-      json.prop("activeRuleCount", 0);
-    }
-  }
-
-  private Long getActiveRuleCount(Multimap<String, FacetValue> profileStats) {
-    Long result = null;
-    if (profileStats.containsKey(ActiveRuleIndex.COUNT_ACTIVE_RULES)) {
-      result = profileStats.get(ActiveRuleIndex.COUNT_ACTIVE_RULES).iterator().next().getValue();
-    }
-    return result;
-  }
-
-  private Long getOverridingRuleCount(Multimap<String, FacetValue> profileStats) {
-    Long result = null;
-    if (profileStats.containsKey(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())) {
-      for (FacetValue value : profileStats.get(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())) {
-        if ("OVERRIDES".equals(value.getKey())) {
-          result = value.getValue();
-        }
-      }
-    }
-    return result;
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileProjectsAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileProjectsAction.java
deleted file mode 100644 (file)
index c36b90a..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import org.apache.commons.lang.builder.CompareToBuilder;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.api.utils.Paging;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.qualityprofile.db.ProjectQprofileAssociationDto;
-import org.sonar.core.util.NonNullInputFunction;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.user.UserSession;
-
-public class QProfileProjectsAction implements QProfileWsAction {
-
-  private static final String PARAM_KEY = "key";
-  private static final String PARAM_SELECTED = "selected";
-  private static final String PARAM_QUERY = "query";
-  private static final String PARAM_PAGE_SIZE = "pageSize";
-  private static final String PARAM_PAGE = "page";
-
-  private static final String SELECTION_ALL = "all";
-  private static final String SELECTION_SELECTED = "selected";
-  private static final String SELECTION_DESELECTED = "deselected";
-
-  private final DbClient dbClient;
-  private final UserSession userSession;
-
-  public QProfileProjectsAction(DbClient dbClient, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(NewController controller) {
-    NewAction projects = controller.createAction("projects")
-      .setSince("5.2")
-      .setHandler(this)
-      .setDescription("List projects with their association status regarding a quality profile.")
-      .setResponseExample(getClass().getResource("example-projects.json"));
-    projects.createParam(PARAM_KEY)
-      .setDescription("A quality profile key.")
-      .setRequired(true)
-      .setExampleValue("sonar-way-java-12345");
-    projects.createParam(PARAM_SELECTED)
-      .setDescription("If specified, return only selected or deselected projects.")
-      .setPossibleValues(SELECTION_SELECTED, SELECTION_DESELECTED, SELECTION_ALL)
-      .setDefaultValue(SELECTION_ALL);
-    projects.createParam(PARAM_QUERY)
-      .setDescription("If specified, return only projects whose name match the query.");
-    projects.createParam(PARAM_PAGE_SIZE)
-      .setDescription("Size for the paging to apply.").setDefaultValue(100);
-    projects.createParam(PARAM_PAGE)
-      .setDescription("Index of the page to display.").setDefaultValue(1);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    String profileKey = request.mandatoryParam(PARAM_KEY);
-
-    DbSession session = dbClient.openSession(false);
-
-    try {
-      checkProfileExists(profileKey, session);
-      String selected = request.param(PARAM_SELECTED);
-      String query = request.param(PARAM_QUERY);
-      int pageSize = request.mandatoryParamAsInt(PARAM_PAGE_SIZE);
-      int page = request.mandatoryParamAsInt(PARAM_PAGE);
-
-      List<ProjectQprofileAssociationDto> projects = loadProjects(profileKey, session, selected, query);
-      Collections.sort(projects, new Comparator<ProjectQprofileAssociationDto>() {
-        @Override
-        public int compare(ProjectQprofileAssociationDto o1, ProjectQprofileAssociationDto o2) {
-          return new CompareToBuilder()
-            // First, sort by name
-            .append(o1.getProjectName(), o2.getProjectName())
-            // Then by UUID to disambiguate
-            .append(o1.getProjectUuid(), o2.getProjectUuid())
-            .toComparison();
-        }
-      });
-
-      Collection<Long> projectIds = Collections2.transform(projects, new NonNullInputFunction<ProjectQprofileAssociationDto, Long>() {
-        @Override
-        protected Long doApply(ProjectQprofileAssociationDto input) {
-          return input.getProjectId();
-        }
-      });
-
-      final Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(session, projectIds, userSession.getUserId(), UserRole.USER);
-      Iterable<ProjectQprofileAssociationDto> authorizedProjects = Iterables.filter(projects, new Predicate<ProjectQprofileAssociationDto>() {
-        @Override
-        public boolean apply(ProjectQprofileAssociationDto input) {
-          return authorizedProjectIds.contains(input.getProjectId());
-        }
-      });
-
-      Paging paging = Paging.create(pageSize, page, authorizedProjectIds.size());
-
-      List<ProjectQprofileAssociationDto> pagedAuthorizedProjects = Lists.newArrayList(authorizedProjects);
-      if (pagedAuthorizedProjects.size() <= paging.offset()) {
-        pagedAuthorizedProjects = Lists.newArrayList();
-      } else if (pagedAuthorizedProjects.size() > paging.pageSize()) {
-        int endIndex = Math.min(paging.offset() + pageSize, pagedAuthorizedProjects.size());
-        pagedAuthorizedProjects = pagedAuthorizedProjects.subList(paging.offset(), endIndex);
-      }
-
-      writeProjects(response.newJsonWriter(), pagedAuthorizedProjects, paging);
-    } finally {
-      session.close();
-    }
-  }
-
-  private void checkProfileExists(String profileKey, DbSession session) {
-    if (dbClient.qualityProfileDao().getByKey(session, profileKey) == null) {
-      throw new NotFoundException(String.format("Could not find a quality profile with key '%s'", profileKey));
-    }
-  }
-
-  private List<ProjectQprofileAssociationDto> loadProjects(String profileKey, DbSession session, String selected, String query) {
-    List<ProjectQprofileAssociationDto> projects = Lists.newArrayList();
-    if (SELECTION_SELECTED.equals(selected)) {
-      projects.addAll(dbClient.qualityProfileDao().selectSelectedProjects(profileKey, query, session));
-    } else if (SELECTION_DESELECTED.equals(selected)) {
-      projects.addAll(dbClient.qualityProfileDao().selectDeselectedProjects(profileKey, query, session));
-    } else {
-      projects.addAll(dbClient.qualityProfileDao().selectProjectAssociations(profileKey, query, session));
-    }
-    return projects;
-  }
-
-  private void writeProjects(JsonWriter json, List<ProjectQprofileAssociationDto> projects, Paging paging) {
-    json.beginObject();
-    json.name("results").beginArray();
-    for (ProjectQprofileAssociationDto project : projects) {
-      json.beginObject()
-        .prop("uuid", project.getProjectUuid())
-        .prop("name", project.getProjectName())
-        .prop("selected", project.isAssociated())
-        .endObject();
-    }
-    json.endArray();
-    json.prop("more", paging.hasNextPage());
-    json.endObject().close();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRenameAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRenameAction.java
deleted file mode 100644 (file)
index 65ef7a3..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.user.UserSession;
-
-public class QProfileRenameAction implements QProfileWsAction {
-
-  private static final String PARAM_PROFILE_NAME = "name";
-  private static final String PARAM_PROFILE_KEY = "key";
-
-  private final QProfileFactory profileFactory;
-  private final UserSession userSession;
-
-  public QProfileRenameAction(QProfileFactory profileFactory, UserSession userSession) {
-    this.profileFactory = profileFactory;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    NewAction setDefault = controller.createAction("rename")
-      .setSince("5.2")
-      .setDescription("Rename a quality profile.")
-      .setPost(true)
-      .setHandler(this);
-
-    setDefault.createParam(PARAM_PROFILE_NAME)
-      .setDescription("The new name for the quality profile.")
-      .setExampleValue("My Sonar way")
-      .setRequired(true);
-
-    setDefault.createParam(PARAM_PROFILE_KEY)
-      .setDescription("The key of a quality profile.")
-      .setExampleValue("sonar-way-js-12345")
-      .setRequired(true);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    String newName = request.mandatoryParam(PARAM_PROFILE_NAME);
-    String profileKey = request.mandatoryParam(PARAM_PROFILE_KEY);
-
-    profileFactory.rename(profileKey, newName);
-
-    response.noContent();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreAction.java
deleted file mode 100644 (file)
index 621bf94..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.base.Preconditions;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.qualityprofile.BulkChangeResult;
-import org.sonar.server.qualityprofile.QProfileBackuper;
-import org.sonar.server.user.UserSession;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-
-public class QProfileRestoreAction implements QProfileWsAction {
-
-  private static final String PARAM_BACKUP = "backup";
-  private final QProfileBackuper backuper;
-  private final Languages languages;
-  private final UserSession userSession;
-
-  public QProfileRestoreAction(QProfileBackuper backuper, Languages languages, UserSession userSession) {
-    this.backuper = backuper;
-    this.languages = languages;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    controller.createAction("restore")
-      .setSince("5.2")
-      .setDescription("Restore a quality profile using an XML file. The restored profile name is taken from the backup file, "
-        + "so if a profile with the same name and language already exists, it will be overwritten.")
-      .setPost(true)
-      .setHandler(this)
-      .createParam(PARAM_BACKUP)
-      .setDescription("A profile backup file in XML format, as generated by api/qualityprofiles/backup " +
-        "or the former api/profiles/backup.")
-      .setRequired(true);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-    InputStream backup = request.paramAsInputStream(PARAM_BACKUP);
-    InputStreamReader reader = null;
-
-    try {
-      Preconditions.checkArgument(backup != null, "A backup file must be provided");
-      reader = new InputStreamReader(backup, StandardCharsets.UTF_8);
-      BulkChangeResult result = backuper.restore(reader, null);
-      writeResponse(response.newJsonWriter(), result);
-    } finally {
-      IOUtils.closeQuietly(reader);
-      IOUtils.closeQuietly(backup);
-    }
-  }
-
-  private void writeResponse(JsonWriter json, BulkChangeResult result) {
-    QualityProfileDto profile = result.profile();
-    if (profile != null) {
-      String language = profile.getLanguage();
-      json.beginObject().name("profile").beginObject()
-        .prop("key", profile.getKey())
-        .prop("name", profile.getName())
-        .prop("language", language)
-        .prop("languageName", languages.get(profile.getLanguage()).getName())
-        .prop("isDefault", false)
-        .prop("isInherited", false)
-        .endObject();
-    }
-    json.prop("ruleSuccesses", result.countSucceeded());
-    json.prop("ruleFailures", result.countFailed());
-    json.endObject().close();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInAction.java
deleted file mode 100644 (file)
index 9127ebe..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualityprofile.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualityprofile.QProfileService;
-
-public class QProfileRestoreBuiltInAction implements QProfileWsAction {
-
-  private final QProfileService service;
-
-  public QProfileRestoreBuiltInAction(QProfileService service) {
-    this.service = service;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction restoreDefault = controller.createAction("restore_built_in")
-      .setDescription("Restore built-in profiles from the definitions declared by plugins. " +
-        "Missing profiles are created, existing ones are updated.")
-      .setSince("4.4")
-      .setPost(true)
-      .setHandler(this);
-    restoreDefault.createParam("language")
-      .setDescription("Restore the built-in profiles defined for this language")
-      .setExampleValue("java")
-      .setRequired(true);
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    String language = request.mandatoryParam("language");
-    service.restoreBuiltInProfilesForLanguage(language);
-    response.noContent();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSearchAction.java
deleted file mode 100644 (file)
index 7a2580e..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import org.apache.commons.lang.builder.CompareToBuilder;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.util.NonNullInputFunction;
-import org.sonar.server.qualityprofile.QProfile;
-import org.sonar.server.qualityprofile.QProfileLoader;
-import org.sonar.server.qualityprofile.QProfileLookup;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class QProfileSearchAction implements QProfileWsAction {
-
-  private static final String FIELD_KEY = "key";
-  private static final String FIELD_NAME = "name";
-  private static final String FIELD_LANGUAGE = "language";
-  private static final String FIELD_LANGUAGE_NAME = "languageName";
-  private static final String FIELD_IS_INHERITED = "isInherited";
-  private static final String FIELD_IS_DEFAULT = "isDefault";
-  private static final String FIELD_PARENT_KEY = "parentKey";
-  private static final String FIELD_PARENT_NAME = "parentName";
-  private static final String FIELD_ACTIVE_RULE_COUNT = "activeRuleCount";
-  private static final String FIELD_PROJECT_COUNT = "projectCount";
-
-  private static final Set<String> ALL_FIELDS = ImmutableSet.of(
-    FIELD_KEY, FIELD_NAME, FIELD_LANGUAGE, FIELD_LANGUAGE_NAME, FIELD_IS_INHERITED, FIELD_PARENT_KEY, FIELD_PARENT_NAME, FIELD_IS_DEFAULT, FIELD_ACTIVE_RULE_COUNT,
-    FIELD_PROJECT_COUNT);
-
-  private static final String PARAM_LANGUAGE = FIELD_LANGUAGE;
-
-  private final Languages languages;
-
-  private final QProfileLookup profileLookup;
-
-  private final QProfileLoader profileLoader;
-
-  private final QualityProfileDao qualityProfileDao;
-
-  public QProfileSearchAction(Languages languages, QProfileLookup profileLookup, QProfileLoader profileLoader, QualityProfileDao qualityProfileDao) {
-    this.languages = languages;
-    this.profileLookup = profileLookup;
-    this.profileLoader = profileLoader;
-    this.qualityProfileDao = qualityProfileDao;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    NewAction search = controller.createAction("search")
-      .setSince("5.2")
-      .setDescription("List quality profiles.")
-      .setHandler(this)
-      .setResponseExample(getClass().getResource("example-search.json"));
-
-    search.createParam(PARAM_LANGUAGE)
-      .setDescription("The key of a language supported by the platform. If specified, only profiles for the given language are returned.")
-      .setExampleValue("js")
-      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages));
-
-    search.createParam(Param.FIELDS)
-      .setDescription("Use to restrict returned fields.")
-      .setExampleValue("key,language")
-      .setPossibleValues(ALL_FIELDS);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    List<String> fields = request.paramAsStrings(Param.FIELDS);
-
-    String language = request.param(PARAM_LANGUAGE);
-
-    List<QProfile> profiles = null;
-    if (language == null) {
-      profiles = profileLookup.allProfiles();
-    } else {
-      profiles = profileLookup.profiles(language);
-    }
-
-    Collections.sort(profiles, new Comparator<QProfile>() {
-      @Override
-      public int compare(QProfile o1, QProfile o2) {
-        return new CompareToBuilder()
-          .append(o1.language(), o2.language())
-          .append(o1.name(), o2.name())
-          .toComparison();
-      }
-    });
-
-    JsonWriter json = response.newJsonWriter().beginObject();
-    writeProfiles(json, profiles, fields);
-    json.endObject().close();
-  }
-
-  private void writeProfiles(JsonWriter json, List<QProfile> profiles, List<String> fields) {
-    Map<String, QProfile> profilesByKey = Maps.uniqueIndex(profiles, new NonNullInputFunction<QProfile, String>() {
-      @Override
-      protected String doApply(QProfile input) {
-        return input.key();
-      }
-    });
-    Map<String, Long> activeRuleCountByKey = profileLoader.countAllActiveRules();
-    Map<String, Long> projectCountByKey = qualityProfileDao.countProjectsByProfileKey();
-
-    json.name("profiles")
-      .beginArray();
-    for (QProfile profile : profiles) {
-      if (languages.get(profile.language()) == null) {
-        // Hide profiles on an unsupported language
-        continue;
-      }
-
-      String key = profile.key();
-      Long activeRuleCount = activeRuleCountByKey.containsKey(key) ? activeRuleCountByKey.get(key) : 0L;
-      Long projectCount = projectCountByKey.containsKey(key) ? projectCountByKey.get(key) : 0L;
-      json.beginObject()
-        .prop(FIELD_KEY, nullUnlessNeeded(FIELD_KEY, key, fields))
-        .prop(FIELD_NAME, nullUnlessNeeded(FIELD_NAME, profile.name(), fields))
-        .prop(FIELD_ACTIVE_RULE_COUNT, nullUnlessNeeded(FIELD_ACTIVE_RULE_COUNT, activeRuleCount, fields));
-
-      if (!profile.isDefault()) {
-        json.prop(FIELD_PROJECT_COUNT, nullUnlessNeeded(FIELD_PROJECT_COUNT, projectCount, fields));
-      }
-      writeLanguageFields(json, profile, fields);
-      writeParentFields(json, profile, fields, profilesByKey);
-      // Special case for booleans
-      if (fieldIsNeeded(FIELD_IS_INHERITED, fields)) {
-        json.prop(FIELD_IS_INHERITED, profile.isInherited());
-      }
-      if (fieldIsNeeded(FIELD_IS_DEFAULT, fields)) {
-        json.prop(FIELD_IS_DEFAULT, profile.isDefault());
-      }
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-  private void writeLanguageFields(JsonWriter json, QProfile profile, List<String> fields) {
-    String languageKey = profile.language();
-    json.prop(FIELD_LANGUAGE, nullUnlessNeeded(FIELD_LANGUAGE, languageKey, fields))
-      .prop(FIELD_LANGUAGE_NAME, nullUnlessNeeded(FIELD_LANGUAGE_NAME, languages.get(languageKey).getName(), fields));
-  }
-
-  private void writeParentFields(JsonWriter json, QProfile profile, List<String> fields, Map<String, QProfile> profilesByKey) {
-    String parentKey = profile.parent();
-    QProfile parent = parentKey == null ? null : profilesByKey.get(parentKey);
-    json.prop(FIELD_PARENT_KEY, nullUnlessNeeded(FIELD_PARENT_KEY, parentKey, fields))
-      .prop(FIELD_PARENT_NAME, nullUnlessNeeded(FIELD_PARENT_NAME, parent == null ? parentKey : parent.name(), fields));
-  }
-
-  @CheckForNull
-  private <T> T nullUnlessNeeded(String field, T value, @Nullable List<String> fields) {
-    return fieldIsNeeded(field, fields) ? value : null;
-  }
-
-  private boolean fieldIsNeeded(String field, @Nullable List<String> fields) {
-    return fields == null || fields.contains(field);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultAction.java
deleted file mode 100644 (file)
index 0d1f048..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.base.Preconditions;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfile;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.user.UserSession;
-
-import static org.apache.commons.lang.StringUtils.isEmpty;
-
-public class QProfileSetDefaultAction implements QProfileWsAction {
-
-  private static final String PARAM_LANGUAGE = "language";
-  private static final String PARAM_PROFILE_NAME = "profileName";
-  private static final String PARAM_PROFILE_KEY = "profileKey";
-
-  private final Languages languages;
-
-  private final QProfileLookup profileLookup;
-
-  private final QProfileFactory profileFactory;
-  private final UserSession userSession;
-
-  public QProfileSetDefaultAction(Languages languages, QProfileLookup profileLookup, QProfileFactory profileFactory, UserSession userSession) {
-    this.languages = languages;
-    this.profileLookup = profileLookup;
-    this.profileFactory = profileFactory;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    NewAction setDefault = controller.createAction("set_default")
-      .setSince("5.2")
-      .setDescription("Select the default profile for a given language.")
-      .setPost(true)
-      .setHandler(this);
-
-    setDefault.createParam(PARAM_LANGUAGE)
-      .setDescription("The key of a language supported by the platform. If specified, profileName must be set to select the default profile for the selected language.")
-      .setExampleValue("js")
-      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages));
-
-    setDefault.createParam(PARAM_PROFILE_NAME)
-      .setDescription("The name of a quality profile. If specified, language must be set. The matching profile will be used as default for the selected language.")
-      .setExampleValue("Sonar way");
-
-    setDefault.createParam(PARAM_PROFILE_KEY)
-      .setDescription("The key of a quality profile. If specified, language and profileName must not be set. The matching profile will be used as default for its language.")
-      .setExampleValue("sonar-way-js-12345");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    String language = request.param(PARAM_LANGUAGE);
-    String profileName = request.param(PARAM_PROFILE_NAME);
-    String profileKey = request.param(PARAM_PROFILE_KEY);
-
-    Preconditions.checkArgument(
-        (!isEmpty(language) && !isEmpty(profileName)) ^ !isEmpty(profileKey), "Either profileKey or profileName + language must be set");
-
-    if(profileKey == null) {
-      profileKey = getProfileKeyFromLanguageAndName(language, profileName);
-    }
-
-    profileFactory.setDefault(profileKey);
-
-    response.noContent();
-  }
-
-  private String getProfileKeyFromLanguageAndName(String language, String profileName) {
-    QProfile profile = profileLookup.profile(profileName, language);
-    if (profile == null) {
-      throw new NotFoundException(String.format("Unable to find a profile for language '%s' with name '%s'", language, profileName));
-    }
-    return profile.key();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RenameAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RenameAction.java
new file mode 100644 (file)
index 0000000..e8202c6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.user.UserSession;
+
+public class RenameAction implements QProfileWsAction {
+
+  private static final String PARAM_PROFILE_NAME = "name";
+  private static final String PARAM_PROFILE_KEY = "key";
+
+  private final QProfileFactory profileFactory;
+  private final UserSession userSession;
+
+  public RenameAction(QProfileFactory profileFactory, UserSession userSession) {
+    this.profileFactory = profileFactory;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction setDefault = controller.createAction("rename")
+      .setSince("5.2")
+      .setDescription("Rename a quality profile.")
+      .setPost(true)
+      .setHandler(this);
+
+    setDefault.createParam(PARAM_PROFILE_NAME)
+      .setDescription("The new name for the quality profile.")
+      .setExampleValue("My Sonar way")
+      .setRequired(true);
+
+    setDefault.createParam(PARAM_PROFILE_KEY)
+      .setDescription("The key of a quality profile.")
+      .setExampleValue("sonar-way-js-12345")
+      .setRequired(true);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    String newName = request.mandatoryParam(PARAM_PROFILE_NAME);
+    String profileKey = request.mandatoryParam(PARAM_PROFILE_KEY);
+
+    profileFactory.rename(profileKey, newName);
+
+    response.noContent();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreAction.java
new file mode 100644 (file)
index 0000000..c94625c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.qualityprofile.BulkChangeResult;
+import org.sonar.server.qualityprofile.QProfileBackuper;
+import org.sonar.server.user.UserSession;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+public class RestoreAction implements QProfileWsAction {
+
+  private static final String PARAM_BACKUP = "backup";
+  private final QProfileBackuper backuper;
+  private final Languages languages;
+  private final UserSession userSession;
+
+  public RestoreAction(QProfileBackuper backuper, Languages languages, UserSession userSession) {
+    this.backuper = backuper;
+    this.languages = languages;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("restore")
+      .setSince("5.2")
+      .setDescription("Restore a quality profile using an XML file. The restored profile name is taken from the backup file, "
+        + "so if a profile with the same name and language already exists, it will be overwritten.")
+      .setPost(true)
+      .setHandler(this)
+      .createParam(PARAM_BACKUP)
+      .setDescription("A profile backup file in XML format, as generated by api/qualityprofiles/backup " +
+        "or the former api/profiles/backup.")
+      .setRequired(true);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+    InputStream backup = request.paramAsInputStream(PARAM_BACKUP);
+    InputStreamReader reader = null;
+
+    try {
+      Preconditions.checkArgument(backup != null, "A backup file must be provided");
+      reader = new InputStreamReader(backup, StandardCharsets.UTF_8);
+      BulkChangeResult result = backuper.restore(reader, null);
+      writeResponse(response.newJsonWriter(), result);
+    } finally {
+      IOUtils.closeQuietly(reader);
+      IOUtils.closeQuietly(backup);
+    }
+  }
+
+  private void writeResponse(JsonWriter json, BulkChangeResult result) {
+    QualityProfileDto profile = result.profile();
+    if (profile != null) {
+      String language = profile.getLanguage();
+      json.beginObject().name("profile").beginObject()
+        .prop("key", profile.getKey())
+        .prop("name", profile.getName())
+        .prop("language", language)
+        .prop("languageName", languages.get(profile.getLanguage()).getName())
+        .prop("isDefault", false)
+        .prop("isInherited", false)
+        .endObject();
+    }
+    json.prop("ruleSuccesses", result.countSucceeded());
+    json.prop("ruleFailures", result.countFailed());
+    json.endObject().close();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInAction.java
new file mode 100644 (file)
index 0000000..8d421a7
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualityprofile.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.qualityprofile.QProfileService;
+
+public class RestoreBuiltInAction implements QProfileWsAction {
+
+  private final QProfileService service;
+
+  public RestoreBuiltInAction(QProfileService service) {
+    this.service = service;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction restoreDefault = controller.createAction("restore_built_in")
+      .setDescription("Restore built-in profiles from the definitions declared by plugins. " +
+        "Missing profiles are created, existing ones are updated.")
+      .setSince("4.4")
+      .setPost(true)
+      .setHandler(this);
+    restoreDefault.createParam("language")
+      .setDescription("Restore the built-in profiles defined for this language")
+      .setExampleValue("java")
+      .setRequired(true);
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    String language = request.mandatoryParam("language");
+    service.restoreBuiltInProfilesForLanguage(language);
+    response.noContent();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java
new file mode 100644 (file)
index 0000000..ecdbbf5
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.builder.CompareToBuilder;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.util.NonNullInputFunction;
+import org.sonar.server.qualityprofile.QProfile;
+import org.sonar.server.qualityprofile.QProfileLoader;
+import org.sonar.server.qualityprofile.QProfileLookup;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class SearchAction implements QProfileWsAction {
+
+  private static final String FIELD_KEY = "key";
+  private static final String FIELD_NAME = "name";
+  private static final String FIELD_LANGUAGE = "language";
+  private static final String FIELD_LANGUAGE_NAME = "languageName";
+  private static final String FIELD_IS_INHERITED = "isInherited";
+  private static final String FIELD_IS_DEFAULT = "isDefault";
+  private static final String FIELD_PARENT_KEY = "parentKey";
+  private static final String FIELD_PARENT_NAME = "parentName";
+  private static final String FIELD_ACTIVE_RULE_COUNT = "activeRuleCount";
+  private static final String FIELD_PROJECT_COUNT = "projectCount";
+
+  private static final Set<String> ALL_FIELDS = ImmutableSet.of(
+    FIELD_KEY, FIELD_NAME, FIELD_LANGUAGE, FIELD_LANGUAGE_NAME, FIELD_IS_INHERITED, FIELD_PARENT_KEY, FIELD_PARENT_NAME, FIELD_IS_DEFAULT, FIELD_ACTIVE_RULE_COUNT,
+    FIELD_PROJECT_COUNT);
+
+  private static final String PARAM_LANGUAGE = FIELD_LANGUAGE;
+
+  private final Languages languages;
+
+  private final QProfileLookup profileLookup;
+
+  private final QProfileLoader profileLoader;
+
+  private final QualityProfileDao qualityProfileDao;
+
+  public SearchAction(Languages languages, QProfileLookup profileLookup, QProfileLoader profileLoader, QualityProfileDao qualityProfileDao) {
+    this.languages = languages;
+    this.profileLookup = profileLookup;
+    this.profileLoader = profileLoader;
+    this.qualityProfileDao = qualityProfileDao;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction search = controller.createAction("search")
+      .setSince("5.2")
+      .setDescription("List quality profiles.")
+      .setHandler(this)
+      .setResponseExample(getClass().getResource("example-search.json"));
+
+    search.createParam(PARAM_LANGUAGE)
+      .setDescription("The key of a language supported by the platform. If specified, only profiles for the given language are returned.")
+      .setExampleValue("js")
+      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages));
+
+    search.createParam(Param.FIELDS)
+      .setDescription("Use to restrict returned fields.")
+      .setExampleValue("key,language")
+      .setPossibleValues(ALL_FIELDS);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    List<String> fields = request.paramAsStrings(Param.FIELDS);
+
+    String language = request.param(PARAM_LANGUAGE);
+
+    List<QProfile> profiles = null;
+    if (language == null) {
+      profiles = profileLookup.allProfiles();
+    } else {
+      profiles = profileLookup.profiles(language);
+    }
+
+    Collections.sort(profiles, new Comparator<QProfile>() {
+      @Override
+      public int compare(QProfile o1, QProfile o2) {
+        return new CompareToBuilder()
+          .append(o1.language(), o2.language())
+          .append(o1.name(), o2.name())
+          .toComparison();
+      }
+    });
+
+    JsonWriter json = response.newJsonWriter().beginObject();
+    writeProfiles(json, profiles, fields);
+    json.endObject().close();
+  }
+
+  private void writeProfiles(JsonWriter json, List<QProfile> profiles, List<String> fields) {
+    Map<String, QProfile> profilesByKey = Maps.uniqueIndex(profiles, new NonNullInputFunction<QProfile, String>() {
+      @Override
+      protected String doApply(QProfile input) {
+        return input.key();
+      }
+    });
+    Map<String, Long> activeRuleCountByKey = profileLoader.countAllActiveRules();
+    Map<String, Long> projectCountByKey = qualityProfileDao.countProjectsByProfileKey();
+
+    json.name("profiles")
+      .beginArray();
+    for (QProfile profile : profiles) {
+      if (languages.get(profile.language()) == null) {
+        // Hide profiles on an unsupported language
+        continue;
+      }
+
+      String key = profile.key();
+      Long activeRuleCount = activeRuleCountByKey.containsKey(key) ? activeRuleCountByKey.get(key) : 0L;
+      Long projectCount = projectCountByKey.containsKey(key) ? projectCountByKey.get(key) : 0L;
+      json.beginObject()
+        .prop(FIELD_KEY, nullUnlessNeeded(FIELD_KEY, key, fields))
+        .prop(FIELD_NAME, nullUnlessNeeded(FIELD_NAME, profile.name(), fields))
+        .prop(FIELD_ACTIVE_RULE_COUNT, nullUnlessNeeded(FIELD_ACTIVE_RULE_COUNT, activeRuleCount, fields));
+
+      if (!profile.isDefault()) {
+        json.prop(FIELD_PROJECT_COUNT, nullUnlessNeeded(FIELD_PROJECT_COUNT, projectCount, fields));
+      }
+      writeLanguageFields(json, profile, fields);
+      writeParentFields(json, profile, fields, profilesByKey);
+      // Special case for booleans
+      if (fieldIsNeeded(FIELD_IS_INHERITED, fields)) {
+        json.prop(FIELD_IS_INHERITED, profile.isInherited());
+      }
+      if (fieldIsNeeded(FIELD_IS_DEFAULT, fields)) {
+        json.prop(FIELD_IS_DEFAULT, profile.isDefault());
+      }
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+  private void writeLanguageFields(JsonWriter json, QProfile profile, List<String> fields) {
+    String languageKey = profile.language();
+    json.prop(FIELD_LANGUAGE, nullUnlessNeeded(FIELD_LANGUAGE, languageKey, fields))
+      .prop(FIELD_LANGUAGE_NAME, nullUnlessNeeded(FIELD_LANGUAGE_NAME, languages.get(languageKey).getName(), fields));
+  }
+
+  private void writeParentFields(JsonWriter json, QProfile profile, List<String> fields, Map<String, QProfile> profilesByKey) {
+    String parentKey = profile.parent();
+    QProfile parent = parentKey == null ? null : profilesByKey.get(parentKey);
+    json.prop(FIELD_PARENT_KEY, nullUnlessNeeded(FIELD_PARENT_KEY, parentKey, fields))
+      .prop(FIELD_PARENT_NAME, nullUnlessNeeded(FIELD_PARENT_NAME, parent == null ? parentKey : parent.name(), fields));
+  }
+
+  @CheckForNull
+  private <T> T nullUnlessNeeded(String field, T value, @Nullable List<String> fields) {
+    return fieldIsNeeded(field, fields) ? value : null;
+  }
+
+  private boolean fieldIsNeeded(String field, @Nullable List<String> fields) {
+    return fields == null || fields.contains(field);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SetDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SetDefaultAction.java
new file mode 100644 (file)
index 0000000..e003298
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.base.Preconditions;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfile;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.user.UserSession;
+
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
+public class SetDefaultAction implements QProfileWsAction {
+
+  private static final String PARAM_LANGUAGE = "language";
+  private static final String PARAM_PROFILE_NAME = "profileName";
+  private static final String PARAM_PROFILE_KEY = "profileKey";
+
+  private final Languages languages;
+
+  private final QProfileLookup profileLookup;
+
+  private final QProfileFactory profileFactory;
+  private final UserSession userSession;
+
+  public SetDefaultAction(Languages languages, QProfileLookup profileLookup, QProfileFactory profileFactory, UserSession userSession) {
+    this.languages = languages;
+    this.profileLookup = profileLookup;
+    this.profileFactory = profileFactory;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction setDefault = controller.createAction("set_default")
+      .setSince("5.2")
+      .setDescription("Select the default profile for a given language.")
+      .setPost(true)
+      .setHandler(this);
+
+    setDefault.createParam(PARAM_LANGUAGE)
+      .setDescription("The key of a language supported by the platform. If specified, profileName must be set to select the default profile for the selected language.")
+      .setExampleValue("js")
+      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages));
+
+    setDefault.createParam(PARAM_PROFILE_NAME)
+      .setDescription("The name of a quality profile. If specified, language must be set. The matching profile will be used as default for the selected language.")
+      .setExampleValue("Sonar way");
+
+    setDefault.createParam(PARAM_PROFILE_KEY)
+      .setDescription("The key of a quality profile. If specified, language and profileName must not be set. The matching profile will be used as default for its language.")
+      .setExampleValue("sonar-way-js-12345");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    String language = request.param(PARAM_LANGUAGE);
+    String profileName = request.param(PARAM_PROFILE_NAME);
+    String profileKey = request.param(PARAM_PROFILE_KEY);
+
+    Preconditions.checkArgument(
+        (!isEmpty(language) && !isEmpty(profileName)) ^ !isEmpty(profileKey), "Either profileKey or profileName + language must be set");
+
+    if(profileKey == null) {
+      profileKey = getProfileKeyFromLanguageAndName(language, profileName);
+    }
+
+    profileFactory.setDefault(profileKey);
+
+    response.noContent();
+  }
+
+  private String getProfileKeyFromLanguageAndName(String language, String profileName) {
+    QProfile profile = profileLookup.profile(profileName, language);
+    if (profile == null) {
+      throw new NotFoundException(String.format("Unable to find a profile for language '%s' with name '%s'", language, profileName));
+    }
+    return profile.key();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/CoveredFilesAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/CoveredFilesAction.java
new file mode 100644 (file)
index 0000000..e09b0c3
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.test.ws;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.test.index.CoveredFileDoc;
+import org.sonar.server.test.index.TestIndex;
+import org.sonar.server.user.UserSession;
+
+import java.util.List;
+import java.util.Map;
+
+public class CoveredFilesAction implements TestsWsAction {
+
+  public static final String TEST_UUID = "testUuid";
+
+  private final DbClient dbClient;
+  private final TestIndex index;
+  private final UserSession userSession;
+
+  public CoveredFilesAction(DbClient dbClient, TestIndex index, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.index = index;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("covered_files")
+      .setDescription("Get the list of source files covered by a test. Require Browse permission on test file's project")
+      .setSince("4.4")
+      .setResponseExample(Resources.getResource(getClass(), "tests-example-covered-files.json"))
+      .setHandler(this)
+      .addPagingParams(100);
+
+    action
+      .createParam(TEST_UUID)
+      .setRequired(true)
+      .setDescription("Test uuid")
+      .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    String testUuid = request.mandatoryParam(TEST_UUID);
+    userSession.checkComponentUuidPermission(UserRole.CODEVIEWER, index.searchByTestUuid(testUuid).fileUuid());
+
+    List<CoveredFileDoc> coveredFiles = index.coveredFiles(testUuid);
+    Map<String, ComponentDto> componentsByUuid = buildComponentsByUuid(coveredFiles);
+    JsonWriter json = response.newJsonWriter().beginObject();
+    if (!coveredFiles.isEmpty()) {
+      writeTests(coveredFiles, componentsByUuid, json);
+    }
+    json.endObject().close();
+  }
+
+  private void writeTests(List<CoveredFileDoc> coveredFiles, Map<String, ComponentDto> componentsByUuid, JsonWriter json) {
+    json.name("files").beginArray();
+    for (CoveredFileDoc coveredFile : coveredFiles) {
+      json.beginObject();
+      json.prop("key", componentsByUuid.get(coveredFile.fileUuid()).key());
+      json.prop("longName", componentsByUuid.get(coveredFile.fileUuid()).longName());
+      json.prop("coveredLines", coveredFile.coveredLines().size());
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+  private Map<String, ComponentDto> buildComponentsByUuid(List<CoveredFileDoc> coveredFiles) {
+    List<String> sourceFileUuids = Lists.transform(coveredFiles, new Function<CoveredFileDoc, String>() {
+      @Override
+      public String apply(CoveredFileDoc coveredFile) {
+        return coveredFile.fileUuid();
+      }
+    });
+    DbSession dbSession = dbClient.openSession(false);
+    List<ComponentDto> components;
+    try {
+      components = dbClient.componentDao().selectByUuids(dbSession, sourceFileUuids);
+    } finally {
+      MyBatis.closeQuietly(dbSession);
+    }
+    return Maps.uniqueIndex(components, new Function<ComponentDto, String>() {
+      @Override
+      public String apply(ComponentDto component) {
+        return component.uuid();
+      }
+    });
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java
new file mode 100644 (file)
index 0000000..d757bc4
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.test.ws;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.util.NonNullInputFunction;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.es.SearchResult;
+import org.sonar.server.test.index.CoveredFileDoc;
+import org.sonar.server.test.index.TestDoc;
+import org.sonar.server.test.index.TestIndex;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+import java.util.Map;
+
+public class ListAction implements TestsWsAction {
+  public static final String TEST_UUID = "testUuid";
+  public static final String TEST_FILE_UUID = "testFileUuid";
+  public static final String TEST_FILE_KEY = "testFileKey";
+  public static final String SOURCE_FILE_UUID = "sourceFileUuid";
+  public static final String SOURCE_FILE_LINE_NUMBER = "sourceFileLineNumber";
+
+  private final DbClient dbClient;
+  private final TestIndex testIndex;
+  private final UserSession userSession;
+
+  public ListAction(DbClient dbClient, TestIndex testIndex, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.testIndex = testIndex;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller
+      .createAction("list")
+      .setDescription(
+        "Get the list of tests.<br /> " +
+          "Require Browse permission on file's project.<br /> " +
+          "One (and only one) of the following combination of parameters must be provided: " +
+          "<ul>" +
+          "<li>Test file UUID</li>" +
+          "<li>Test UUID</li>" +
+          "<li>Source file UUID and Source file line number</li>" +
+          "</ul>")
+      .setSince("5.2")
+      .setResponseExample(Resources.getResource(getClass(), "tests-example-list.json"))
+      .setHandler(this)
+      .addPagingParams(100);
+
+    action
+      .createParam(TEST_FILE_UUID)
+      .setDescription("Test file UUID")
+      .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d");
+
+    action
+      .createParam(TEST_FILE_KEY)
+      .setDescription("Test file key")
+      .setExampleValue("org.codehaus.sonar:sonar-server:src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java");
+
+    action
+      .createParam(TEST_UUID)
+      .setDescription("Test UUID")
+      .setExampleValue("c526ef20-131b-4486-9357-063fa64b5079");
+
+    action
+      .createParam(SOURCE_FILE_UUID)
+      .setDescription("Source file UUID. Must be provided with the source file line number.")
+      .setExampleValue("584a89f2-8037-4f7b-b82c-8b45d2d63fb2");
+
+    action
+      .createParam(SOURCE_FILE_LINE_NUMBER)
+      .setDescription("Source file line number. Must be provided with the source file UUID.")
+      .setExampleValue("10");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    String testUuid = request.param(TEST_UUID);
+    String testFileUuid = request.param(TEST_FILE_UUID);
+    String testFileKey = request.param(TEST_FILE_KEY);
+    String sourceFileUuid = request.param(SOURCE_FILE_UUID);
+    Integer sourceFileLineNumber = request.paramAsInt(SOURCE_FILE_LINE_NUMBER);
+    SearchOptions searchOptions = new SearchOptions().setPage(
+      request.mandatoryParamAsInt(WebService.Param.PAGE),
+      request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE)
+    );
+
+    DbSession dbSession = dbClient.openSession(false);
+    SearchResult<TestDoc> tests;
+    Map<String, ComponentDto> componentsByTestFileUuid;
+    try {
+      tests = searchTests(dbSession, testUuid, testFileUuid, testFileKey, sourceFileUuid, sourceFileLineNumber, searchOptions);
+      componentsByTestFileUuid = buildComponentsByTestFileUuid(dbSession, tests.getDocs());
+    } finally {
+      MyBatis.closeQuietly(dbSession);
+    }
+
+    JsonWriter json = response.newJsonWriter().beginObject();
+    writeTests(tests.getDocs(), componentsByTestFileUuid, json);
+    searchOptions.writeJson(json, tests.getTotal());
+    json.endObject().close();
+  }
+
+  private void writeTests(List<TestDoc> tests, Map<String, ComponentDto> componentsByTestFileUuid, JsonWriter json) {
+    json.name("tests").beginArray();
+    for (TestDoc test : tests) {
+      String fileUuid = test.fileUuid();
+      json.beginObject();
+      json.prop("testUuid", test.testUuid());
+      json.prop("fileUuid", fileUuid);
+      json.prop("name", test.name());
+      json.prop("status", test.status());
+      json.prop("durationInMs", test.durationInMs());
+      json.prop("message", test.message());
+      json.prop("stacktrace", test.stackTrace());
+      json.prop("coveredLines", coveredLines(test.coveredFiles()));
+      json.prop("fileKey", componentsByTestFileUuid.get(fileUuid).key());
+      json.prop("fileLongName", componentsByTestFileUuid.get(fileUuid).longName());
+      json.endObject();
+    }
+    json.endArray();
+  }
+
+  private long coveredLines(List<CoveredFileDoc> coveredFiles) {
+    long numberOfLinesCovered = 0L;
+    for (CoveredFileDoc coveredFile : coveredFiles) {
+      numberOfLinesCovered += coveredFile.coveredLines().size();
+    }
+
+    return numberOfLinesCovered;
+  }
+
+  private Map<String, ComponentDto> buildComponentsByTestFileUuid(DbSession dbSession, List<TestDoc> tests) {
+    List<String> fileUuids = Lists.transform(tests, new NonNullInputFunction<TestDoc, String>() {
+      @Override
+      protected String doApply(TestDoc testDoc) {
+        return testDoc.fileUuid();
+      }
+    });
+    List<ComponentDto> components = dbClient.componentDao().selectByUuids(dbSession, fileUuids);
+
+    return Maps.uniqueIndex(components, new NonNullInputFunction<ComponentDto, String>() {
+      @Override
+      public String doApply(ComponentDto componentDto) {
+        return componentDto.uuid();
+      }
+    });
+  }
+
+  private SearchResult<TestDoc> searchTests(DbSession dbSession, @Nullable String testUuid, @Nullable String testFileUuid, @Nullable String testFileKey,
+    @Nullable String sourceFileUuid, @Nullable Integer sourceFileLineNumber, SearchOptions searchOptions) {
+    if (testUuid != null) {
+      return searchTestsByTestUuid(dbSession, testUuid, searchOptions);
+    }
+    if (testFileUuid != null) {
+      return searchTestsByTestFileUuid(dbSession, testFileUuid, searchOptions);
+    }
+    if (testFileKey != null) {
+      return searchTestsByTestFileKey(dbSession, testFileKey, searchOptions);
+    }
+    if (sourceFileUuid != null && sourceFileLineNumber != null) {
+      return searchTestsBySourceFileUuidAndLineNumber(dbSession, sourceFileUuid, sourceFileLineNumber, searchOptions);
+    }
+
+    throw new IllegalArgumentException(
+      "One (and only one) of the following combination of parameters must be provided: 1) test UUID. 2) test file UUID. " +
+        "3) test file key. 4) source file UUID and source file line number.");
+  }
+
+  private SearchResult<TestDoc> searchTestsBySourceFileUuidAndLineNumber(DbSession dbSession, String sourceFileUuid, Integer sourceFileLineNumber, SearchOptions searchOptions) {
+    checkComponentUuidPermission(dbSession, sourceFileUuid);
+    return testIndex.searchBySourceFileUuidAndLineNumber(sourceFileUuid, sourceFileLineNumber, searchOptions);
+  }
+
+  private SearchResult<TestDoc> searchTestsByTestFileKey(DbSession dbSession, String testFileKey, SearchOptions searchOptions) {
+    userSession.checkComponentPermission(UserRole.CODEVIEWER, testFileKey);
+    ComponentDto testFile = dbClient.componentDao().selectByKey(dbSession, testFileKey);
+
+    return testIndex.searchByTestFileUuid(testFile.uuid(), searchOptions);
+  }
+
+  private SearchResult<TestDoc> searchTestsByTestFileUuid(DbSession dbSession, String testFileUuid, SearchOptions searchOptions) {
+    checkComponentUuidPermission(dbSession, testFileUuid);
+    return testIndex.searchByTestFileUuid(testFileUuid, searchOptions);
+  }
+
+  private SearchResult<TestDoc> searchTestsByTestUuid(DbSession dbSession, String testUuid, SearchOptions searchOptions) {
+    checkComponentUuidPermission(dbSession, testIndex.searchByTestUuid(testUuid).fileUuid());
+    return testIndex.searchByTestUuid(testUuid, searchOptions);
+  }
+
+  private void checkComponentUuidPermission(DbSession dbSession, String componentUuid) {
+    ComponentDto component = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
+    userSession.checkProjectUuidPermission(UserRole.CODEVIEWER, component.projectUuid());
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsCoveredFilesAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsCoveredFilesAction.java
deleted file mode 100644 (file)
index 50c87ea..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.test.ws;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.io.Resources;
-import java.util.List;
-import java.util.Map;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.test.index.CoveredFileDoc;
-import org.sonar.server.test.index.TestIndex;
-import org.sonar.server.user.UserSession;
-
-public class TestsCoveredFilesAction implements TestsWsAction {
-
-  public static final String TEST_UUID = "testUuid";
-
-  private final DbClient dbClient;
-  private final TestIndex index;
-  private final UserSession userSession;
-
-  public TestsCoveredFilesAction(DbClient dbClient, TestIndex index, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.index = index;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("covered_files")
-      .setDescription("Get the list of source files covered by a test. Require Browse permission on test file's project")
-      .setSince("4.4")
-      .setResponseExample(Resources.getResource(getClass(), "tests-example-covered-files.json"))
-      .setHandler(this)
-      .addPagingParams(100);
-
-    action
-      .createParam(TEST_UUID)
-      .setRequired(true)
-      .setDescription("Test uuid")
-      .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    String testUuid = request.mandatoryParam(TEST_UUID);
-    userSession.checkComponentUuidPermission(UserRole.CODEVIEWER, index.searchByTestUuid(testUuid).fileUuid());
-
-    List<CoveredFileDoc> coveredFiles = index.coveredFiles(testUuid);
-    Map<String, ComponentDto> componentsByUuid = buildComponentsByUuid(coveredFiles);
-    JsonWriter json = response.newJsonWriter().beginObject();
-    if (!coveredFiles.isEmpty()) {
-      writeTests(coveredFiles, componentsByUuid, json);
-    }
-    json.endObject().close();
-  }
-
-  private void writeTests(List<CoveredFileDoc> coveredFiles, Map<String, ComponentDto> componentsByUuid, JsonWriter json) {
-    json.name("files").beginArray();
-    for (CoveredFileDoc coveredFile : coveredFiles) {
-      json.beginObject();
-      json.prop("key", componentsByUuid.get(coveredFile.fileUuid()).key());
-      json.prop("longName", componentsByUuid.get(coveredFile.fileUuid()).longName());
-      json.prop("coveredLines", coveredFile.coveredLines().size());
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-  private Map<String, ComponentDto> buildComponentsByUuid(List<CoveredFileDoc> coveredFiles) {
-    List<String> sourceFileUuids = Lists.transform(coveredFiles, new Function<CoveredFileDoc, String>() {
-      @Override
-      public String apply(CoveredFileDoc coveredFile) {
-        return coveredFile.fileUuid();
-      }
-    });
-    DbSession dbSession = dbClient.openSession(false);
-    List<ComponentDto> components;
-    try {
-      components = dbClient.componentDao().selectByUuids(dbSession, sourceFileUuids);
-    } finally {
-      MyBatis.closeQuietly(dbSession);
-    }
-    return Maps.uniqueIndex(components, new Function<ComponentDto, String>() {
-      @Override
-      public String apply(ComponentDto component) {
-        return component.uuid();
-      }
-    });
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsListAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsListAction.java
deleted file mode 100644 (file)
index f74b34f..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.test.ws;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.io.Resources;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.util.NonNullInputFunction;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.es.SearchResult;
-import org.sonar.server.test.index.CoveredFileDoc;
-import org.sonar.server.test.index.TestDoc;
-import org.sonar.server.test.index.TestIndex;
-import org.sonar.server.user.UserSession;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-import java.util.Map;
-
-public class TestsListAction implements TestsWsAction {
-  public static final String TEST_UUID = "testUuid";
-  public static final String TEST_FILE_UUID = "testFileUuid";
-  public static final String TEST_FILE_KEY = "testFileKey";
-  public static final String SOURCE_FILE_UUID = "sourceFileUuid";
-  public static final String SOURCE_FILE_LINE_NUMBER = "sourceFileLineNumber";
-
-  private final DbClient dbClient;
-  private final TestIndex testIndex;
-  private final UserSession userSession;
-
-  public TestsListAction(DbClient dbClient, TestIndex testIndex, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.testIndex = testIndex;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller
-      .createAction("list")
-      .setDescription(
-        "Get the list of tests.<br /> " +
-          "Require Browse permission on file's project.<br /> " +
-          "One (and only one) of the following combination of parameters must be provided: " +
-          "<ul>" +
-          "<li>Test file UUID</li>" +
-          "<li>Test UUID</li>" +
-          "<li>Source file UUID and Source file line number</li>" +
-          "</ul>")
-      .setSince("5.2")
-      .setResponseExample(Resources.getResource(getClass(), "tests-example-list.json"))
-      .setHandler(this)
-      .addPagingParams(100);
-
-    action
-      .createParam(TEST_FILE_UUID)
-      .setDescription("Test file UUID")
-      .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d");
-
-    action
-      .createParam(TEST_FILE_KEY)
-      .setDescription("Test file key")
-      .setExampleValue("org.codehaus.sonar:sonar-server:src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java");
-
-    action
-      .createParam(TEST_UUID)
-      .setDescription("Test UUID")
-      .setExampleValue("c526ef20-131b-4486-9357-063fa64b5079");
-
-    action
-      .createParam(SOURCE_FILE_UUID)
-      .setDescription("Source file UUID. Must be provided with the source file line number.")
-      .setExampleValue("584a89f2-8037-4f7b-b82c-8b45d2d63fb2");
-
-    action
-      .createParam(SOURCE_FILE_LINE_NUMBER)
-      .setDescription("Source file line number. Must be provided with the source file UUID.")
-      .setExampleValue("10");
-  }
-
-  @Override
-  public void handle(Request request, Response response) {
-    String testUuid = request.param(TEST_UUID);
-    String testFileUuid = request.param(TEST_FILE_UUID);
-    String testFileKey = request.param(TEST_FILE_KEY);
-    String sourceFileUuid = request.param(SOURCE_FILE_UUID);
-    Integer sourceFileLineNumber = request.paramAsInt(SOURCE_FILE_LINE_NUMBER);
-    SearchOptions searchOptions = new SearchOptions().setPage(
-      request.mandatoryParamAsInt(WebService.Param.PAGE),
-      request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE)
-    );
-
-    DbSession dbSession = dbClient.openSession(false);
-    SearchResult<TestDoc> tests;
-    Map<String, ComponentDto> componentsByTestFileUuid;
-    try {
-      tests = searchTests(dbSession, testUuid, testFileUuid, testFileKey, sourceFileUuid, sourceFileLineNumber, searchOptions);
-      componentsByTestFileUuid = buildComponentsByTestFileUuid(dbSession, tests.getDocs());
-    } finally {
-      MyBatis.closeQuietly(dbSession);
-    }
-
-    JsonWriter json = response.newJsonWriter().beginObject();
-    writeTests(tests.getDocs(), componentsByTestFileUuid, json);
-    searchOptions.writeJson(json, tests.getTotal());
-    json.endObject().close();
-  }
-
-  private void writeTests(List<TestDoc> tests, Map<String, ComponentDto> componentsByTestFileUuid, JsonWriter json) {
-    json.name("tests").beginArray();
-    for (TestDoc test : tests) {
-      String fileUuid = test.fileUuid();
-      json.beginObject();
-      json.prop("testUuid", test.testUuid());
-      json.prop("fileUuid", fileUuid);
-      json.prop("name", test.name());
-      json.prop("status", test.status());
-      json.prop("durationInMs", test.durationInMs());
-      json.prop("message", test.message());
-      json.prop("stacktrace", test.stackTrace());
-      json.prop("coveredLines", coveredLines(test.coveredFiles()));
-      json.prop("fileKey", componentsByTestFileUuid.get(fileUuid).key());
-      json.prop("fileLongName", componentsByTestFileUuid.get(fileUuid).longName());
-      json.endObject();
-    }
-    json.endArray();
-  }
-
-  private long coveredLines(List<CoveredFileDoc> coveredFiles) {
-    long numberOfLinesCovered = 0L;
-    for (CoveredFileDoc coveredFile : coveredFiles) {
-      numberOfLinesCovered += coveredFile.coveredLines().size();
-    }
-
-    return numberOfLinesCovered;
-  }
-
-  private Map<String, ComponentDto> buildComponentsByTestFileUuid(DbSession dbSession, List<TestDoc> tests) {
-    List<String> fileUuids = Lists.transform(tests, new NonNullInputFunction<TestDoc, String>() {
-      @Override
-      protected String doApply(TestDoc testDoc) {
-        return testDoc.fileUuid();
-      }
-    });
-    List<ComponentDto> components = dbClient.componentDao().selectByUuids(dbSession, fileUuids);
-
-    return Maps.uniqueIndex(components, new NonNullInputFunction<ComponentDto, String>() {
-      @Override
-      public String doApply(ComponentDto componentDto) {
-        return componentDto.uuid();
-      }
-    });
-  }
-
-  private SearchResult<TestDoc> searchTests(DbSession dbSession, @Nullable String testUuid, @Nullable String testFileUuid, @Nullable String testFileKey,
-    @Nullable String sourceFileUuid, @Nullable Integer sourceFileLineNumber, SearchOptions searchOptions) {
-    if (testUuid != null) {
-      return searchTestsByTestUuid(dbSession, testUuid, searchOptions);
-    }
-    if (testFileUuid != null) {
-      return searchTestsByTestFileUuid(dbSession, testFileUuid, searchOptions);
-    }
-    if (testFileKey != null) {
-      return searchTestsByTestFileKey(dbSession, testFileKey, searchOptions);
-    }
-    if (sourceFileUuid != null && sourceFileLineNumber != null) {
-      return searchTestsBySourceFileUuidAndLineNumber(dbSession, sourceFileUuid, sourceFileLineNumber, searchOptions);
-    }
-
-    throw new IllegalArgumentException(
-      "One (and only one) of the following combination of parameters must be provided: 1) test UUID. 2) test file UUID. " +
-        "3) test file key. 4) source file UUID and source file line number.");
-  }
-
-  private SearchResult<TestDoc> searchTestsBySourceFileUuidAndLineNumber(DbSession dbSession, String sourceFileUuid, Integer sourceFileLineNumber, SearchOptions searchOptions) {
-    checkComponentUuidPermission(dbSession, sourceFileUuid);
-    return testIndex.searchBySourceFileUuidAndLineNumber(sourceFileUuid, sourceFileLineNumber, searchOptions);
-  }
-
-  private SearchResult<TestDoc> searchTestsByTestFileKey(DbSession dbSession, String testFileKey, SearchOptions searchOptions) {
-    userSession.checkComponentPermission(UserRole.CODEVIEWER, testFileKey);
-    ComponentDto testFile = dbClient.componentDao().selectByKey(dbSession, testFileKey);
-
-    return testIndex.searchByTestFileUuid(testFile.uuid(), searchOptions);
-  }
-
-  private SearchResult<TestDoc> searchTestsByTestFileUuid(DbSession dbSession, String testFileUuid, SearchOptions searchOptions) {
-    checkComponentUuidPermission(dbSession, testFileUuid);
-    return testIndex.searchByTestFileUuid(testFileUuid, searchOptions);
-  }
-
-  private SearchResult<TestDoc> searchTestsByTestUuid(DbSession dbSession, String testUuid, SearchOptions searchOptions) {
-    checkComponentUuidPermission(dbSession, testIndex.searchByTestUuid(testUuid).fileUuid());
-    return testIndex.searchByTestUuid(testUuid, searchOptions);
-  }
-
-  private void checkComponentUuidPermission(DbSession dbSession, String componentUuid) {
-    ComponentDto component = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
-    userSession.checkProjectUuidPermission(UserRole.CODEVIEWER, component.projectUuid());
-  }
-}
index 71a39f1e1f911e6582c004b1e42a16384a06dbc3..5e08f594cc90e3c926625d64685ae4cec7ff4d70 100644 (file)
@@ -58,6 +58,7 @@ import org.sonar.server.platform.Platform;
 import org.sonar.server.platform.ServerIdGenerator;
 import org.sonar.server.platform.ServerSettings;
 import org.sonar.server.platform.SettingsChangeNotifier;
+import org.sonar.server.platform.ws.UpgradesAction;
 import org.sonar.server.plugins.InstalledPluginReferentialFactory;
 import org.sonar.server.plugins.PluginDownloader;
 import org.sonar.server.plugins.ServerPluginRepository;
@@ -382,9 +383,9 @@ public final class JRubyFacade {
   /**
    * Checks whether the SQ instance is up and running (ie. not in safemode and with an up-to-date database).
    * <p>
-   * This method duplicates most of the logic code written in {@link org.sonar.server.platform.ws.UpgradesSystemWsAction}
+   * This method duplicates most of the logic code written in {@link UpgradesAction}
    * class. There is no need to refactor code to avoid this duplication since this method is only used by RoR code
-   * which will soon be replaced by pure JS code based on the {@link org.sonar.server.platform.ws.UpgradesSystemWsAction}
+   * which will soon be replaced by pure JS code based on the {@link UpgradesAction}
    * WebService.
    * </p>
    */
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java
new file mode 100644 (file)
index 0000000..f3784f0
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.user.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.user.UserSession;
+
+public class CurrentAction implements UsersWsAction {
+  private final UserSession userSession;
+
+  public CurrentAction(UserSession userSession) {
+    this.userSession = userSession;
+  }
+
+
+  @Override
+  public void define(NewController context) {
+    context.createAction("current")
+      .setDescription("Get the details of the current authenticated user.")
+      .setHandler(this)
+      .setInternal(true)
+      .setResponseExample(getClass().getResource("example-current.json"))
+      .setSince("5.2");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter json = response.newJsonWriter().beginObject();
+
+    writeUserDetails(json, userSession);
+
+    json.endObject().close();
+  }
+
+  private void writeUserDetails(JsonWriter json, UserSession session) {
+    json.prop("isLoggedIn", session.isLoggedIn())
+      .prop("login", session.getLogin())
+      .prop("name", session.getName());
+    writePermissions(json, session);
+  }
+
+  private void writePermissions(JsonWriter json, UserSession session) {
+    json.name("permissions").beginObject();
+    writeGlobalPermissions(json, session);
+    json.endObject();
+  }
+
+  private void writeGlobalPermissions(JsonWriter json, UserSession session) {
+    json.name("global").beginArray();
+    for (String permission : session.globalPermissions()) {
+      json.value(permission);
+    }
+    json.endArray();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentUserAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentUserAction.java
deleted file mode 100644 (file)
index 422d453..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.user.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.user.UserSession;
-
-public class CurrentUserAction implements UsersWsAction {
-  private final UserSession userSession;
-
-  public CurrentUserAction(UserSession userSession) {
-    this.userSession = userSession;
-  }
-
-
-  @Override
-  public void define(NewController context) {
-    context.createAction("current")
-      .setDescription("Get the details of the current authenticated user.")
-      .setHandler(this)
-      .setInternal(true)
-      .setResponseExample(getClass().getResource("example-current.json"))
-      .setSince("5.2");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter json = response.newJsonWriter().beginObject();
-
-    writeUserDetails(json, userSession);
-
-    json.endObject().close();
-  }
-
-  private void writeUserDetails(JsonWriter json, UserSession session) {
-    json.prop("isLoggedIn", session.isLoggedIn())
-      .prop("login", session.getLogin())
-      .prop("name", session.getName());
-    writePermissions(json, session);
-  }
-
-  private void writePermissions(JsonWriter json, UserSession session) {
-    json.name("permissions").beginObject();
-    writeGlobalPermissions(json, session);
-    json.endObject();
-  }
-
-  private void writeGlobalPermissions(JsonWriter json, UserSession session) {
-    json.name("global").beginArray();
-    for (String permission : session.globalPermissions()) {
-      json.value(permission);
-    }
-    json.endArray();
-  }
-
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-create.json b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-create.json
deleted file mode 100644 (file)
index 043c4bb..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "id": "30057",
-  "k": "org.jenkins-ci.plugins:sonar",
-  "nm": "Jenkins Sonar Plugin",
-  "sc": "PRJ",
-  "qu": "TRK"
-}
-
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-ghosts.json b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-ghosts.json
deleted file mode 100644 (file)
index 4bb9f84..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "projects": [
-    {
-      "uuid": "ce4c03d6-430f-40a9-b777-ad877c00aa4d",
-      "key": "org.apache.hbas:hbase",
-      "name": "HBase",
-      "creationDate": "2015-03-04T23:03:44+0100"
-    },
-    {
-      "uuid": "c526ef20-131b-4486-9357-063fa64b5079",
-      "key": "com.microsoft.roslyn:roslyn",
-      "name": "Roslyn",
-      "creationDate": "2013-03-04T23:03:44+0100"
-    }
-  ],
-  "total": 2,
-  "p": 1,
-  "ps": 100
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-index.json b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-index.json
deleted file mode 100644 (file)
index a5d82ab..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-[
-  {
-    "id": "5035",
-    "k": "org.jenkins-ci.plugins:sonar",
-    "nm": "Jenkins Sonar Plugin",
-    "sc": "PRJ",
-    "qu": "TRK"
-  },
-  {
-    "id": "5146",
-    "k": "org.codehaus.sonar-plugins:sonar-ant-task",
-    "nm": "Sonar Ant Task",
-    "sc": "PRJ",
-    "qu": "TRK"
-  },
-  {
-    "id": "15964",
-    "k": "org.codehaus.sonar-plugins:sonar-build-breaker-plugin",
-    "nm": "Sonar Build Breaker Plugin",
-    "sc": "PRJ",
-    "qu": "TRK"
-  }
-]
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-provisioned.json b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-provisioned.json
deleted file mode 100644 (file)
index 4bb9f84..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "projects": [
-    {
-      "uuid": "ce4c03d6-430f-40a9-b777-ad877c00aa4d",
-      "key": "org.apache.hbas:hbase",
-      "name": "HBase",
-      "creationDate": "2015-03-04T23:03:44+0100"
-    },
-    {
-      "uuid": "c526ef20-131b-4486-9357-063fa64b5079",
-      "key": "com.microsoft.roslyn:roslyn",
-      "name": "Roslyn",
-      "creationDate": "2013-03-04T23:03:44+0100"
-    }
-  ],
-  "total": 2,
-  "p": 1,
-  "ps": 100
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-create.json b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-create.json
new file mode 100644 (file)
index 0000000..043c4bb
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "id": "30057",
+  "k": "org.jenkins-ci.plugins:sonar",
+  "nm": "Jenkins Sonar Plugin",
+  "sc": "PRJ",
+  "qu": "TRK"
+}
+
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-ghosts.json b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-ghosts.json
new file mode 100644 (file)
index 0000000..4bb9f84
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "projects": [
+    {
+      "uuid": "ce4c03d6-430f-40a9-b777-ad877c00aa4d",
+      "key": "org.apache.hbas:hbase",
+      "name": "HBase",
+      "creationDate": "2015-03-04T23:03:44+0100"
+    },
+    {
+      "uuid": "c526ef20-131b-4486-9357-063fa64b5079",
+      "key": "com.microsoft.roslyn:roslyn",
+      "name": "Roslyn",
+      "creationDate": "2013-03-04T23:03:44+0100"
+    }
+  ],
+  "total": 2,
+  "p": 1,
+  "ps": 100
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-index.json b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-index.json
new file mode 100644 (file)
index 0000000..a5d82ab
--- /dev/null
@@ -0,0 +1,23 @@
+[
+  {
+    "id": "5035",
+    "k": "org.jenkins-ci.plugins:sonar",
+    "nm": "Jenkins Sonar Plugin",
+    "sc": "PRJ",
+    "qu": "TRK"
+  },
+  {
+    "id": "5146",
+    "k": "org.codehaus.sonar-plugins:sonar-ant-task",
+    "nm": "Sonar Ant Task",
+    "sc": "PRJ",
+    "qu": "TRK"
+  },
+  {
+    "id": "15964",
+    "k": "org.codehaus.sonar-plugins:sonar-build-breaker-plugin",
+    "nm": "Sonar Build Breaker Plugin",
+    "sc": "PRJ",
+    "qu": "TRK"
+  }
+]
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-provisioned.json b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-provisioned.json
new file mode 100644 (file)
index 0000000..4bb9f84
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "projects": [
+    {
+      "uuid": "ce4c03d6-430f-40a9-b777-ad877c00aa4d",
+      "key": "org.apache.hbas:hbase",
+      "name": "HBase",
+      "creationDate": "2015-03-04T23:03:44+0100"
+    },
+    {
+      "uuid": "c526ef20-131b-4486-9357-063fa64b5079",
+      "key": "com.microsoft.roslyn:roslyn",
+      "name": "Roslyn",
+      "creationDate": "2013-03-04T23:03:44+0100"
+    }
+  ],
+  "total": 2,
+  "p": 1,
+  "ps": 100
+}
index 3dee07e1a0264c13e6159a638dac2dd93cce784e..f0778ab7da0dda4b1c0363f4bd5b945c6e52d3b0 100644 (file)
@@ -58,8 +58,8 @@ public class BatchWsTest {
   @Before
   public void before() {
     tester = new WsTester(new BatchWs(batchIndex,
-      new GlobalRepositoryAction(mock(DbClient.class), mock(PropertiesDao.class), userSessionRule),
-      new ProjectRepositoryAction(mock(ProjectRepositoryLoader.class)),
+      new GlobalAction(mock(DbClient.class), mock(PropertiesDao.class), userSessionRule),
+      new ProjectAction(mock(ProjectRepositoryLoader.class)),
       new IssuesAction(mock(DbClient.class), mock(IssueIndex.class), userSessionRule)));
   }
 
diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalActionTest.java
new file mode 100644 (file)
index 0000000..b9ffed8
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.batch;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.core.measure.db.MetricDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.properties.PropertiesDao;
+import org.sonar.core.properties.PropertyDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.measure.persistence.MetricDao;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class GlobalActionTest {
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Mock
+  DbSession session;
+
+  @Mock
+  MetricDao metricDao;
+
+  @Mock
+  PropertiesDao propertiesDao;
+
+  WsTester tester;
+
+  @Before
+  public void setUp() {
+    DbClient dbClient = mock(DbClient.class);
+    when(dbClient.openSession(false)).thenReturn(session);
+    when(dbClient.metricDao()).thenReturn(metricDao);
+
+    tester = new WsTester(new BatchWs(mock(BatchIndex.class), new GlobalAction(dbClient, propertiesDao, userSessionRule)));
+  }
+
+  @Test
+  public void return_metrics() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.PREVIEW_EXECUTION);
+
+    when(metricDao.selectEnabled(session)).thenReturn(newArrayList(
+      new MetricDto().setId(1).setKey("coverage").setDescription("Coverage by unit tests").setValueType("PERCENT").setQualitative(true)
+        .setWorstValue(0d).setBestValue(100d).setOptimizedBestValue(false).setDirection(1).setEnabled(true)
+      ));
+
+    WsTester.TestRequest request = tester.newGetRequest("batch", "global");
+    request.execute().assertJson(getClass(), "return_global_referentials.json");
+  }
+
+  @Test
+  public void return_global_settings() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.PREVIEW_EXECUTION);
+
+    when(propertiesDao.selectGlobalProperties(session)).thenReturn(newArrayList(
+      new PropertyDto().setKey("foo").setValue("bar"),
+      new PropertyDto().setKey("foo.secured").setValue("1234"),
+      new PropertyDto().setKey("foo.license.secured").setValue("5678")
+      ));
+
+    WsTester.TestRequest request = tester.newGetRequest("batch", "global");
+    request.execute().assertJson(getClass(), "return_global_settings.json");
+  }
+
+  @Test
+  public void return_only_license_settings_without_scan_but_with_preview_permission() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.PREVIEW_EXECUTION);
+
+    when(propertiesDao.selectGlobalProperties(session)).thenReturn(newArrayList(
+      new PropertyDto().setKey("foo").setValue("bar"),
+      new PropertyDto().setKey("foo.secured").setValue("1234"),
+      new PropertyDto().setKey("foo.license.secured").setValue("5678")
+      ));
+
+    WsTester.TestRequest request = tester.newGetRequest("batch", "global");
+    request.execute().assertJson(getClass(), "return_only_license_settings_without_scan_but_with_preview_permission.json");
+  }
+
+  @Test
+  public void access_forbidden_without_scan_and_preview_permission() throws Exception {
+    userSessionRule.setGlobalPermissions();
+
+    when(propertiesDao.selectGlobalProperties(session)).thenReturn(newArrayList(
+      new PropertyDto().setKey("foo").setValue("bar"),
+      new PropertyDto().setKey("foo.secured").setValue("1234"),
+      new PropertyDto().setKey("foo.license.secured").setValue("5678")
+      ));
+
+    thrown.expect(ForbiddenException.class);
+
+    tester.newGetRequest("batch", "global").execute();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalRepositoryActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalRepositoryActionTest.java
deleted file mode 100644 (file)
index b6944c7..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.batch;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.core.measure.db.MetricDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.properties.PropertiesDao;
-import org.sonar.core.properties.PropertyDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.measure.persistence.MetricDao;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class GlobalRepositoryActionTest {
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Mock
-  DbSession session;
-
-  @Mock
-  MetricDao metricDao;
-
-  @Mock
-  PropertiesDao propertiesDao;
-
-  WsTester tester;
-
-  @Before
-  public void setUp() {
-    DbClient dbClient = mock(DbClient.class);
-    when(dbClient.openSession(false)).thenReturn(session);
-    when(dbClient.metricDao()).thenReturn(metricDao);
-
-    tester = new WsTester(new BatchWs(mock(BatchIndex.class), new GlobalRepositoryAction(dbClient, propertiesDao, userSessionRule)));
-  }
-
-  @Test
-  public void return_metrics() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.PREVIEW_EXECUTION);
-
-    when(metricDao.selectEnabled(session)).thenReturn(newArrayList(
-      new MetricDto().setId(1).setKey("coverage").setDescription("Coverage by unit tests").setValueType("PERCENT").setQualitative(true)
-        .setWorstValue(0d).setBestValue(100d).setOptimizedBestValue(false).setDirection(1).setEnabled(true)
-      ));
-
-    WsTester.TestRequest request = tester.newGetRequest("batch", "global");
-    request.execute().assertJson(getClass(), "return_global_referentials.json");
-  }
-
-  @Test
-  public void return_global_settings() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.PREVIEW_EXECUTION);
-
-    when(propertiesDao.selectGlobalProperties(session)).thenReturn(newArrayList(
-      new PropertyDto().setKey("foo").setValue("bar"),
-      new PropertyDto().setKey("foo.secured").setValue("1234"),
-      new PropertyDto().setKey("foo.license.secured").setValue("5678")
-      ));
-
-    WsTester.TestRequest request = tester.newGetRequest("batch", "global");
-    request.execute().assertJson(getClass(), "return_global_settings.json");
-  }
-
-  @Test
-  public void return_only_license_settings_without_scan_but_with_preview_permission() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.PREVIEW_EXECUTION);
-
-    when(propertiesDao.selectGlobalProperties(session)).thenReturn(newArrayList(
-      new PropertyDto().setKey("foo").setValue("bar"),
-      new PropertyDto().setKey("foo.secured").setValue("1234"),
-      new PropertyDto().setKey("foo.license.secured").setValue("5678")
-      ));
-
-    WsTester.TestRequest request = tester.newGetRequest("batch", "global");
-    request.execute().assertJson(getClass(), "return_only_license_settings_without_scan_but_with_preview_permission.json");
-  }
-
-  @Test
-  public void access_forbidden_without_scan_and_preview_permission() throws Exception {
-    userSessionRule.setGlobalPermissions();
-
-    when(propertiesDao.selectGlobalProperties(session)).thenReturn(newArrayList(
-      new PropertyDto().setKey("foo").setValue("bar"),
-      new PropertyDto().setKey("foo.secured").setValue("1234"),
-      new PropertyDto().setKey("foo.license.secured").setValue("5678")
-      ));
-
-    thrown.expect(ForbiddenException.class);
-
-    tester.newGetRequest("batch", "global").execute();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectActionTest.java
new file mode 100644 (file)
index 0000000..dc70a1e
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.batch;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ProjectActionTest {
+
+  @Mock
+  ProjectRepositoryLoader projectRepositoryLoader;
+
+  WsTester tester;
+
+  @Before
+  public void setUp() {
+    tester = new WsTester(new BatchWs(mock(BatchIndex.class), new ProjectAction(projectRepositoryLoader)));
+  }
+
+  @Test
+  public void project_referentials() throws Exception {
+    String projectKey = "org.codehaus.sonar:sonar";
+
+    ProjectRepositories projectReferentials = mock(ProjectRepositories.class);
+    when(projectReferentials.toJson()).thenReturn("{\"settingsByModule\": {}}");
+
+    ArgumentCaptor<ProjectRepositoryQuery> queryArgumentCaptor = ArgumentCaptor.forClass(ProjectRepositoryQuery.class);
+    when(projectRepositoryLoader.load(queryArgumentCaptor.capture())).thenReturn(projectReferentials);
+
+    WsTester.TestRequest request = tester.newGetRequest("batch", "project")
+      .setParam("key", projectKey)
+      .setParam("profile", "Default")
+      .setParam("preview", "false");
+    request.execute().assertJson("{\"settingsByModule\": {}}");
+
+    assertThat(queryArgumentCaptor.getValue().getModuleKey()).isEqualTo(projectKey);
+    assertThat(queryArgumentCaptor.getValue().getProfileName()).isEqualTo("Default");
+    assertThat(queryArgumentCaptor.getValue().isPreview()).isFalse();
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryActionTest.java
deleted file mode 100644 (file)
index 161d65c..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.batch;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.batch.protocol.input.ProjectRepositories;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class ProjectRepositoryActionTest {
-
-  @Mock
-  ProjectRepositoryLoader projectRepositoryLoader;
-
-  WsTester tester;
-
-  @Before
-  public void setUp() {
-    tester = new WsTester(new BatchWs(mock(BatchIndex.class), new ProjectRepositoryAction(projectRepositoryLoader)));
-  }
-
-  @Test
-  public void project_referentials() throws Exception {
-    String projectKey = "org.codehaus.sonar:sonar";
-
-    ProjectRepositories projectReferentials = mock(ProjectRepositories.class);
-    when(projectReferentials.toJson()).thenReturn("{\"settingsByModule\": {}}");
-
-    ArgumentCaptor<ProjectRepositoryQuery> queryArgumentCaptor = ArgumentCaptor.forClass(ProjectRepositoryQuery.class);
-    when(projectRepositoryLoader.load(queryArgumentCaptor.capture())).thenReturn(projectReferentials);
-
-    WsTester.TestRequest request = tester.newGetRequest("batch", "project")
-      .setParam("key", projectKey)
-      .setParam("profile", "Default")
-      .setParam("preview", "false");
-    request.execute().assertJson("{\"settingsByModule\": {}}");
-
-    assertThat(queryArgumentCaptor.getValue().getModuleKey()).isEqualTo(projectKey);
-    assertThat(queryArgumentCaptor.getValue().getProfileName()).isEqualTo("Default");
-    assertThat(queryArgumentCaptor.getValue().isPreview()).isFalse();
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/AppActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/AppActionTest.java
new file mode 100644 (file)
index 0000000..c29c021
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.component.ws;
+
+import java.util.List;
+import java.util.Locale;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.utils.Duration;
+import org.sonar.api.utils.Durations;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.properties.PropertiesDao;
+import org.sonar.core.properties.PropertyDto;
+import org.sonar.core.properties.PropertyQuery;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.measure.persistence.MeasureDao;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+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.Matchers.any;
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AppActionTest {
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  static final String SUB_PROJECT_KEY = "org.codehaus.sonar:sonar-plugin-api";
+  static final String COMPONENT_KEY = "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java";
+  static final String COMPONENT_UUID = "ABCDE";
+  static final String PROJECT_UUID = "THE_PROJECT";
+
+  @Mock
+  DbSession session;
+
+  @Mock
+  ComponentDao componentDao;
+
+  @Mock
+  PropertiesDao propertiesDao;
+
+  @Mock
+  MeasureDao measureDao;
+  @Mock
+  Durations durations;
+
+  @Mock
+  I18n i18n;
+
+  @Captor
+  ArgumentCaptor<List<String>> measureKeysCaptor;
+
+  List<MeasureDto> measures = newArrayList();
+
+  WsTester tester;
+
+  @Before
+  public void setUp() {
+    DbClient dbClient = mock(DbClient.class);
+    when(dbClient.openSession(false)).thenReturn(session);
+    when(dbClient.componentDao()).thenReturn(componentDao);
+    when(dbClient.propertiesDao()).thenReturn(propertiesDao);
+    when(dbClient.measureDao()).thenReturn(measureDao);
+
+    when(measureDao.findByComponentKeyAndMetricKeys(eq(session), anyString(), anyListOf(String.class))).thenReturn(measures);
+
+    tester = new WsTester(new ComponentsWs(new AppAction(dbClient, durations, i18n, userSessionRule), mock(SearchAction.class)));
+  }
+
+  @Test
+  public void app() throws Exception {
+    userSessionRule.login("john").addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
+    ComponentDto project = newProject();
+
+    ComponentDto file = ComponentTesting.newFileDto(project)
+      .setId(10L)
+      .setKey(COMPONENT_KEY)
+      .setUuid(COMPONENT_UUID)
+      .setName("Plugin.java")
+      .setProjectUuid("THE_PROJECT")
+      .setLongName("src/main/java/org/sonar/api/Plugin.java")
+      .setPath("src/main/java/org/sonar/api/Plugin.java")
+      .setParentProjectId(5L);
+    when(componentDao.selectNullableByUuid(session, COMPONENT_UUID)).thenReturn(file);
+    when(componentDao.selectById(5L, session)).thenReturn(new ComponentDto().setId(5L).setLongName("SonarQube :: Plugin API").setKey(SUB_PROJECT_KEY));
+    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
+    when(propertiesDao.selectByQuery(any(PropertyQuery.class), eq(session))).thenReturn(newArrayList(new PropertyDto()));
+
+    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
+    request.execute().assertJson(getClass(), "app.json");
+  }
+
+  @Test
+  public void app_with_measures() throws Exception {
+    userSessionRule.addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
+    ComponentDto project = newProject();
+    newComponent(project);
+
+    addMeasure(CoreMetrics.LINES_KEY, 200);
+    addMeasure(CoreMetrics.COVERAGE_KEY, 95.4);
+    addMeasure(CoreMetrics.DUPLICATED_LINES_DENSITY_KEY, 7.4);
+    addMeasure(CoreMetrics.SQALE_RATING_KEY, "C");
+    addMeasure(CoreMetrics.SQALE_DEBT_RATIO_KEY, 35d);
+
+    measures.add(new MeasureDto().setComponentKey(COMPONENT_KEY).setMetricKey(CoreMetrics.TECHNICAL_DEBT_KEY).setValue(182.0));
+    when(durations.format(any(Locale.class), any(Duration.class), eq(Durations.DurationFormat.SHORT))).thenReturn("3h 2min");
+
+    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
+    request.execute().assertJson(getClass(), "app_with_measures.json");
+
+    verify(measureDao).findByComponentKeyAndMetricKeys(eq(session), eq(COMPONENT_KEY), measureKeysCaptor.capture());
+    assertThat(measureKeysCaptor.getValue()).contains(CoreMetrics.LINES_KEY, CoreMetrics.COVERAGE_KEY, CoreMetrics.DUPLICATED_LINES_DENSITY_KEY,
+      CoreMetrics.TECHNICAL_DEBT_KEY);
+  }
+
+  @Test
+  public void app_with_overall_measure() throws Exception {
+    userSessionRule.addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
+    ComponentDto project = newProject();
+    newComponent(project);
+
+    addMeasure(CoreMetrics.OVERALL_COVERAGE_KEY, 90.1);
+    addMeasure(CoreMetrics.COVERAGE_KEY, 95.4);
+    addMeasure(CoreMetrics.IT_COVERAGE_KEY, 85.2);
+
+    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
+    request.execute().assertJson(getClass(), "app_with_overall_measure.json");
+  }
+
+  @Test
+  public void app_with_ut_measure() throws Exception {
+    userSessionRule.addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
+    ComponentDto project = newProject();
+    newComponent(project);
+
+    addMeasure(CoreMetrics.COVERAGE_KEY, 95.4);
+    addMeasure(CoreMetrics.IT_COVERAGE_KEY, 85.2);
+
+    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
+    request.execute().assertJson(getClass(), "app_with_ut_measure.json");
+  }
+
+  @Test
+  public void app_with_it_measure() throws Exception {
+    userSessionRule.addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
+    ComponentDto project = newProject();
+    newComponent(project);
+
+    addMeasure(CoreMetrics.IT_COVERAGE_KEY, 85.2);
+
+    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
+    request.execute().assertJson(getClass(), "app_with_it_measure.json");
+  }
+
+  @Test
+  public void fail_on_unknown_component() {
+    userSessionRule.login("john").addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
+    when(componentDao.selectNullableByUuid(session, COMPONENT_UUID)).thenReturn(null);
+
+    try {
+      tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID).execute();
+      fail();
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Component 'ABCDE' does not exist");
+    }
+  }
+
+  private ComponentDto newProject() {
+    return ComponentTesting.newProjectDto()
+      .setId(1L)
+      .setName("SonarQube")
+      .setUuid(PROJECT_UUID)
+      .setLongName("SonarQube")
+      .setKey("org.codehaus.sonar:sonar");
+  }
+
+  private ComponentDto newComponent(ComponentDto project) {
+    ComponentDto file = ComponentTesting.newFileDto(project)
+      .setId(10L)
+      .setQualifier("FIL")
+      .setKey(COMPONENT_KEY)
+      .setUuid(COMPONENT_UUID)
+      .setProjectUuid(PROJECT_UUID)
+      .setName("Plugin.java")
+      .setLongName("src/main/java/org/sonar/api/Plugin.java")
+      .setPath("src/main/java/org/sonar/api/Plugin.java")
+      .setParentProjectId(5L);
+    when(componentDao.selectNullableByUuid(session, COMPONENT_UUID)).thenReturn(file);
+    when(componentDao.selectById(5L, session)).thenReturn(new ComponentDto().setId(5L).setLongName("SonarQube :: Plugin API").setKey(SUB_PROJECT_KEY));
+    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
+    return file;
+  }
+
+  private void addMeasure(String metricKey, Integer value) {
+    measures.add(new MeasureDto().setComponentKey(COMPONENT_KEY).setMetricKey(metricKey).setValue(value.doubleValue()));
+    when(i18n.formatInteger(any(Locale.class), eq(value.intValue()))).thenReturn(Integer.toString(value));
+  }
+
+  private void addMeasure(String metricKey, Double value) {
+    measures.add(new MeasureDto().setComponentKey(COMPONENT_KEY).setMetricKey(metricKey).setValue(value));
+    when(i18n.formatDouble(any(Locale.class), eq(value))).thenReturn(Double.toString(value));
+  }
+
+  private void addMeasure(String metricKey, String value) {
+    measures.add(new MeasureDto().setComponentKey(COMPONENT_KEY).setMetricKey(metricKey).setData(value));
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java
deleted file mode 100644 (file)
index 5089d87..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import java.util.List;
-import java.util.Locale;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.Duration;
-import org.sonar.api.utils.Durations;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.measure.db.MeasureDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.properties.PropertiesDao;
-import org.sonar.core.properties.PropertyDto;
-import org.sonar.core.properties.PropertyQuery;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.measure.persistence.MeasureDao;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-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.Matchers.any;
-import static org.mockito.Matchers.anyListOf;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class ComponentAppActionTest {
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  static final String SUB_PROJECT_KEY = "org.codehaus.sonar:sonar-plugin-api";
-  static final String COMPONENT_KEY = "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java";
-  static final String COMPONENT_UUID = "ABCDE";
-  static final String PROJECT_UUID = "THE_PROJECT";
-
-  @Mock
-  DbSession session;
-
-  @Mock
-  ComponentDao componentDao;
-
-  @Mock
-  PropertiesDao propertiesDao;
-
-  @Mock
-  MeasureDao measureDao;
-  @Mock
-  Durations durations;
-
-  @Mock
-  I18n i18n;
-
-  @Captor
-  ArgumentCaptor<List<String>> measureKeysCaptor;
-
-  List<MeasureDto> measures = newArrayList();
-
-  WsTester tester;
-
-  @Before
-  public void setUp() {
-    DbClient dbClient = mock(DbClient.class);
-    when(dbClient.openSession(false)).thenReturn(session);
-    when(dbClient.componentDao()).thenReturn(componentDao);
-    when(dbClient.propertiesDao()).thenReturn(propertiesDao);
-    when(dbClient.measureDao()).thenReturn(measureDao);
-
-    when(measureDao.findByComponentKeyAndMetricKeys(eq(session), anyString(), anyListOf(String.class))).thenReturn(measures);
-
-    tester = new WsTester(new ComponentsWs(new ComponentAppAction(dbClient, durations, i18n, userSessionRule), mock(SearchAction.class)));
-  }
-
-  @Test
-  public void app() throws Exception {
-    userSessionRule.login("john").addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
-    ComponentDto project = newProject();
-
-    ComponentDto file = ComponentTesting.newFileDto(project)
-      .setId(10L)
-      .setKey(COMPONENT_KEY)
-      .setUuid(COMPONENT_UUID)
-      .setName("Plugin.java")
-      .setProjectUuid("THE_PROJECT")
-      .setLongName("src/main/java/org/sonar/api/Plugin.java")
-      .setPath("src/main/java/org/sonar/api/Plugin.java")
-      .setParentProjectId(5L);
-    when(componentDao.selectNullableByUuid(session, COMPONENT_UUID)).thenReturn(file);
-    when(componentDao.selectById(5L, session)).thenReturn(new ComponentDto().setId(5L).setLongName("SonarQube :: Plugin API").setKey(SUB_PROJECT_KEY));
-    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
-    when(propertiesDao.selectByQuery(any(PropertyQuery.class), eq(session))).thenReturn(newArrayList(new PropertyDto()));
-
-    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
-    request.execute().assertJson(getClass(), "app.json");
-  }
-
-  @Test
-  public void app_with_measures() throws Exception {
-    userSessionRule.addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
-    ComponentDto project = newProject();
-    newComponent(project);
-
-    addMeasure(CoreMetrics.LINES_KEY, 200);
-    addMeasure(CoreMetrics.COVERAGE_KEY, 95.4);
-    addMeasure(CoreMetrics.DUPLICATED_LINES_DENSITY_KEY, 7.4);
-    addMeasure(CoreMetrics.SQALE_RATING_KEY, "C");
-    addMeasure(CoreMetrics.SQALE_DEBT_RATIO_KEY, 35d);
-
-    measures.add(new MeasureDto().setComponentKey(COMPONENT_KEY).setMetricKey(CoreMetrics.TECHNICAL_DEBT_KEY).setValue(182.0));
-    when(durations.format(any(Locale.class), any(Duration.class), eq(Durations.DurationFormat.SHORT))).thenReturn("3h 2min");
-
-    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
-    request.execute().assertJson(getClass(), "app_with_measures.json");
-
-    verify(measureDao).findByComponentKeyAndMetricKeys(eq(session), eq(COMPONENT_KEY), measureKeysCaptor.capture());
-    assertThat(measureKeysCaptor.getValue()).contains(CoreMetrics.LINES_KEY, CoreMetrics.COVERAGE_KEY, CoreMetrics.DUPLICATED_LINES_DENSITY_KEY,
-      CoreMetrics.TECHNICAL_DEBT_KEY);
-  }
-
-  @Test
-  public void app_with_overall_measure() throws Exception {
-    userSessionRule.addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
-    ComponentDto project = newProject();
-    newComponent(project);
-
-    addMeasure(CoreMetrics.OVERALL_COVERAGE_KEY, 90.1);
-    addMeasure(CoreMetrics.COVERAGE_KEY, 95.4);
-    addMeasure(CoreMetrics.IT_COVERAGE_KEY, 85.2);
-
-    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
-    request.execute().assertJson(getClass(), "app_with_overall_measure.json");
-  }
-
-  @Test
-  public void app_with_ut_measure() throws Exception {
-    userSessionRule.addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
-    ComponentDto project = newProject();
-    newComponent(project);
-
-    addMeasure(CoreMetrics.COVERAGE_KEY, 95.4);
-    addMeasure(CoreMetrics.IT_COVERAGE_KEY, 85.2);
-
-    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
-    request.execute().assertJson(getClass(), "app_with_ut_measure.json");
-  }
-
-  @Test
-  public void app_with_it_measure() throws Exception {
-    userSessionRule.addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
-    ComponentDto project = newProject();
-    newComponent(project);
-
-    addMeasure(CoreMetrics.IT_COVERAGE_KEY, 85.2);
-
-    WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID);
-    request.execute().assertJson(getClass(), "app_with_it_measure.json");
-  }
-
-  @Test
-  public void fail_on_unknown_component() {
-    userSessionRule.login("john").addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
-    when(componentDao.selectNullableByUuid(session, COMPONENT_UUID)).thenReturn(null);
-
-    try {
-      tester.newGetRequest("api/components", "app").setParam("uuid", COMPONENT_UUID).execute();
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Component 'ABCDE' does not exist");
-    }
-  }
-
-  private ComponentDto newProject() {
-    return ComponentTesting.newProjectDto()
-      .setId(1L)
-      .setName("SonarQube")
-      .setUuid(PROJECT_UUID)
-      .setLongName("SonarQube")
-      .setKey("org.codehaus.sonar:sonar");
-  }
-
-  private ComponentDto newComponent(ComponentDto project) {
-    ComponentDto file = ComponentTesting.newFileDto(project)
-      .setId(10L)
-      .setQualifier("FIL")
-      .setKey(COMPONENT_KEY)
-      .setUuid(COMPONENT_UUID)
-      .setProjectUuid(PROJECT_UUID)
-      .setName("Plugin.java")
-      .setLongName("src/main/java/org/sonar/api/Plugin.java")
-      .setPath("src/main/java/org/sonar/api/Plugin.java")
-      .setParentProjectId(5L);
-    when(componentDao.selectNullableByUuid(session, COMPONENT_UUID)).thenReturn(file);
-    when(componentDao.selectById(5L, session)).thenReturn(new ComponentDto().setId(5L).setLongName("SonarQube :: Plugin API").setKey(SUB_PROJECT_KEY));
-    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
-    return file;
-  }
-
-  private void addMeasure(String metricKey, Integer value) {
-    measures.add(new MeasureDto().setComponentKey(COMPONENT_KEY).setMetricKey(metricKey).setValue(value.doubleValue()));
-    when(i18n.formatInteger(any(Locale.class), eq(value.intValue()))).thenReturn(Integer.toString(value));
-  }
-
-  private void addMeasure(String metricKey, Double value) {
-    measures.add(new MeasureDto().setComponentKey(COMPONENT_KEY).setMetricKey(metricKey).setValue(value));
-    when(i18n.formatDouble(any(Locale.class), eq(value))).thenReturn(Double.toString(value));
-  }
-
-  private void addMeasure(String metricKey, String value) {
-    measures.add(new MeasureDto().setComponentKey(COMPONENT_KEY).setMetricKey(metricKey).setData(value));
-  }
-
-}
index 486e5b3374151fc9aab28366f6e6c4a8c78a1983..94baa386fc692f9fb58279475c9213d9ff729f6b 100644 (file)
@@ -42,7 +42,7 @@ public class ComponentsWsTest {
 
   @Before
   public void setUp() {
-    WsTester tester = new WsTester(new ComponentsWs(new ComponentAppAction(mock(DbClient.class), mock(Durations.class), mock(I18n.class), userSessionRule), new SearchAction(mock(DbClient.class), userSessionRule)));
+    WsTester tester = new WsTester(new ComponentsWs(new AppAction(mock(DbClient.class), mock(Durations.class), mock(I18n.class), userSessionRule), new SearchAction(mock(DbClient.class), userSessionRule)));
     controller = tester.controller("api/components");
   }
 
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsDeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsDeleteActionTest.java
deleted file mode 100644 (file)
index b21454b..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import com.google.common.collect.ImmutableMap;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.component.SnapshotDto;
-import org.sonar.core.issue.db.IssueDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeProfiler;
-import org.sonar.core.resource.ResourceDao;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.component.ComponentCleanerService;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.SnapshotTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.issue.IssueTesting;
-import org.sonar.server.issue.db.IssueDao;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
-import org.sonar.server.issue.index.IssueIndexDefinition;
-import org.sonar.server.issue.index.IssueIndexer;
-import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.source.index.SourceLineDoc;
-import org.sonar.server.source.index.SourceLineIndexDefinition;
-import org.sonar.server.source.index.SourceLineIndexer;
-import org.sonar.server.test.index.TestDoc;
-import org.sonar.server.test.index.TestIndexDefinition;
-import org.sonar.server.test.index.TestIndexer;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-import org.sonar.test.DbTests;
-
-import java.util.Arrays;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-@Category(DbTests.class)
-public class ProjectsDeleteActionTest {
-
-  @ClassRule
-  public static DbTester db = new DbTester();
-  @ClassRule
-  public static EsTester es = new EsTester().addDefinitions(new IssueIndexDefinition(new Settings()), new SourceLineIndexDefinition(new Settings()),
-    new TestIndexDefinition(new Settings()));
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  WsTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-  ResourceType resourceType;
-
-  @Before
-  public void setUp() throws Exception {
-    ComponentDao componentDao = new ComponentDao();
-    ResourceDao resourceDao = new ResourceDao(db.myBatis(), System2.INSTANCE);
-    PurgeDao purgeDao = new PurgeDao(db.myBatis(), resourceDao, new PurgeProfiler(), System2.INSTANCE);
-    dbClient = new DbClient(db.database(), db.myBatis(), componentDao, purgeDao, new RuleDao(System2.INSTANCE), new IssueDao(db.myBatis()), new SnapshotDao(System2.INSTANCE));
-    dbSession = dbClient.openSession(false);
-    resourceType = mock(ResourceType.class);
-    when(resourceType.getBooleanProperty(anyString())).thenReturn(true);
-    ResourceTypes mockResourceTypes = mock(ResourceTypes.class);
-    when(mockResourceTypes.get(anyString())).thenReturn(resourceType);
-    ws = new WsTester(new ProjectsWs(new ProjectsDeleteAction(new ComponentCleanerService(dbClient, new IssueAuthorizationIndexer(dbClient, es.client()), new IssueIndexer(
-      dbClient, es.client()), new SourceLineIndexer(dbClient, es.client()), new TestIndexer(dbClient, es.client()), mockResourceTypes), dbClient, userSessionRule)));
-    db.truncateTables();
-    es.truncateIndices();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    dbSession.close();
-  }
-
-  @Test
-  public void delete_projects_and_data_in_db_by_uuids() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    long snapshotId1 = insertNewProjectInDbAndReturnSnapshotId(1);
-    long snapshotId2 = insertNewProjectInDbAndReturnSnapshotId(2);
-    long snapshotId3 = insertNewProjectInDbAndReturnSnapshotId(3);
-    long snapshotId4 = insertNewProjectInDbAndReturnSnapshotId(4);
-
-    ws.newGetRequest("api/projects", "delete")
-      .setParam("uuids", "project-uuid-1, project-uuid-3, project-uuid-4").execute();
-    dbSession.commit();
-
-    assertThat(dbClient.componentDao().selectByUuids(dbSession, Arrays.asList("project-uuid-1", "project-uuid-3", "project-uuid-4"))).isEmpty();
-    assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-2")).isNotNull();
-    assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId1)).isNull();
-    assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId3)).isNull();
-    assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId4)).isNull();
-    assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId2)).isNotNull();
-    assertThat(dbClient.issueDao().selectByKeys(dbSession, Arrays.asList("issue-key-1", "issue-key-3", "issue-key-4"))).isEmpty();
-    assertThat(dbClient.issueDao().selectByKey(dbSession, "issue-key-2")).isNotNull();
-  }
-
-  @Test
-  public void delete_projects_and_data_in_db_by_keys() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    insertNewProjectInDbAndReturnSnapshotId(1);
-    insertNewProjectInDbAndReturnSnapshotId(2);
-    insertNewProjectInDbAndReturnSnapshotId(3);
-    insertNewProjectInDbAndReturnSnapshotId(4);
-
-    ws.newGetRequest("api/projects", "delete")
-      .setParam("keys", "project-key-1, project-key-3, project-key-4").execute();
-    dbSession.commit();
-
-    assertThat(dbClient.componentDao().selectByUuids(dbSession, Arrays.asList("project-uuid-1", "project-uuid-3", "project-uuid-4"))).isEmpty();
-    assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-2")).isNotNull();
-  }
-
-  @Test
-  public void delete_documents_indexes() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    insertNewProjectInIndexes(1);
-    insertNewProjectInIndexes(2);
-    insertNewProjectInIndexes(3);
-    insertNewProjectInIndexes(4);
-
-    ws.newGetRequest("api/projects", "delete")
-      .setParam("keys", "project-key-1, project-key-3, project-key-4").execute();
-
-    String remainingProjectUuid = "project-uuid-2";
-    assertThat(es.getDocumentFieldValues(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID))
-      .containsOnly(remainingProjectUuid);
-    assertThat(es.getDocumentFieldValues(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID))
-      .containsOnly(remainingProjectUuid);
-    assertThat(es.getDocumentFieldValues(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE, SourceLineIndexDefinition.FIELD_PROJECT_UUID))
-      .containsOnly(remainingProjectUuid);
-    assertThat(es.getDocumentFieldValues(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, TestIndexDefinition.FIELD_PROJECT_UUID))
-      .containsOnly(remainingProjectUuid);
-  }
-
-  @Test
-  public void web_service_returns_204() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    insertNewProjectInDbAndReturnSnapshotId(1);
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "delete").setParam("uuids", "project-uuid-1").execute();
-
-    result.assertNoContent();
-  }
-
-  @Test
-  public void fail_if_insufficient_privileges() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, UserRole.USER);
-    expectedException.expect(ForbiddenException.class);
-
-    ws.newGetRequest("api/projects", "delete").setParam("uuids", "whatever-the-uuid").execute();
-  }
-
-  @Test
-  public void fail_if_scope_is_not_project() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    expectedException.expect(IllegalArgumentException.class);
-    dbClient.componentDao().insert(dbSession, ComponentTesting.newFileDto(ComponentTesting.newProjectDto(), "file-uuid"));
-    dbSession.commit();
-
-    ws.newGetRequest("api/projects", "delete").setParam("uuids", "file-uuid").execute();
-  }
-
-  @Test
-  public void fail_if_qualifier_is_not_deletable() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    expectedException.expect(IllegalArgumentException.class);
-    dbClient.componentDao().insert(dbSession, ComponentTesting.newProjectDto("project-uuid").setQualifier(Qualifiers.FILE));
-    dbSession.commit();
-    when(resourceType.getBooleanProperty(anyString())).thenReturn(false);
-
-    ws.newGetRequest("api/projects", "delete").setParam("uuids", "project-uuid").execute();
-  }
-
-  private long insertNewProjectInDbAndReturnSnapshotId(int id) {
-    String suffix = String.valueOf(id);
-    ComponentDto project = ComponentTesting
-      .newProjectDto("project-uuid-" + suffix)
-      .setKey("project-key-" + suffix);
-    RuleDto rule = RuleTesting.newDto(RuleKey.of("sonarqube", "rule-" + suffix));
-    dbClient.ruleDao().insert(dbSession, rule);
-    IssueDto issue = IssueTesting.newDto(rule, project, project).setKee("issue-key-" + suffix);
-    dbClient.componentDao().insert(dbSession, project);
-    SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, SnapshotTesting.createForProject(project));
-    dbClient.issueDao().insert(dbSession, issue);
-    dbSession.commit();
-
-    return snapshot.getId();
-  }
-
-  private void insertNewProjectInIndexes(int id) throws Exception {
-    String suffix = String.valueOf(id);
-    ComponentDto project = ComponentTesting
-      .newProjectDto("project-uuid-" + suffix)
-      .setKey("project-key-" + suffix);
-    dbClient.componentDao().insert(dbSession, project);
-    dbSession.commit();
-
-    es.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueTesting.newDoc("issue-key-" + suffix, project));
-    SourceLineDoc sourceLineDoc = new SourceLineDoc()
-      .setProjectUuid(project.uuid())
-      .setFileUuid(project.uuid());
-    es.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION,
-      ImmutableMap.<String, Object>of(IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, project.uuid()));
-
-    es.putDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE, sourceLineDoc);
-    TestDoc testDoc = new TestDoc().setUuid("test-uuid-" + suffix).setProjectUuid(project.uuid()).setFileUuid(project.uuid());
-    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, testDoc);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsGhostsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsGhostsActionTest.java
deleted file mode 100644 (file)
index 1cd6a64..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import com.google.common.io.Resources;
-import org.apache.commons.lang.StringUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.component.SnapshotDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.SnapshotTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-import org.sonar.test.DbTests;
-import org.sonar.test.JsonAssert;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@Category(DbTests.class)
-public class ProjectsGhostsActionTest {
-
-  @ClassRule
-  public static DbTester db = new DbTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-  WsTester ws;
-
-  DbClient dbClient;
-  DbSession dbSession;
-
-  @Before
-  public void setUp() {
-    dbClient = new DbClient(db.database(), db.myBatis(), new ComponentDao(), new SnapshotDao(System2.INSTANCE));
-    dbSession = dbClient.openSession(false);
-    ws = new WsTester(new ProjectsWs(new ProjectsGhostsAction(dbClient, userSessionRule)));
-    db.truncateTables();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    dbSession.close();
-  }
-
-  @Test
-  public void ghost_projects_without_analyzed_projects() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    insertNewGhostProject("1");
-    insertNewGhostProject("2");
-    insertNewActiveProject("3");
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts").execute();
-
-    result.assertJson(getClass(), "all-projects.json");
-    assertThat(result.outputAsString()).doesNotContain("analyzed-uuid-3");
-  }
-
-  @Test
-  public void ghost_projects_with_correct_pagination() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    for (int i = 1; i <= 10; i++) {
-      insertNewGhostProject(String.valueOf(i));
-    }
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts")
-      .setParam(Param.PAGE, "3")
-      .setParam(Param.PAGE_SIZE, "4")
-      .execute();
-
-    result.assertJson(getClass(), "pagination.json");
-    assertThat(StringUtils.countMatches(result.outputAsString(), "ghost-uuid-")).isEqualTo(2);
-  }
-
-  @Test
-  public void ghost_projects_with_chosen_fields() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    insertNewGhostProject("1");
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts")
-      .setParam(Param.FIELDS, "name")
-      .execute();
-
-    assertThat(result.outputAsString()).contains("uuid", "name")
-      .doesNotContain("key")
-      .doesNotContain("creationDate");
-  }
-
-  @Test
-  public void ghost_projects_with_partial_query_on_name() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-
-    insertNewGhostProject("10");
-    insertNewGhostProject("11");
-    insertNewGhostProject("2");
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts")
-      .setParam(Param.TEXT_QUERY, "name-1")
-      .execute();
-
-    assertThat(result.outputAsString()).contains("ghost-name-10", "ghost-name-11")
-      .doesNotContain("ghost-name-2");
-  }
-
-  @Test
-  public void ghost_projects_with_partial_query_on_key() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-
-    insertNewGhostProject("1");
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts")
-      .setParam(Param.TEXT_QUERY, "GHOST-key")
-      .execute();
-
-    assertThat(result.outputAsString()).contains("ghost-key-1");
-  }
-
-  @Test
-  public void ghost_projects_base_on_json_example() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
-    ComponentDto hBaseProject = ComponentTesting.newProjectDto("ce4c03d6-430f-40a9-b777-ad877c00aa4d")
-      .setKey("org.apache.hbas:hbase")
-      .setName("HBase")
-      .setCreatedAt(DateUtils.parseDateTime("2015-03-04T23:03:44+0100"));
-    dbClient.componentDao().insert(dbSession, hBaseProject);
-    dbClient.snapshotDao().insert(dbSession, SnapshotTesting.createForProject(hBaseProject)
-      .setStatus(SnapshotDto.STATUS_UNPROCESSED));
-    ComponentDto roslynProject = ComponentTesting.newProjectDto("c526ef20-131b-4486-9357-063fa64b5079")
-      .setKey("com.microsoft.roslyn:roslyn")
-      .setName("Roslyn")
-      .setCreatedAt(DateUtils.parseDateTime("2013-03-04T23:03:44+0100"));
-    dbClient.componentDao().insert(dbSession, roslynProject);
-    dbClient.snapshotDao().insert(dbSession, SnapshotTesting.createForProject(roslynProject)
-      .setStatus(SnapshotDto.STATUS_UNPROCESSED));
-    dbSession.commit();
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts").execute();
-
-    JsonAssert.assertJson(result.outputAsString()).isSimilarTo(Resources.getResource(getClass(), "projects-example-ghosts.json"));
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_if_does_not_have_sufficient_rights() throws Exception {
-    userSessionRule.setGlobalPermissions(UserRole.USER, UserRole.ISSUE_ADMIN, UserRole.CODEVIEWER);
-
-    ws.newGetRequest("api/projects", "ghosts").execute();
-  }
-
-  private void insertNewGhostProject(String id) {
-    ComponentDto project = ComponentTesting
-      .newProjectDto("ghost-uuid-" + id)
-      .setName("ghost-name-" + id)
-      .setKey("ghost-key-" + id);
-    dbClient.componentDao().insert(dbSession, project);
-    SnapshotDto snapshot = SnapshotTesting.createForProject(project)
-      .setStatus(SnapshotDto.STATUS_UNPROCESSED);
-    dbClient.snapshotDao().insert(dbSession, snapshot);
-    dbSession.commit();
-  }
-
-  private void insertNewActiveProject(String id) {
-    ComponentDto project = ComponentTesting
-      .newProjectDto("analyzed-uuid-" + id)
-      .setName("analyzed-name-" + id)
-      .setKey("analyzed-key-" + id);
-    dbClient.componentDao().insert(dbSession, project);
-    SnapshotDto snapshot = SnapshotTesting.createForProject(project);
-    dbClient.snapshotDao().insert(dbSession, snapshot);
-    dbSession.commit();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsProvisionedActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsProvisionedActionTest.java
deleted file mode 100644 (file)
index 2abe36c..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import com.google.common.io.Resources;
-import org.apache.commons.lang.StringUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.System2;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.component.SnapshotDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.SnapshotTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-import org.sonar.test.DbTests;
-import org.sonar.test.JsonAssert;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@Category(DbTests.class)
-public class ProjectsProvisionedActionTest {
-
-  @ClassRule
-  public static DbTester db = new DbTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  WsTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-  ComponentDao componentDao;
-
-  @After
-  public void tearDown() {
-    dbSession.close();
-  }
-
-  @Before
-  public void setUp() {
-    dbClient = new DbClient(db.database(), db.myBatis(), new ComponentDao(), new SnapshotDao(System2.INSTANCE));
-    dbSession = dbClient.openSession(false);
-    componentDao = dbClient.componentDao();
-    db.truncateTables();
-    ws = new WsTester(new ProjectsWs(new ProjectsProvisionedAction(dbClient, userSessionRule)));
-  }
-
-  @Test
-  public void all_provisioned_projects_without_analyzed_projects() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
-    ComponentDto analyzedProject = ComponentTesting.newProjectDto("analyzed-uuid-1");
-    componentDao.insert(dbSession, newProvisionedProject("1"), newProvisionedProject("2"), analyzedProject);
-    SnapshotDto snapshot = SnapshotTesting.createForProject(analyzedProject);
-    dbClient.snapshotDao().insert(dbSession, snapshot);
-    dbSession.commit();
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "provisioned").execute();
-
-    result.assertJson(getClass(), "all-projects.json");
-    assertThat(result.outputAsString()).doesNotContain("analyzed-uuid-1");
-  }
-
-  @Test
-  public void provisioned_projects_with_correct_pagination() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
-    for (int i = 1; i <= 10; i++) {
-      componentDao.insert(dbSession, newProvisionedProject(String.valueOf(i)));
-    }
-    dbSession.commit();
-
-    WsTester.TestRequest request = ws.newGetRequest("api/projects", "provisioned")
-      .setParam(Param.PAGE, "3")
-      .setParam(Param.PAGE_SIZE, "4");
-
-    String jsonOutput = request.execute().outputAsString();
-
-    assertThat(StringUtils.countMatches(jsonOutput, "provisioned-uuid-")).isEqualTo(2);
-  }
-
-  @Test
-  public void provisioned_projects_with_desired_fields() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
-    componentDao.insert(dbSession, newProvisionedProject("1"));
-    dbSession.commit();
-
-    String jsonOutput = ws.newGetRequest("api/projects", "provisioned")
-      .setParam(Param.FIELDS, "key")
-      .execute().outputAsString();
-
-    assertThat(jsonOutput).contains("uuid", "key")
-      .doesNotContain("name")
-      .doesNotContain("creationDate");
-  }
-
-  @Test
-  public void provisioned_projects_with_query() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
-    componentDao.insert(dbSession, newProvisionedProject("1"), newProvisionedProject("2"));
-    dbSession.commit();
-
-    String jsonOutput = ws.newGetRequest("api/projects", "provisioned")
-      .setParam(Param.TEXT_QUERY, "PROVISIONED-name-2")
-      .execute().outputAsString();
-
-    assertThat(jsonOutput)
-      .contains("provisioned-name-2", "provisioned-uuid-2")
-      .doesNotContain("provisioned-uuid-1");
-    assertThat(componentDao.countProvisionedProjects(dbSession, "name-2")).isEqualTo(1);
-    assertThat(componentDao.countProvisionedProjects(dbSession, "key-2")).isEqualTo(1);
-    assertThat(componentDao.countProvisionedProjects(dbSession, "visioned-name-")).isEqualTo(2);
-  }
-
-  @Test
-  public void provisioned_projects_as_defined_in_the_example() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
-    ComponentDto hBaseProject = ComponentTesting.newProjectDto("ce4c03d6-430f-40a9-b777-ad877c00aa4d")
-      .setKey("org.apache.hbas:hbase")
-      .setName("HBase")
-      .setCreatedAt(DateUtils.parseDateTime("2015-03-04T23:03:44+0100"));
-    ComponentDto roslynProject = ComponentTesting.newProjectDto("c526ef20-131b-4486-9357-063fa64b5079")
-      .setKey("com.microsoft.roslyn:roslyn")
-      .setName("Roslyn")
-      .setCreatedAt(DateUtils.parseDateTime("2013-03-04T23:03:44+0100"));
-    componentDao.insert(dbSession, hBaseProject, roslynProject);
-    dbSession.commit();
-
-    WsTester.Result result = ws.newGetRequest("api/projects", "provisioned").execute();
-
-    JsonAssert.assertJson(result.outputAsString()).isSimilarTo(Resources.getResource(getClass(), "projects-example-provisioned.json"));
-  }
-
-  @Test
-  public void fail_when_not_enough_privileges() throws Exception {
-    expectedException.expect(ForbiddenException.class);
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    componentDao.insert(dbSession, newProvisionedProject("1"));
-
-    ws.newGetRequest("api/projects", "provisioned").execute();
-  }
-
-  private static ComponentDto newProvisionedProject(String uuid) {
-    return ComponentTesting
-      .newProjectDto("provisioned-uuid-" + uuid)
-      .setName("provisioned-name-" + uuid)
-      .setKey("provisioned-key-" + uuid);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectsWsTest.java
deleted file mode 100644 (file)
index 003bb4f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.component.ws;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.server.ws.RailsHandler;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ProjectsWsTest {
-
-  WebService.Controller controller;
-  WsTester ws;
-
-  @Before
-  public void setUp() {
-    ws = new WsTester(new ProjectsWs());
-    controller = ws.controller("api/projects");
-  }
-
-  @Test
-  public void define_controller() {
-    assertThat(controller).isNotNull();
-    assertThat(controller.description()).isNotEmpty();
-    assertThat(controller.since()).isEqualTo("2.10");
-    assertThat(controller.actions()).hasSize(3);
-  }
-
-  @Test
-  public void define_index_action() {
-    WebService.Action action = controller.action("index");
-    assertThat(action).isNotNull();
-    assertThat(action.handler()).isInstanceOf(RailsHandler.class);
-    assertThat(action.responseExampleAsString()).isNotEmpty();
-    assertThat(action.params()).hasSize(8);
-  }
-
-  @Test
-  public void define_create_action() {
-    WebService.Action action = controller.action("create");
-    assertThat(action).isNotNull();
-    assertThat(action.handler()).isInstanceOf(RailsHandler.class);
-    assertThat(action.responseExampleAsString()).isNotEmpty();
-    assertThat(action.params()).hasSize(4);
-  }
-
-  @Test
-  public void define_destroy_action() {
-    WebService.Action action = controller.action("destroy");
-    assertThat(action).isNotNull();
-    assertThat(action.handler()).isInstanceOf(RailsHandler.class);
-    assertThat(action.params()).hasSize(1);
-  }
-
-}
index c63ff362391d97e9c33a0751a7ea0bf53e5c7ff1..7e3a07668958282d38becb0725411487b2e5c2e9 100644 (file)
@@ -55,7 +55,7 @@ public class SearchActionTest {
     DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(),
       new ComponentDao(), new AuthorizationDao(dbTester.myBatis()), new ComponentIndexDao()
       );
-    tester = new WsTester(new ComponentsWs(mock(ComponentAppAction.class), new SearchAction(dbClient, userSessionRule)));
+    tester = new WsTester(new ComponentsWs(mock(AppAction.class), new SearchAction(dbClient, userSessionRule)));
   }
 
   @Test
index 8da36798f956c36ff1639941ff26bc81e8cd55c9..742afbf0d2784677a1690cbd01846037f7122e57 100644 (file)
 package org.sonar.server.computation.ws;
 
 import org.junit.Test;
-import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.WebService;
+import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.computation.ComputationThreadLauncher;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.user.UserSession;
+import org.sonar.server.ws.WsTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 
 public class ComputationWsTest {
 
+  WsTester ws = new WsTester(new ComputationWs(
+    new QueueAction(mock(ReportQueue.class)),
+    new SubmitReportAction(mock(ReportQueue.class), mock(ComputationThreadLauncher.class), mock(UserSession.class)),
+    new HistoryAction(mock(ActivityIndex.class), mock(UserSession.class))));
+
   @Test
   public void define() {
-    ComputationWs ws = new ComputationWs(new ComputationWsAction() {
-      @Override
-      public void define(WebService.NewController controller) {
-        WebService.NewAction upload = controller.createAction("upload");
-        upload.setHandler(mock(RequestHandler.class));
-      }
-    });
-    WebService.Context context = new WebService.Context();
-    ws.define(context);
+    WebService.Controller controller = ws.controller("api/computation");
 
-    WebService.Controller controller = context.controller("api/computation");
     assertThat(controller).isNotNull();
     assertThat(controller.description()).isNotEmpty();
-    assertThat(controller.actions()).hasSize(1);
+    assertThat(controller.actions()).hasSize(3);
   }
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryActionMediumTest.java
new file mode 100644 (file)
index 0000000..21bd552
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.ws;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.activity.Activity;
+import org.sonar.server.activity.ActivityService;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import java.util.Date;
+
+/**
+ * TODO replace this medium test by a small test
+ */
+public class HistoryActionMediumTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
+
+  HistoryAction sut;
+  ActivityService activityService;
+
+  @Before
+  public void setUp() {
+    tester.clearDbAndIndexes();
+    sut = tester.get(HistoryAction.class);
+    activityService = tester.get(ActivityService.class);
+  }
+
+  @Test
+  public void search() throws Exception {
+    Activity activity1 = new Activity();
+    activity1.setType(Activity.Type.ANALYSIS_REPORT);
+    activity1.setAction("LOG_ANALYSIS_REPORT");
+    activity1.setData("projectKey", "P1");
+    activity1.setData("projectName", "POne");
+    activity1.setData("projectUuid", "U1");
+    activity1.setData("status", AnalysisReportDto.Status.SUCCESS);
+    activity1.setData("submittedAt", new Date());
+    activityService.save(activity1);
+
+    Activity activity2 = new Activity();
+    activity2.setType(Activity.Type.ANALYSIS_REPORT);
+    activity2.setAction("LOG_ANALYSIS_REPORT");
+    activity2.setData("projectKey", "P2");
+    activity2.setData("projectName", "PTwo");
+    activity2.setData("projectUuid", "U2");
+    activity2.setData("status", AnalysisReportDto.Status.FAILED);
+    activity2.setData("submittedAt", new Date());
+    activityService.save(activity2);
+
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    WsTester.TestRequest request = tester.wsTester().newGetRequest("api/computation", "history");
+    request.execute().assertJson(getClass(), "list_history_reports.json");
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void requires_admin_right() throws Exception {
+    WsTester.TestRequest request = tester.wsTester().newGetRequest("api/computation", "history");
+    request.execute();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryWsActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryWsActionMediumTest.java
deleted file mode 100644 (file)
index 82da614..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.ActivityService;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-/**
- * TODO replace this medium test by a small test
- */
-public class HistoryWsActionMediumTest {
-
-  @ClassRule
-  public static ServerTester tester = new ServerTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
-  HistoryWsAction sut;
-  ActivityService activityService;
-
-  @Before
-  public void setUp() {
-    tester.clearDbAndIndexes();
-    sut = tester.get(HistoryWsAction.class);
-    activityService = tester.get(ActivityService.class);
-  }
-
-  @Test
-  public void search() throws Exception {
-    Activity activity1 = new Activity();
-    activity1.setType(Activity.Type.ANALYSIS_REPORT);
-    activity1.setAction("LOG_ANALYSIS_REPORT");
-    activity1.setData("projectKey", "P1");
-    activity1.setData("projectName", "POne");
-    activity1.setData("projectUuid", "U1");
-    activity1.setData("status", AnalysisReportDto.Status.SUCCESS);
-    activity1.setData("submittedAt", new Date());
-    activityService.save(activity1);
-
-    Activity activity2 = new Activity();
-    activity2.setType(Activity.Type.ANALYSIS_REPORT);
-    activity2.setAction("LOG_ANALYSIS_REPORT");
-    activity2.setData("projectKey", "P2");
-    activity2.setData("projectName", "PTwo");
-    activity2.setData("projectUuid", "U2");
-    activity2.setData("status", AnalysisReportDto.Status.FAILED);
-    activity2.setData("submittedAt", new Date());
-    activityService.save(activity2);
-
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    WsTester.TestRequest request = tester.wsTester().newGetRequest("api/computation", "history");
-    request.execute().assertJson(getClass(), "list_history_reports.json");
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void requires_admin_right() throws Exception {
-    WsTester.TestRequest request = tester.wsTester().newGetRequest("api/computation", "history");
-    request.execute();
-  }
-}
index 32c9e9432d920c3fcd24e685b00d05f66de89e43..e88401ec61aed1edd985d6916c411a207986b4cf 100644 (file)
@@ -38,14 +38,14 @@ import static org.mockito.Mockito.when;
 
 public class IsQueueEmptyWsTest {
 
-  IsQueueEmptyWs.IsQueueEmptyWsAction sut;
+  IsQueueEmptyWs.IsQueueEmptyAction sut;
   ReportQueue queue;
   Response response;
 
   @Before
   public void before() {
     queue = mock(ReportQueue.class);
-    sut = new IsQueueEmptyWs.IsQueueEmptyWsAction(queue);
+    sut = new IsQueueEmptyWs.IsQueueEmptyAction(queue);
 
     response = mock(Response.class);
     when(response.stream()).thenReturn(new FakeStream());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueActionTest.java
new file mode 100644 (file)
index 0000000..86e2772
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.ws;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.ws.WsTester;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;
+
+public class QueueActionTest {
+
+  WsTester tester;
+  private ReportQueue queue;
+
+  @Before
+  public void setup() {
+    queue = mock(ReportQueue.class);
+    tester = new WsTester(new ComputationWs(new QueueAction(queue)));
+  }
+
+  @Test
+  public void list_active_reports() throws Exception {
+    AnalysisReportDto report = AnalysisReportDto
+      .newForTests(1L)
+      .setProjectKey("project-key")
+      .setStatus(PENDING)
+      .setUuid("PROJECT_UUID")
+      .setCreatedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime())
+      .setStartedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime())
+      .setFinishedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime());
+    List<AnalysisReportDto> reports = Lists.newArrayList(report);
+    when(queue.all()).thenReturn(reports);
+
+    WsTester.TestRequest request = tester.newGetRequest(ComputationWs.ENDPOINT, "queue");
+    request.execute().assertJson(getClass(), "list_queue_reports.json");
+  }
+
+  @Test
+  public void define() {
+    assertThat(tester.controller(ComputationWs.ENDPOINT).action("queue")).isNotNull();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueWsActionTest.java
deleted file mode 100644 (file)
index 42f6f11..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.ws.WsTester;
-
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;
-
-public class QueueWsActionTest {
-
-  WsTester tester;
-  private ReportQueue queue;
-
-  @Before
-  public void setup() {
-    queue = mock(ReportQueue.class);
-    tester = new WsTester(new ComputationWs(new QueueWsAction(queue)));
-  }
-
-  @Test
-  public void list_active_reports() throws Exception {
-    AnalysisReportDto report = AnalysisReportDto
-      .newForTests(1L)
-      .setProjectKey("project-key")
-      .setStatus(PENDING)
-      .setUuid("PROJECT_UUID")
-      .setCreatedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime())
-      .setStartedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime())
-      .setFinishedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime());
-    List<AnalysisReportDto> reports = Lists.newArrayList(report);
-    when(queue.all()).thenReturn(reports);
-
-    WsTester.TestRequest request = tester.newGetRequest(ComputationWs.ENDPOINT, "queue");
-    request.execute().assertJson(getClass(), "list_queue_reports.json");
-  }
-
-  @Test
-  public void define() {
-    assertThat(tester.controller(ComputationWs.ENDPOINT).action("queue")).isNotNull();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportActionTest.java
new file mode 100644 (file)
index 0000000..4998ab6
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.ws;
+
+import java.io.InputStream;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.computation.ComputationThreadLauncher;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class SubmitReportActionTest {
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  ComputationThreadLauncher workerLauncher = mock(ComputationThreadLauncher.class);
+  ReportQueue queue = mock(ReportQueue.class);
+  WsTester wsTester;
+  SubmitReportAction sut;
+
+  @Before
+  public void before() {
+    sut = new SubmitReportAction(queue, workerLauncher, userSessionRule);
+    wsTester = new WsTester(new ComputationWs(sut));
+  }
+
+  @Test
+  public void define_metadata() {
+    WebService.Context context = new WebService.Context();
+    WebService.NewController controller = context.createController("api/computation");
+    sut.define(controller);
+    controller.done();
+
+    WebService.Action action = context.controller("api/computation").action("submit_report");
+    assertThat(action).isNotNull();
+    assertThat(action.params()).hasSize(2);
+  }
+
+  @Test
+  public void add_element_to_queue_and_launch_analysis_task() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+    AnalysisReportDto dto = mock(AnalysisReportDto.class);
+    when(dto.getId()).thenReturn(42L);
+    when(queue.add(any(String.class), any(InputStream.class))).thenReturn(new ReportQueue.Item(dto, null));
+
+    WsTester.TestRequest request = wsTester
+      .newGetRequest(ComputationWs.ENDPOINT, "submit_report")
+      .setParam(SubmitReportAction.PARAM_PROJECT_KEY, "P1")
+      .setParam(SubmitReportAction.PARAM_REPORT_DATA, null);
+    WsTester.Result response = request.execute();
+
+    verify(queue).add(eq("P1"), any(InputStream.class));
+    verify(workerLauncher).startAnalysisTaskNow();
+    assertThat(response.outputAsString()).isEqualTo("{\"key\":\"42\"}");
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void requires_scan_permission() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.DASHBOARD_SHARING);
+
+    WsTester.TestRequest request = wsTester
+      .newGetRequest(ComputationWs.ENDPOINT, "submit_report")
+      .setParam(SubmitReportAction.PARAM_PROJECT_KEY, "P1")
+      .setParam(SubmitReportAction.PARAM_REPORT_DATA, null);
+    request.execute();
+
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportWsActionTest.java
deleted file mode 100644 (file)
index 95910bc..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import java.io.InputStream;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.computation.ComputationThreadLauncher;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class SubmitReportWsActionTest {
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  ComputationThreadLauncher workerLauncher = mock(ComputationThreadLauncher.class);
-  ReportQueue queue = mock(ReportQueue.class);
-  WsTester wsTester;
-  SubmitReportWsAction sut;
-
-  @Before
-  public void before() {
-    sut = new SubmitReportWsAction(queue, workerLauncher, userSessionRule);
-    wsTester = new WsTester(new ComputationWs(sut));
-  }
-
-  @Test
-  public void define_metadata() {
-    WebService.Context context = new WebService.Context();
-    WebService.NewController controller = context.createController("api/computation");
-    sut.define(controller);
-    controller.done();
-
-    WebService.Action action = context.controller("api/computation").action("submit_report");
-    assertThat(action).isNotNull();
-    assertThat(action.params()).hasSize(2);
-  }
-
-  @Test
-  public void add_element_to_queue_and_launch_analysis_task() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    AnalysisReportDto dto = mock(AnalysisReportDto.class);
-    when(dto.getId()).thenReturn(42L);
-    when(queue.add(any(String.class), any(InputStream.class))).thenReturn(new ReportQueue.Item(dto, null));
-
-    WsTester.TestRequest request = wsTester
-      .newGetRequest(ComputationWs.ENDPOINT, "submit_report")
-      .setParam(SubmitReportWsAction.PARAM_PROJECT_KEY, "P1")
-      .setParam(SubmitReportWsAction.PARAM_REPORT_DATA, null);
-    WsTester.Result response = request.execute();
-
-    verify(queue).add(eq("P1"), any(InputStream.class));
-    verify(workerLauncher).startAnalysisTaskNow();
-    assertThat(response.outputAsString()).isEqualTo("{\"key\":\"42\"}");
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void requires_scan_permission() throws Exception {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.DASHBOARD_SHARING);
-
-    WsTester.TestRequest request = wsTester
-      .newGetRequest(ComputationWs.ENDPOINT, "submit_report")
-      .setParam(SubmitReportWsAction.PARAM_PROJECT_KEY, "P1")
-      .setParam(SubmitReportWsAction.PARAM_REPORT_DATA, null);
-    request.execute();
-
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java
deleted file mode 100644 (file)
index ab039a8..0000000
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.issue.ws;
-
-import com.google.common.collect.Lists;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.DefaultIssueComment;
-import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
-import org.sonar.api.user.User;
-import org.sonar.api.user.UserFinder;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.Duration;
-import org.sonar.api.utils.Durations;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.issue.DefaultActionPlan;
-import org.sonar.core.issue.workflow.Transition;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.user.DefaultUser;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.debt.DebtModelService;
-import org.sonar.server.issue.ActionService;
-import org.sonar.server.issue.IssueChangelog;
-import org.sonar.server.issue.IssueChangelogService;
-import org.sonar.server.issue.IssueCommentService;
-import org.sonar.server.issue.IssueService;
-import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.rule.Rule;
-import org.sonar.server.rule.RuleService;
-import org.sonar.server.source.SourceService;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.user.ThreadLocalUserSession;
-import org.sonar.server.ws.WsTester;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- * TODO Should be replaced by medium tests, as there are too many dependencies
- */
-@RunWith(MockitoJUnitRunner.class)
-public class IssueShowActionTest {
-
-  @org.junit.Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  @Mock
-  DbClient dbClient;
-
-  @Mock
-  DbSession session;
-
-  @Mock
-  ComponentDao componentDao;
-
-  @Mock
-  IssueService issueService;
-
-  @Mock
-  IssueChangelogService issueChangelogService;
-
-  @Mock
-  IssueCommentService commentService;
-
-  @Mock
-  ActionPlanService actionPlanService;
-
-  @Mock
-  ActionService actionService;
-
-  @Mock
-  UserFinder userFinder;
-
-  @Mock
-  DebtModelService debtModel;
-
-  @Mock
-  RuleService ruleService;
-
-  @Mock
-  I18n i18n;
-
-  @Mock
-  Durations durations;
-
-  @Mock
-  SourceService sourceService;
-
-  Date issueCreationDate;
-
-  Rule rule;
-
-  WsTester tester;
-
-  @Before
-  public void setUp() {
-    when(dbClient.openSession(false)).thenReturn(session);
-    when(dbClient.componentDao()).thenReturn(componentDao);
-
-    rule = mock(Rule.class);
-    when(rule.key()).thenReturn(RuleKey.of("squid", "AvoidCycle"));
-    when(rule.name()).thenReturn("Avoid cycle");
-    when(ruleService.getNonNullByKey(rule.key())).thenReturn(rule);
-
-    when(issueChangelogService.changelog(any(Issue.class))).thenReturn(mock(IssueChangelog.class));
-
-    issueCreationDate = DateUtils.parseDateTime("2014-01-22T19:10:03+0100");
-    when(i18n.formatDateTime(any(Locale.class), eq(issueCreationDate))).thenReturn("Jan 22, 2014 10:03 AM");
-
-    when(i18n.message(any(Locale.class), eq("created"), eq((String) null))).thenReturn("Created");
-
-    tester = new WsTester(new IssuesWs(
-      new IssueShowAction(
-          dbClient, issueService, issueChangelogService, commentService,
-          new IssueActionsWriter(issueService, actionService, userSessionRule),
-          actionPlanService, userFinder, debtModel, ruleService, i18n, durations, userSessionRule)
-      ));
-  }
-
-  @Test
-  public void show_issue() throws Exception {
-    String issueKey = "ABCD";
-
-    ComponentDto project = ComponentTesting.newProjectDto()
-      .setId(1L)
-      .setKey("org.sonar.Sonar")
-      .setLongName("SonarQube")
-      .setName("SonarQube");
-    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
-
-    ComponentDto file = ComponentTesting.newFileDto(project)
-      .setId(10L)
-      .setKey("org.sonar.server.issue.IssueClient")
-      .setLongName("SonarQube :: Issue Client")
-      .setName("SonarQube :: Issue Client")
-      .setQualifier("FIL")
-      .setParentProjectId(1L);
-    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
-
-    DefaultIssue issue = new DefaultIssue()
-      .setKey(issueKey)
-      .setComponentKey("org.sonar.server.issue.IssueClient")
-      .setComponentUuid(file.uuid())
-      .setProjectKey("org.sonar.Sonar")
-      .setProjectUuid(project.uuid())
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
-      .setLine(12)
-      .setMessage("Fix it")
-      .setResolution("FIXED")
-      .setStatus("CLOSED")
-      .setSeverity("MAJOR")
-      .setCreationDate(issueCreationDate);
-    when(issueService.getByKey(issueKey)).thenReturn(issue);
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey);
-    request.execute().assertJson(getClass(), "show_issue.json");
-  }
-
-  @Test
-  public void show_issue_with_sub_project() throws Exception {
-    String issueKey = "ABCD";
-
-    // Project
-    ComponentDto project = ComponentTesting.newProjectDto()
-      .setId(1L)
-      .setKey("org.sonar.Sonar")
-      .setLongName("SonarQube");
-    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
-
-    // Module
-    ComponentDto module = ComponentTesting.newModuleDto(project)
-      .setId(2L)
-      .setKey("org.sonar.server.Server")
-      .setLongName("SonarQube :: Server")
-      .setQualifier("BRC")
-      .setParentProjectId(1L);
-    when(componentDao.selectNullableById(module.getId(), session)).thenReturn(module);
-
-    // File
-    ComponentDto file = ComponentTesting.newFileDto(module)
-      .setId(10L)
-      .setKey("org.sonar.server.issue.IssueClient")
-      .setLongName("SonarQube :: Issue Client")
-      .setQualifier("FIL")
-      .setParentProjectId(2L);
-    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
-
-    DefaultIssue issue = new DefaultIssue()
-      .setKey(issueKey)
-      .setComponentKey("org.sonar.server.issue.IssueClient")
-      .setComponentUuid(file.uuid())
-      .setProjectKey("org.sonar.Sonar")
-      .setProjectUuid(project.uuid())
-      .setModuleUuid(module.uuid())
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
-      .setLine(12)
-      .setMessage("Fix it")
-      .setResolution("FIXED")
-      .setStatus("CLOSED")
-      .setSeverity("MAJOR")
-      .setCreationDate(issueCreationDate);
-    when(issueService.getByKey(issueKey)).thenReturn(issue);
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey);
-    request.execute().assertJson(getClass(), "show_issue_with_sub_project.json");
-  }
-
-  @Test
-  public void use_project_and_sub_project_names_if_no_long_name() throws Exception {
-    String issueKey = "ABCD";
-
-    // Project
-    ComponentDto project = ComponentTesting.newProjectDto()
-      .setId(1L)
-      .setKey("org.sonar.Sonar")
-      .setName("SonarQube")
-      .setLongName(null);
-    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
-
-    // Module
-    ComponentDto module = ComponentTesting.newModuleDto(project)
-      .setId(2L)
-      .setKey("org.sonar.server.Server")
-      .setName("SonarQube :: Server")
-      .setLongName(null)
-      .setQualifier("BRC")
-      .setParentProjectId(1L);
-    when(componentDao.selectNullableById(module.getId(), session)).thenReturn(module);
-
-    // File
-    ComponentDto file = ComponentTesting.newFileDto(module)
-      .setId(10L)
-      .setKey("org.sonar.server.issue.IssueClient")
-      .setLongName("SonarQube :: Issue Client")
-      .setQualifier("FIL")
-      .setParentProjectId(2L);
-    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
-
-    DefaultIssue issue = new DefaultIssue()
-      .setKey(issueKey)
-      .setComponentKey("org.sonar.server.issue.IssueClient")
-      .setComponentUuid(file.uuid())
-      .setProjectKey("org.sonar.Sonar")
-      .setProjectUuid(project.uuid())
-      .setModuleUuid(module.uuid())
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
-      .setLine(12)
-      .setEffortToFix(2.0)
-      .setMessage("Fix it")
-      .setResolution("FIXED")
-      .setStatus("CLOSED")
-      .setSeverity("MAJOR")
-      .setCreationDate(issueCreationDate);
-    when(issueService.getByKey(issueKey)).thenReturn(issue);
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey);
-    request.execute().assertJson(getClass(), "show_issue_with_sub_project.json");
-  }
-
-  @Test
-  public void show_issue_on_removed_component() throws Exception {
-    String issueKey = "ABCD";
-
-    ComponentDto project = ComponentTesting.newProjectDto()
-      .setId(1L)
-      .setKey("org.sonar.Sonar")
-      .setLongName("SonarQube")
-      .setName("SonarQube");
-    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
-
-    ComponentDto file = ComponentTesting.newFileDto(project)
-      .setId(10L)
-      .setEnabled(false)
-      .setKey("org.sonar.server.issue.IssueClient")
-      .setLongName("SonarQube :: Issue Client")
-      .setName("SonarQube :: Issue Client")
-      .setQualifier("FIL")
-      .setParentProjectId(1L);
-    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
-
-    DefaultIssue issue = createIssue()
-      .setComponentUuid(file.uuid())
-      .setProjectUuid(project.uuid());
-    when(issueService.getByKey(issueKey)).thenReturn(issue);
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey);
-    request.execute().assertJson(getClass(), "show_issue_on_removed_component.json");
-  }
-
-  @Test
-  public void show_issue_with_action_plan() throws Exception {
-    DefaultIssue issue = createStandardIssue()
-      .setActionPlanKey("AP-ABCD");
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    when(actionPlanService.findByKey(eq(issue.actionPlanKey()), any(ThreadLocalUserSession.class))).thenReturn(new DefaultActionPlan().setKey("AP-ABCD").setName("Version 4.2"));
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_action_plan.json");
-  }
-
-  @Test
-  public void show_issue_with_users() throws Exception {
-    DefaultIssue issue = createStandardIssue()
-      .setAssignee("john")
-      .setReporter("steven")
-      .setAuthorLogin("Henry");
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    when(userFinder.findByLogin("john")).thenReturn(new DefaultUser().setLogin("john").setName("John"));
-    when(userFinder.findByLogin("steven")).thenReturn(new DefaultUser().setLogin("steven").setName("Steven"));
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_users.json");
-  }
-
-  @Test
-  public void show_issue_with_technical_debt() throws Exception {
-    Duration debt = (Duration.create(7260L));
-    DefaultIssue issue = createStandardIssue().setDebt(debt);
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    when(durations.encode(debt)).thenReturn("2h1min");
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_technical_debt.json");
-  }
-
-  @Test
-  public void show_issue_with_user_characteristics() throws Exception {
-    DefaultIssue issue = createStandardIssue().setDebt(Duration.create(7260L));
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    when(rule.debtCharacteristicKey()).thenReturn("K2");
-    when(debtModel.characteristicById(1)).thenReturn(new DefaultDebtCharacteristic().setKey("K1").setId(1).setName("Maintainability"));
-    when(debtModel.characteristicById(2)).thenReturn(new DefaultDebtCharacteristic().setKey("K2").setId(2).setName("Readability").setParentId(1));
-    when(debtModel.characteristicByKey("K2")).thenReturn(new DefaultDebtCharacteristic().setKey("K2").setId(2).setName("Readability").setParentId(1));
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_characteristics.json");
-  }
-
-  @Test
-  public void show_issue_with_default_characteristics() throws Exception {
-    DefaultIssue issue = createStandardIssue().setDebt(Duration.create(7260L));
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    when(rule.debtCharacteristicKey()).thenReturn("K2");
-    when(debtModel.characteristicById(1)).thenReturn(new DefaultDebtCharacteristic().setKey("K1").setId(1).setName("Maintainability"));
-    when(debtModel.characteristicById(2)).thenReturn(new DefaultDebtCharacteristic().setKey("K2").setId(2).setName("Readability").setParentId(1));
-    when(debtModel.characteristicByKey("K2")).thenReturn(new DefaultDebtCharacteristic().setKey("K2").setId(2).setName("Readability").setParentId(1));
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_characteristics.json");
-  }
-
-  @Test
-  public void show_issue_with_dates() throws Exception {
-    Date creationDate = DateUtils.parseDateTime("2014-01-22T19:10:03+0100");
-    Date updateDate = DateUtils.parseDateTime("2014-01-23T19:10:03+0100");
-    Date closedDate = DateUtils.parseDateTime("2014-01-24T19:10:03+0100");
-
-    DefaultIssue issue = createStandardIssue()
-      .setCreationDate(creationDate)
-      .setUpdateDate(updateDate)
-      .setCloseDate(closedDate);
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    when(i18n.formatDateTime(any(Locale.class), eq(creationDate))).thenReturn("Jan 22, 2014 10:03 AM");
-    when(i18n.formatDateTime(any(Locale.class), eq(updateDate))).thenReturn("Jan 23, 2014 10:03 AM");
-    when(i18n.ageFromNow(any(Locale.class), eq(updateDate))).thenReturn("9 days");
-    when(i18n.formatDateTime(any(Locale.class), eq(closedDate))).thenReturn("Jan 24, 2014 10:03 AM");
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_dates.json");
-  }
-
-  @Test
-  public void show_issue_with_comments() throws Exception {
-    Date date1 = DateUtils.parseDateTime("2014-02-22T19:10:03+0100");
-    Date date2 = DateUtils.parseDateTime("2014-02-23T19:10:03+0100");
-
-    DefaultIssue issue = createStandardIssue();
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    when(commentService.findComments(issue.key())).thenReturn(newArrayList(
-      new DefaultIssueComment()
-        .setKey("COMMENT-ABCD")
-        .setMarkdownText("*My comment*")
-        .setUserLogin("john")
-        .setCreatedAt(date1),
-      new DefaultIssueComment()
-        .setKey("COMMENT-ABCE")
-        .setMarkdownText("Another comment")
-        .setUserLogin("arthur")
-        .setCreatedAt(date2)
-      ));
-
-    when(userFinder.findByLogin("john")).thenReturn(new DefaultUser().setLogin("john").setName("John"));
-    when(userFinder.findByLogin("arthur")).thenReturn(new DefaultUser().setLogin("arthur").setName("Arthur"));
-
-    when(i18n.ageFromNow(any(Locale.class), eq(date1))).thenReturn("9 days");
-    when(i18n.ageFromNow(any(Locale.class), eq(date2))).thenReturn("10 days");
-
-    userSessionRule.login("arthur");
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_comments.json");
-  }
-
-  @Test
-  public void show_issue_with_transitions() throws Exception {
-    DefaultIssue issue = createStandardIssue()
-      .setStatus("RESOLVED")
-      .setResolution("FIXED");
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    when(issueService.listTransitions(eq(issue))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
-
-    userSessionRule.login("john");
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_transitions.json");
-  }
-
-  @Test
-  public void show_issue_with_actions() throws Exception {
-    DefaultIssue issue = createStandardIssue()
-      .setStatus("OPEN");
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    userSessionRule.login("john");
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_actions.json");
-  }
-
-  @Test
-  public void show_issue_with_changelog() throws Exception {
-    DefaultIssue issue = createStandardIssue();
-    when(issueService.getByKey(issue.key())).thenReturn(issue);
-
-    Date date1 = DateUtils.parseDateTime("2014-02-22T19:10:03+0100");
-    Date date2 = DateUtils.parseDateTime("2014-02-23T19:10:03+0100");
-
-    List<User> users = Lists.<User>newArrayList(new DefaultUser().setLogin("john").setName("John"));
-    FieldDiffs userChange = new FieldDiffs()
-      .setUserLogin("john")
-      .setDiff("actionPlan", null, "1.0")
-      .setCreationDate(date1);
-    FieldDiffs scanChange = new FieldDiffs()
-      .setDiff("severity", "INFO", "BLOCKER")
-      .setDiff("status", "REOPEN", "RESOLVED")
-      .setCreationDate(date2);
-    when(issueChangelogService.changelog(issue)).thenReturn(new IssueChangelog(newArrayList(userChange, scanChange), users));
-    when(issueChangelogService.formatDiffs(userChange)).thenReturn(newArrayList("Action plan updated to 1.0"));
-    when(issueChangelogService.formatDiffs(scanChange)).thenReturn(newArrayList("Severity updated from Info to Blocker", "Status updated from Reopen to Resolved"));
-
-    when(i18n.formatDateTime(any(Locale.class), eq(date1))).thenReturn("Fev 22, 2014 10:03 AM");
-    when(i18n.formatDateTime(any(Locale.class), eq(date2))).thenReturn("Fev 23, 2014 10:03 AM");
-
-    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
-    request.execute().assertJson(getClass(), "show_issue_with_changelog.json");
-  }
-
-  private DefaultIssue createStandardIssue() {
-    ComponentDto project = ComponentTesting.newProjectDto()
-      .setId(1L)
-      .setKey("org.sonar.Sonar")
-      .setLongName("SonarQube")
-      .setName("SonarQube");
-    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
-
-    ComponentDto file = ComponentTesting.newFileDto(project)
-      .setId(10L)
-      .setKey("org.sonar.server.issue.IssueClient")
-      .setLongName("SonarQube :: Issue Client")
-      .setName("SonarQube :: Issue Client")
-      .setQualifier("FIL")
-      .setParentProjectId(1L);
-    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
-
-    return createIssue()
-      .setComponentUuid(file.uuid())
-      .setProjectUuid(project.uuid());
-  }
-
-  private DefaultIssue createIssue() {
-    return new DefaultIssue()
-      .setKey("ABCD")
-      .setComponentKey("org.sonar.server.issue.IssueClient")
-      .setProjectKey("org.sonar.Sonar")
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
-      .setCreationDate(issueCreationDate);
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/ShowActionTest.java
new file mode 100644 (file)
index 0000000..61e7a76
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.issue.ws;
+
+import com.google.common.collect.Lists;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.issue.internal.DefaultIssueComment;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
+import org.sonar.api.user.User;
+import org.sonar.api.user.UserFinder;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.Duration;
+import org.sonar.api.utils.Durations;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.DefaultActionPlan;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.user.DefaultUser;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.debt.DebtModelService;
+import org.sonar.server.issue.ActionService;
+import org.sonar.server.issue.IssueChangelog;
+import org.sonar.server.issue.IssueChangelogService;
+import org.sonar.server.issue.IssueCommentService;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.rule.Rule;
+import org.sonar.server.rule.RuleService;
+import org.sonar.server.source.SourceService;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.user.ThreadLocalUserSession;
+import org.sonar.server.ws.WsTester;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * TODO Should be replaced by medium tests, as there are too many dependencies
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ShowActionTest {
+
+  @org.junit.Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  @Mock
+  DbClient dbClient;
+
+  @Mock
+  DbSession session;
+
+  @Mock
+  ComponentDao componentDao;
+
+  @Mock
+  IssueService issueService;
+
+  @Mock
+  IssueChangelogService issueChangelogService;
+
+  @Mock
+  IssueCommentService commentService;
+
+  @Mock
+  ActionPlanService actionPlanService;
+
+  @Mock
+  ActionService actionService;
+
+  @Mock
+  UserFinder userFinder;
+
+  @Mock
+  DebtModelService debtModel;
+
+  @Mock
+  RuleService ruleService;
+
+  @Mock
+  I18n i18n;
+
+  @Mock
+  Durations durations;
+
+  @Mock
+  SourceService sourceService;
+
+  Date issueCreationDate;
+
+  Rule rule;
+
+  WsTester tester;
+
+  @Before
+  public void setUp() {
+    when(dbClient.openSession(false)).thenReturn(session);
+    when(dbClient.componentDao()).thenReturn(componentDao);
+
+    rule = mock(Rule.class);
+    when(rule.key()).thenReturn(RuleKey.of("squid", "AvoidCycle"));
+    when(rule.name()).thenReturn("Avoid cycle");
+    when(ruleService.getNonNullByKey(rule.key())).thenReturn(rule);
+
+    when(issueChangelogService.changelog(any(Issue.class))).thenReturn(mock(IssueChangelog.class));
+
+    issueCreationDate = DateUtils.parseDateTime("2014-01-22T19:10:03+0100");
+    when(i18n.formatDateTime(any(Locale.class), eq(issueCreationDate))).thenReturn("Jan 22, 2014 10:03 AM");
+
+    when(i18n.message(any(Locale.class), eq("created"), eq((String) null))).thenReturn("Created");
+
+    tester = new WsTester(new IssuesWs(
+      new ShowAction(
+          dbClient, issueService, issueChangelogService, commentService,
+          new IssueActionsWriter(issueService, actionService, userSessionRule),
+          actionPlanService, userFinder, debtModel, ruleService, i18n, durations, userSessionRule)
+      ));
+  }
+
+  @Test
+  public void show_issue() throws Exception {
+    String issueKey = "ABCD";
+
+    ComponentDto project = ComponentTesting.newProjectDto()
+      .setId(1L)
+      .setKey("org.sonar.Sonar")
+      .setLongName("SonarQube")
+      .setName("SonarQube");
+    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
+
+    ComponentDto file = ComponentTesting.newFileDto(project)
+      .setId(10L)
+      .setKey("org.sonar.server.issue.IssueClient")
+      .setLongName("SonarQube :: Issue Client")
+      .setName("SonarQube :: Issue Client")
+      .setQualifier("FIL")
+      .setParentProjectId(1L);
+    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
+
+    DefaultIssue issue = new DefaultIssue()
+      .setKey(issueKey)
+      .setComponentKey("org.sonar.server.issue.IssueClient")
+      .setComponentUuid(file.uuid())
+      .setProjectKey("org.sonar.Sonar")
+      .setProjectUuid(project.uuid())
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
+      .setLine(12)
+      .setMessage("Fix it")
+      .setResolution("FIXED")
+      .setStatus("CLOSED")
+      .setSeverity("MAJOR")
+      .setCreationDate(issueCreationDate);
+    when(issueService.getByKey(issueKey)).thenReturn(issue);
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey);
+    request.execute().assertJson(getClass(), "show_issue.json");
+  }
+
+  @Test
+  public void show_issue_with_sub_project() throws Exception {
+    String issueKey = "ABCD";
+
+    // Project
+    ComponentDto project = ComponentTesting.newProjectDto()
+      .setId(1L)
+      .setKey("org.sonar.Sonar")
+      .setLongName("SonarQube");
+    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
+
+    // Module
+    ComponentDto module = ComponentTesting.newModuleDto(project)
+      .setId(2L)
+      .setKey("org.sonar.server.Server")
+      .setLongName("SonarQube :: Server")
+      .setQualifier("BRC")
+      .setParentProjectId(1L);
+    when(componentDao.selectNullableById(module.getId(), session)).thenReturn(module);
+
+    // File
+    ComponentDto file = ComponentTesting.newFileDto(module)
+      .setId(10L)
+      .setKey("org.sonar.server.issue.IssueClient")
+      .setLongName("SonarQube :: Issue Client")
+      .setQualifier("FIL")
+      .setParentProjectId(2L);
+    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
+
+    DefaultIssue issue = new DefaultIssue()
+      .setKey(issueKey)
+      .setComponentKey("org.sonar.server.issue.IssueClient")
+      .setComponentUuid(file.uuid())
+      .setProjectKey("org.sonar.Sonar")
+      .setProjectUuid(project.uuid())
+      .setModuleUuid(module.uuid())
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
+      .setLine(12)
+      .setMessage("Fix it")
+      .setResolution("FIXED")
+      .setStatus("CLOSED")
+      .setSeverity("MAJOR")
+      .setCreationDate(issueCreationDate);
+    when(issueService.getByKey(issueKey)).thenReturn(issue);
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey);
+    request.execute().assertJson(getClass(), "show_issue_with_sub_project.json");
+  }
+
+  @Test
+  public void use_project_and_sub_project_names_if_no_long_name() throws Exception {
+    String issueKey = "ABCD";
+
+    // Project
+    ComponentDto project = ComponentTesting.newProjectDto()
+      .setId(1L)
+      .setKey("org.sonar.Sonar")
+      .setName("SonarQube")
+      .setLongName(null);
+    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
+
+    // Module
+    ComponentDto module = ComponentTesting.newModuleDto(project)
+      .setId(2L)
+      .setKey("org.sonar.server.Server")
+      .setName("SonarQube :: Server")
+      .setLongName(null)
+      .setQualifier("BRC")
+      .setParentProjectId(1L);
+    when(componentDao.selectNullableById(module.getId(), session)).thenReturn(module);
+
+    // File
+    ComponentDto file = ComponentTesting.newFileDto(module)
+      .setId(10L)
+      .setKey("org.sonar.server.issue.IssueClient")
+      .setLongName("SonarQube :: Issue Client")
+      .setQualifier("FIL")
+      .setParentProjectId(2L);
+    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
+
+    DefaultIssue issue = new DefaultIssue()
+      .setKey(issueKey)
+      .setComponentKey("org.sonar.server.issue.IssueClient")
+      .setComponentUuid(file.uuid())
+      .setProjectKey("org.sonar.Sonar")
+      .setProjectUuid(project.uuid())
+      .setModuleUuid(module.uuid())
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
+      .setLine(12)
+      .setEffortToFix(2.0)
+      .setMessage("Fix it")
+      .setResolution("FIXED")
+      .setStatus("CLOSED")
+      .setSeverity("MAJOR")
+      .setCreationDate(issueCreationDate);
+    when(issueService.getByKey(issueKey)).thenReturn(issue);
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey);
+    request.execute().assertJson(getClass(), "show_issue_with_sub_project.json");
+  }
+
+  @Test
+  public void show_issue_on_removed_component() throws Exception {
+    String issueKey = "ABCD";
+
+    ComponentDto project = ComponentTesting.newProjectDto()
+      .setId(1L)
+      .setKey("org.sonar.Sonar")
+      .setLongName("SonarQube")
+      .setName("SonarQube");
+    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
+
+    ComponentDto file = ComponentTesting.newFileDto(project)
+      .setId(10L)
+      .setEnabled(false)
+      .setKey("org.sonar.server.issue.IssueClient")
+      .setLongName("SonarQube :: Issue Client")
+      .setName("SonarQube :: Issue Client")
+      .setQualifier("FIL")
+      .setParentProjectId(1L);
+    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
+
+    DefaultIssue issue = createIssue()
+      .setComponentUuid(file.uuid())
+      .setProjectUuid(project.uuid());
+    when(issueService.getByKey(issueKey)).thenReturn(issue);
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey);
+    request.execute().assertJson(getClass(), "show_issue_on_removed_component.json");
+  }
+
+  @Test
+  public void show_issue_with_action_plan() throws Exception {
+    DefaultIssue issue = createStandardIssue()
+      .setActionPlanKey("AP-ABCD");
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    when(actionPlanService.findByKey(eq(issue.actionPlanKey()), any(ThreadLocalUserSession.class))).thenReturn(new DefaultActionPlan().setKey("AP-ABCD").setName("Version 4.2"));
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_action_plan.json");
+  }
+
+  @Test
+  public void show_issue_with_users() throws Exception {
+    DefaultIssue issue = createStandardIssue()
+      .setAssignee("john")
+      .setReporter("steven")
+      .setAuthorLogin("Henry");
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    when(userFinder.findByLogin("john")).thenReturn(new DefaultUser().setLogin("john").setName("John"));
+    when(userFinder.findByLogin("steven")).thenReturn(new DefaultUser().setLogin("steven").setName("Steven"));
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_users.json");
+  }
+
+  @Test
+  public void show_issue_with_technical_debt() throws Exception {
+    Duration debt = (Duration.create(7260L));
+    DefaultIssue issue = createStandardIssue().setDebt(debt);
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    when(durations.encode(debt)).thenReturn("2h1min");
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_technical_debt.json");
+  }
+
+  @Test
+  public void show_issue_with_user_characteristics() throws Exception {
+    DefaultIssue issue = createStandardIssue().setDebt(Duration.create(7260L));
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    when(rule.debtCharacteristicKey()).thenReturn("K2");
+    when(debtModel.characteristicById(1)).thenReturn(new DefaultDebtCharacteristic().setKey("K1").setId(1).setName("Maintainability"));
+    when(debtModel.characteristicById(2)).thenReturn(new DefaultDebtCharacteristic().setKey("K2").setId(2).setName("Readability").setParentId(1));
+    when(debtModel.characteristicByKey("K2")).thenReturn(new DefaultDebtCharacteristic().setKey("K2").setId(2).setName("Readability").setParentId(1));
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_characteristics.json");
+  }
+
+  @Test
+  public void show_issue_with_default_characteristics() throws Exception {
+    DefaultIssue issue = createStandardIssue().setDebt(Duration.create(7260L));
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    when(rule.debtCharacteristicKey()).thenReturn("K2");
+    when(debtModel.characteristicById(1)).thenReturn(new DefaultDebtCharacteristic().setKey("K1").setId(1).setName("Maintainability"));
+    when(debtModel.characteristicById(2)).thenReturn(new DefaultDebtCharacteristic().setKey("K2").setId(2).setName("Readability").setParentId(1));
+    when(debtModel.characteristicByKey("K2")).thenReturn(new DefaultDebtCharacteristic().setKey("K2").setId(2).setName("Readability").setParentId(1));
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_characteristics.json");
+  }
+
+  @Test
+  public void show_issue_with_dates() throws Exception {
+    Date creationDate = DateUtils.parseDateTime("2014-01-22T19:10:03+0100");
+    Date updateDate = DateUtils.parseDateTime("2014-01-23T19:10:03+0100");
+    Date closedDate = DateUtils.parseDateTime("2014-01-24T19:10:03+0100");
+
+    DefaultIssue issue = createStandardIssue()
+      .setCreationDate(creationDate)
+      .setUpdateDate(updateDate)
+      .setCloseDate(closedDate);
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    when(i18n.formatDateTime(any(Locale.class), eq(creationDate))).thenReturn("Jan 22, 2014 10:03 AM");
+    when(i18n.formatDateTime(any(Locale.class), eq(updateDate))).thenReturn("Jan 23, 2014 10:03 AM");
+    when(i18n.ageFromNow(any(Locale.class), eq(updateDate))).thenReturn("9 days");
+    when(i18n.formatDateTime(any(Locale.class), eq(closedDate))).thenReturn("Jan 24, 2014 10:03 AM");
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_dates.json");
+  }
+
+  @Test
+  public void show_issue_with_comments() throws Exception {
+    Date date1 = DateUtils.parseDateTime("2014-02-22T19:10:03+0100");
+    Date date2 = DateUtils.parseDateTime("2014-02-23T19:10:03+0100");
+
+    DefaultIssue issue = createStandardIssue();
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    when(commentService.findComments(issue.key())).thenReturn(newArrayList(
+      new DefaultIssueComment()
+        .setKey("COMMENT-ABCD")
+        .setMarkdownText("*My comment*")
+        .setUserLogin("john")
+        .setCreatedAt(date1),
+      new DefaultIssueComment()
+        .setKey("COMMENT-ABCE")
+        .setMarkdownText("Another comment")
+        .setUserLogin("arthur")
+        .setCreatedAt(date2)
+      ));
+
+    when(userFinder.findByLogin("john")).thenReturn(new DefaultUser().setLogin("john").setName("John"));
+    when(userFinder.findByLogin("arthur")).thenReturn(new DefaultUser().setLogin("arthur").setName("Arthur"));
+
+    when(i18n.ageFromNow(any(Locale.class), eq(date1))).thenReturn("9 days");
+    when(i18n.ageFromNow(any(Locale.class), eq(date2))).thenReturn("10 days");
+
+    userSessionRule.login("arthur");
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_comments.json");
+  }
+
+  @Test
+  public void show_issue_with_transitions() throws Exception {
+    DefaultIssue issue = createStandardIssue()
+      .setStatus("RESOLVED")
+      .setResolution("FIXED");
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    when(issueService.listTransitions(eq(issue))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
+
+    userSessionRule.login("john");
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_transitions.json");
+  }
+
+  @Test
+  public void show_issue_with_actions() throws Exception {
+    DefaultIssue issue = createStandardIssue()
+      .setStatus("OPEN");
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    userSessionRule.login("john");
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_actions.json");
+  }
+
+  @Test
+  public void show_issue_with_changelog() throws Exception {
+    DefaultIssue issue = createStandardIssue();
+    when(issueService.getByKey(issue.key())).thenReturn(issue);
+
+    Date date1 = DateUtils.parseDateTime("2014-02-22T19:10:03+0100");
+    Date date2 = DateUtils.parseDateTime("2014-02-23T19:10:03+0100");
+
+    List<User> users = Lists.<User>newArrayList(new DefaultUser().setLogin("john").setName("John"));
+    FieldDiffs userChange = new FieldDiffs()
+      .setUserLogin("john")
+      .setDiff("actionPlan", null, "1.0")
+      .setCreationDate(date1);
+    FieldDiffs scanChange = new FieldDiffs()
+      .setDiff("severity", "INFO", "BLOCKER")
+      .setDiff("status", "REOPEN", "RESOLVED")
+      .setCreationDate(date2);
+    when(issueChangelogService.changelog(issue)).thenReturn(new IssueChangelog(newArrayList(userChange, scanChange), users));
+    when(issueChangelogService.formatDiffs(userChange)).thenReturn(newArrayList("Action plan updated to 1.0"));
+    when(issueChangelogService.formatDiffs(scanChange)).thenReturn(newArrayList("Severity updated from Info to Blocker", "Status updated from Reopen to Resolved"));
+
+    when(i18n.formatDateTime(any(Locale.class), eq(date1))).thenReturn("Fev 22, 2014 10:03 AM");
+    when(i18n.formatDateTime(any(Locale.class), eq(date2))).thenReturn("Fev 23, 2014 10:03 AM");
+
+    WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
+    request.execute().assertJson(getClass(), "show_issue_with_changelog.json");
+  }
+
+  private DefaultIssue createStandardIssue() {
+    ComponentDto project = ComponentTesting.newProjectDto()
+      .setId(1L)
+      .setKey("org.sonar.Sonar")
+      .setLongName("SonarQube")
+      .setName("SonarQube");
+    when(componentDao.selectByUuid(session, project.uuid())).thenReturn(project);
+
+    ComponentDto file = ComponentTesting.newFileDto(project)
+      .setId(10L)
+      .setKey("org.sonar.server.issue.IssueClient")
+      .setLongName("SonarQube :: Issue Client")
+      .setName("SonarQube :: Issue Client")
+      .setQualifier("FIL")
+      .setParentProjectId(1L);
+    when(componentDao.selectByUuid(session, file.uuid())).thenReturn(file);
+
+    return createIssue()
+      .setComponentUuid(file.uuid())
+      .setProjectUuid(project.uuid());
+  }
+
+  private DefaultIssue createIssue() {
+    return new DefaultIssue()
+      .setKey("ABCD")
+      .setComponentKey("org.sonar.server.issue.IssueClient")
+      .setProjectKey("org.sonar.Sonar")
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
+      .setCreationDate(issueCreationDate);
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java
new file mode 100644 (file)
index 0000000..74cf84b
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.platform.ws;
+
+import java.util.LinkedHashMap;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.internal.SimpleGetRequest;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.platform.monitoring.Monitor;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class InfoActionTest {
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone().login("login")
+      .setName("name");
+
+  Monitor monitor1 = mock(Monitor.class);
+  Monitor monitor2 = mock(Monitor.class);
+  InfoAction sut = new InfoAction(userSessionRule, monitor1, monitor2);
+
+  @Test(expected = ForbiddenException.class)
+  public void should_fail_when_does_not_have_admin_right() {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+
+    sut.handle(mock(Request.class), mock(Response.class));
+  }
+
+  @Test
+  public void write_json() {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    LinkedHashMap<String, Object> attributes1 = new LinkedHashMap<>();
+    attributes1.put("foo", "bar");
+    LinkedHashMap<String, Object> attributes2 = new LinkedHashMap<>();
+    attributes2.put("one", 1);
+    attributes2.put("two", 2);
+    when(monitor1.name()).thenReturn("Monitor One");
+    when(monitor1.attributes()).thenReturn(attributes1);
+    when(monitor2.name()).thenReturn("Monitor Two");
+    when(monitor2.attributes()).thenReturn(attributes2);
+
+    WsTester.TestResponse response = new WsTester.TestResponse();
+    sut.handle(new SimpleGetRequest(), response);
+    assertThat(response.outputAsString()).isEqualTo("{\"Monitor One\":{\"foo\":\"bar\"},\"Monitor Two\":{\"one\":1,\"two\":2}}");
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbSystemActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbSystemActionTest.java
new file mode 100644 (file)
index 0000000..8cbee38
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
+import java.util.Date;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.persistence.Database;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.dialect.Dialect;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.db.migrations.DatabaseMigration.Status;
+import org.sonar.server.ws.WsTester;
+
+import static com.google.common.base.Predicates.in;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.Iterables.filter;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.sonar.server.db.migrations.DatabaseMigration.Status.FAILED;
+import static org.sonar.server.db.migrations.DatabaseMigration.Status.NONE;
+import static org.sonar.server.db.migrations.DatabaseMigration.Status.RUNNING;
+import static org.sonar.server.db.migrations.DatabaseMigration.Status.SUCCEEDED;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class MigrateDbSystemActionTest {
+
+  private static final String UPTODATE_MSG = "Database is up-to-date, no migration needed.";
+  private static final String MIG_NOT_SUPPORTED_MSG = "Upgrade is not supported on embedded database.";
+  private static final String RUNNING_MSG = "Database migration is running.";
+  private static final Date SOME_DATE = new Date();
+  private static final String SOME_THROWABLE_MSG = "blablabla pop !";
+  private static final String DEFAULT_ERROR_MSG = "No failure error";
+  private static final String MIG_SUCCESS_MSG = "Migration succeeded.";
+  private static final int CURRENT_VERSION = DatabaseVersion.LAST_VERSION;
+  private static final int OLD_VERSION = CURRENT_VERSION - 1;
+  private static final int NEWER_VERSION = CURRENT_VERSION + 1;
+  private static final String STATUS_NONE = "NO_MIGRATION";
+  private static final String STATUS_NOT_SUPPORTED = "NOT_SUPPORTED";
+  private static final String STATUS_RUNNING = "MIGRATION_RUNNING";
+  private static final String STATUS_SUCCEEDED = "MIGRATION_SUCCEEDED";
+  private static final String STATUS_FAILED = "MIGRATION_FAILED";
+
+  DatabaseVersion databaseVersion = mock(DatabaseVersion.class);
+  Database database = mock(Database.class);
+  Dialect dialect = mock(Dialect.class);
+  DatabaseMigration databaseMigration = mock(DatabaseMigration.class);
+  MigrateDbSystemAction underTest = new MigrateDbSystemAction(databaseVersion, database, databaseMigration);
+
+  Request request = mock(Request.class);
+  WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Before
+  public void wireMocksTogether() {
+    when(database.getDialect()).thenReturn(dialect);
+  }
+
+  @Test(expected = IllegalStateException.class)
+  public void ISE_is_thrown_when_version_can_not_be_retrieved_from_database() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(null);
+
+    underTest.handle(request, response);
+  }
+
+  @Test
+  public void verify_example() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
+    when(dialect.supportsMigration()).thenReturn(true);
+    when(databaseMigration.status()).thenReturn(RUNNING);
+    when(databaseMigration.startedAt()).thenReturn(DateUtils.parseDateTime("2015-02-23T18:54:23+0100"));
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(getClass().getResource("example-migrate_db.json"));
+  }
+
+  @Test
+  public void msg_is_operational_and_state_from_databasemigration_when_databaseversion_is_equal_to_currentversion() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(CURRENT_VERSION);
+    when(databaseMigration.status()).thenReturn(NONE);
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_NONE, UPTODATE_MSG));
+  }
+
+  // this test will raise a IllegalArgumentException when an unsupported value is added to the Status enum
+  @Test
+  public void defensive_test_all_values_of_Status_must_be_supported() throws Exception {
+    for (Status status : filter(Arrays.asList(Status.values()), not(in(ImmutableList.of(NONE, RUNNING, FAILED, SUCCEEDED))))) {
+      when(databaseVersion.getVersion()).thenReturn(CURRENT_VERSION);
+      when(databaseMigration.status()).thenReturn(status);
+
+      underTest.handle(request, response);
+    }
+  }
+
+  @Test
+  public void state_from_databasemigration_when_databaseversion_greater_than_currentversion() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(NEWER_VERSION);
+    when(databaseMigration.status()).thenReturn(NONE);
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_NONE, UPTODATE_MSG));
+  }
+
+  @Test
+  public void state_is_NONE_with_specific_msg_when_version_is_less_than_current_version_and_dialect_does_not_support_migration() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
+    when(dialect.supportsMigration()).thenReturn(false);
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_NOT_SUPPORTED, MIG_NOT_SUPPORTED_MSG));
+  }
+
+  @Test
+  public void state_from_databasemigration_when_dbmigration_status_is_RUNNING() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
+    when(dialect.supportsMigration()).thenReturn(true);
+    when(databaseMigration.status()).thenReturn(RUNNING);
+    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_RUNNING, RUNNING_MSG, SOME_DATE));
+  }
+
+  @Test
+  public void state_from_databasemigration_and_msg_includes_error_when_dbmigration_status_is_FAILED() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
+    when(dialect.supportsMigration()).thenReturn(true);
+    when(databaseMigration.status()).thenReturn(FAILED);
+    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
+    when(databaseMigration.failureError()).thenReturn(new UnsupportedOperationException(SOME_THROWABLE_MSG));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_FAILED, failedMsg(SOME_THROWABLE_MSG), SOME_DATE));
+  }
+
+  @Test
+  public void state_from_databasemigration_and_msg_has_default_msg_when_dbmigration_status_is_FAILED() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
+    when(dialect.supportsMigration()).thenReturn(true);
+    when(databaseMigration.status()).thenReturn(FAILED);
+    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
+    when(databaseMigration.failureError()).thenReturn(null); // no failure throwable caught
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_FAILED, failedMsg(DEFAULT_ERROR_MSG), SOME_DATE));
+  }
+
+  @Test
+  public void state_from_databasemigration_and_msg_has_default_msg_when_dbmigration_status_is_SUCCEEDED() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
+    when(dialect.supportsMigration()).thenReturn(true);
+    when(databaseMigration.status()).thenReturn(SUCCEEDED);
+    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_SUCCEEDED, MIG_SUCCESS_MSG, SOME_DATE));
+  }
+
+  @Test
+  public void start_migration_and_return_state_from_databasemigration_when_dbmigration_status_is_NONE() throws Exception {
+    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
+    when(dialect.supportsMigration()).thenReturn(true);
+    when(databaseMigration.status()).thenReturn(NONE);
+    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
+
+    underTest.handle(request, response);
+
+    verify(databaseMigration).startIt();
+    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_RUNNING, RUNNING_MSG, SOME_DATE));
+  }
+
+  private static String failedMsg(@Nullable String t) {
+    return "Migration failed: " + t + ".<br/> Please check logs.";
+  }
+
+  private static String expectedResponse(String status, String msg) {
+    return "{" +
+      "\"state\":\"" + status + "\"," +
+      "\"message\":\"" + msg + "\"" +
+      "}";
+  }
+
+  private static String expectedResponse(String status, String msg, Date date) {
+    return "{" +
+      "\"state\":\"" + status + "\"," +
+      "\"message\":\"" + msg + "\"," +
+      "\"startedAt\":\"" + DateUtils.formatDateTime(date) + "\"" +
+      "}";
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbSystemWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbSystemWsActionTest.java
deleted file mode 100644 (file)
index 1090640..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.ws;
-
-import com.google.common.collect.ImmutableList;
-import java.util.Arrays;
-import java.util.Date;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.persistence.Database;
-import org.sonar.core.persistence.DatabaseVersion;
-import org.sonar.core.persistence.dialect.Dialect;
-import org.sonar.server.db.migrations.DatabaseMigration;
-import org.sonar.server.db.migrations.DatabaseMigration.Status;
-import org.sonar.server.ws.WsTester;
-
-import static com.google.common.base.Predicates.in;
-import static com.google.common.base.Predicates.not;
-import static com.google.common.collect.Iterables.filter;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.db.migrations.DatabaseMigration.Status.FAILED;
-import static org.sonar.server.db.migrations.DatabaseMigration.Status.NONE;
-import static org.sonar.server.db.migrations.DatabaseMigration.Status.RUNNING;
-import static org.sonar.server.db.migrations.DatabaseMigration.Status.SUCCEEDED;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class MigrateDbSystemWsActionTest {
-
-  private static final String UPTODATE_MSG = "Database is up-to-date, no migration needed.";
-  private static final String MIG_NOT_SUPPORTED_MSG = "Upgrade is not supported on embedded database.";
-  private static final String RUNNING_MSG = "Database migration is running.";
-  private static final Date SOME_DATE = new Date();
-  private static final String SOME_THROWABLE_MSG = "blablabla pop !";
-  private static final String DEFAULT_ERROR_MSG = "No failure error";
-  private static final String MIG_SUCCESS_MSG = "Migration succeeded.";
-  private static final int CURRENT_VERSION = DatabaseVersion.LAST_VERSION;
-  private static final int OLD_VERSION = CURRENT_VERSION - 1;
-  private static final int NEWER_VERSION = CURRENT_VERSION + 1;
-  private static final String STATUS_NONE = "NO_MIGRATION";
-  private static final String STATUS_NOT_SUPPORTED = "NOT_SUPPORTED";
-  private static final String STATUS_RUNNING = "MIGRATION_RUNNING";
-  private static final String STATUS_SUCCEEDED = "MIGRATION_SUCCEEDED";
-  private static final String STATUS_FAILED = "MIGRATION_FAILED";
-
-  DatabaseVersion databaseVersion = mock(DatabaseVersion.class);
-  Database database = mock(Database.class);
-  Dialect dialect = mock(Dialect.class);
-  DatabaseMigration databaseMigration = mock(DatabaseMigration.class);
-  MigrateDbSystemWsAction underTest = new MigrateDbSystemWsAction(databaseVersion, database, databaseMigration);
-
-  Request request = mock(Request.class);
-  WsTester.TestResponse response = new WsTester.TestResponse();
-
-  @Before
-  public void wireMocksTogether() {
-    when(database.getDialect()).thenReturn(dialect);
-  }
-
-  @Test(expected = IllegalStateException.class)
-  public void ISE_is_thrown_when_version_can_not_be_retrieved_from_database() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(null);
-
-    underTest.handle(request, response);
-  }
-
-  @Test
-  public void verify_example() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
-    when(dialect.supportsMigration()).thenReturn(true);
-    when(databaseMigration.status()).thenReturn(RUNNING);
-    when(databaseMigration.startedAt()).thenReturn(DateUtils.parseDateTime("2015-02-23T18:54:23+0100"));
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(getClass().getResource("example-migrate_db.json"));
-  }
-
-  @Test
-  public void msg_is_operational_and_state_from_databasemigration_when_databaseversion_is_equal_to_currentversion() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(CURRENT_VERSION);
-    when(databaseMigration.status()).thenReturn(NONE);
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_NONE, UPTODATE_MSG));
-  }
-
-  // this test will raise a IllegalArgumentException when an unsupported value is added to the Status enum
-  @Test
-  public void defensive_test_all_values_of_Status_must_be_supported() throws Exception {
-    for (Status status : filter(Arrays.asList(Status.values()), not(in(ImmutableList.of(NONE, RUNNING, FAILED, SUCCEEDED))))) {
-      when(databaseVersion.getVersion()).thenReturn(CURRENT_VERSION);
-      when(databaseMigration.status()).thenReturn(status);
-
-      underTest.handle(request, response);
-    }
-  }
-
-  @Test
-  public void state_from_databasemigration_when_databaseversion_greater_than_currentversion() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(NEWER_VERSION);
-    when(databaseMigration.status()).thenReturn(NONE);
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_NONE, UPTODATE_MSG));
-  }
-
-  @Test
-  public void state_is_NONE_with_specific_msg_when_version_is_less_than_current_version_and_dialect_does_not_support_migration() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
-    when(dialect.supportsMigration()).thenReturn(false);
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_NOT_SUPPORTED, MIG_NOT_SUPPORTED_MSG));
-  }
-
-  @Test
-  public void state_from_databasemigration_when_dbmigration_status_is_RUNNING() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
-    when(dialect.supportsMigration()).thenReturn(true);
-    when(databaseMigration.status()).thenReturn(RUNNING);
-    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_RUNNING, RUNNING_MSG, SOME_DATE));
-  }
-
-  @Test
-  public void state_from_databasemigration_and_msg_includes_error_when_dbmigration_status_is_FAILED() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
-    when(dialect.supportsMigration()).thenReturn(true);
-    when(databaseMigration.status()).thenReturn(FAILED);
-    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
-    when(databaseMigration.failureError()).thenReturn(new UnsupportedOperationException(SOME_THROWABLE_MSG));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_FAILED, failedMsg(SOME_THROWABLE_MSG), SOME_DATE));
-  }
-
-  @Test
-  public void state_from_databasemigration_and_msg_has_default_msg_when_dbmigration_status_is_FAILED() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
-    when(dialect.supportsMigration()).thenReturn(true);
-    when(databaseMigration.status()).thenReturn(FAILED);
-    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
-    when(databaseMigration.failureError()).thenReturn(null); // no failure throwable caught
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_FAILED, failedMsg(DEFAULT_ERROR_MSG), SOME_DATE));
-  }
-
-  @Test
-  public void state_from_databasemigration_and_msg_has_default_msg_when_dbmigration_status_is_SUCCEEDED() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
-    when(dialect.supportsMigration()).thenReturn(true);
-    when(databaseMigration.status()).thenReturn(SUCCEEDED);
-    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_SUCCEEDED, MIG_SUCCESS_MSG, SOME_DATE));
-  }
-
-  @Test
-  public void start_migration_and_return_state_from_databasemigration_when_dbmigration_status_is_NONE() throws Exception {
-    when(databaseVersion.getVersion()).thenReturn(OLD_VERSION);
-    when(dialect.supportsMigration()).thenReturn(true);
-    when(databaseMigration.status()).thenReturn(NONE);
-    when(databaseMigration.startedAt()).thenReturn(SOME_DATE);
-
-    underTest.handle(request, response);
-
-    verify(databaseMigration).startIt();
-    assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_RUNNING, RUNNING_MSG, SOME_DATE));
-  }
-
-  private static String failedMsg(@Nullable String t) {
-    return "Migration failed: " + t + ".<br/> Please check logs.";
-  }
-
-  private static String expectedResponse(String status, String msg) {
-    return "{" +
-      "\"state\":\"" + status + "\"," +
-      "\"message\":\"" + msg + "\"" +
-      "}";
-  }
-
-  private static String expectedResponse(String status, String msg, Date date) {
-    return "{" +
-      "\"state\":\"" + status + "\"," +
-      "\"message\":\"" + msg + "\"," +
-      "\"startedAt\":\"" + DateUtils.formatDateTime(date) + "\"" +
-      "}";
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/RestartActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/RestartActionTest.java
new file mode 100644 (file)
index 0000000..34db99a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.platform.Platform;
+import org.sonar.server.ws.WsTester;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.*;
+
+public class RestartActionTest {
+
+  Settings settings = new Settings();
+  Platform platform = mock(Platform.class);
+  RestartAction sut = new RestartAction(settings, platform);
+
+  @Test
+  public void restart_if_dev_mode() throws Exception {
+    settings.setProperty("sonar.web.dev", true);
+
+    SystemWs ws = new SystemWs(sut);
+
+    WsTester tester = new WsTester(ws);
+    tester.newPostRequest("api/system", "restart").execute();
+    verify(platform).restart();
+  }
+
+  @Test
+  public void fail_if_production_mode() throws Exception {
+    SystemWs ws = new SystemWs(sut);
+
+    WsTester tester = new WsTester(ws);
+    try {
+      tester.newPostRequest("api/system", "restart").execute();
+      fail();
+    } catch (ForbiddenException e) {
+      verifyZeroInteractions(platform);
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/StatusActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/StatusActionTest.java
new file mode 100644 (file)
index 0000000..26f3c2d
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.platform.Server;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.IsAliveMapper;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.platform.Platform;
+import org.sonar.server.ws.WsTester;
+
+import java.io.File;
+import java.util.Date;
+import java.util.Set;
+
+import static com.google.common.base.Predicates.in;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.ImmutableSet.of;
+import static com.google.common.collect.Iterables.filter;
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class StatusActionTest {
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+
+  private static final String SERVER_ID = "20150504120436";
+  private static final String SERVER_VERSION = "5.1";
+  private static final String STATUS_UP = "UP";
+  private static final String STATUS_DOWN = "DOWN";
+  private static final String STATUS_MIGRATION_NEEDED = "DB_MIGRATION_NEEDED";
+  private static final String STATUS_MIGRATION_RUNNING = "DB_MIGRATION_RUNNING";
+  private static final Set<DatabaseMigration.Status> SUPPORTED_DATABASE_MIGRATION_STATUSES = of(DatabaseMigration.Status.FAILED, DatabaseMigration.Status.NONE,
+    DatabaseMigration.Status.SUCCEEDED, DatabaseMigration.Status.RUNNING);
+  private static final Set<Platform.Status> SUPPORTED_PLATFORM_STATUSES = of(Platform.Status.BOOTING, Platform.Status.SAFEMODE, Platform.Status.UP);
+
+  private static Server server = new Dummy51Server();
+  private DatabaseMigration databaseMigration = mock(DatabaseMigration.class);
+  private Platform platform = mock(Platform.class);
+  private DbClient dbClient = mock(DbClient.class);
+  private DbSession dbSession = mock(DbSession.class);
+  private IsAliveMapper isAliveMapper = mock(IsAliveMapper.class);
+  private StatusAction underTest = new StatusAction(server, databaseMigration, platform, dbClient);
+
+  private Request request = mock(Request.class);
+
+  @Before
+  public void wireMocks() {
+    when(dbClient.openSession(anyBoolean())).thenReturn(dbSession);
+    when(dbSession.getMapper(IsAliveMapper.class)).thenReturn(isAliveMapper);
+  }
+
+  @Test
+  public void action_status_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly("status");
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isFalse();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNotNull();
+
+    assertThat(action.params()).isEmpty();
+  }
+
+  @Test
+  public void verify_example() throws Exception {
+    when(isAliveMapper.isAlive()).thenReturn(IsAliveMapper.IS_ALIVE_RETURNED_VALUE);
+    when(platform.status()).thenReturn(Platform.Status.UP);
+
+    WsTester.TestResponse response = new WsTester.TestResponse();
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(getClass().getResource("example-status.json"));
+  }
+
+  @Test
+  public void status_is_UP_if_platform_is_UP_whatever_databaseMigration_status_is() throws Exception {
+    for (DatabaseMigration.Status databaseMigrationStatus : DatabaseMigration.Status.values()) {
+      verifyStatus(Platform.Status.UP, databaseMigrationStatus, STATUS_UP);
+    }
+  }
+
+  @Test
+  public void status_is_DOWN_if_platform_is_BOOTING_whatever_databaseMigration_status_is() throws Exception {
+    for (DatabaseMigration.Status databaseMigrationStatus : DatabaseMigration.Status.values()) {
+      verifyStatus(Platform.Status.BOOTING, databaseMigrationStatus, STATUS_DOWN);
+    }
+  }
+
+  @Test
+  public void status_is_DB_MIGRATION_NEEDED_if_platform_is_SAFEMODE_and_databaseMigration_is_NONE() throws Exception {
+    verifyStatus(Platform.Status.SAFEMODE, DatabaseMigration.Status.NONE, STATUS_MIGRATION_NEEDED);
+  }
+
+  @Test
+  public void status_is_DB_MIGRATION_RUNNING_if_platform_is_SAFEMODE_and_databaseMigration_is_RUNNING() throws Exception {
+    verifyStatus(Platform.Status.SAFEMODE, DatabaseMigration.Status.RUNNING, STATUS_MIGRATION_RUNNING);
+  }
+
+  @Test
+  public void status_is_UP_if_platform_is_SAFEMODE_and_databaseMigration_is_SUCCEEDED() throws Exception {
+    verifyStatus(Platform.Status.SAFEMODE, DatabaseMigration.Status.SUCCEEDED, STATUS_UP);
+  }
+
+  @Test
+  public void status_is_DOWN_if_platform_is_SAFEMODE_and_databaseMigration_is_FAILED() throws Exception {
+    verifyStatus(Platform.Status.SAFEMODE, DatabaseMigration.Status.FAILED, STATUS_DOWN);
+  }
+
+  @Test
+  public void status_is_DOWN_if_any_error_occurs_when_checking_DB() throws Exception {
+    when(isAliveMapper.isAlive()).thenThrow(new RuntimeException("simulated runtime exception when querying DB"));
+
+    WsTester.TestResponse response = new WsTester.TestResponse();
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo("{" +
+      "  \"status\": \"DOWN\"\n" +
+      "}");
+  }
+
+  /**
+   * By contract {@link IsAliveMapper#isAlive()} can not return anything but 1. Still we write this test as a
+   * protection against change in this contract.
+   */
+  @Test
+  public void status_is_DOWN_if_isAlive_does_not_return_1() throws Exception {
+    when(isAliveMapper.isAlive()).thenReturn(12);
+
+    WsTester.TestResponse response = new WsTester.TestResponse();
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo("{" +
+      "  \"status\": \"" + STATUS_DOWN + "\"\n" +
+      "}");
+  }
+
+  @Test
+  public void safety_test_for_new_platform_status() throws Exception {
+    for (Platform.Status platformStatus : filter(asList(Platform.Status.values()), not(in(SUPPORTED_PLATFORM_STATUSES)))) {
+      for (DatabaseMigration.Status databaseMigrationStatus : DatabaseMigration.Status.values()) {
+        verifyStatus(platformStatus, databaseMigrationStatus, STATUS_DOWN);
+      }
+    }
+  }
+
+  @Test
+  public void safety_test_for_new_databaseMigration_status_when_platform_is_SAFEMODE() throws Exception {
+    for (DatabaseMigration.Status databaseMigrationStatus : filter(asList(DatabaseMigration.Status.values()), not(in(SUPPORTED_DATABASE_MIGRATION_STATUSES)))) {
+      when(platform.status()).thenReturn(Platform.Status.SAFEMODE);
+      when(databaseMigration.status()).thenReturn(databaseMigrationStatus);
+
+      WsTester.TestResponse response = new WsTester.TestResponse();
+      underTest.handle(request, response);
+    }
+  }
+
+  private void verifyStatus(Platform.Status platformStatus, DatabaseMigration.Status databaseMigrationStatus, String expectedStatus) throws Exception {
+    when(isAliveMapper.isAlive()).thenReturn(IsAliveMapper.IS_ALIVE_RETURNED_VALUE);
+    when(platform.status()).thenReturn(platformStatus);
+    when(databaseMigration.status()).thenReturn(databaseMigrationStatus);
+
+    WsTester.TestResponse response = new WsTester.TestResponse();
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo("{" +
+      "  \"status\": \"" + expectedStatus + "\"\n" +
+      "}");
+  }
+
+  private static class Dummy51Server extends Server {
+    @Override
+    public String getId() {
+      return SERVER_ID;
+    }
+
+    @Override
+    public String getVersion() {
+      return SERVER_VERSION;
+    }
+
+    @Override
+    public Date getStartedAt() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public File getRootDir() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public File getDeployDir() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getContextPath() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getURL() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getPermanentServerId() {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemInfoWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemInfoWsActionTest.java
deleted file mode 100644 (file)
index f93b1fd..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.platform.ws;
-
-import java.util.LinkedHashMap;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.internal.SimpleGetRequest;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.platform.monitoring.Monitor;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class SystemInfoWsActionTest {
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone().login("login")
-      .setName("name");
-
-  Monitor monitor1 = mock(Monitor.class);
-  Monitor monitor2 = mock(Monitor.class);
-  SystemInfoWsAction sut = new SystemInfoWsAction(userSessionRule, monitor1, monitor2);
-
-  @Test(expected = ForbiddenException.class)
-  public void should_fail_when_does_not_have_admin_right() {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-
-    sut.handle(mock(Request.class), mock(Response.class));
-  }
-
-  @Test
-  public void write_json() {
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    LinkedHashMap<String, Object> attributes1 = new LinkedHashMap<>();
-    attributes1.put("foo", "bar");
-    LinkedHashMap<String, Object> attributes2 = new LinkedHashMap<>();
-    attributes2.put("one", 1);
-    attributes2.put("two", 2);
-    when(monitor1.name()).thenReturn("Monitor One");
-    when(monitor1.attributes()).thenReturn(attributes1);
-    when(monitor2.name()).thenReturn("Monitor Two");
-    when(monitor2.attributes()).thenReturn(attributes2);
-
-    WsTester.TestResponse response = new WsTester.TestResponse();
-    sut.handle(new SimpleGetRequest(), response);
-    assertThat(response.outputAsString()).isEqualTo("{\"Monitor One\":{\"foo\":\"bar\"},\"Monitor Two\":{\"one\":1,\"two\":2}}");
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemRestartWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemRestartWsActionTest.java
deleted file mode 100644 (file)
index 4329ff9..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.ws;
-
-import org.junit.Test;
-import org.sonar.api.config.Settings;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.platform.Platform;
-import org.sonar.server.ws.WsTester;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.*;
-
-public class SystemRestartWsActionTest {
-
-  Settings settings = new Settings();
-  Platform platform = mock(Platform.class);
-  SystemRestartWsAction sut = new SystemRestartWsAction(settings, platform);
-
-  @Test
-  public void restart_if_dev_mode() throws Exception {
-    settings.setProperty("sonar.web.dev", true);
-
-    SystemWs ws = new SystemWs(sut);
-
-    WsTester tester = new WsTester(ws);
-    tester.newPostRequest("api/system", "restart").execute();
-    verify(platform).restart();
-  }
-
-  @Test
-  public void fail_if_production_mode() throws Exception {
-    SystemWs ws = new SystemWs(sut);
-
-    WsTester tester = new WsTester(ws);
-    try {
-      tester.newPostRequest("api/system", "restart").execute();
-      fail();
-    } catch (ForbiddenException e) {
-      verifyZeroInteractions(platform);
-    }
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemStatusWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemStatusWsActionTest.java
deleted file mode 100644 (file)
index a64e45a..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.ws;
-
-import java.io.File;
-import java.util.Date;
-import java.util.Set;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.platform.Server;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.IsAliveMapper;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.db.migrations.DatabaseMigration;
-import org.sonar.server.platform.Platform;
-import org.sonar.server.ws.WsTester;
-
-import static com.google.common.base.Predicates.in;
-import static com.google.common.base.Predicates.not;
-import static com.google.common.collect.ImmutableSet.of;
-import static com.google.common.collect.Iterables.filter;
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class SystemStatusWsActionTest {
-  private static final String DUMMY_CONTROLLER_KEY = "dummy";
-
-  private static final String SERVER_ID = "20150504120436";
-  private static final String SERVER_VERSION = "5.1";
-  private static final String STATUS_UP = "UP";
-  private static final String STATUS_DOWN = "DOWN";
-  private static final String STATUS_MIGRATION_NEEDED = "DB_MIGRATION_NEEDED";
-  private static final String STATUS_MIGRATION_RUNNING = "DB_MIGRATION_RUNNING";
-  private static final Set<DatabaseMigration.Status> SUPPORTED_DATABASE_MIGRATION_STATUSES = of(DatabaseMigration.Status.FAILED, DatabaseMigration.Status.NONE,
-    DatabaseMigration.Status.SUCCEEDED, DatabaseMigration.Status.RUNNING);
-  private static final Set<Platform.Status> SUPPORTED_PLATFORM_STATUSES = of(Platform.Status.BOOTING, Platform.Status.SAFEMODE, Platform.Status.UP);
-
-  private static Server server = new Dummy51Server();
-  private DatabaseMigration databaseMigration = mock(DatabaseMigration.class);
-  private Platform platform = mock(Platform.class);
-  private DbClient dbClient = mock(DbClient.class);
-  private DbSession dbSession = mock(DbSession.class);
-  private IsAliveMapper isAliveMapper = mock(IsAliveMapper.class);
-  private SystemStatusWsAction underTest = new SystemStatusWsAction(server, databaseMigration, platform, dbClient);
-
-  private Request request = mock(Request.class);
-
-  @Before
-  public void wireMocks() {
-    when(dbClient.openSession(anyBoolean())).thenReturn(dbSession);
-    when(dbSession.getMapper(IsAliveMapper.class)).thenReturn(isAliveMapper);
-  }
-
-  @Test
-  public void action_status_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly("status");
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNotNull();
-
-    assertThat(action.params()).isEmpty();
-  }
-
-  @Test
-  public void verify_example() throws Exception {
-    when(isAliveMapper.isAlive()).thenReturn(IsAliveMapper.IS_ALIVE_RETURNED_VALUE);
-    when(platform.status()).thenReturn(Platform.Status.UP);
-
-    WsTester.TestResponse response = new WsTester.TestResponse();
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(getClass().getResource("example-status.json"));
-  }
-
-  @Test
-  public void status_is_UP_if_platform_is_UP_whatever_databaseMigration_status_is() throws Exception {
-    for (DatabaseMigration.Status databaseMigrationStatus : DatabaseMigration.Status.values()) {
-      verifyStatus(Platform.Status.UP, databaseMigrationStatus, STATUS_UP);
-    }
-  }
-
-  @Test
-  public void status_is_DOWN_if_platform_is_BOOTING_whatever_databaseMigration_status_is() throws Exception {
-    for (DatabaseMigration.Status databaseMigrationStatus : DatabaseMigration.Status.values()) {
-      verifyStatus(Platform.Status.BOOTING, databaseMigrationStatus, STATUS_DOWN);
-    }
-  }
-
-  @Test
-  public void status_is_DB_MIGRATION_NEEDED_if_platform_is_SAFEMODE_and_databaseMigration_is_NONE() throws Exception {
-    verifyStatus(Platform.Status.SAFEMODE, DatabaseMigration.Status.NONE, STATUS_MIGRATION_NEEDED);
-  }
-
-  @Test
-  public void status_is_DB_MIGRATION_RUNNING_if_platform_is_SAFEMODE_and_databaseMigration_is_RUNNING() throws Exception {
-    verifyStatus(Platform.Status.SAFEMODE, DatabaseMigration.Status.RUNNING, STATUS_MIGRATION_RUNNING);
-  }
-
-  @Test
-  public void status_is_UP_if_platform_is_SAFEMODE_and_databaseMigration_is_SUCCEEDED() throws Exception {
-    verifyStatus(Platform.Status.SAFEMODE, DatabaseMigration.Status.SUCCEEDED, STATUS_UP);
-  }
-
-  @Test
-  public void status_is_DOWN_if_platform_is_SAFEMODE_and_databaseMigration_is_FAILED() throws Exception {
-    verifyStatus(Platform.Status.SAFEMODE, DatabaseMigration.Status.FAILED, STATUS_DOWN);
-  }
-
-  @Test
-  public void status_is_DOWN_if_any_error_occurs_when_checking_DB() throws Exception {
-    when(isAliveMapper.isAlive()).thenThrow(new RuntimeException("simulated runtime exception when querying DB"));
-
-    WsTester.TestResponse response = new WsTester.TestResponse();
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo("{" +
-      "  \"status\": \"DOWN\"\n" +
-      "}");
-  }
-
-  /**
-   * By contract {@link IsAliveMapper#isAlive()} can not return anything but 1. Still we write this test as a
-   * protection against change in this contract.
-   */
-  @Test
-  public void status_is_DOWN_if_isAlive_does_not_return_1() throws Exception {
-    when(isAliveMapper.isAlive()).thenReturn(12);
-
-    WsTester.TestResponse response = new WsTester.TestResponse();
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo("{" +
-      "  \"status\": \"" + STATUS_DOWN + "\"\n" +
-      "}");
-  }
-
-  @Test
-  public void safety_test_for_new_platform_status() throws Exception {
-    for (Platform.Status platformStatus : filter(asList(Platform.Status.values()), not(in(SUPPORTED_PLATFORM_STATUSES)))) {
-      for (DatabaseMigration.Status databaseMigrationStatus : DatabaseMigration.Status.values()) {
-        verifyStatus(platformStatus, databaseMigrationStatus, STATUS_DOWN);
-      }
-    }
-  }
-
-  @Test
-  public void safety_test_for_new_databaseMigration_status_when_platform_is_SAFEMODE() throws Exception {
-    for (DatabaseMigration.Status databaseMigrationStatus : filter(asList(DatabaseMigration.Status.values()), not(in(SUPPORTED_DATABASE_MIGRATION_STATUSES)))) {
-      when(platform.status()).thenReturn(Platform.Status.SAFEMODE);
-      when(databaseMigration.status()).thenReturn(databaseMigrationStatus);
-
-      WsTester.TestResponse response = new WsTester.TestResponse();
-      underTest.handle(request, response);
-    }
-  }
-
-  private void verifyStatus(Platform.Status platformStatus, DatabaseMigration.Status databaseMigrationStatus, String expectedStatus) throws Exception {
-    when(isAliveMapper.isAlive()).thenReturn(IsAliveMapper.IS_ALIVE_RETURNED_VALUE);
-    when(platform.status()).thenReturn(platformStatus);
-    when(databaseMigration.status()).thenReturn(databaseMigrationStatus);
-
-    WsTester.TestResponse response = new WsTester.TestResponse();
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo("{" +
-      "  \"status\": \"" + expectedStatus + "\"\n" +
-      "}");
-  }
-
-  private static class Dummy51Server extends Server {
-    @Override
-    public String getId() {
-      return SERVER_ID;
-    }
-
-    @Override
-    public String getVersion() {
-      return SERVER_VERSION;
-    }
-
-    @Override
-    public Date getStartedAt() {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public File getRootDir() {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public File getDeployDir() {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String getContextPath() {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String getURL() {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String getPermanentServerId() {
-      throw new UnsupportedOperationException();
-    }
-  }
-}
index a475adf91f72c2066aefd41a01716f6a3b7a7473..a00bc635f872bb09b58c6fd5f2c05c923160072b 100644 (file)
@@ -32,8 +32,8 @@ public class SystemWsTest {
 
   @Test
   public void define() {
-    SystemRestartWsAction action1 = new SystemRestartWsAction(mock(Settings.class), mock(Platform.class));
-    SystemInfoWsAction action2 = new SystemInfoWsAction(new AnonymousMockUserSession());
+    RestartAction action1 = new RestartAction(mock(Settings.class), mock(Platform.class));
+    InfoAction action2 = new InfoAction(new AnonymousMockUserSession());
     SystemWs ws = new SystemWs(action1, action2);
     WebService.Context context = new WebService.Context();
 
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/UpgradesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/UpgradesActionTest.java
new file mode 100644 (file)
index 0000000..e5939d5
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.ws.PluginWSCommons;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.Release;
+import org.sonar.updatecenter.common.Sonar;
+import org.sonar.updatecenter.common.SonarUpdate;
+import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.Version;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class UpgradesActionTest {
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+  private static final String JSON_EMPTY_UPGRADE_LIST =
+    "{" +
+      "  \"upgrades\":" + "[]" +
+      "}";
+
+  private UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class);
+  private UpdateCenter updateCenter = mock(UpdateCenter.class);
+  private UpgradesAction underTest = new UpgradesAction(updateCenterFactory, new PluginWSCommons());
+
+  private Request request = mock(Request.class);
+  private WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Before
+  public void wireMocks() {
+    when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
+    when(updateCenter.getDate()).thenReturn(DateUtils.parseDateTime("2015-04-24T16:08:36+0200"));
+  }
+
+  @Test
+  public void action_updates_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly("upgrades");
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isFalse();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNotNull();
+
+    assertThat(action.params()).isEmpty();
+  }
+
+  @Test
+  public void empty_array_is_returned_when_there_is_no_upgrade_available() throws Exception {
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_UPGRADE_LIST);
+  }
+
+  @Test
+  public void verify_JSON_response_against_example() throws Exception {
+    SonarUpdate sonarUpdate = createSonar_51_update();
+    when(updateCenter.findSonarUpdates()).thenReturn(of(sonarUpdate));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true)
+      .isSimilarTo(getClass().getResource("example-upgrades_plugins.json"));
+  }
+
+  private static SonarUpdate createSonar_51_update() {
+    Plugin brandingPlugin = new Plugin("branding")
+      .setCategory("Integration")
+      .setName("Branding")
+      .setDescription("Allows to add your own logo to the SonarQube UI.")
+      .setHomepageUrl("http://docs.codehaus.org/display/SONAR/Branding+Plugin")
+      .setLicense("GNU LGPL 3")
+      .setOrganization("SonarSource")
+      .setOrganizationUrl("http://www.sonarsource.com")
+      .setIssueTrackerUrl("http://jira.codehaus.org/browse/SONARPLUGINS/component/14663")
+      .setSourcesUrl("https://github.com/SonarCommunity/sonar-branding");
+    Plugin viewsPlugin = new Plugin("views")
+      .setName("Views")
+      .setCategory("Governance")
+      .setDescription("Create aggregation trees to group projects. Projects can for instance be grouped by applications,   applications by team, teams by department.")
+      .setHomepageUrl("http://redirect.sonarsource.com/plugins/views.html")
+      .setLicense("Commercial")
+      .setOrganization("SonarSource")
+      .setOrganizationUrl("http://www.sonarsource.com")
+      .setTermsConditionsUrl("http://dist.sonarsource.com/SonarSource_Terms_And_Conditions.pdf")
+      .setIssueTrackerUrl("http://jira.sonarsource.com/browse/VIEWS");
+
+    SonarUpdate sonarUpdate = new SonarUpdate(
+      new Release(new Sonar(), Version.create("5.1"))
+        .setDate(DateUtils.parseDate("2015-04-02"))
+        .setDescription("New overall layout, merge Issues Drilldown [...]")
+        .setDownloadUrl("http://dist.sonar.codehaus.org/sonarqube-5.1.zip")
+        .setChangelogUrl("http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=11694&version=20666")
+      );
+
+    sonarUpdate.addIncompatiblePlugin(brandingPlugin);
+    sonarUpdate.addPluginToUpgrade(new Release(viewsPlugin, Version.create("2.8")));
+
+    return sonarUpdate;
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/UpgradesSystemWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/UpgradesSystemWsActionTest.java
deleted file mode 100644 (file)
index 24557f8..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.ws;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.plugins.ws.PluginWSCommons;
-import org.sonar.server.ws.WsTester;
-import org.sonar.updatecenter.common.Plugin;
-import org.sonar.updatecenter.common.Release;
-import org.sonar.updatecenter.common.Sonar;
-import org.sonar.updatecenter.common.SonarUpdate;
-import org.sonar.updatecenter.common.UpdateCenter;
-import org.sonar.updatecenter.common.Version;
-
-import static com.google.common.collect.ImmutableList.of;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class UpgradesSystemWsActionTest {
-  private static final String DUMMY_CONTROLLER_KEY = "dummy";
-  private static final String JSON_EMPTY_UPGRADE_LIST =
-    "{" +
-      "  \"upgrades\":" + "[]" +
-      "}";
-
-  private UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class);
-  private UpdateCenter updateCenter = mock(UpdateCenter.class);
-  private UpgradesSystemWsAction underTest = new UpgradesSystemWsAction(updateCenterFactory, new PluginWSCommons());
-
-  private Request request = mock(Request.class);
-  private WsTester.TestResponse response = new WsTester.TestResponse();
-
-  @Before
-  public void wireMocks() {
-    when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
-    when(updateCenter.getDate()).thenReturn(DateUtils.parseDateTime("2015-04-24T16:08:36+0200"));
-  }
-
-  @Test
-  public void action_updates_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly("upgrades");
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNotNull();
-
-    assertThat(action.params()).isEmpty();
-  }
-
-  @Test
-  public void empty_array_is_returned_when_there_is_no_upgrade_available() throws Exception {
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_UPGRADE_LIST);
-  }
-
-  @Test
-  public void verify_JSON_response_against_example() throws Exception {
-    SonarUpdate sonarUpdate = createSonar_51_update();
-    when(updateCenter.findSonarUpdates()).thenReturn(of(sonarUpdate));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true)
-      .isSimilarTo(getClass().getResource("example-upgrades_plugins.json"));
-  }
-
-  private static SonarUpdate createSonar_51_update() {
-    Plugin brandingPlugin = new Plugin("branding")
-      .setCategory("Integration")
-      .setName("Branding")
-      .setDescription("Allows to add your own logo to the SonarQube UI.")
-      .setHomepageUrl("http://docs.codehaus.org/display/SONAR/Branding+Plugin")
-      .setLicense("GNU LGPL 3")
-      .setOrganization("SonarSource")
-      .setOrganizationUrl("http://www.sonarsource.com")
-      .setIssueTrackerUrl("http://jira.codehaus.org/browse/SONARPLUGINS/component/14663")
-      .setSourcesUrl("https://github.com/SonarCommunity/sonar-branding");
-    Plugin viewsPlugin = new Plugin("views")
-      .setName("Views")
-      .setCategory("Governance")
-      .setDescription("Create aggregation trees to group projects. Projects can for instance be grouped by applications,   applications by team, teams by department.")
-      .setHomepageUrl("http://redirect.sonarsource.com/plugins/views.html")
-      .setLicense("Commercial")
-      .setOrganization("SonarSource")
-      .setOrganizationUrl("http://www.sonarsource.com")
-      .setTermsConditionsUrl("http://dist.sonarsource.com/SonarSource_Terms_And_Conditions.pdf")
-      .setIssueTrackerUrl("http://jira.sonarsource.com/browse/VIEWS");
-
-    SonarUpdate sonarUpdate = new SonarUpdate(
-      new Release(new Sonar(), Version.create("5.1"))
-        .setDate(DateUtils.parseDate("2015-04-02"))
-        .setDescription("New overall layout, merge Issues Drilldown [...]")
-        .setDownloadUrl("http://dist.sonar.codehaus.org/sonarqube-5.1.zip")
-        .setChangelogUrl("http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=11694&version=20666")
-      );
-
-    sonarUpdate.addIncompatiblePlugin(brandingPlugin);
-    sonarUpdate.addPluginToUpgrade(new Release(viewsPlugin, Version.create("2.8")));
-
-    return sonarUpdate;
-  }
-}
index 92c7fbab55a23f8772f0ab49036c472968e9771a..03682b2ffdb1bee73c0e4fe92b1b01ac6995e4ad 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.server.plugins.ws;
 
-import java.net.URL;
 import org.junit.Before;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.utils.DateUtils;
@@ -31,6 +30,8 @@ import org.sonar.updatecenter.common.Release;
 import org.sonar.updatecenter.common.UpdateCenter;
 import org.sonar.updatecenter.common.Version;
 
+import java.net.URL;
+
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -60,7 +61,7 @@ public class AbstractUpdateCenterBasedPluginsWsActionTest {
   }
 
   protected static URL resource(String s) {
-    Class<AvailablePluginsWsActionTest> clazz = AvailablePluginsWsActionTest.class;
+    Class<AvailableActionTest> clazz = AvailableActionTest.class;
     return clazz.getResource(clazz.getSimpleName() + "/" + s);
   }
 
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/AvailableActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/AvailableActionTest.java
new file mode 100644 (file)
index 0000000..b6c59f1
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.PluginUpdate;
+import org.sonar.updatecenter.common.Release;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.COMPATIBLE;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.DEPENDENCIES_REQUIRE_SONAR_UPGRADE;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.INCOMPATIBLE;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.REQUIRE_SONAR_UPGRADE;
+
+public class AvailableActionTest extends AbstractUpdateCenterBasedPluginsWsActionTest {
+
+  private static final Plugin FULL_PROPERTIES_PLUGIN = new Plugin("p_key")
+    .setName("p_name")
+    .setCategory("p_category")
+    .setDescription("p_description")
+    .setLicense("p_license")
+    .setOrganization("p_orga_name")
+    .setOrganizationUrl("p_orga_url")
+    .setTermsConditionsUrl("p_t_and_c_url");
+  private static final Release FULL_PROPERTIES_PLUGIN_RELEASE = release(FULL_PROPERTIES_PLUGIN, "1.12.1")
+    .setDate(DateUtils.parseDate("2015-04-16"))
+    .setDownloadUrl("http://p_file.jar")
+    .addOutgoingDependency(release(PLUGIN_1, "0.3.6"))
+    .addOutgoingDependency(release(PLUGIN_2, "1.0.0"));
+
+  private AvailableAction underTest = new AvailableAction(updateCenterFactory, new PluginWSCommons());
+
+  @Test
+  public void action_available_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly("available");
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isFalse();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNotNull();
+  }
+
+  @Test
+  public void empty_array_is_returned_when_there_is_no_plugin_available() throws Exception {
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
+  }
+
+  @Test
+  public void verify_properties_displayed_in_json_per_plugin() throws Exception {
+    when(updateCenter.findAvailablePlugins()).thenReturn(of(
+      pluginUpdate(FULL_PROPERTIES_PLUGIN_RELEASE, COMPATIBLE)
+      ));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(resource("properties_per_plugin.json"));
+  }
+
+  @Test
+  public void status_COMPATIBLE_is_displayed_COMPATIBLE_in_JSON() throws Exception {
+    checkStatusDisplayedInJson(COMPATIBLE, "COMPATIBLE");
+  }
+
+  @Test
+  public void status_INCOMPATIBLE_is_displayed_INCOMPATIBLE_in_JSON() throws Exception {
+    checkStatusDisplayedInJson(INCOMPATIBLE, "INCOMPATIBLE");
+  }
+
+  @Test
+  public void status_REQUIRE_SONAR_UPGRADE_is_displayed_REQUIRES_SYSTEM_UPGRADE_in_JSON() throws Exception {
+    checkStatusDisplayedInJson(REQUIRE_SONAR_UPGRADE, "REQUIRES_SYSTEM_UPGRADE");
+  }
+
+  @Test
+  public void status_DEPENDENCIES_REQUIRE_SONAR_UPGRADE_is_displayed_DEPS_REQUIRE_SYSTEM_UPGRADE_in_JSON() throws Exception {
+    checkStatusDisplayedInJson(DEPENDENCIES_REQUIRE_SONAR_UPGRADE, "DEPS_REQUIRE_SYSTEM_UPGRADE");
+  }
+
+  private void checkStatusDisplayedInJson(PluginUpdate.Status status, String expectedValue) throws Exception {
+    when(updateCenter.findAvailablePlugins()).thenReturn(of(
+      pluginUpdate(release(PLUGIN_1, "1.0.0"), status)
+      ));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(
+      "{" +
+        "  \"plugins\": [" +
+        "    {" +
+        "      \"update\": {" +
+        "        \"status\": \"" + expectedValue + "\"" +
+        "      }" +
+        "    }" +
+        "  ]" +
+        "}"
+      );
+  }
+
+  @Test
+  public void plugins_are_sorted_by_name_then_key_and_made_unique() {
+    when(updateCenter.findAvailablePlugins()).thenReturn(of(
+      pluginUpdate("key2", "name2"),
+      pluginUpdate("key1", "name2"),
+      pluginUpdate("key2", "name2"),
+      pluginUpdate("key0", "name0"),
+      pluginUpdate("key1", "name1")
+      ));
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/AvailablePluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/AvailablePluginsWsActionTest.java
deleted file mode 100644 (file)
index 220975f..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.junit.Test;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.server.ws.WsTester;
-import org.sonar.updatecenter.common.Plugin;
-import org.sonar.updatecenter.common.PluginUpdate;
-import org.sonar.updatecenter.common.Release;
-
-import static com.google.common.collect.ImmutableList.of;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.when;
-import static org.sonar.test.JsonAssert.assertJson;
-import static org.sonar.updatecenter.common.PluginUpdate.Status.COMPATIBLE;
-import static org.sonar.updatecenter.common.PluginUpdate.Status.DEPENDENCIES_REQUIRE_SONAR_UPGRADE;
-import static org.sonar.updatecenter.common.PluginUpdate.Status.INCOMPATIBLE;
-import static org.sonar.updatecenter.common.PluginUpdate.Status.REQUIRE_SONAR_UPGRADE;
-
-public class AvailablePluginsWsActionTest extends AbstractUpdateCenterBasedPluginsWsActionTest {
-
-  private static final Plugin FULL_PROPERTIES_PLUGIN = new Plugin("p_key")
-    .setName("p_name")
-    .setCategory("p_category")
-    .setDescription("p_description")
-    .setLicense("p_license")
-    .setOrganization("p_orga_name")
-    .setOrganizationUrl("p_orga_url")
-    .setTermsConditionsUrl("p_t_and_c_url");
-  private static final Release FULL_PROPERTIES_PLUGIN_RELEASE = release(FULL_PROPERTIES_PLUGIN, "1.12.1")
-    .setDate(DateUtils.parseDate("2015-04-16"))
-    .setDownloadUrl("http://p_file.jar")
-    .addOutgoingDependency(release(PLUGIN_1, "0.3.6"))
-    .addOutgoingDependency(release(PLUGIN_2, "1.0.0"));
-
-  private AvailablePluginsWsAction underTest = new AvailablePluginsWsAction(updateCenterFactory, new PluginWSCommons());
-
-  @Test
-  public void action_available_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly("available");
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNotNull();
-  }
-
-  @Test
-  public void empty_array_is_returned_when_there_is_no_plugin_available() throws Exception {
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
-  }
-
-  @Test
-  public void verify_properties_displayed_in_json_per_plugin() throws Exception {
-    when(updateCenter.findAvailablePlugins()).thenReturn(of(
-      pluginUpdate(FULL_PROPERTIES_PLUGIN_RELEASE, COMPATIBLE)
-      ));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(resource("properties_per_plugin.json"));
-  }
-
-  @Test
-  public void status_COMPATIBLE_is_displayed_COMPATIBLE_in_JSON() throws Exception {
-    checkStatusDisplayedInJson(COMPATIBLE, "COMPATIBLE");
-  }
-
-  @Test
-  public void status_INCOMPATIBLE_is_displayed_INCOMPATIBLE_in_JSON() throws Exception {
-    checkStatusDisplayedInJson(INCOMPATIBLE, "INCOMPATIBLE");
-  }
-
-  @Test
-  public void status_REQUIRE_SONAR_UPGRADE_is_displayed_REQUIRES_SYSTEM_UPGRADE_in_JSON() throws Exception {
-    checkStatusDisplayedInJson(REQUIRE_SONAR_UPGRADE, "REQUIRES_SYSTEM_UPGRADE");
-  }
-
-  @Test
-  public void status_DEPENDENCIES_REQUIRE_SONAR_UPGRADE_is_displayed_DEPS_REQUIRE_SYSTEM_UPGRADE_in_JSON() throws Exception {
-    checkStatusDisplayedInJson(DEPENDENCIES_REQUIRE_SONAR_UPGRADE, "DEPS_REQUIRE_SYSTEM_UPGRADE");
-  }
-
-  private void checkStatusDisplayedInJson(PluginUpdate.Status status, String expectedValue) throws Exception {
-    when(updateCenter.findAvailablePlugins()).thenReturn(of(
-      pluginUpdate(release(PLUGIN_1, "1.0.0"), status)
-      ));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(
-      "{" +
-        "  \"plugins\": [" +
-        "    {" +
-        "      \"update\": {" +
-        "        \"status\": \"" + expectedValue + "\"" +
-        "      }" +
-        "    }" +
-        "  ]" +
-        "}"
-      );
-  }
-
-  @Test
-  public void plugins_are_sorted_by_name_then_key_and_made_unique() {
-    when(updateCenter.findAvailablePlugins()).thenReturn(of(
-      pluginUpdate("key2", "name2"),
-      pluginUpdate("key1", "name2"),
-      pluginUpdate("key2", "name2"),
-      pluginUpdate("key0", "name0"),
-      pluginUpdate("key1", "name1")
-      ));
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllActionTest.java
new file mode 100644 (file)
index 0000000..26d06a8
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class CancelAllActionTest {
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+  private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
+  private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
+  private CancelAllAction underTest = new CancelAllAction(pluginDownloader, pluginRepository, userSessionRule);
+
+  private Request request = mock(Request.class);
+  private WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void action_cancel_all_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly("cancel_all");
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isTrue();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNull();
+
+    assertThat(action.params()).isEmpty();
+  }
+
+  @Test
+  public void user_must_have_system_admin_permission() throws Exception {
+    expectedException.expect(ForbiddenException.class);
+    expectedException.expectMessage("Insufficient privileges");
+
+    // no permission on user
+    userSessionRule.setGlobalPermissions();
+
+    underTest.handle(request, response);
+  }
+
+  @Test
+  public void triggers_cancel_for_downloads_and_uninstalls() throws Exception {
+    underTest.handle(request, response);
+
+    verify(pluginDownloader, times(1)).cancelDownloads();
+    verify(pluginRepository, times(1)).cancelUninstalls();
+    assertThat(response.outputAsString()).isEmpty();
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllPluginsWsActionTest.java
deleted file mode 100644 (file)
index 11f91f1..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-public class CancelAllPluginsWsActionTest {
-  private static final String DUMMY_CONTROLLER_KEY = "dummy";
-
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-  private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
-  private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
-  private CancelAllPluginsWsAction underTest = new CancelAllPluginsWsAction(pluginDownloader, pluginRepository, userSessionRule);
-
-  private Request request = mock(Request.class);
-  private WsTester.TestResponse response = new WsTester.TestResponse();
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  public void action_cancel_all_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly("cancel_all");
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isTrue();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNull();
-
-    assertThat(action.params()).isEmpty();
-  }
-
-  @Test
-  public void user_must_have_system_admin_permission() throws Exception {
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage("Insufficient privileges");
-
-    // no permission on user
-    userSessionRule.setGlobalPermissions();
-
-    underTest.handle(request, response);
-  }
-
-  @Test
-  public void triggers_cancel_for_downloads_and_uninstalls() throws Exception {
-    underTest.handle(request, response);
-
-    verify(pluginDownloader, times(1)).cancelDownloads();
-    verify(pluginRepository, times(1)).cancelUninstalls();
-    assertThat(response.outputAsString()).isEmpty();
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstallActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstallActionTest.java
new file mode 100644 (file)
index 0000000..6cac3de
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.PluginUpdate;
+import org.sonar.updatecenter.common.Release;
+import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.Version;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class InstallActionTest {
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+  private static final String CONTROLLER_KEY = "api/plugins";
+  private static final String ACTION_KEY = "install";
+  private static final String KEY_PARAM = "key";
+  private static final String PLUGIN_KEY = "pluginKey";
+  
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class);
+  private UpdateCenter updateCenter = mock(UpdateCenter.class);
+  private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
+  private InstallAction underTest = new InstallAction(updateCenterFactory, pluginDownloader, userSessionRule);
+
+  private WsTester wsTester = new WsTester(new PluginsWs(underTest));
+  private WsTester.TestRequest invalidRequest = wsTester.newPostRequest(CONTROLLER_KEY, ACTION_KEY);
+  private WsTester.TestRequest validRequest = wsTester.newPostRequest(CONTROLLER_KEY, ACTION_KEY)
+    .setParam(KEY_PARAM, PLUGIN_KEY);
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Before
+  public void wireMocks() {
+    when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
+
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+  }
+
+  @Test
+  public void user_must_have_system_admin_permission() throws Exception {
+    expectedException.expect(ForbiddenException.class);
+    expectedException.expectMessage("Insufficient privileges");
+
+    // no permission on user
+    userSessionRule.setGlobalPermissions();
+
+    validRequest.execute();
+  }
+
+  @Test
+  public void action_install_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly(ACTION_KEY);
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isTrue();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNull();
+
+    assertThat(action.params()).hasSize(1);
+    WebService.Param keyParam = action.param(KEY_PARAM);
+    assertThat(keyParam).isNotNull();
+    assertThat(keyParam.isRequired()).isTrue();
+    assertThat(keyParam.description()).isNotNull();
+  }
+
+  @Test
+  public void IAE_is_raised_when_key_param_is_not_provided() throws Exception {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Parameter 'key' is missing");
+
+    invalidRequest.execute();
+  }
+
+  @Test
+  public void IAE_is_raised_when_there_is_no_available_plugin_for_the_key() throws Exception {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("No plugin with key 'pluginKey'");
+
+    validRequest.execute();
+  }
+
+  @Test
+  public void if_plugin_is_found_available_download_is_triggered_with_latest_version_from_updatecenter() throws Exception {
+    Version version = Version.create("1.0");
+    when(updateCenter.findAvailablePlugins()).thenReturn(ImmutableList.of(
+      PluginUpdate.createWithStatus(new Release(new Plugin(PLUGIN_KEY), version), PluginUpdate.Status.COMPATIBLE)
+      ));
+
+    WsTester.Result result = validRequest.execute();
+
+    verify(pluginDownloader).download(PLUGIN_KEY, version);
+    result.assertNoContent();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstallPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstallPluginsWsActionTest.java
deleted file mode 100644 (file)
index 1be07a3..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-import org.sonar.updatecenter.common.Plugin;
-import org.sonar.updatecenter.common.PluginUpdate;
-import org.sonar.updatecenter.common.Release;
-import org.sonar.updatecenter.common.UpdateCenter;
-import org.sonar.updatecenter.common.Version;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class InstallPluginsWsActionTest {
-  private static final String DUMMY_CONTROLLER_KEY = "dummy";
-  private static final String CONTROLLER_KEY = "api/plugins";
-  private static final String ACTION_KEY = "install";
-  private static final String KEY_PARAM = "key";
-  private static final String PLUGIN_KEY = "pluginKey";
-  
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class);
-  private UpdateCenter updateCenter = mock(UpdateCenter.class);
-  private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
-  private InstallPluginsWsAction underTest = new InstallPluginsWsAction(updateCenterFactory, pluginDownloader, userSessionRule);
-
-  private WsTester wsTester = new WsTester(new PluginsWs(underTest));
-  private WsTester.TestRequest invalidRequest = wsTester.newPostRequest(CONTROLLER_KEY, ACTION_KEY);
-  private WsTester.TestRequest validRequest = wsTester.newPostRequest(CONTROLLER_KEY, ACTION_KEY)
-    .setParam(KEY_PARAM, PLUGIN_KEY);
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Before
-  public void wireMocks() {
-    when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
-
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-  }
-
-  @Test
-  public void user_must_have_system_admin_permission() throws Exception {
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage("Insufficient privileges");
-
-    // no permission on user
-    userSessionRule.setGlobalPermissions();
-
-    validRequest.execute();
-  }
-
-  @Test
-  public void action_install_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly(ACTION_KEY);
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isTrue();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNull();
-
-    assertThat(action.params()).hasSize(1);
-    WebService.Param keyParam = action.param(KEY_PARAM);
-    assertThat(keyParam).isNotNull();
-    assertThat(keyParam.isRequired()).isTrue();
-    assertThat(keyParam.description()).isNotNull();
-  }
-
-  @Test
-  public void IAE_is_raised_when_key_param_is_not_provided() throws Exception {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Parameter 'key' is missing");
-
-    invalidRequest.execute();
-  }
-
-  @Test
-  public void IAE_is_raised_when_there_is_no_available_plugin_for_the_key() throws Exception {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("No plugin with key 'pluginKey'");
-
-    validRequest.execute();
-  }
-
-  @Test
-  public void if_plugin_is_found_available_download_is_triggered_with_latest_version_from_updatecenter() throws Exception {
-    Version version = Version.create("1.0");
-    when(updateCenter.findAvailablePlugins()).thenReturn(ImmutableList.of(
-      PluginUpdate.createWithStatus(new Release(new Plugin(PLUGIN_KEY), version), PluginUpdate.Status.COMPATIBLE)
-      ));
-
-    WsTester.Result result = validRequest.execute();
-
-    verify(pluginDownloader).download(PLUGIN_KEY, version);
-    result.assertNoContent();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java
new file mode 100644 (file)
index 0000000..15d405c
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Version;
+
+import java.io.File;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class InstalledActionTest {
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+  private static final String JSON_EMPTY_PLUGIN_LIST =
+    "{" +
+      "  \"plugins\":" + "[]" +
+      "}";
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
+  private InstalledAction underTest = new InstalledAction(pluginRepository, new PluginWSCommons());
+
+  private Request request = mock(Request.class);
+  private WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Test
+  public void action_installed_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly("installed");
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isFalse();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNotNull();
+  }
+
+  @Test
+  public void empty_array_is_returned_when_there_is_not_plugin_installed() throws Exception {
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
+  }
+
+  @Test
+  public void core_plugin_are_not_returned() throws Exception {
+    when(pluginRepository.getPluginInfos()).thenReturn(of(corePlugin("core1", "1.0")));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
+  }
+
+  @Test
+  public void empty_fields_are_not_serialized_to_json() throws Exception {
+    when(pluginRepository.getPluginInfos()).thenReturn(
+      of(
+      new PluginInfo("").setName("").setCore(false)
+      )
+      );
+
+    underTest.handle(request, response);
+
+    assertThat(response.outputAsString()).doesNotContain("name").doesNotContain("key");
+  }
+
+  @Test
+  public void verify_properties_displayed_in_json_per_plugin() throws Exception {
+    String jarFilename = getClass().getSimpleName() + "/" + "some.jar";
+    when(pluginRepository.getPluginInfos()).thenReturn(of(
+      new PluginInfo("plugKey")
+        .setName("plugName")
+        .setCore(false)
+        .setDescription("desc_it")
+        .setVersion(Version.create("1.0"))
+        .setLicense("license_hey")
+        .setOrganizationName("org_name")
+        .setOrganizationUrl("org_url")
+        .setHomepageUrl("homepage_url")
+        .setIssueTrackerUrl("issueTracker_url")
+        .setImplementationBuild("sou_rev_sha1")
+        .setJarFile(new File(getClass().getResource(jarFilename).toURI()))
+      )
+      );
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(
+      "{" +
+        "  \"plugins\":" +
+        "  [" +
+        "    {" +
+        "      \"key\": \"plugKey\"," +
+        "      \"name\": \"plugName\"," +
+        "      \"description\": \"desc_it\"," +
+        "      \"version\": \"1.0\"," +
+        "      \"license\": \"license_hey\"," +
+        "      \"organizationName\": \"org_name\"," +
+        "      \"organizationUrl\": \"org_url\"," +
+        "      \"homepageUrl\": \"homepage_url\"," +
+        "      \"issueTrackerUrl\": \"issueTracker_url\"," +
+        "      \"implementationBuild\": \"sou_rev_sha1\"" +
+        "    }" +
+        "  ]" +
+        "}"
+      );
+  }
+
+  @Test
+  public void plugins_are_sorted_by_name_then_key_and_only_one_plugin_can_have_a_specific_name() throws Exception {
+    when(pluginRepository.getPluginInfos()).thenReturn(
+      of(
+        plugin("A", "name2"),
+        plugin("B", "name1"),
+        plugin("C", "name0"),
+        plugin("D", "name0")
+      )
+      );
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"plugins\":" +
+        "  [" +
+        "    {\"key\": \"C\"}" + "," +
+        "    {\"key\": \"D\"}" + "," +
+        "    {\"key\": \"B\"}" + "," +
+        "    {\"key\": \"A\"}" +
+        "  ]" +
+        "}"
+      );
+  }
+
+  @Test
+  public void only_one_plugin_can_have_a_specific_name_and_key() throws Exception {
+    when(pluginRepository.getPluginInfos()).thenReturn(
+      of(
+        plugin("A", "name2"),
+        plugin("A", "name2")
+      )
+      );
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"plugins\":" +
+        "  [" +
+        "    {\"key\": \"A\"}" +
+        "  ]" +
+        "}"
+      );
+    assertThat(response.outputAsString()).containsOnlyOnce("name2");
+  }
+
+  private PluginInfo corePlugin(String key, String version) {
+    return new PluginInfo(key).setName(key).setCore(true).setVersion(Version.create(version));
+  }
+
+  private PluginInfo plugin(String key, String name) {
+    return new PluginInfo(key).setName(name).setCore(false).setVersion(Version.create("1.0"));
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java
deleted file mode 100644 (file)
index ab79848..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.platform.PluginInfo;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.ws.WsTester;
-import org.sonar.updatecenter.common.Version;
-
-import java.io.File;
-
-import static com.google.common.collect.ImmutableList.of;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class InstalledPluginsWsActionTest {
-  private static final String DUMMY_CONTROLLER_KEY = "dummy";
-  private static final String JSON_EMPTY_PLUGIN_LIST =
-    "{" +
-      "  \"plugins\":" + "[]" +
-      "}";
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
-  private InstalledPluginsWsAction underTest = new InstalledPluginsWsAction(pluginRepository, new PluginWSCommons());
-
-  private Request request = mock(Request.class);
-  private WsTester.TestResponse response = new WsTester.TestResponse();
-
-  @Test
-  public void action_installed_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly("installed");
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNotNull();
-  }
-
-  @Test
-  public void empty_array_is_returned_when_there_is_not_plugin_installed() throws Exception {
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
-  }
-
-  @Test
-  public void core_plugin_are_not_returned() throws Exception {
-    when(pluginRepository.getPluginInfos()).thenReturn(of(corePlugin("core1", "1.0")));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
-  }
-
-  @Test
-  public void empty_fields_are_not_serialized_to_json() throws Exception {
-    when(pluginRepository.getPluginInfos()).thenReturn(
-      of(
-      new PluginInfo("").setName("").setCore(false)
-      )
-      );
-
-    underTest.handle(request, response);
-
-    assertThat(response.outputAsString()).doesNotContain("name").doesNotContain("key");
-  }
-
-  @Test
-  public void verify_properties_displayed_in_json_per_plugin() throws Exception {
-    String jarFilename = getClass().getSimpleName() + "/" + "some.jar";
-    when(pluginRepository.getPluginInfos()).thenReturn(of(
-      new PluginInfo("plugKey")
-        .setName("plugName")
-        .setCore(false)
-        .setDescription("desc_it")
-        .setVersion(Version.create("1.0"))
-        .setLicense("license_hey")
-        .setOrganizationName("org_name")
-        .setOrganizationUrl("org_url")
-        .setHomepageUrl("homepage_url")
-        .setIssueTrackerUrl("issueTracker_url")
-        .setImplementationBuild("sou_rev_sha1")
-        .setJarFile(new File(getClass().getResource(jarFilename).toURI()))
-      )
-      );
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(
-      "{" +
-        "  \"plugins\":" +
-        "  [" +
-        "    {" +
-        "      \"key\": \"plugKey\"," +
-        "      \"name\": \"plugName\"," +
-        "      \"description\": \"desc_it\"," +
-        "      \"version\": \"1.0\"," +
-        "      \"license\": \"license_hey\"," +
-        "      \"organizationName\": \"org_name\"," +
-        "      \"organizationUrl\": \"org_url\"," +
-        "      \"homepageUrl\": \"homepage_url\"," +
-        "      \"issueTrackerUrl\": \"issueTracker_url\"," +
-        "      \"implementationBuild\": \"sou_rev_sha1\"" +
-        "    }" +
-        "  ]" +
-        "}"
-      );
-  }
-
-  @Test
-  public void plugins_are_sorted_by_name_then_key_and_only_one_plugin_can_have_a_specific_name() throws Exception {
-    when(pluginRepository.getPluginInfos()).thenReturn(
-      of(
-        plugin("A", "name2"),
-        plugin("B", "name1"),
-        plugin("C", "name0"),
-        plugin("D", "name0")
-      )
-      );
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
-      "{" +
-        "  \"plugins\":" +
-        "  [" +
-        "    {\"key\": \"C\"}" + "," +
-        "    {\"key\": \"D\"}" + "," +
-        "    {\"key\": \"B\"}" + "," +
-        "    {\"key\": \"A\"}" +
-        "  ]" +
-        "}"
-      );
-  }
-
-  @Test
-  public void only_one_plugin_can_have_a_specific_name_and_key() throws Exception {
-    when(pluginRepository.getPluginInfos()).thenReturn(
-      of(
-        plugin("A", "name2"),
-        plugin("A", "name2")
-      )
-      );
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
-      "{" +
-        "  \"plugins\":" +
-        "  [" +
-        "    {\"key\": \"A\"}" +
-        "  ]" +
-        "}"
-      );
-    assertThat(response.outputAsString()).containsOnlyOnce("name2");
-  }
-
-  private PluginInfo corePlugin(String key, String version) {
-    return new PluginInfo(key).setName(key).setCore(true).setVersion(Version.create(version));
-  }
-
-  private PluginInfo plugin(String key, String name) {
-    return new PluginInfo(key).setName(name).setCore(false).setVersion(Version.create("1.0"));
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingActionTest.java
new file mode 100644 (file)
index 0000000..a9620d4
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Version;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class PendingActionTest {
+
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+
+  PluginDownloader pluginDownloader = mock(PluginDownloader.class);
+  ServerPluginRepository serverPluginRepository = mock(ServerPluginRepository.class);
+  PendingAction underTest = new PendingAction(pluginDownloader, serverPluginRepository, new PluginWSCommons());
+  Request request = mock(Request.class);
+  WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Test
+  public void action_pending_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly("pending");
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isFalse();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNotNull();
+  }
+
+  @Test
+  public void empty_arrays_are_returned_when_there_nothing_pending() throws Exception {
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"installing\": []," +
+        "  \"removing\": []" +
+        "}"
+      );
+  }
+
+  @Test
+  public void verify_properties_displayed_in_json_per_installing_plugin() throws Exception {
+    when(pluginDownloader.getDownloadedPlugins()).thenReturn(of(gitPluginInfo()));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(
+      "{" +
+        "  \"installing\": " +
+        "  [" +
+        "    {" +
+        "      \"key\": \"scmgit\"," +
+        "      \"name\": \"Git\"," +
+        "      \"description\": \"Git SCM Provider.\"," +
+        "      \"version\": \"1.0\"," +
+        "      \"license\": \"GNU LGPL 3\"," +
+        "      \"organizationName\": \"SonarSource\"," +
+        "      \"organizationUrl\": \"http://www.sonarsource.com\"," +
+        "      \"homepageUrl\": \"http://redirect.sonarsource.com/plugins/scmgit.html\"," +
+        "      \"issueTrackerUrl\": \"http://jira.codehaus.org/browse/SONARSCGIT\"," +
+        "      \"implementationBuild\": \"9ce9d330c313c296fab051317cc5ad4b26319e07\"" +
+        "    }" +
+        "  ]," +
+        "  \"removing\": []" +
+        "}"
+      );
+  }
+
+  @Test
+  public void verify_properties_displayed_in_json_per_removing_plugin() throws Exception {
+    when(serverPluginRepository.getUninstalledPlugins()).thenReturn(of(gitPluginInfo()));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(
+      "{" +
+        "  \"installing\": []," +
+        "  \"removing\": " +
+        "  [" +
+        "    {" +
+        "      \"key\": \"scmgit\"," +
+        "      \"name\": \"Git\"," +
+        "      \"description\": \"Git SCM Provider.\"," +
+        "      \"version\": \"1.0\"," +
+        "      \"license\": \"GNU LGPL 3\"," +
+        "      \"organizationName\": \"SonarSource\"," +
+        "      \"organizationUrl\": \"http://www.sonarsource.com\"," +
+        "      \"homepageUrl\": \"http://redirect.sonarsource.com/plugins/scmgit.html\"," +
+        "      \"issueTrackerUrl\": \"http://jira.codehaus.org/browse/SONARSCGIT\"," +
+        "      \"implementationBuild\": \"9ce9d330c313c296fab051317cc5ad4b26319e07\"" +
+        "    }" +
+        "  ]" +
+        "}"
+      );
+  }
+
+  @Test
+  public void installing_plugins_are_sorted_by_name_then_key_and_are_unique() throws Exception {
+    when(pluginDownloader.getDownloadedPlugins()).thenReturn(of(
+      newPluginInfo(0).setName("Foo"),
+      newPluginInfo(3).setName("Bar"),
+      newPluginInfo(2).setName("Bar")
+      ));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"installing\": " +
+        "  [" +
+        "    {" +
+        "      \"key\": \"key2\"," +
+        "      \"name\": \"Bar\"," +
+        "    }," +
+        "    {" +
+        "      \"key\": \"key3\"," +
+        "      \"name\": \"Bar\"," +
+        "    }," +
+        "    {" +
+        "      \"key\": \"key0\"," +
+        "      \"name\": \"Foo\"," +
+        "    }" +
+        "  ]," +
+        "  \"removing\": []" +
+        "}"
+      );
+  }
+
+  @Test
+  public void removing_plugins_are_sorted_and_unique() throws Exception {
+    when(serverPluginRepository.getUninstalledPlugins()).thenReturn(of(
+      newPluginInfo(0).setName("Foo"),
+      newPluginInfo(3).setName("Bar"),
+      newPluginInfo(2).setName("Bar")
+      ));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"installing\": []," +
+        "  \"removing\": " +
+        "  [" +
+        "    {" +
+        "      \"key\": \"key2\"," +
+        "      \"name\": \"Bar\"," +
+        "    }," +
+        "    {" +
+        "      \"key\": \"key3\"," +
+        "      \"name\": \"Bar\"," +
+        "    }," +
+        "    {" +
+        "      \"key\": \"key0\"," +
+        "      \"name\": \"Foo\"," +
+        "    }" +
+        "  ]" +
+        "}"
+      );
+  }
+
+  public PluginInfo gitPluginInfo() {
+    return new PluginInfo("scmgit")
+      .setName("Git")
+      .setDescription("Git SCM Provider.")
+      .setVersion(Version.create("1.0"))
+      .setLicense("GNU LGPL 3")
+      .setOrganizationName("SonarSource")
+      .setOrganizationUrl("http://www.sonarsource.com")
+      .setHomepageUrl("http://redirect.sonarsource.com/plugins/scmgit.html")
+      .setIssueTrackerUrl("http://jira.codehaus.org/browse/SONARSCGIT")
+      .setImplementationBuild("9ce9d330c313c296fab051317cc5ad4b26319e07");
+  }
+
+  public PluginInfo newPluginInfo(int id) {
+    return new PluginInfo("key" + id).setName("name" + id);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java
deleted file mode 100644 (file)
index 56cd9e8..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.junit.Test;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.platform.PluginInfo;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.ws.WsTester;
-import org.sonar.updatecenter.common.Version;
-
-import static com.google.common.collect.ImmutableList.of;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class PendingPluginsWsActionTest {
-
-  private static final String DUMMY_CONTROLLER_KEY = "dummy";
-
-  PluginDownloader pluginDownloader = mock(PluginDownloader.class);
-  ServerPluginRepository serverPluginRepository = mock(ServerPluginRepository.class);
-  PendingPluginsWsAction underTest = new PendingPluginsWsAction(pluginDownloader, serverPluginRepository, new PluginWSCommons());
-  Request request = mock(Request.class);
-  WsTester.TestResponse response = new WsTester.TestResponse();
-
-  @Test
-  public void action_pending_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly("pending");
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNotNull();
-  }
-
-  @Test
-  public void empty_arrays_are_returned_when_there_nothing_pending() throws Exception {
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
-      "{" +
-        "  \"installing\": []," +
-        "  \"removing\": []" +
-        "}"
-      );
-  }
-
-  @Test
-  public void verify_properties_displayed_in_json_per_installing_plugin() throws Exception {
-    when(pluginDownloader.getDownloadedPlugins()).thenReturn(of(gitPluginInfo()));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(
-      "{" +
-        "  \"installing\": " +
-        "  [" +
-        "    {" +
-        "      \"key\": \"scmgit\"," +
-        "      \"name\": \"Git\"," +
-        "      \"description\": \"Git SCM Provider.\"," +
-        "      \"version\": \"1.0\"," +
-        "      \"license\": \"GNU LGPL 3\"," +
-        "      \"organizationName\": \"SonarSource\"," +
-        "      \"organizationUrl\": \"http://www.sonarsource.com\"," +
-        "      \"homepageUrl\": \"http://redirect.sonarsource.com/plugins/scmgit.html\"," +
-        "      \"issueTrackerUrl\": \"http://jira.codehaus.org/browse/SONARSCGIT\"," +
-        "      \"implementationBuild\": \"9ce9d330c313c296fab051317cc5ad4b26319e07\"" +
-        "    }" +
-        "  ]," +
-        "  \"removing\": []" +
-        "}"
-      );
-  }
-
-  @Test
-  public void verify_properties_displayed_in_json_per_removing_plugin() throws Exception {
-    when(serverPluginRepository.getUninstalledPlugins()).thenReturn(of(gitPluginInfo()));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(
-      "{" +
-        "  \"installing\": []," +
-        "  \"removing\": " +
-        "  [" +
-        "    {" +
-        "      \"key\": \"scmgit\"," +
-        "      \"name\": \"Git\"," +
-        "      \"description\": \"Git SCM Provider.\"," +
-        "      \"version\": \"1.0\"," +
-        "      \"license\": \"GNU LGPL 3\"," +
-        "      \"organizationName\": \"SonarSource\"," +
-        "      \"organizationUrl\": \"http://www.sonarsource.com\"," +
-        "      \"homepageUrl\": \"http://redirect.sonarsource.com/plugins/scmgit.html\"," +
-        "      \"issueTrackerUrl\": \"http://jira.codehaus.org/browse/SONARSCGIT\"," +
-        "      \"implementationBuild\": \"9ce9d330c313c296fab051317cc5ad4b26319e07\"" +
-        "    }" +
-        "  ]" +
-        "}"
-      );
-  }
-
-  @Test
-  public void installing_plugins_are_sorted_by_name_then_key_and_are_unique() throws Exception {
-    when(pluginDownloader.getDownloadedPlugins()).thenReturn(of(
-      newPluginInfo(0).setName("Foo"),
-      newPluginInfo(3).setName("Bar"),
-      newPluginInfo(2).setName("Bar")
-      ));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
-      "{" +
-        "  \"installing\": " +
-        "  [" +
-        "    {" +
-        "      \"key\": \"key2\"," +
-        "      \"name\": \"Bar\"," +
-        "    }," +
-        "    {" +
-        "      \"key\": \"key3\"," +
-        "      \"name\": \"Bar\"," +
-        "    }," +
-        "    {" +
-        "      \"key\": \"key0\"," +
-        "      \"name\": \"Foo\"," +
-        "    }" +
-        "  ]," +
-        "  \"removing\": []" +
-        "}"
-      );
-  }
-
-  @Test
-  public void removing_plugins_are_sorted_and_unique() throws Exception {
-    when(serverPluginRepository.getUninstalledPlugins()).thenReturn(of(
-      newPluginInfo(0).setName("Foo"),
-      newPluginInfo(3).setName("Bar"),
-      newPluginInfo(2).setName("Bar")
-      ));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
-      "{" +
-        "  \"installing\": []," +
-        "  \"removing\": " +
-        "  [" +
-        "    {" +
-        "      \"key\": \"key2\"," +
-        "      \"name\": \"Bar\"," +
-        "    }," +
-        "    {" +
-        "      \"key\": \"key3\"," +
-        "      \"name\": \"Bar\"," +
-        "    }," +
-        "    {" +
-        "      \"key\": \"key0\"," +
-        "      \"name\": \"Foo\"," +
-        "    }" +
-        "  ]" +
-        "}"
-      );
-  }
-
-  public PluginInfo gitPluginInfo() {
-    return new PluginInfo("scmgit")
-      .setName("Git")
-      .setDescription("Git SCM Provider.")
-      .setVersion(Version.create("1.0"))
-      .setLicense("GNU LGPL 3")
-      .setOrganizationName("SonarSource")
-      .setOrganizationUrl("http://www.sonarsource.com")
-      .setHomepageUrl("http://redirect.sonarsource.com/plugins/scmgit.html")
-      .setIssueTrackerUrl("http://jira.codehaus.org/browse/SONARSCGIT")
-      .setImplementationBuild("9ce9d330c313c296fab051317cc5ad4b26319e07");
-  }
-
-  public PluginInfo newPluginInfo(int id) {
-    return new PluginInfo("key" + id).setName("name" + id);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallActionTest.java
new file mode 100644 (file)
index 0000000..4bf85e0
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+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 UninstallActionTest {
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+  private static final String CONTROLLER_KEY = "api/plugins";
+  private static final String ACTION_KEY = "uninstall";
+  private static final String KEY_PARAM = "key";
+  private static final String PLUGIN_KEY = "findbugs";
+
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
+  private UninstallAction underTest = new UninstallAction(pluginRepository, userSessionRule);
+
+  private WsTester wsTester = new WsTester(new PluginsWs(underTest));
+  private Request invalidRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY);
+  private Request validRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY).setParam(KEY_PARAM, PLUGIN_KEY);
+  private WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Test
+  public void user_must_have_system_admin_permission() throws Exception {
+    expectedException.expect(ForbiddenException.class);
+    expectedException.expectMessage("Insufficient privileges");
+
+    // no permission on user
+    userSessionRule.setGlobalPermissions();
+
+    underTest.handle(validRequest, response);
+  }
+
+  @Test
+  public void action_uninstall_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly(ACTION_KEY);
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isTrue();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNull();
+
+    assertThat(action.params()).hasSize(1);
+    WebService.Param keyParam = action.param(KEY_PARAM);
+    assertThat(keyParam).isNotNull();
+    assertThat(keyParam.isRequired()).isTrue();
+    assertThat(keyParam.description()).isNotNull();
+  }
+
+  @Test
+  public void IAE_is_raised_when_key_param_is_not_provided() throws Exception {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Parameter 'key' is missing");
+
+    underTest.handle(invalidRequest, response);
+  }
+
+  @Test
+  public void IAE_is_raised_when_plugin_is_not_installed() throws Exception {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Plugin [findbugs] is not installed");
+
+    underTest.handle(validRequest, response);
+  }
+
+  @Test
+  public void if_plugin_is_installed_uninstallation_is_triggered() throws Exception {
+    when(pluginRepository.hasPlugin(PLUGIN_KEY)).thenReturn(true);
+
+    underTest.handle(validRequest, response);
+
+    verify(pluginRepository).uninstall(PLUGIN_KEY);
+    assertThat(response.outputAsString()).isEmpty();
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallPluginsWsActionTest.java
deleted file mode 100644 (file)
index 42f42aa..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-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 UninstallPluginsWsActionTest {
-  private static final String DUMMY_CONTROLLER_KEY = "dummy";
-  private static final String CONTROLLER_KEY = "api/plugins";
-  private static final String ACTION_KEY = "uninstall";
-  private static final String KEY_PARAM = "key";
-  private static final String PLUGIN_KEY = "findbugs";
-
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
-  private UninstallPluginsWsAction underTest = new UninstallPluginsWsAction(pluginRepository, userSessionRule);
-
-  private WsTester wsTester = new WsTester(new PluginsWs(underTest));
-  private Request invalidRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY);
-  private Request validRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY).setParam(KEY_PARAM, PLUGIN_KEY);
-  private WsTester.TestResponse response = new WsTester.TestResponse();
-
-  @Test
-  public void user_must_have_system_admin_permission() throws Exception {
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage("Insufficient privileges");
-
-    // no permission on user
-    userSessionRule.setGlobalPermissions();
-
-    underTest.handle(validRequest, response);
-  }
-
-  @Test
-  public void action_uninstall_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly(ACTION_KEY);
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isTrue();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNull();
-
-    assertThat(action.params()).hasSize(1);
-    WebService.Param keyParam = action.param(KEY_PARAM);
-    assertThat(keyParam).isNotNull();
-    assertThat(keyParam.isRequired()).isTrue();
-    assertThat(keyParam.description()).isNotNull();
-  }
-
-  @Test
-  public void IAE_is_raised_when_key_param_is_not_provided() throws Exception {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Parameter 'key' is missing");
-
-    underTest.handle(invalidRequest, response);
-  }
-
-  @Test
-  public void IAE_is_raised_when_plugin_is_not_installed() throws Exception {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Plugin [findbugs] is not installed");
-
-    underTest.handle(validRequest, response);
-  }
-
-  @Test
-  public void if_plugin_is_installed_uninstallation_is_triggered() throws Exception {
-    when(pluginRepository.hasPlugin(PLUGIN_KEY)).thenReturn(true);
-
-    underTest.handle(validRequest, response);
-
-    verify(pluginRepository).uninstall(PLUGIN_KEY);
-    assertThat(response.outputAsString()).isEmpty();
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdateActionTest.java
new file mode 100644 (file)
index 0000000..22c8ac0
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.PluginUpdate;
+import org.sonar.updatecenter.common.PluginUpdate.Status;
+import org.sonar.updatecenter.common.Release;
+import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.Version;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class UpdateActionTest {
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+  private static final String CONTROLLER_KEY = "api/plugins";
+  private static final String ACTION_KEY = "update";
+  private static final String KEY_PARAM = "key";
+  private static final String PLUGIN_KEY = "pluginKey";
+
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class);
+  private UpdateCenter updateCenter = mock(UpdateCenter.class);
+  private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
+  private UpdateAction underTest = new UpdateAction(updateCenterFactory, pluginDownloader, userSessionRule);
+
+  private WsTester wsTester = new WsTester(new PluginsWs(underTest));
+  private Request invalidRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY);
+  private Request validRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY).setParam(KEY_PARAM, PLUGIN_KEY);
+  private WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Before
+  public void setUp() {
+    when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
+
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+  }
+
+  @Test
+  public void user_must_have_system_admin_permission() throws Exception {
+    expectedException.expect(ForbiddenException.class);
+    expectedException.expectMessage("Insufficient privileges");
+
+    // no permission on user
+    userSessionRule.setGlobalPermissions();
+
+    underTest.handle(validRequest, response);
+  }
+
+  @Test
+  public void action_update_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly(ACTION_KEY);
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isTrue();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNull();
+
+    assertThat(action.params()).hasSize(1);
+    WebService.Param key = action.param(KEY_PARAM);
+    assertThat(key).isNotNull();
+    assertThat(key.isRequired()).isTrue();
+    assertThat(key.description()).isNotNull();
+  }
+
+  @Test
+  public void IAE_is_raised_when_key_param_is_not_provided() throws Exception {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Parameter 'key' is missing");
+
+    underTest.handle(invalidRequest, response);
+  }
+
+  @Test
+  public void IAE_is_raised_when_there_is_no_plugin_update_for_the_key() throws Exception {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("No plugin with key 'pluginKey'");
+
+    underTest.handle(validRequest, response);
+  }
+
+  @Test
+  public void if_plugin_has_an_update_download_is_triggered_with_latest_version_from_updatecenter() throws Exception {
+    Version version = Version.create("1.0");
+    when(updateCenter.findPluginUpdates()).thenReturn(ImmutableList.of(
+      PluginUpdate.createWithStatus(new Release(new Plugin(PLUGIN_KEY), version), Status.COMPATIBLE)
+      ));
+
+    underTest.handle(validRequest, response);
+
+    verify(pluginDownloader).download(PLUGIN_KEY, version);
+    assertThat(response.outputAsString()).isEmpty();
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatePluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatePluginsWsActionTest.java
deleted file mode 100644 (file)
index 750dae4..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-import org.sonar.updatecenter.common.Plugin;
-import org.sonar.updatecenter.common.PluginUpdate;
-import org.sonar.updatecenter.common.PluginUpdate.Status;
-import org.sonar.updatecenter.common.Release;
-import org.sonar.updatecenter.common.UpdateCenter;
-import org.sonar.updatecenter.common.Version;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class UpdatePluginsWsActionTest {
-  private static final String DUMMY_CONTROLLER_KEY = "dummy";
-  private static final String CONTROLLER_KEY = "api/plugins";
-  private static final String ACTION_KEY = "update";
-  private static final String KEY_PARAM = "key";
-  private static final String PLUGIN_KEY = "pluginKey";
-
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class);
-  private UpdateCenter updateCenter = mock(UpdateCenter.class);
-  private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
-  private UpdatePluginsWsAction underTest = new UpdatePluginsWsAction(updateCenterFactory, pluginDownloader, userSessionRule);
-
-  private WsTester wsTester = new WsTester(new PluginsWs(underTest));
-  private Request invalidRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY);
-  private Request validRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY).setParam(KEY_PARAM, PLUGIN_KEY);
-  private WsTester.TestResponse response = new WsTester.TestResponse();
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Before
-  public void setUp() {
-    when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
-
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-  }
-
-  @Test
-  public void user_must_have_system_admin_permission() throws Exception {
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage("Insufficient privileges");
-
-    // no permission on user
-    userSessionRule.setGlobalPermissions();
-
-    underTest.handle(validRequest, response);
-  }
-
-  @Test
-  public void action_update_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly(ACTION_KEY);
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isTrue();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNull();
-
-    assertThat(action.params()).hasSize(1);
-    WebService.Param key = action.param(KEY_PARAM);
-    assertThat(key).isNotNull();
-    assertThat(key.isRequired()).isTrue();
-    assertThat(key.description()).isNotNull();
-  }
-
-  @Test
-  public void IAE_is_raised_when_key_param_is_not_provided() throws Exception {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Parameter 'key' is missing");
-
-    underTest.handle(invalidRequest, response);
-  }
-
-  @Test
-  public void IAE_is_raised_when_there_is_no_plugin_update_for_the_key() throws Exception {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("No plugin with key 'pluginKey'");
-
-    underTest.handle(validRequest, response);
-  }
-
-  @Test
-  public void if_plugin_has_an_update_download_is_triggered_with_latest_version_from_updatecenter() throws Exception {
-    Version version = Version.create("1.0");
-    when(updateCenter.findPluginUpdates()).thenReturn(ImmutableList.of(
-      PluginUpdate.createWithStatus(new Release(new Plugin(PLUGIN_KEY), version), Status.COMPATIBLE)
-      ));
-
-    underTest.handle(validRequest, response);
-
-    verify(pluginDownloader).download(PLUGIN_KEY, version);
-    assertThat(response.outputAsString()).isEmpty();
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatesActionTest.java
new file mode 100644 (file)
index 0000000..54aedde
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.Release;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.COMPATIBLE;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.INCOMPATIBLE;
+
+public class UpdatesActionTest extends AbstractUpdateCenterBasedPluginsWsActionTest {
+  private static final Plugin JAVA_PLUGIN = new Plugin("java")
+    .setName("Java")
+    .setDescription("SonarQube rule engine.");
+  private static final Plugin ABAP_PLUGIN = new Plugin("abap")
+    .setName("ABAP")
+    .setCategory("Languages")
+    .setDescription("Enable analysis and reporting on ABAP projects")
+    .setLicense("Commercial")
+    .setOrganization("SonarSource")
+    .setOrganizationUrl("http://www.sonarsource.com")
+    .setTermsConditionsUrl("http://dist.sonarsource.com/SonarSource_Terms_And_Conditions.pdf");
+  private static final Release ABAP_31 = release(ABAP_PLUGIN, "3.1")
+    .setDate(DateUtils.parseDate("2014-12-21"))
+    .setDescription("New rules, several improvements")
+    .setDownloadUrl("http://dist.sonarsource.com/abap/download/sonar-abap-plugin-3.1.jar")
+    .setChangelogUrl("http://jira.sonarsource.com/secure/ReleaseNote.jspa?projectId=10054&version=10552");
+  private static final Release ABAP_32 = release(ABAP_PLUGIN, "3.2")
+    .setDate(DateUtils.parseDate("2015-03-10"))
+    .setDescription("14 new rules, most of them designed to detect potential performance hotspots.")
+    .setDownloadUrl("http://dist.sonarsource.com/abap/download/sonar-abap-plugin-3.2.jar")
+    .setChangelogUrl("http://jira.sonarsource.com/secure/ReleaseNote.jspa?projectId=10054&version=10575");
+  private static final Plugin ANDROID_PLUGIN = new Plugin("android")
+    .setName("Android")
+    .setCategory("Languages")
+    .setDescription("Import Android Lint reports.")
+    .setLicense("GNU LGPL 3")
+    .setOrganization("SonarSource and Jerome Van Der Linden, Stephane Nicolas, Florian Roncari, Thomas Bores")
+    .setOrganizationUrl("http://www.sonarsource.com");
+  private static final Release ANDROID_10 = release(ANDROID_PLUGIN, "1.0")
+    .setDate(DateUtils.parseDate("2014-03-31"))
+    .setDescription("Makes the plugin compatible with multi-language analysis introduced in SonarQube 4.2 and adds support of Emma 2.0 reports")
+    .setDownloadUrl("http://repository.codehaus.org/org/codehaus/sonar-plugins/android/sonar-android-plugin/1.0/sonar-android-plugin-1.0.jar")
+    .setChangelogUrl("http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=13235&version=20187")
+
+    .addOutgoingDependency(release(JAVA_PLUGIN, "1.0"));
+
+  private UpdatesAction underTest = new UpdatesAction(updateCenterFactory,
+    new PluginWSCommons(), new PluginUpdateAggregator()
+    );
+
+  @Test
+  public void action_updatable_is_defined() {
+    WsTester wsTester = new WsTester();
+    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+    underTest.define(newController);
+    newController.done();
+
+    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+    assertThat(controller.actions()).extracting("key").containsExactly("updates");
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isFalse();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNotNull();
+  }
+
+  @Test
+  public void empty_array_is_returned_when_there_is_no_plugin_available() throws Exception {
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
+  }
+
+  @Test
+  public void verify_response_against_example() throws Exception {
+    when(updateCenter.findPluginUpdates()).thenReturn(of(
+      pluginUpdate(ABAP_32, COMPATIBLE),
+      pluginUpdate(ABAP_31, INCOMPATIBLE),
+      pluginUpdate(ANDROID_10, COMPATIBLE)
+      ));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(getClass().getResource("example-updates_plugins.json"));
+  }
+
+  @Test
+  public void status_COMPATIBLE_is_displayed_COMPATIBLE_in_JSON() throws Exception {
+    when(updateCenter.findPluginUpdates()).thenReturn(of(
+      pluginUpdate(release(PLUGIN_1, "1.0.0"), COMPATIBLE)
+      ));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(
+      "{" +
+        "  \"plugins\": [" +
+        "   {" +
+        "      \"updates\": [" +
+        "        {" +
+        "          \"status\": \"COMPATIBLE\"" +
+        "        }" +
+        "      ]" +
+        "    }" +
+        "  ]" +
+        "}"
+      );
+  }
+
+  @Test
+  public void plugins_are_sorted_by_name_and_made_unique() throws Exception {
+    when(updateCenter.findPluginUpdates()).thenReturn(of(
+      pluginUpdate("key2", "name2"),
+      pluginUpdate("key2", "name2"),
+      pluginUpdate("key0", "name0"),
+      pluginUpdate("key1", "name1")
+      ));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"plugins\": [" +
+        "    {" +
+        "      \"key\": \"key0\"," +
+        "      \"name\": \"name0\"" +
+        "    }," +
+        "    {" +
+        "      \"key\": \"key1\"," +
+        "      \"name\": \"name1\"" +
+        "    }," +
+        "    {" +
+        "      \"key\": \"key2\"," +
+        "      \"name\": \"name2\"" +
+        "    }," +
+        "  ]" +
+        "}"
+      );
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatesPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatesPluginsWsActionTest.java
deleted file mode 100644 (file)
index 4784b7c..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.plugins.ws;
-
-import org.junit.Test;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.server.ws.WsTester;
-import org.sonar.updatecenter.common.Plugin;
-import org.sonar.updatecenter.common.Release;
-
-import static com.google.common.collect.ImmutableList.of;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.when;
-import static org.sonar.test.JsonAssert.assertJson;
-import static org.sonar.updatecenter.common.PluginUpdate.Status.COMPATIBLE;
-import static org.sonar.updatecenter.common.PluginUpdate.Status.INCOMPATIBLE;
-
-public class UpdatesPluginsWsActionTest extends AbstractUpdateCenterBasedPluginsWsActionTest {
-  private static final Plugin JAVA_PLUGIN = new Plugin("java")
-    .setName("Java")
-    .setDescription("SonarQube rule engine.");
-  private static final Plugin ABAP_PLUGIN = new Plugin("abap")
-    .setName("ABAP")
-    .setCategory("Languages")
-    .setDescription("Enable analysis and reporting on ABAP projects")
-    .setLicense("Commercial")
-    .setOrganization("SonarSource")
-    .setOrganizationUrl("http://www.sonarsource.com")
-    .setTermsConditionsUrl("http://dist.sonarsource.com/SonarSource_Terms_And_Conditions.pdf");
-  private static final Release ABAP_31 = release(ABAP_PLUGIN, "3.1")
-    .setDate(DateUtils.parseDate("2014-12-21"))
-    .setDescription("New rules, several improvements")
-    .setDownloadUrl("http://dist.sonarsource.com/abap/download/sonar-abap-plugin-3.1.jar")
-    .setChangelogUrl("http://jira.sonarsource.com/secure/ReleaseNote.jspa?projectId=10054&version=10552");
-  private static final Release ABAP_32 = release(ABAP_PLUGIN, "3.2")
-    .setDate(DateUtils.parseDate("2015-03-10"))
-    .setDescription("14 new rules, most of them designed to detect potential performance hotspots.")
-    .setDownloadUrl("http://dist.sonarsource.com/abap/download/sonar-abap-plugin-3.2.jar")
-    .setChangelogUrl("http://jira.sonarsource.com/secure/ReleaseNote.jspa?projectId=10054&version=10575");
-  private static final Plugin ANDROID_PLUGIN = new Plugin("android")
-    .setName("Android")
-    .setCategory("Languages")
-    .setDescription("Import Android Lint reports.")
-    .setLicense("GNU LGPL 3")
-    .setOrganization("SonarSource and Jerome Van Der Linden, Stephane Nicolas, Florian Roncari, Thomas Bores")
-    .setOrganizationUrl("http://www.sonarsource.com");
-  private static final Release ANDROID_10 = release(ANDROID_PLUGIN, "1.0")
-    .setDate(DateUtils.parseDate("2014-03-31"))
-    .setDescription("Makes the plugin compatible with multi-language analysis introduced in SonarQube 4.2 and adds support of Emma 2.0 reports")
-    .setDownloadUrl("http://repository.codehaus.org/org/codehaus/sonar-plugins/android/sonar-android-plugin/1.0/sonar-android-plugin-1.0.jar")
-    .setChangelogUrl("http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=13235&version=20187")
-
-    .addOutgoingDependency(release(JAVA_PLUGIN, "1.0"));
-
-  private UpdatesPluginsWsAction underTest = new UpdatesPluginsWsAction(updateCenterFactory,
-    new PluginWSCommons(), new PluginUpdateAggregator()
-    );
-
-  @Test
-  public void action_updatable_is_defined() {
-    WsTester wsTester = new WsTester();
-    WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
-
-    underTest.define(newController);
-    newController.done();
-
-    WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
-    assertThat(controller.actions()).extracting("key").containsExactly("updates");
-
-    WebService.Action action = controller.actions().iterator().next();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.responseExample()).isNotNull();
-  }
-
-  @Test
-  public void empty_array_is_returned_when_there_is_no_plugin_available() throws Exception {
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
-  }
-
-  @Test
-  public void verify_response_against_example() throws Exception {
-    when(updateCenter.findPluginUpdates()).thenReturn(of(
-      pluginUpdate(ABAP_32, COMPATIBLE),
-      pluginUpdate(ABAP_31, INCOMPATIBLE),
-      pluginUpdate(ANDROID_10, COMPATIBLE)
-      ));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(getClass().getResource("example-updates_plugins.json"));
-  }
-
-  @Test
-  public void status_COMPATIBLE_is_displayed_COMPATIBLE_in_JSON() throws Exception {
-    when(updateCenter.findPluginUpdates()).thenReturn(of(
-      pluginUpdate(release(PLUGIN_1, "1.0.0"), COMPATIBLE)
-      ));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).isSimilarTo(
-      "{" +
-        "  \"plugins\": [" +
-        "   {" +
-        "      \"updates\": [" +
-        "        {" +
-        "          \"status\": \"COMPATIBLE\"" +
-        "        }" +
-        "      ]" +
-        "    }" +
-        "  ]" +
-        "}"
-      );
-  }
-
-  @Test
-  public void plugins_are_sorted_by_name_and_made_unique() throws Exception {
-    when(updateCenter.findPluginUpdates()).thenReturn(of(
-      pluginUpdate("key2", "name2"),
-      pluginUpdate("key2", "name2"),
-      pluginUpdate("key0", "name0"),
-      pluginUpdate("key1", "name1")
-      ));
-
-    underTest.handle(request, response);
-
-    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
-      "{" +
-        "  \"plugins\": [" +
-        "    {" +
-        "      \"key\": \"key0\"," +
-        "      \"name\": \"name0\"" +
-        "    }," +
-        "    {" +
-        "      \"key\": \"key1\"," +
-        "      \"name\": \"name1\"" +
-        "    }," +
-        "    {" +
-        "      \"key\": \"key2\"," +
-        "      \"name\": \"name2\"" +
-        "    }," +
-        "  ]" +
-        "}"
-      );
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java
new file mode 100644 (file)
index 0000000..38915de
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.component.SnapshotDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.component.ComponentCleanerService;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.SnapshotTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.component.db.SnapshotDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.issue.IssueTesting;
+import org.sonar.server.issue.db.IssueDao;
+import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.issue.index.IssueIndexDefinition;
+import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.source.index.SourceLineDoc;
+import org.sonar.server.source.index.SourceLineIndexDefinition;
+import org.sonar.server.source.index.SourceLineIndexer;
+import org.sonar.server.test.index.TestDoc;
+import org.sonar.server.test.index.TestIndexDefinition;
+import org.sonar.server.test.index.TestIndexer;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.test.DbTests;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@Category(DbTests.class)
+public class DeleteActionTest {
+
+  @ClassRule
+  public static DbTester db = new DbTester();
+  @ClassRule
+  public static EsTester es = new EsTester().addDefinitions(new IssueIndexDefinition(new Settings()), new SourceLineIndexDefinition(new Settings()),
+    new TestIndexDefinition(new Settings()));
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  WsTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+  ResourceType resourceType;
+
+  @Before
+  public void setUp() throws Exception {
+    ComponentDao componentDao = new ComponentDao();
+    ResourceDao resourceDao = new ResourceDao(db.myBatis(), System2.INSTANCE);
+    PurgeDao purgeDao = new PurgeDao(db.myBatis(), resourceDao, new PurgeProfiler(), System2.INSTANCE);
+    dbClient = new DbClient(db.database(), db.myBatis(), componentDao, purgeDao, new RuleDao(System2.INSTANCE), new IssueDao(db.myBatis()), new SnapshotDao(System2.INSTANCE));
+    dbSession = dbClient.openSession(false);
+    resourceType = mock(ResourceType.class);
+    when(resourceType.getBooleanProperty(anyString())).thenReturn(true);
+    ResourceTypes mockResourceTypes = mock(ResourceTypes.class);
+    when(mockResourceTypes.get(anyString())).thenReturn(resourceType);
+    ws = new WsTester(new ProjectsWs(new DeleteAction(new ComponentCleanerService(dbClient, new IssueAuthorizationIndexer(dbClient, es.client()), new IssueIndexer(
+      dbClient, es.client()), new SourceLineIndexer(dbClient, es.client()), new TestIndexer(dbClient, es.client()), mockResourceTypes), dbClient, userSessionRule)));
+    db.truncateTables();
+    es.truncateIndices();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void delete_projects_and_data_in_db_by_uuids() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    long snapshotId1 = insertNewProjectInDbAndReturnSnapshotId(1);
+    long snapshotId2 = insertNewProjectInDbAndReturnSnapshotId(2);
+    long snapshotId3 = insertNewProjectInDbAndReturnSnapshotId(3);
+    long snapshotId4 = insertNewProjectInDbAndReturnSnapshotId(4);
+
+    ws.newGetRequest("api/projects", "delete")
+      .setParam("uuids", "project-uuid-1, project-uuid-3, project-uuid-4").execute();
+    dbSession.commit();
+
+    assertThat(dbClient.componentDao().selectByUuids(dbSession, Arrays.asList("project-uuid-1", "project-uuid-3", "project-uuid-4"))).isEmpty();
+    assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-2")).isNotNull();
+    assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId1)).isNull();
+    assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId3)).isNull();
+    assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId4)).isNull();
+    assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId2)).isNotNull();
+    assertThat(dbClient.issueDao().selectByKeys(dbSession, Arrays.asList("issue-key-1", "issue-key-3", "issue-key-4"))).isEmpty();
+    assertThat(dbClient.issueDao().selectByKey(dbSession, "issue-key-2")).isNotNull();
+  }
+
+  @Test
+  public void delete_projects_and_data_in_db_by_keys() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    insertNewProjectInDbAndReturnSnapshotId(1);
+    insertNewProjectInDbAndReturnSnapshotId(2);
+    insertNewProjectInDbAndReturnSnapshotId(3);
+    insertNewProjectInDbAndReturnSnapshotId(4);
+
+    ws.newGetRequest("api/projects", "delete")
+      .setParam("keys", "project-key-1, project-key-3, project-key-4").execute();
+    dbSession.commit();
+
+    assertThat(dbClient.componentDao().selectByUuids(dbSession, Arrays.asList("project-uuid-1", "project-uuid-3", "project-uuid-4"))).isEmpty();
+    assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-2")).isNotNull();
+  }
+
+  @Test
+  public void delete_documents_indexes() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    insertNewProjectInIndexes(1);
+    insertNewProjectInIndexes(2);
+    insertNewProjectInIndexes(3);
+    insertNewProjectInIndexes(4);
+
+    ws.newGetRequest("api/projects", "delete")
+      .setParam("keys", "project-key-1, project-key-3, project-key-4").execute();
+
+    String remainingProjectUuid = "project-uuid-2";
+    assertThat(es.getDocumentFieldValues(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID))
+      .containsOnly(remainingProjectUuid);
+    assertThat(es.getDocumentFieldValues(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID))
+      .containsOnly(remainingProjectUuid);
+    assertThat(es.getDocumentFieldValues(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE, SourceLineIndexDefinition.FIELD_PROJECT_UUID))
+      .containsOnly(remainingProjectUuid);
+    assertThat(es.getDocumentFieldValues(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, TestIndexDefinition.FIELD_PROJECT_UUID))
+      .containsOnly(remainingProjectUuid);
+  }
+
+  @Test
+  public void web_service_returns_204() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    insertNewProjectInDbAndReturnSnapshotId(1);
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "delete").setParam("uuids", "project-uuid-1").execute();
+
+    result.assertNoContent();
+  }
+
+  @Test
+  public void fail_if_insufficient_privileges() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, UserRole.USER);
+    expectedException.expect(ForbiddenException.class);
+
+    ws.newGetRequest("api/projects", "delete").setParam("uuids", "whatever-the-uuid").execute();
+  }
+
+  @Test
+  public void fail_if_scope_is_not_project() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    expectedException.expect(IllegalArgumentException.class);
+    dbClient.componentDao().insert(dbSession, ComponentTesting.newFileDto(ComponentTesting.newProjectDto(), "file-uuid"));
+    dbSession.commit();
+
+    ws.newGetRequest("api/projects", "delete").setParam("uuids", "file-uuid").execute();
+  }
+
+  @Test
+  public void fail_if_qualifier_is_not_deletable() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    expectedException.expect(IllegalArgumentException.class);
+    dbClient.componentDao().insert(dbSession, ComponentTesting.newProjectDto("project-uuid").setQualifier(Qualifiers.FILE));
+    dbSession.commit();
+    when(resourceType.getBooleanProperty(anyString())).thenReturn(false);
+
+    ws.newGetRequest("api/projects", "delete").setParam("uuids", "project-uuid").execute();
+  }
+
+  private long insertNewProjectInDbAndReturnSnapshotId(int id) {
+    String suffix = String.valueOf(id);
+    ComponentDto project = ComponentTesting
+      .newProjectDto("project-uuid-" + suffix)
+      .setKey("project-key-" + suffix);
+    RuleDto rule = RuleTesting.newDto(RuleKey.of("sonarqube", "rule-" + suffix));
+    dbClient.ruleDao().insert(dbSession, rule);
+    IssueDto issue = IssueTesting.newDto(rule, project, project).setKee("issue-key-" + suffix);
+    dbClient.componentDao().insert(dbSession, project);
+    SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, SnapshotTesting.createForProject(project));
+    dbClient.issueDao().insert(dbSession, issue);
+    dbSession.commit();
+
+    return snapshot.getId();
+  }
+
+  private void insertNewProjectInIndexes(int id) throws Exception {
+    String suffix = String.valueOf(id);
+    ComponentDto project = ComponentTesting
+      .newProjectDto("project-uuid-" + suffix)
+      .setKey("project-key-" + suffix);
+    dbClient.componentDao().insert(dbSession, project);
+    dbSession.commit();
+
+    es.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueTesting.newDoc("issue-key-" + suffix, project));
+    SourceLineDoc sourceLineDoc = new SourceLineDoc()
+      .setProjectUuid(project.uuid())
+      .setFileUuid(project.uuid());
+    es.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION,
+      ImmutableMap.<String, Object>of(IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, project.uuid()));
+
+    es.putDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE, sourceLineDoc);
+    TestDoc testDoc = new TestDoc().setUuid("test-uuid-" + suffix).setProjectUuid(project.uuid()).setFileUuid(project.uuid());
+    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, testDoc);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/GhostsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/GhostsActionTest.java
new file mode 100644 (file)
index 0000000..3b3535d
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import com.google.common.io.Resources;
+import org.apache.commons.lang.StringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.component.SnapshotDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.SnapshotTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.component.db.SnapshotDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.test.DbTests;
+import org.sonar.test.JsonAssert;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class GhostsActionTest {
+
+  @ClassRule
+  public static DbTester db = new DbTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+  WsTester ws;
+
+  DbClient dbClient;
+  DbSession dbSession;
+
+  @Before
+  public void setUp() {
+    dbClient = new DbClient(db.database(), db.myBatis(), new ComponentDao(), new SnapshotDao(System2.INSTANCE));
+    dbSession = dbClient.openSession(false);
+    ws = new WsTester(new ProjectsWs(new GhostsAction(dbClient, userSessionRule)));
+    db.truncateTables();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void ghost_projects_without_analyzed_projects() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    insertNewGhostProject("1");
+    insertNewGhostProject("2");
+    insertNewActiveProject("3");
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts").execute();
+
+    result.assertJson(getClass(), "all-projects.json");
+    assertThat(result.outputAsString()).doesNotContain("analyzed-uuid-3");
+  }
+
+  @Test
+  public void ghost_projects_with_correct_pagination() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    for (int i = 1; i <= 10; i++) {
+      insertNewGhostProject(String.valueOf(i));
+    }
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts")
+      .setParam(Param.PAGE, "3")
+      .setParam(Param.PAGE_SIZE, "4")
+      .execute();
+
+    result.assertJson(getClass(), "pagination.json");
+    assertThat(StringUtils.countMatches(result.outputAsString(), "ghost-uuid-")).isEqualTo(2);
+  }
+
+  @Test
+  public void ghost_projects_with_chosen_fields() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    insertNewGhostProject("1");
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts")
+      .setParam(Param.FIELDS, "name")
+      .execute();
+
+    assertThat(result.outputAsString()).contains("uuid", "name")
+      .doesNotContain("key")
+      .doesNotContain("creationDate");
+  }
+
+  @Test
+  public void ghost_projects_with_partial_query_on_name() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+
+    insertNewGhostProject("10");
+    insertNewGhostProject("11");
+    insertNewGhostProject("2");
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts")
+      .setParam(Param.TEXT_QUERY, "name-1")
+      .execute();
+
+    assertThat(result.outputAsString()).contains("ghost-name-10", "ghost-name-11")
+      .doesNotContain("ghost-name-2");
+  }
+
+  @Test
+  public void ghost_projects_with_partial_query_on_key() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+
+    insertNewGhostProject("1");
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts")
+      .setParam(Param.TEXT_QUERY, "GHOST-key")
+      .execute();
+
+    assertThat(result.outputAsString()).contains("ghost-key-1");
+  }
+
+  @Test
+  public void ghost_projects_base_on_json_example() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+    ComponentDto hBaseProject = ComponentTesting.newProjectDto("ce4c03d6-430f-40a9-b777-ad877c00aa4d")
+      .setKey("org.apache.hbas:hbase")
+      .setName("HBase")
+      .setCreatedAt(DateUtils.parseDateTime("2015-03-04T23:03:44+0100"));
+    dbClient.componentDao().insert(dbSession, hBaseProject);
+    dbClient.snapshotDao().insert(dbSession, SnapshotTesting.createForProject(hBaseProject)
+      .setStatus(SnapshotDto.STATUS_UNPROCESSED));
+    ComponentDto roslynProject = ComponentTesting.newProjectDto("c526ef20-131b-4486-9357-063fa64b5079")
+      .setKey("com.microsoft.roslyn:roslyn")
+      .setName("Roslyn")
+      .setCreatedAt(DateUtils.parseDateTime("2013-03-04T23:03:44+0100"));
+    dbClient.componentDao().insert(dbSession, roslynProject);
+    dbClient.snapshotDao().insert(dbSession, SnapshotTesting.createForProject(roslynProject)
+      .setStatus(SnapshotDto.STATUS_UNPROCESSED));
+    dbSession.commit();
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "ghosts").execute();
+
+    JsonAssert.assertJson(result.outputAsString()).isSimilarTo(Resources.getResource(getClass(), "projects-example-ghosts.json"));
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_if_does_not_have_sufficient_rights() throws Exception {
+    userSessionRule.setGlobalPermissions(UserRole.USER, UserRole.ISSUE_ADMIN, UserRole.CODEVIEWER);
+
+    ws.newGetRequest("api/projects", "ghosts").execute();
+  }
+
+  private void insertNewGhostProject(String id) {
+    ComponentDto project = ComponentTesting
+      .newProjectDto("ghost-uuid-" + id)
+      .setName("ghost-name-" + id)
+      .setKey("ghost-key-" + id);
+    dbClient.componentDao().insert(dbSession, project);
+    SnapshotDto snapshot = SnapshotTesting.createForProject(project)
+      .setStatus(SnapshotDto.STATUS_UNPROCESSED);
+    dbClient.snapshotDao().insert(dbSession, snapshot);
+    dbSession.commit();
+  }
+
+  private void insertNewActiveProject(String id) {
+    ComponentDto project = ComponentTesting
+      .newProjectDto("analyzed-uuid-" + id)
+      .setName("analyzed-name-" + id)
+      .setKey("analyzed-key-" + id);
+    dbClient.componentDao().insert(dbSession, project);
+    SnapshotDto snapshot = SnapshotTesting.createForProject(project);
+    dbClient.snapshotDao().insert(dbSession, snapshot);
+    dbSession.commit();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java
new file mode 100644 (file)
index 0000000..7bd3f1d
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.server.ws.RailsHandler;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProjectsWsTest {
+
+  WebService.Controller controller;
+  WsTester ws;
+
+  @Before
+  public void setUp() {
+    ws = new WsTester(new ProjectsWs());
+    controller = ws.controller("api/projects");
+  }
+
+  @Test
+  public void define_controller() {
+    assertThat(controller).isNotNull();
+    assertThat(controller.description()).isNotEmpty();
+    assertThat(controller.since()).isEqualTo("2.10");
+    assertThat(controller.actions()).hasSize(3);
+  }
+
+  @Test
+  public void define_index_action() {
+    WebService.Action action = controller.action("index");
+    assertThat(action).isNotNull();
+    assertThat(action.handler()).isInstanceOf(RailsHandler.class);
+    assertThat(action.responseExampleAsString()).isNotEmpty();
+    assertThat(action.params()).hasSize(8);
+  }
+
+  @Test
+  public void define_create_action() {
+    WebService.Action action = controller.action("create");
+    assertThat(action).isNotNull();
+    assertThat(action.handler()).isInstanceOf(RailsHandler.class);
+    assertThat(action.responseExampleAsString()).isNotEmpty();
+    assertThat(action.params()).hasSize(4);
+  }
+
+  @Test
+  public void define_destroy_action() {
+    WebService.Action action = controller.action("destroy");
+    assertThat(action).isNotNull();
+    assertThat(action.handler()).isInstanceOf(RailsHandler.class);
+    assertThat(action.params()).hasSize(1);
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProvisionedActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProvisionedActionTest.java
new file mode 100644 (file)
index 0000000..c96928f
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.project.ws;
+
+import com.google.common.io.Resources;
+import org.apache.commons.lang.StringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.component.SnapshotDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.SnapshotTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.component.db.SnapshotDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.test.DbTests;
+import org.sonar.test.JsonAssert;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class ProvisionedActionTest {
+
+  @ClassRule
+  public static DbTester db = new DbTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  WsTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+  ComponentDao componentDao;
+
+  @After
+  public void tearDown() {
+    dbSession.close();
+  }
+
+  @Before
+  public void setUp() {
+    dbClient = new DbClient(db.database(), db.myBatis(), new ComponentDao(), new SnapshotDao(System2.INSTANCE));
+    dbSession = dbClient.openSession(false);
+    componentDao = dbClient.componentDao();
+    db.truncateTables();
+    ws = new WsTester(new ProjectsWs(new ProvisionedAction(dbClient, userSessionRule)));
+  }
+
+  @Test
+  public void all_provisioned_projects_without_analyzed_projects() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
+    ComponentDto analyzedProject = ComponentTesting.newProjectDto("analyzed-uuid-1");
+    componentDao.insert(dbSession, newProvisionedProject("1"), newProvisionedProject("2"), analyzedProject);
+    SnapshotDto snapshot = SnapshotTesting.createForProject(analyzedProject);
+    dbClient.snapshotDao().insert(dbSession, snapshot);
+    dbSession.commit();
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "provisioned").execute();
+
+    result.assertJson(getClass(), "all-projects.json");
+    assertThat(result.outputAsString()).doesNotContain("analyzed-uuid-1");
+  }
+
+  @Test
+  public void provisioned_projects_with_correct_pagination() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
+    for (int i = 1; i <= 10; i++) {
+      componentDao.insert(dbSession, newProvisionedProject(String.valueOf(i)));
+    }
+    dbSession.commit();
+
+    WsTester.TestRequest request = ws.newGetRequest("api/projects", "provisioned")
+      .setParam(Param.PAGE, "3")
+      .setParam(Param.PAGE_SIZE, "4");
+
+    String jsonOutput = request.execute().outputAsString();
+
+    assertThat(StringUtils.countMatches(jsonOutput, "provisioned-uuid-")).isEqualTo(2);
+  }
+
+  @Test
+  public void provisioned_projects_with_desired_fields() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
+    componentDao.insert(dbSession, newProvisionedProject("1"));
+    dbSession.commit();
+
+    String jsonOutput = ws.newGetRequest("api/projects", "provisioned")
+      .setParam(Param.FIELDS, "key")
+      .execute().outputAsString();
+
+    assertThat(jsonOutput).contains("uuid", "key")
+      .doesNotContain("name")
+      .doesNotContain("creationDate");
+  }
+
+  @Test
+  public void provisioned_projects_with_query() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
+    componentDao.insert(dbSession, newProvisionedProject("1"), newProvisionedProject("2"));
+    dbSession.commit();
+
+    String jsonOutput = ws.newGetRequest("api/projects", "provisioned")
+      .setParam(Param.TEXT_QUERY, "PROVISIONED-name-2")
+      .execute().outputAsString();
+
+    assertThat(jsonOutput)
+      .contains("provisioned-name-2", "provisioned-uuid-2")
+      .doesNotContain("provisioned-uuid-1");
+    assertThat(componentDao.countProvisionedProjects(dbSession, "name-2")).isEqualTo(1);
+    assertThat(componentDao.countProvisionedProjects(dbSession, "key-2")).isEqualTo(1);
+    assertThat(componentDao.countProvisionedProjects(dbSession, "visioned-name-")).isEqualTo(2);
+  }
+
+  @Test
+  public void provisioned_projects_as_defined_in_the_example() throws Exception {
+    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
+    ComponentDto hBaseProject = ComponentTesting.newProjectDto("ce4c03d6-430f-40a9-b777-ad877c00aa4d")
+      .setKey("org.apache.hbas:hbase")
+      .setName("HBase")
+      .setCreatedAt(DateUtils.parseDateTime("2015-03-04T23:03:44+0100"));
+    ComponentDto roslynProject = ComponentTesting.newProjectDto("c526ef20-131b-4486-9357-063fa64b5079")
+      .setKey("com.microsoft.roslyn:roslyn")
+      .setName("Roslyn")
+      .setCreatedAt(DateUtils.parseDateTime("2013-03-04T23:03:44+0100"));
+    componentDao.insert(dbSession, hBaseProject, roslynProject);
+    dbSession.commit();
+
+    WsTester.Result result = ws.newGetRequest("api/projects", "provisioned").execute();
+
+    JsonAssert.assertJson(result.outputAsString()).isSimilarTo(Resources.getResource(getClass(), "projects-example-provisioned.json"));
+  }
+
+  @Test
+  public void fail_when_not_enough_privileges() throws Exception {
+    expectedException.expect(ForbiddenException.class);
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+    componentDao.insert(dbSession, newProvisionedProject("1"));
+
+    ws.newGetRequest("api/projects", "provisioned").execute();
+  }
+
+  private static ComponentDto newProvisionedProject(String uuid) {
+    return ComponentTesting
+      .newProjectDto("provisioned-uuid-" + uuid)
+      .setName("provisioned-name-" + uuid)
+      .setKey("provisioned-key-" + uuid);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/AppActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/AppActionTest.java
new file mode 100644 (file)
index 0000000..8da15e9
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualitygate.ws;
+
+import com.google.common.collect.ImmutableList;
+import org.json.simple.JSONValue;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metric.ValueType;
+import org.sonar.core.timemachine.Periods;
+import org.sonar.server.qualitygate.QgateProjectFinder;
+import org.sonar.server.qualitygate.QualityGates;
+import org.sonar.server.ws.WsTester;
+
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AppActionTest {
+
+  @Mock
+  private QualityGates qGates;
+
+  @Mock
+  private Periods periods;
+
+  @Mock
+  private I18n i18n;
+
+  WsTester tester;
+
+  @Before
+  public void setUp() {
+    tester = new WsTester(new QGatesWs(
+      new ListAction(qGates), new ShowAction(qGates), new SearchAction(mock(QgateProjectFinder.class)),
+      new CreateAction(qGates), new CopyAction(qGates), new DestroyAction(qGates), new RenameAction(qGates),
+      new SetAsDefaultAction(qGates), new UnsetDefaultAction(qGates),
+      new CreateConditionAction(qGates), new UpdateConditionAction(qGates), new DeleteConditionAction(qGates),
+      new SelectAction(qGates), new DeselectAction(qGates), new AppAction(qGates, periods, i18n)));
+  }
+
+  @Test
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  public void should_initialize_app() throws Exception {
+    doAnswer(new Answer<String>() {
+      @Override
+      public String answer(InvocationOnMock invocation) throws Throwable {
+        return (String) invocation.getArguments()[1];
+      }
+    }).when(i18n).message(any(Locale.class), any(String.class), any(String.class));
+
+    Metric metric = mock(Metric.class);
+    when(metric.getId()).thenReturn(42);
+    when(metric.getKey()).thenReturn("metric");
+    when(metric.getName()).thenReturn("Metric");
+    when(metric.getType()).thenReturn(ValueType.BOOL);
+    when(metric.getDomain()).thenReturn("General");
+    when(metric.isHidden()).thenReturn(false);
+    when(qGates.gateMetrics()).thenReturn(ImmutableList.of(metric));
+
+    String json = tester.newGetRequest("api/qualitygates", "app").execute().outputAsString();
+
+    Map responseJson = (Map) JSONValue.parse(json);
+    assertThat((Boolean) responseJson.get("edit")).isFalse();
+    Collection<Map> periods = (Collection<Map>) responseJson.get("periods");
+    assertThat(periods).hasSize(5);
+    Collection<Map> metrics = (Collection<Map>) responseJson.get("metrics");
+    assertThat(metrics).hasSize(1);
+    Map metricMap = metrics.iterator().next();
+    assertThat(metricMap.get("id").toString()).isEqualTo("42");
+    assertThat(metricMap.get("key")).isEqualTo("metric");
+    assertThat(metricMap.get("name")).isEqualTo("Metric");
+    assertThat(metricMap.get("type")).isEqualTo("BOOL");
+    assertThat(metricMap.get("domain")).isEqualTo("General");
+    assertThat(metricMap.get("hidden")).isEqualTo(false);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesAppActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesAppActionTest.java
deleted file mode 100644 (file)
index 7cbbb3d..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualitygate.ws;
-
-import com.google.common.collect.ImmutableList;
-import org.json.simple.JSONValue;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.Metric.ValueType;
-import org.sonar.core.timemachine.Periods;
-import org.sonar.server.qualitygate.QgateProjectFinder;
-import org.sonar.server.qualitygate.QualityGates;
-import org.sonar.server.ws.WsTester;
-
-import java.util.Collection;
-import java.util.Locale;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class QGatesAppActionTest {
-
-  @Mock
-  private QualityGates qGates;
-
-  @Mock
-  private Periods periods;
-
-  @Mock
-  private I18n i18n;
-
-  WsTester tester;
-
-  @Before
-  public void setUp() {
-    tester = new WsTester(new QGatesWs(
-      new QGatesListAction(qGates), new QGatesShowAction(qGates), new QGatesSearchAction(mock(QgateProjectFinder.class)),
-      new QGatesCreateAction(qGates), new QGatesCopyAction(qGates), new QGatesDestroyAction(qGates), new QGatesRenameAction(qGates),
-      new QGatesSetAsDefaultAction(qGates), new QGatesUnsetDefaultAction(qGates),
-      new QGatesCreateConditionAction(qGates), new QGatesUpdateConditionAction(qGates), new QGatesDeleteConditionAction(qGates),
-      new QGatesSelectAction(qGates), new QGatesDeselectAction(qGates), new QGatesAppAction(qGates, periods, i18n)));
-  }
-
-  @Test
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  public void should_initialize_app() throws Exception {
-    doAnswer(new Answer<String>() {
-      @Override
-      public String answer(InvocationOnMock invocation) throws Throwable {
-        return (String) invocation.getArguments()[1];
-      }
-    }).when(i18n).message(any(Locale.class), any(String.class), any(String.class));
-
-    Metric metric = mock(Metric.class);
-    when(metric.getId()).thenReturn(42);
-    when(metric.getKey()).thenReturn("metric");
-    when(metric.getName()).thenReturn("Metric");
-    when(metric.getType()).thenReturn(ValueType.BOOL);
-    when(metric.getDomain()).thenReturn("General");
-    when(metric.isHidden()).thenReturn(false);
-    when(qGates.gateMetrics()).thenReturn(ImmutableList.of(metric));
-
-    String json = tester.newGetRequest("api/qualitygates", "app").execute().outputAsString();
-
-    Map responseJson = (Map) JSONValue.parse(json);
-    assertThat((Boolean) responseJson.get("edit")).isFalse();
-    Collection<Map> periods = (Collection<Map>) responseJson.get("periods");
-    assertThat(periods).hasSize(5);
-    Collection<Map> metrics = (Collection<Map>) responseJson.get("metrics");
-    assertThat(metrics).hasSize(1);
-    Map metricMap = metrics.iterator().next();
-    assertThat(metricMap.get("id").toString()).isEqualTo("42");
-    assertThat(metricMap.get("key")).isEqualTo("metric");
-    assertThat(metricMap.get("name")).isEqualTo("Metric");
-    assertThat(metricMap.get("type")).isEqualTo("BOOL");
-    assertThat(metricMap.get("domain")).isEqualTo("General");
-    assertThat(metricMap.get("hidden")).isEqualTo(false);
-  }
-}
index 0eea3c11b57718d047ef3aa0eb547fa133a86fb8..e912b7816786275d474f5742b4a0e2d33d4c1dc0 100644 (file)
@@ -60,18 +60,18 @@ public class QGatesWsTest {
   private QgateProjectFinder projectFinder;
 
   @Mock
-  private QGatesAppAction appHandler;
+  private AppAction appHandler;
 
   WsTester tester;
 
   @Before
   public void setUp() {
     tester = new WsTester(new QGatesWs(
-      new QGatesListAction(qGates), new QGatesShowAction(qGates), new QGatesSearchAction(projectFinder),
-      new QGatesCreateAction(qGates), new QGatesCopyAction(qGates), new QGatesDestroyAction(qGates), new QGatesRenameAction(qGates),
-      new QGatesSetAsDefaultAction(qGates), new QGatesUnsetDefaultAction(qGates),
-      new QGatesCreateConditionAction(qGates), new QGatesUpdateConditionAction(qGates), new QGatesDeleteConditionAction(qGates),
-      new QGatesSelectAction(qGates), new QGatesDeselectAction(qGates), new QGatesAppAction(qGates, mock(Periods.class), mock(I18n.class))));
+      new ListAction(qGates), new ShowAction(qGates), new SearchAction(projectFinder),
+      new CreateAction(qGates), new CopyAction(qGates), new DestroyAction(qGates), new RenameAction(qGates),
+      new SetAsDefaultAction(qGates), new UnsetDefaultAction(qGates),
+      new CreateConditionAction(qGates), new UpdateConditionAction(qGates), new DeleteConditionAction(qGates),
+      new SelectAction(qGates), new DeselectAction(qGates), new AppAction(qGates, mock(Periods.class), mock(I18n.class))));
   }
 
   @Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java
new file mode 100644 (file)
index 0000000..37c920b
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileBackuper;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.WsTester.Result;
+
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+@RunWith(MockitoJUnitRunner.class)
+public class BackupActionTest {
+
+  @ClassRule
+  public static final DbTester db = new DbTester();
+
+  // TODO Replace with proper DbTester + EsTester medium test once DaoV2 is removed
+  @Mock
+  private QProfileBackuper backuper;
+
+  private WsTester tester;
+
+  @Before
+  public void setUp() {
+    DbClient dbClient = new DbClient(db.database(), db.myBatis());
+
+    tester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new BackupAction(backuper, dbClient, new QProfileFactory(dbClient), LanguageTesting.newLanguages("xoo"))));
+  }
+
+  @Test
+  public void backup_profile() throws Exception {
+    String profileKey = "polop-palap-xoo-12345";
+
+    final String response = "<polop><palap/></polop>";
+    doAnswer(new Answer<Void>() {
+      @Override
+      public Void answer(InvocationOnMock invocation) throws Throwable {
+        Writer w = (Writer) invocation.getArguments()[1];
+        new PrintWriter(w).print(response);
+        w.close();
+        return null;
+      }
+    }).when(backuper).backup(eq(profileKey), any(Writer.class));
+
+    Result result = tester.newGetRequest("api/qualityprofiles", "backup").setParam("profileKey", profileKey).execute();
+    assertThat(result.outputAsString()).isEqualTo(response);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_key() throws Exception {
+    tester.newGetRequest("api/qualityprofiles", "backup").execute();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionMediumTest.java
new file mode 100644 (file)
index 0000000..52ead31
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.qualityprofile.QProfileTesting;
+import org.sonar.server.qualityprofile.RuleActivator;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ChangeParentActionMediumTest {
+
+  // TODO Replace with DbTester + EsTester once DaoV2 is removed
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
+
+  QProfilesWs ws;
+  DbClient db;
+  DbSession session;
+  WsTester wsTester;
+
+  @Before
+  public void setUp() {
+    tester.clearDbAndIndexes();
+    db = tester.get(DbClient.class);
+    ws = tester.get(QProfilesWs.class);
+    wsTester = tester.get(WsTester.class);
+    session = db.openSession(false);
+    userSessionRule.login("gandalf").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+  }
+
+  @After
+  public void after() {
+    session.close();
+  }
+
+  @Test
+  public void change_parent_with_no_parent_before() throws Exception {
+    QualityProfileDto parent1 = createProfile("xoo", "Parent 1");
+    QualityProfileDto child = createProfile("xoo", "Child");
+
+    RuleDto rule1 = createRule("xoo", "rule1");
+    createActiveRule(rule1, parent1);
+    session.commit();
+
+    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
+
+    // Set parent
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey())
+      .setParam("parentKey", parent1.getKey().toString())
+      .execute();
+    session.clearCache();
+
+    // Check rule 1 enabled
+    List<ActiveRuleDto> activeRules1 = db.activeRuleDao().findByProfileKey(session, child.getKey());
+    assertThat(activeRules1).hasSize(1);
+    assertThat(activeRules1.get(0).getKey().ruleKey().rule()).isEqualTo("rule1");
+  }
+
+  @Test
+  public void replace_existing_parent() throws Exception {
+    QualityProfileDto parent1 = createProfile("xoo", "Parent 1");
+    QualityProfileDto parent2 = createProfile("xoo", "Parent 2");
+    QualityProfileDto child = createProfile("xoo", "Child");
+
+    RuleDto rule1 = createRule("xoo", "rule1");
+    RuleDto rule2 = createRule("xoo", "rule2");
+    createActiveRule(rule1, parent1);
+    createActiveRule(rule2, parent2);
+    session.commit();
+
+    // Set parent 1
+    tester.get(RuleActivator.class).setParent(child.getKey(), parent1.getKey());
+    session.clearCache();
+
+    // Set parent 2 through WS
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey())
+      .setParam("parentKey", parent2.getKey().toString())
+      .execute();
+    session.clearCache();
+
+    // Check rule 2 enabled
+    List<ActiveRuleDto> activeRules2 = db.activeRuleDao().findByProfileKey(session, child.getKey());
+    assertThat(activeRules2).hasSize(1);
+    assertThat(activeRules2.get(0).getKey().ruleKey().rule()).isEqualTo("rule2");
+  }
+
+  @Test
+  public void remove_parent() throws Exception {
+    QualityProfileDto parent = createProfile("xoo", "Parent 1");
+    QualityProfileDto child = createProfile("xoo", "Child");
+
+    RuleDto rule1 = createRule("xoo", "rule1");
+    createActiveRule(rule1, parent);
+    session.commit();
+
+    // Set parent
+    tester.get(RuleActivator.class).setParent(child.getKey(), parent.getKey());
+    session.clearCache();
+
+    // Remove parent through WS
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey())
+      .execute();
+    session.clearCache();
+
+    // Check no rule enabled
+    List<ActiveRuleDto> activeRules = db.activeRuleDao().findByProfileKey(session, child.getKey());
+    assertThat(activeRules).isEmpty();
+  }
+
+  @Test
+  public void change_parent_with_names() throws Exception {
+    QualityProfileDto parent1 = createProfile("xoo", "Parent 1");
+    QualityProfileDto parent2 = createProfile("xoo", "Parent 2");
+    QualityProfileDto child = createProfile("xoo", "Child");
+
+    RuleDto rule1 = createRule("xoo", "rule1");
+    RuleDto rule2 = createRule("xoo", "rule2");
+    createActiveRule(rule1, parent1);
+    createActiveRule(rule2, parent2);
+    session.commit();
+
+    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
+
+    // 1. Set parent 1
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
+      .setParam("parentName", parent1.getName())
+      .execute();
+    session.clearCache();
+
+    // 1. check rule 1 enabled
+    List<ActiveRuleDto> activeRules1 = db.activeRuleDao().findByProfileKey(session, child.getKey());
+    assertThat(activeRules1).hasSize(1);
+    assertThat(activeRules1.get(0).getKey().ruleKey().rule()).isEqualTo("rule1");
+
+    // 2. Set parent 2
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
+      .setParam("parentName", parent2.getName())
+      .execute();
+    session.clearCache();
+
+    // 2. check rule 2 enabled
+    List<ActiveRuleDto> activeRules2 = db.activeRuleDao().findByProfileKey(session, child.getKey());
+    assertThat(activeRules2).hasSize(1);
+    assertThat(activeRules2.get(0).getKey().ruleKey().rule()).isEqualTo("rule2");
+
+    // 3. Remove parent
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
+      .setParam("parentName", "")
+      .execute();
+    session.clearCache();
+
+    // 3. check no rule enabled
+    List<ActiveRuleDto> activeRules = db.activeRuleDao().findByProfileKey(session, child.getKey());
+    assertThat(activeRules).isEmpty();
+  }
+
+  @Test
+  public void remove_parent_with_empty_key() throws Exception {
+    QualityProfileDto parent = createProfile("xoo", "Parent 1");
+    QualityProfileDto child = createProfile("xoo", "Child");
+
+    RuleDto rule1 = createRule("xoo", "rule1");
+    createActiveRule(rule1, parent);
+    session.commit();
+
+    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
+
+    // Set parent
+    tester.get(RuleActivator.class).setParent(child.getKey(), parent.getKey());
+    session.clearCache();
+
+    // Remove parent
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey())
+      .setParam("parentKey", "")
+      .execute();
+    session.clearCache();
+
+    // Check no rule enabled
+    List<ActiveRuleDto> activeRules = db.activeRuleDao().findByProfileKey(session, child.getKey());
+    assertThat(activeRules).isEmpty();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_if_parent_key_and_name_both_set() throws Exception {
+    QualityProfileDto child = createProfile("xoo", "Child");
+    session.commit();
+
+    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
+
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKee())
+      .setParam("parentName", "polop")
+      .setParam("parentKey", "palap")
+      .execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_if_profile_key_and_name_both_set() throws Exception {
+    QualityProfileDto child = createProfile("xoo", "Child");
+    session.commit();
+
+    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
+
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKee())
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
+      .setParam("parentKey", "palap")
+      .execute();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_if_missing_permission() throws Exception {
+    userSessionRule.login("anakin");
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, "polop")
+      .setParam("parentKey", "pulup")
+      .execute();
+  }
+
+  private QualityProfileDto createProfile(String lang, String name) {
+    QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), "p" + lang + "-" + name.toLowerCase());
+    db.qualityProfileDao().insert(session, profile);
+    return profile;
+  }
+
+  private RuleDto createRule(String lang, String id) {
+    RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id))
+      .setLanguage(lang)
+      .setSeverity(Severity.BLOCKER)
+      .setStatus(RuleStatus.READY);
+    db.ruleDao().insert(session, rule);
+    return rule;
+  }
+
+  private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) {
+    ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
+      .setSeverity(rule.getSeverityString());
+    db.activeRuleDao().insert(session, activeRule);
+    return activeRule;
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java
new file mode 100644 (file)
index 0000000..3aaf763
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.collect.Maps;
+import org.joda.time.DateTime;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.Uuids;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.ActiveRuleKey;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.activity.Activity;
+import org.sonar.server.activity.index.ActivityDoc;
+import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.activity.index.ActivityIndexDefinition;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.ActiveRuleChange;
+import org.sonar.server.qualityprofile.ActiveRuleChange.Type;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileTesting;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.user.db.UserDao;
+import org.sonar.server.ws.WsTester;
+
+import java.util.Date;
+import java.util.Map;
+
+import static org.mockito.Mockito.mock;
+import static org.sonar.server.qualityprofile.QProfileTesting.XOO_P1_KEY;
+
+public class ChangelogActionTest {
+
+  @ClassRule
+  public static DbTester dbTester = new DbTester();
+
+  @ClassRule
+  public static EsTester esTester = new EsTester().addDefinitions(new ActivityIndexDefinition(new Settings()));
+
+  private DbClient db;
+  private DbSession dbSession;
+  private WsTester wsTester;
+  private String login;
+
+  @Before
+  public void before() {
+    dbTester.truncateTables();
+    esTester.truncateIndices();
+
+    System2 system = mock(System2.class);
+
+    db = new DbClient(dbTester.database(), dbTester.myBatis(), new RuleDao(system), new QualityProfileDao(dbTester.myBatis(), system), new UserDao(dbTester.myBatis(), system));
+    dbSession = db.openSession(false);
+
+    // create pre-defined rules
+    RuleDto xooRule1 = RuleTesting.newXooX1().setSeverity("MINOR");
+    db.ruleDao().insert(dbSession, xooRule1);
+
+    // create pre-defined profiles P1 and P2
+    db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1(), QProfileTesting.newXooP2());
+
+    login = "david";
+    UserDto user = new UserDto().setLogin(login).setName("David").setEmail("dav@id.com").setCreatedAt(System.currentTimeMillis()).setUpdatedAt(System.currentTimeMillis());
+    db.userDao().insert(dbSession, user);
+
+    dbSession.commit();
+    dbSession.clearCache();
+
+    wsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
+      new ChangelogAction(db, new ActivityIndex(esTester.client()), new QProfileFactory(db), LanguageTesting.newLanguages("xoo"))));
+  }
+
+  @After
+  public void after() {
+    dbSession.close();
+  }
+
+  @Test
+  public void changelog_empty() throws Exception {
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
+      .execute().assertJson(getClass(), "changelog_empty.json");
+  }
+
+  @Test
+  public void changelog_nominal() throws Exception {
+    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, new Date(), "max", "10");
+
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
+      .execute().assertJson(getClass(), "changelog_nominal.json");
+  }
+
+  @Test
+  public void changelog_no_param() throws Exception {
+    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, new Date());
+
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
+      .execute().assertJson(getClass(), "changelog_no_param.json");
+  }
+
+  @Test
+  public void changelog_system_user() throws Exception {
+    createActivity(null, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, new Date());
+
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
+      .execute().assertJson(getClass(), "changelog_no_login.json");
+  }
+
+  @Test
+  public void changelog_with_dates() throws Exception {
+    Date yesterday = DateTime.now().minusDays(1).toDate();
+    Date tomorrow = DateTime.now().plusDays(1).toDate();
+
+    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, new Date(), "max", "10");
+
+    // Tests with "since"
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("since",
+      DateUtils.formatDateTime(yesterday))
+      .execute().assertJson(getClass(), "changelog_nominal.json");
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("since",
+      DateUtils.formatDateTime(tomorrow))
+      .execute().assertJson(getClass(), "changelog_empty.json");
+
+    // Tests with "to"
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("to",
+      DateUtils.formatDateTime(yesterday))
+      .execute().assertJson(getClass(), "changelog_empty.json");
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("to",
+      DateUtils.formatDateTime(tomorrow))
+      .execute().assertJson(getClass(), "changelog_nominal.json");
+
+    // Test with both bounds set
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
+      .setParam("since", DateUtils.formatDateTime(yesterday))
+      .setParam("to", DateUtils.formatDateTime(tomorrow))
+      .execute().assertJson(getClass(), "changelog_nominal.json");
+  }
+
+  @Test
+  public void changelog_with_pagination() throws Exception {
+    Date farthest = new Date(1_500_000_000_000L);
+    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, farthest, "max", "10");
+    Date nearest = new Date(1_500_000_100_000L);
+    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.CRITICAL, nearest, "max", "20");
+
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("ps", "1")
+      .execute().assertJson(getClass(), "changelog_page1.json");
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("ps", "1").setParam("p", "2")
+      .execute().assertJson(getClass(), "changelog_page2.json");
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("ps", "1").setParam("p", "3")
+      .execute().assertJson(getClass(), "changelog_page3.json");
+  }
+
+  @Test(expected = NotFoundException.class)
+  public void fail_on_unknown_profile() throws Exception {
+    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", "unknown-profile").execute();
+  }
+
+  private void createActivity(String login, Type type, ActiveRuleKey activeRuleKey, String severity, Date createdAt, String... params) throws Exception {
+    Map<String, String> details = Maps.newHashMap();
+    details.put("key", activeRuleKey.toString());
+    details.put("ruleKey", activeRuleKey.ruleKey().toString());
+    details.put("profileKey", activeRuleKey.qProfile());
+    details.put("severity", severity);
+    for (int i = 0; i < params.length; i += 2) {
+      details.put("param_" + params[i], params[i + 1]);
+    }
+    ActivityDoc doc = new ActivityDoc(Maps.<String, Object>newHashMap());
+    doc.setAction(type.toString());
+    doc.setCreatedAt(createdAt);
+    doc.setDetails(details);
+    doc.setKey(Uuids.create());
+    doc.setLogin(login);
+    doc.setType(Activity.Type.QPROFILE.toString());
+
+    esTester.putDocuments(ActivityIndexDefinition.INDEX, ActivityIndexDefinition.TYPE, doc);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CompareActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CompareActionMediumTest.java
new file mode 100644 (file)
index 0000000..d60550f
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.server.rule.RuleParamType;
+import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.rule.RuleParamDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.qualityprofile.QProfileTesting;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+public class CompareActionMediumTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester().addXoo()
+    .addComponents(new RulesDefinition() {
+      @Override
+      public void define(Context context) {
+        context.createRepository("blah", "xoo")
+          .setName("Blah")
+          .done();
+      }
+    });
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
+
+  private DbClient db;
+
+  private WsTester wsTester;
+
+  private DbSession session;
+
+  @Before
+  public void setUp() {
+    tester.clearDbAndIndexes();
+    db = tester.get(DbClient.class);
+    session = db.openSession(false);
+
+    wsTester = new WsTester(tester.get(QProfilesWs.class));
+  }
+
+  @After
+  public void tearDown() {
+    session.close();
+  }
+
+  @Test
+  public void compare_nominal() throws Exception {
+    RuleDto rule1 = createRule("xoo", "rule1");
+    RuleDto rule2 = createRule("xoo", "rule2");
+    RuleDto rule3 = createRule("xoo", "rule3");
+    RuleDto rule4 = createRuleWithParam("xoo", "rule4");
+    RuleDto rule5 = createRule("xoo", "rule5");
+
+    /*
+     * Profile 1:
+     * - rule 1 active (on both profiles) => "same"
+     * - rule 2 active (only in this profile) => "inLeft"
+     * - rule 4 active with different parameters => "modified"
+     * - rule 5 active with different severity => "modified"
+     */
+    QualityProfileDto profile1 = createProfile("xoo", "Profile 1", "xoo-profile-1-01234");
+    createActiveRule(rule1, profile1);
+    createActiveRule(rule2, profile1);
+    createActiveRuleWithParam(rule4, profile1, "polop");
+    createActiveRuleWithSeverity(rule5, profile1, Severity.MINOR);
+    session.commit();
+
+    /*
+     * Profile 1:
+     * - rule 1 active (on both profiles) => "same"
+     * - rule 3 active (only in this profile) => "inRight"
+     * - rule 4 active with different parameters => "modified"
+     */
+    QualityProfileDto profile2 = createProfile("xoo", "Profile 2", "xoo-profile-2-12345");
+    createActiveRule(rule1, profile2);
+    createActiveRule(rule3, profile2);
+    createActiveRuleWithParam(rule4, profile2, "palap");
+    createActiveRuleWithSeverity(rule5, profile2, Severity.MAJOR);
+    session.commit();
+
+    wsTester.newGetRequest("api/qualityprofiles", "compare")
+      .setParam("leftKey", profile1.getKey())
+      .setParam("rightKey", profile2.getKey())
+      .execute().assertJson(this.getClass(), "compare_nominal.json");
+  }
+
+  @Test
+  public void compare_param_on_left() throws Exception {
+    RuleDto rule1 = createRuleWithParam("xoo", "rule1");
+
+    QualityProfileDto profile1 = createProfile("xoo", "Profile 1", "xoo-profile-1-01234");
+    createActiveRuleWithParam(rule1, profile1, "polop");
+    session.commit();
+
+    QualityProfileDto profile2 = createProfile("xoo", "Profile 2", "xoo-profile-2-12345");
+    createActiveRule(rule1, profile2);
+    session.commit();
+
+    wsTester.newGetRequest("api/qualityprofiles", "compare")
+      .setParam("leftKey", profile1.getKey())
+      .setParam("rightKey", profile2.getKey())
+      .execute().assertJson(this.getClass(), "compare_param_on_left.json");
+  }
+
+  @Test
+  public void compare_param_on_right() throws Exception {
+    RuleDto rule1 = createRuleWithParam("xoo", "rule1");
+
+    QualityProfileDto profile1 = createProfile("xoo", "Profile 1", "xoo-profile-1-01234");
+    createActiveRule(rule1, profile1);
+    session.commit();
+
+    QualityProfileDto profile2 = createProfile("xoo", "Profile 2", "xoo-profile-2-12345");
+    createActiveRuleWithParam(rule1, profile2, "polop");
+    session.commit();
+
+    wsTester.newGetRequest("api/qualityprofiles", "compare")
+      .setParam("leftKey", profile1.getKey())
+      .setParam("rightKey", profile2.getKey())
+      .execute().assertJson(this.getClass(), "compare_param_on_right.json");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_left_param() throws Exception {
+    wsTester.newGetRequest("api/qualityprofiles", "compare")
+      .setParam("rightKey", "polop")
+      .execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_right_param() throws Exception {
+    wsTester.newGetRequest("api/qualityprofiles", "compare")
+      .setParam("leftKey", "polop")
+      .execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_left_profile_not_found() throws Exception {
+    createProfile("xoo", "Right", "xoo-right-12345");
+    wsTester.newGetRequest("api/qualityprofiles", "compare")
+      .setParam("leftKey", "polop")
+      .setParam("rightKey", "xoo-right-12345")
+      .execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_right_profile_not_found() throws Exception {
+    createProfile("xoo", "Left", "xoo-left-12345");
+    wsTester.newGetRequest("api/qualityprofiles", "compare")
+      .setParam("leftKey", "xoo-left-12345")
+      .setParam("rightKey", "polop")
+      .execute();
+  }
+
+  private QualityProfileDto createProfile(String lang, String name, String key) {
+    QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), key);
+    db.qualityProfileDao().insert(session, profile);
+    session.commit();
+    return profile;
+  }
+
+  private RuleDto createRule(String lang, String id) {
+    RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id))
+      .setName(StringUtils.capitalize(id))
+      .setLanguage(lang)
+      .setSeverity(Severity.BLOCKER)
+      .setStatus(RuleStatus.READY);
+    db.ruleDao().insert(session, rule);
+    RuleParamDto param = RuleParamDto.createFor(rule).setName("param_" + id).setType(RuleParamType.STRING.toString());
+    db.ruleDao().addRuleParam(session, rule, param);
+    return rule;
+  }
+
+  private RuleDto createRuleWithParam(String lang, String id) {
+    RuleDto rule = createRule(lang, id);
+    RuleParamDto param = RuleParamDto.createFor(rule).setName("param_" + id).setType(RuleParamType.STRING.toString());
+    db.ruleDao().addRuleParam(session, rule, param);
+    return rule;
+  }
+
+  private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) {
+    ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
+      .setSeverity(rule.getSeverityString());
+    db.activeRuleDao().insert(session, activeRule);
+    return activeRule;
+  }
+
+  private ActiveRuleDto createActiveRuleWithParam(RuleDto rule, QualityProfileDto profile, String value) {
+    ActiveRuleDto activeRule = createActiveRule(rule, profile);
+    RuleParamDto paramDto = db.ruleDao().findRuleParamsByRuleKey(session, rule.getKey()).get(0);
+    ActiveRuleParamDto activeRuleParam = ActiveRuleParamDto.createFor(paramDto).setValue(value);
+    db.activeRuleDao().addParam(session, activeRule, activeRuleParam);
+    return activeRule;
+  }
+
+  private ActiveRuleDto createActiveRuleWithSeverity(RuleDto rule, QualityProfileDto profile, String severity) {
+    ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
+      .setSeverity(severity);
+    db.activeRuleDao().insert(session, activeRule);
+    return activeRule;
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java
new file mode 100644 (file)
index 0000000..161132b
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileCopier;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CopyActionTest {
+
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private WsTester tester;
+
+  // TODO Replace with proper DbTester + EsTester medium test during removal of DaoV2
+  @Mock
+  private QProfileCopier qProfileCopier;
+
+  @Before
+  public void setUp() {
+    tester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new CopyAction(qProfileCopier, LanguageTesting.newLanguages("xoo"), userSessionRule)));
+  }
+
+  @Test
+  public void copy_nominal() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    String fromProfileKey = "xoo-sonar-way-23456";
+    String toName = "Other Sonar Way";
+
+    when(qProfileCopier.copyToName(fromProfileKey, toName)).thenReturn(
+      QualityProfileDto.createFor("xoo-other-sonar-way-12345")
+        .setName(toName)
+        .setLanguage("xoo"));
+
+    tester.newPostRequest("api/qualityprofiles", "copy")
+      .setParam("fromKey", fromProfileKey)
+      .setParam("toName", toName)
+      .execute().assertJson(getClass(), "copy_nominal.json");
+
+    verify(qProfileCopier).copyToName(fromProfileKey, toName);
+  }
+
+  @Test
+  public void copy_with_parent() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    String fromProfileKey = "xoo-sonar-way-23456";
+    String toName = "Other Sonar Way";
+
+    when(qProfileCopier.copyToName(fromProfileKey, toName)).thenReturn(
+      QualityProfileDto.createFor("xoo-other-sonar-way-12345")
+        .setName(toName)
+        .setLanguage("xoo")
+        .setParentKee("xoo-parent-profile-01324"));
+
+    tester.newPostRequest("api/qualityprofiles", "copy")
+      .setParam("fromKey", fromProfileKey)
+      .setParam("toName", toName)
+      .execute().assertJson(getClass(), "copy_with_parent.json");
+
+    verify(qProfileCopier).copyToName(fromProfileKey, toName);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_key() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "copy")
+      .setParam("name", "Other Sonar Way")
+      .execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_name() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "copy")
+      .setParam("key", "sonar-way-xoo1-13245")
+      .execute();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_on_missing_permission() throws Exception {
+    userSessionRule.login("obiwan");
+
+    tester.newPostRequest("api/qualityprofiles", "copy")
+      .setParam("key", "sonar-way-xoo1-13245")
+      .setParam("name", "Hey look I am not quality profile admin!")
+      .execute();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionMediumTest.java
new file mode 100644 (file)
index 0000000..994cee4
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.qualityprofile.QProfileExporters;
+import org.sonar.server.qualityprofile.QProfileExportersTest.StandardExporter;
+import org.sonar.server.qualityprofile.QProfileExportersTest.XooExporter;
+import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileDefinition;
+import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporter;
+import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporterWithError;
+import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporterWithMessages;
+import org.sonar.server.qualityprofile.QProfileExportersTest.XooRulesDefinition;
+import org.sonar.server.qualityprofile.QProfileLoader;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+public class CreateActionMediumTest {
+
+  // TODO Replace with simpler test with DbTester / EsTester after removal of DaoV2
+  @ClassRule
+  public static ServerTester tester = new ServerTester().addXoo().addComponents(
+    XooRulesDefinition.class, XooProfileDefinition.class,
+    XooExporter.class, StandardExporter.class,
+    XooProfileImporter.class, XooProfileImporterWithMessages.class, XooProfileImporterWithError.class);
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
+
+  DbClient db;
+  DbSession dbSession;
+  QProfileExporters exporters;
+  QProfileLoader loader;
+  WsTester wsTester;
+
+  @Before
+  public void before() {
+    db = tester.get(DbClient.class);
+    dbSession = db.openSession(false);
+    exporters = tester.get(QProfileExporters.class);
+    loader = tester.get(QProfileLoader.class);
+    wsTester = new WsTester(tester.get(QProfilesWs.class));
+  }
+
+  @After
+  public void after() {
+    dbSession.close();
+  }
+
+  @Test
+  public void create_nominal() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    wsTester.newPostRequest("api/qualityprofiles", "create")
+      .setParam("backup_XooProfileImporter", "a value for xoo importer")
+      .setParam("language", "xoo")
+      .setParam("name", "My New Profile")
+      .execute().assertJson(this.getClass(), "create-nominal.json");
+  }
+
+  @Test
+  public void create_with_messages() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    wsTester.newPostRequest("api/qualityprofiles", "create")
+      .setParam("backup_XooProfileImporter", "a value for xoo importer")
+      .setParam("backup_XooProfileImporterWithMessages", "this will generate some messages")
+      .setParam("language", "xoo")
+      .setParam("name", "My Other Profile")
+      .execute().assertJson(this.getClass(), "create-with-messages.json");
+  }
+
+  @Test(expected = BadRequestException.class)
+  public void fail_on_error_from_importer() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    wsTester.newPostRequest("api/qualityprofiles", "create")
+      .setParam("backup_XooProfileImporter", "a value for xoo importer")
+      .setParam("backup_XooProfileImporterWithError", "this will fail")
+      .setParam("language", "xoo")
+      .setParam("name", "Error In Importer")
+      .execute();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java
new file mode 100644 (file)
index 0000000..1b6a67a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService.Action;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class CreateActionTest {
+
+  @ClassRule
+  public static final DbTester db = new DbTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  @Test
+  public void should_not_fail_on_no_importers() throws Exception {
+    QualityProfileDao profileDao = new QualityProfileDao(db.myBatis(), mock(System2.class));
+    DbClient dbClient = new DbClient(db.database(), db.myBatis(), profileDao);
+
+    String xooKey = "xoo";
+    WsTester wsTester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
+      new CreateAction(dbClient, new QProfileFactory(dbClient), null, LanguageTesting.newLanguages(xooKey), userSessionRule)));
+
+    Action create = wsTester.controller("api/qualityprofiles").action("create");
+    assertThat(create.params()).hasSize(2);
+
+    userSessionRule.login("anakin").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    wsTester.newPostRequest("api/qualityprofiles", "create")
+      .setParam("language", xooKey).setParam("name", "Yeehaw!").execute().assertJson(getClass(), "create-no-importer.json");
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/DeleteActionTest.java
new file mode 100644 (file)
index 0000000..083e203
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.utils.System2;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.db.ActiveRuleDao;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class DeleteActionTest {
+
+  @ClassRule
+  public static DbTester dbTester = new DbTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private DbClient dbClient;
+
+  private QualityProfileDao qualityProfileDao;
+
+  private ComponentDao componentDao;
+
+  private Language xoo1, xoo2;
+
+  private WsTester tester;
+
+  private DbSession session;
+
+  System2 system2 = mock(System2.class);
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
+    componentDao = new ComponentDao();
+
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao, new ActiveRuleDao(qualityProfileDao, new RuleDao(system2), system2));
+    session = dbClient.openSession(false);
+
+    xoo1 = LanguageTesting.newLanguage("xoo1");
+    xoo2 = LanguageTesting.newLanguage("xoo2");
+
+    tester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new DeleteAction(new Languages(xoo1, xoo2), new QProfileFactory(dbClient), dbClient, userSessionRule)));
+  }
+
+  @After
+  public void teadDown() {
+    session.close();
+  }
+
+  @Test
+  public void delete_nominal_with_key() throws Exception {
+    String profileKey = "sonar-way-xoo1-12345";
+
+    ComponentDto project = ComponentTesting.newProjectDto("polop");
+    componentDao.insert(session, project);
+    qualityProfileDao.insert(session, QualityProfileDto.createFor(profileKey).setLanguage(xoo1.getKey()).setName("Sonar way"));
+    qualityProfileDao.insertProjectProfileAssociation(project.uuid(), profileKey, session);
+    session.commit();
+
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileKey", "sonar-way-xoo1-12345").execute().assertNoContent();
+
+    assertThat(qualityProfileDao.getByKey(session, "sonar-way-xoo1-12345")).isNull();
+    assertThat(qualityProfileDao.selectProjects("Sonar way", xoo1.getName())).isEmpty();
+  }
+
+  @Test
+  public void delete_nominal_with_language_and_name() throws Exception {
+    String profileKey = "sonar-way-xoo1-12345";
+
+    ComponentDto project = ComponentTesting.newProjectDto("polop");
+    componentDao.insert(session, project);
+    qualityProfileDao.insert(session, QualityProfileDto.createFor(profileKey).setLanguage(xoo1.getKey()).setName("Sonar way"));
+    qualityProfileDao.insertProjectProfileAssociation(project.uuid(), profileKey, session);
+    session.commit();
+
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Sonar way").setParam("language", xoo1.getKey()).execute().assertNoContent();
+
+    assertThat(qualityProfileDao.getByKey(session, "sonar-way-xoo1-12345")).isNull();
+    assertThat(qualityProfileDao.selectProjects("Sonar way", xoo1.getName())).isEmpty();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_on_missing_permission() throws Exception {
+    userSessionRule.login("obiwan");
+    tester.newPostRequest("api/qualityprofiles", "delete").execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_arguments() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+    tester.newPostRequest("api/qualityprofiles", "delete").execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_language() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_name() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+    tester.newPostRequest("api/qualityprofiles", "delete").setParam("language", xoo1.getKey()).execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_too_many_arguments() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").setParam("language", xoo1.getKey()).setParam("profileKey", "polop").execute();
+  }
+
+  @Test(expected = NotFoundException.class)
+  public void fail_on_unexisting_profile() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").setParam("language", xoo1.getKey()).execute();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java
new file mode 100644 (file)
index 0000000..d87d18a
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.server.ws.WebService.Action;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.*;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
+import org.sonar.server.search.IndexClient;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.WsTester.Result;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ExportActionTest {
+
+  @ClassRule
+  public static final DbTester db = new DbTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  WsTester wsTester;
+
+  QualityProfileDao qualityProfileDao;
+
+  DbClient dbClient;
+
+  DbSession session;
+
+  QProfileBackuper backuper;
+
+  QProfileExporters exporters;
+
+  @Before
+  public void before() {
+    qualityProfileDao = new QualityProfileDao(db.myBatis(), mock(System2.class));
+    dbClient = new DbClient(db.database(), db.myBatis(), qualityProfileDao);
+    session = dbClient.openSession(false);
+    backuper = mock(QProfileBackuper.class);
+
+    db.truncateTables();
+
+    ProfileExporter exporter1 = newExporter("polop");
+    ProfileExporter exporter2 = newExporter("palap");
+
+    IndexClient indexClient = mock(IndexClient.class);
+    ActiveRuleIndex activeRuleIndex = mock(ActiveRuleIndex.class);
+    when(activeRuleIndex.findByProfile(Matchers.anyString())).thenReturn(Sets.<ActiveRule>newHashSet().iterator());
+
+    when(indexClient.get(ActiveRuleIndex.class)).thenReturn(activeRuleIndex);
+    exporters = new QProfileExporters(new QProfileLoader(dbClient, indexClient, userSessionRule), null, null, new ProfileExporter[] {exporter1, exporter2}, null);
+    wsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new ExportAction(dbClient, new QProfileFactory(dbClient), backuper, exporters, LanguageTesting.newLanguages("xoo"))));
+  }
+
+  @After
+  public void after() {
+    session.close();
+  }
+
+  private ProfileExporter newExporter(final String key) {
+    return new ProfileExporter(key, StringUtils.capitalize(key)) {
+      @Override
+      public String getMimeType() {
+        return "text/plain+" + key;
+      }
+
+      @Override
+      public void exportProfile(RulesProfile profile, Writer writer) {
+        try {
+          writer.write(String.format("Profile %s exported by %s", profile.getName(), key));
+        } catch (IOException ioe) {
+          throw new RuntimeException(ioe);
+        }
+      }
+    };
+  }
+
+  @Test
+  public void export_without_format() throws Exception {
+    QualityProfileDto profile = QProfileTesting.newXooP1();
+    qualityProfileDao.insert(session, profile);
+    session.commit();
+
+    doAnswer(new Answer<Void>() {
+      @Override
+      public Void answer(InvocationOnMock invocation) throws Throwable {
+        invocation.getArgumentAt(1, Writer.class).write("As exported by SQ !");
+        return null;
+      }
+    }).when(backuper).backup(Matchers.eq(profile.getKey()), Matchers.any(Writer.class));
+
+    Result result = wsTester.newGetRequest("api/qualityprofiles", "export").setParam("language", profile.getLanguage()).setParam("name", profile.getName()).execute();
+
+    assertThat(result.outputAsString()).isEqualTo("As exported by SQ !");
+  }
+
+  @Test
+  public void export_with_format() throws Exception {
+    QualityProfileDto profile = QProfileTesting.newXooP1();
+    qualityProfileDao.insert(session, profile);
+    session.commit();
+
+    Result result = wsTester.newGetRequest("api/qualityprofiles", "export")
+      .setParam("language", profile.getLanguage()).setParam("name", profile.getName()).setParam("exporterKey", "polop").execute();
+
+    assertThat(result.outputAsString()).isEqualTo("Profile " + profile.getName() + " exported by polop");
+  }
+
+  @Test
+  public void export_default_profile() throws Exception {
+    QualityProfileDto profile1 = QProfileTesting.newXooP1();
+    QualityProfileDto profile2 = QProfileTesting.newXooP2().setDefault(true);
+    qualityProfileDao.insert(session, profile1, profile2);
+    session.commit();
+
+    Result result = wsTester.newGetRequest("api/qualityprofiles", "export")
+      .setParam("language", "xoo").setParam("exporterKey", "polop").execute();
+
+    assertThat(result.outputAsString()).isEqualTo("Profile " + profile2.getName() + " exported by polop");
+  }
+
+  @Test(expected = NotFoundException.class)
+  public void fail_on_unknown_profile() throws Exception {
+    wsTester.newGetRequest("api/qualityprofiles", "export")
+      .setParam("language", "xoo").setParam("exporterKey", "polop").execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_unknown_exporter() throws Exception {
+    QualityProfileDto profile = QProfileTesting.newXooP1();
+    qualityProfileDao.insert(session, profile);
+    session.commit();
+
+    wsTester.newGetRequest("api/qualityprofiles", "export")
+      .setParam("language", "xoo").setParam("exporterKey", "unknown").execute();
+  }
+
+  @Test
+  public void do_not_fail_when_no_exporters() throws Exception {
+    QProfileExporters myExporters = new QProfileExporters(null, null, null, new ProfileExporter[0], null);
+    WsTester myWsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new ExportAction(dbClient, new QProfileFactory(dbClient), backuper, myExporters, LanguageTesting.newLanguages("xoo"))));
+
+    Action export = myWsTester.controller("api/qualityprofiles").action("export");
+    assertThat(export.params()).hasSize(2);
+
+    QualityProfileDto profile = QProfileTesting.newXooP1();
+    qualityProfileDao.insert(session, profile);
+    session.commit();
+
+    myWsTester.newGetRequest("api/qualityprofiles", "export").setParam("language", "xoo").setParam("name", profile.getName()).execute();
+
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportersActionTest.java
new file mode 100644 (file)
index 0000000..fb84e89
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.Test;
+import org.sonar.api.profiles.ProfileExporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.server.ws.WsTester;
+
+import java.io.Writer;
+
+import static org.mockito.Mockito.mock;
+
+public class ExportersActionTest {
+
+  @Test
+  public void importers_nominal() throws Exception {
+    WsTester wsTester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
+      new ExportersAction(createExporters())));
+
+    wsTester.newGetRequest("api/qualityprofiles", "exporters").execute().assertJson(getClass(), "exporters.json");
+  }
+
+  private ProfileExporter[] createExporters() {
+    class NoopImporter extends ProfileExporter {
+      private NoopImporter(String key, String name, String... languages) {
+        super(key, name);
+        setSupportedLanguages(languages);
+      }
+
+      @Override
+      public void exportProfile(RulesProfile profile, Writer writer) {
+        // Nothing
+      }
+
+    }
+    return new ProfileExporter[] {
+      new NoopImporter("findbugs", "FindBugs", "java"),
+      new NoopImporter("jslint", "JS Lint", "js"),
+      new NoopImporter("vaadin", "Vaadin", "java", "js")
+    };
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ImportersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ImportersActionTest.java
new file mode 100644 (file)
index 0000000..955d744
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.Test;
+import org.sonar.api.profiles.ProfileImporter;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.server.ws.WsTester;
+
+import java.io.Reader;
+
+import static org.mockito.Mockito.mock;
+
+public class ImportersActionTest {
+
+  @Test
+  public void importers_nominal() throws Exception {
+    WsTester wsTester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
+      new ImportersAction(createImporters())));
+
+    wsTester.newGetRequest("api/qualityprofiles", "importers").execute().assertJson(getClass(), "importers.json");
+  }
+
+  private ProfileImporter[] createImporters() {
+    class NoopImporter extends ProfileImporter {
+      private NoopImporter(String key, String name, String... languages) {
+        super(key, name);
+        setSupportedLanguages(languages);
+      }
+
+      @Override
+      public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
+        return RulesProfile.create();
+      }
+
+    }
+    return new ProfileImporter[] {
+      new NoopImporter("findbugs", "FindBugs", "java"),
+      new NoopImporter("jslint", "JS Lint", "js"),
+      new NoopImporter("vaadin", "Vaadin", "java", "js")
+    };
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest.java
new file mode 100644 (file)
index 0000000..6db05c6
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.qualityprofile.QProfileTesting;
+import org.sonar.server.qualityprofile.RuleActivation;
+import org.sonar.server.qualityprofile.RuleActivator;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+public class InheritanceActionMediumTest {
+
+  @ClassRule
+  public static final ServerTester tester = new ServerTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
+
+  private WsTester wsTester;
+
+  private DbClient db;
+
+  private DbSession session;
+
+  @Before
+  public void setUp() {
+    tester.clearDbAndIndexes();
+    db = tester.get(DbClient.class);
+    session = db.openSession(false);
+
+    wsTester = new WsTester(tester.get(QProfilesWs.class));
+  }
+
+  @After
+  public void tearDown() {
+    session.close();
+  }
+
+  @Test
+  public void inheritance_nominal() throws Exception {
+    RuleDto rule1 = createRule("xoo", "rule1");
+    RuleDto rule2 = createRule("xoo", "rule2");
+    RuleDto rule3 = createRule("xoo", "rule3");
+
+    /*
+     * groupWide (2) <- companyWide (2) <- buWide (2, 1 overriding) <- (forProject1 (2), forProject2 (2))
+     */
+    QualityProfileDto groupWide = createProfile("xoo", "My Group Profile", "xoo-my-group-profile-01234");
+    createActiveRule(rule1, groupWide);
+    createActiveRule(rule2, groupWide);
+    session.commit();
+
+    QualityProfileDto companyWide = createProfile("xoo", "My Company Profile", "xoo-my-company-profile-12345");
+    setParent(groupWide, companyWide);
+
+    QualityProfileDto buWide = createProfile("xoo", "My BU Profile", "xoo-my-bu-profile-23456");
+    setParent(companyWide, buWide);
+    overrideActiveRuleSeverity(rule1, buWide, Severity.CRITICAL);
+
+    QualityProfileDto forProject1 = createProfile("xoo", "For Project One", "xoo-for-project-one-34567");
+    setParent(buWide, forProject1);
+    createActiveRule(rule3, forProject1);
+    session.commit();
+
+    QualityProfileDto forProject2 = createProfile("xoo", "For Project Two", "xoo-for-project-two-45678");
+    setParent(buWide, forProject2);
+    overrideActiveRuleSeverity(rule2, forProject2, Severity.CRITICAL);
+
+    wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", buWide.getKee()).execute().assertJson(getClass(), "inheritance-buWide.json");
+  }
+
+  @Test
+  public void inheritance_no_family() throws Exception {
+    // Simple profile, no parent, no child
+    QualityProfileDto remi = createProfile("xoo", "Nobodys Boy", "xoo-nobody-s-boy-01234");
+
+    wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", remi.getKee()).execute().assertJson(getClass(), "inheritance-simple.json");
+  }
+
+  @Test(expected = NotFoundException.class)
+  public void fail_if_not_found() throws Exception {
+    wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", "polop").execute();
+  }
+
+  private QualityProfileDto createProfile(String lang, String name, String key) {
+    QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), key);
+    db.qualityProfileDao().insert(session, profile);
+    session.commit();
+    return profile;
+  }
+
+  private void setParent(QualityProfileDto profile, QualityProfileDto parent) {
+    tester.get(RuleActivator.class).setParent(parent.getKey(), profile.getKey());
+  }
+
+  private RuleDto createRule(String lang, String id) {
+    RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id))
+      .setLanguage(lang)
+      .setSeverity(Severity.BLOCKER)
+      .setStatus(RuleStatus.READY);
+    db.ruleDao().insert(session, rule);
+    return rule;
+  }
+
+  private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) {
+    ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
+      .setSeverity(rule.getSeverityString());
+    db.activeRuleDao().insert(session, activeRule);
+    return activeRule;
+  }
+
+  private void overrideActiveRuleSeverity(RuleDto rule, QualityProfileDto profile, String severity) {
+    tester.get(RuleActivator.class).activate(session, new RuleActivation(rule.getKey()).setSeverity(severity), profile.getKey());
+    session.commit();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ProjectsActionTest.java
new file mode 100644 (file)
index 0000000..097531c
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.user.AuthorizationDao;
+import org.sonar.core.user.GroupRoleDto;
+import org.sonar.core.user.RoleDao;
+import org.sonar.core.user.UserDto;
+import org.sonar.core.user.UserRoleDto;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfileTesting;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.user.db.UserDao;
+import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.WsTester.TestRequest;
+import org.sonar.test.DbTests;
+
+import static org.mockito.Mockito.mock;
+
+@Category(DbTests.class)
+public class ProjectsActionTest {
+
+  @ClassRule
+  public static final DbTester dbTester = new DbTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private WsTester wsTester;
+
+  private DbClient dbClient;
+
+  private DbSession session;
+
+  private QualityProfileDto xooP1, xooP2;
+
+  private ComponentDto project1, project2, project3, project4;
+
+  private Long userId = 42L;
+
+  private RoleDao roleDao;
+
+  System2 system2 = mock(System2.class);
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(),
+      new QualityProfileDao(dbTester.myBatis(), system2),
+      new ComponentDao(),
+      new AuthorizationDao(dbTester.myBatis()));
+    roleDao = new RoleDao();
+    session = dbClient.openSession(false);
+
+    wsTester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new ProjectsAction(dbClient, userSessionRule)));
+
+    userSessionRule.login("obiwan").setUserId(userId.intValue());
+    new UserDao(dbTester.myBatis(), mock(System2.class))
+      .insert(session, new UserDto()
+        .setActive(true)
+        .setId(userId)
+        .setLogin("obiwan"));
+
+    createProfiles();
+
+    session.commit();
+  }
+
+  @After
+  public void tearDown() {
+    session.close();
+  }
+
+  @Test
+  public void should_list_authorized_projects_only() throws Exception {
+    project1 = newProject("ABCD", "Project One");
+    project2 = newProject("BCDE", "Project Two");
+    dbClient.componentDao().insert(session, project1, project2);
+
+    // user only sees project1
+    roleDao.insertUserRole(new UserRoleDto().setUserId(userId).setResourceId(project1.getId()).setRole(UserRole.USER), session);
+
+    associateProjectsWithProfile(session, xooP1, project1, project2);
+
+    session.commit();
+
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").execute().assertJson(this.getClass(), "authorized_selected.json");
+  }
+
+  @Test
+  public void should_paginate() throws Exception {
+    project1 = newProject("ABCD", "Project One");
+    project2 = newProject("BCDE", "Project Two");
+    project3 = newProject("CDEF", "Project Three");
+    project4 = newProject("DEFA", "Project Four");
+    dbClient.componentDao().insert(session, project1, project2, project3, project4);
+
+    addBrowsePermissionToAnyone(session, project1, project2, project3, project4);
+
+    associateProjectsWithProfile(session, xooP1, project1, project2, project3, project4);
+
+    session.commit();
+
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "2")
+      .execute().assertJson(this.getClass(), "selected_page1.json");
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "2").setParam("page", "2")
+      .execute().assertJson(this.getClass(), "selected_page2.json");
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "2").setParam("page", "3")
+      .execute().assertJson(this.getClass(), "empty.json");
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "2").setParam("page", "4")
+      .execute().assertJson(this.getClass(), "empty.json");
+
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "3").setParam("page", "1")
+      .execute().assertJson(this.getClass(), "selected_ps3_page1.json");
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "3").setParam("page", "2")
+      .execute().assertJson(this.getClass(), "selected_ps3_page2.json");
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "3").setParam("page", "3")
+      .execute().assertJson(this.getClass(), "empty.json");
+  }
+
+  @Test
+  public void should_show_unselected() throws Exception {
+    project1 = newProject("ABCD", "Project One");
+    project2 = newProject("BCDE", "Project Two");
+    project3 = newProject("CDEF", "Project Three");
+    project4 = newProject("DEFA", "Project Four");
+    dbClient.componentDao().insert(session, project1, project2, project3, project4);
+
+    addBrowsePermissionToAnyone(session, project1, project2, project3, project4);
+
+    associateProjectsWithProfile(session, xooP1, project1, project2);
+
+    session.commit();
+
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "deselected").execute().assertJson(this.getClass(), "deselected.json");
+  }
+
+  @Test
+  public void should_show_all() throws Exception {
+    project1 = newProject("ABCD", "Project One");
+    project2 = newProject("BCDE", "Project Two");
+    project3 = newProject("CDEF", "Project Three");
+    project4 = newProject("DEFA", "Project Four");
+    dbClient.componentDao().insert(session, project1, project2, project3, project4);
+
+    addBrowsePermissionToAnyone(session, project1, project2, project3, project4);
+
+    associateProjectsWithProfile(session, xooP1, project1, project2);
+    // project3 is associated with P2, must appear as not associated with xooP1
+    associateProjectsWithProfile(session, xooP2, project3);
+
+    session.commit();
+
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "all").execute().assertJson(this.getClass(), "all.json");
+  }
+
+  @Test
+  public void should_filter_on_name() throws Exception {
+    project1 = newProject("ABCD", "Project One");
+    project2 = newProject("BCDE", "Project Two");
+    project3 = newProject("CDEF", "Project Three");
+    project4 = newProject("DEFA", "Project Four");
+    dbClient.componentDao().insert(session, project1, project2, project3, project4);
+
+    addBrowsePermissionToAnyone(session, project1, project2, project3, project4);
+
+    associateProjectsWithProfile(session, xooP1, project1, project2);
+
+    session.commit();
+
+    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "all").setParam("query", "project t").execute().assertJson(this.getClass(), "all_filtered.json");
+  }
+
+  @Test(expected = NotFoundException.class)
+  public void should_fail_on_nonexistent_profile() throws Exception {
+    newRequest().setParam("key", "unknown").setParam("selected", "all").execute();
+  }
+
+  private void createProfiles() {
+    xooP1 = QProfileTesting.newXooP1();
+    xooP2 = QProfileTesting.newXooP2();
+    dbClient.qualityProfileDao().insert(session, xooP1, xooP2);
+  }
+
+  private TestRequest newRequest() {
+    return wsTester.newGetRequest("api/qualityprofiles", "projects");
+  }
+
+  private ComponentDto newProject(String uuid, String name) {
+    return ComponentTesting.newProjectDto(uuid).setName(name);
+  }
+
+  private void addBrowsePermissionToAnyone(DbSession session, ComponentDto... projects) {
+    for (ComponentDto project : projects) {
+      roleDao.insertGroupRole(new GroupRoleDto().setGroupId(null).setResourceId(project.getId()).setRole(UserRole.USER), session);
+    }
+  }
+
+  private void associateProjectsWithProfile(DbSession session, QualityProfileDto profile, ComponentDto... projects) {
+    for (ComponentDto project : projects) {
+      dbClient.qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profile.getKey(), session);
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileBackupActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileBackupActionTest.java
deleted file mode 100644 (file)
index b039d48..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.mockito.stubbing.Answer;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.QProfileBackuper;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.ws.WsTester;
-import org.sonar.server.ws.WsTester.Result;
-
-import java.io.PrintWriter;
-import java.io.Writer;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-
-@RunWith(MockitoJUnitRunner.class)
-public class QProfileBackupActionTest {
-
-  @ClassRule
-  public static final DbTester db = new DbTester();
-
-  // TODO Replace with proper DbTester + EsTester medium test once DaoV2 is removed
-  @Mock
-  private QProfileBackuper backuper;
-
-  private WsTester tester;
-
-  @Before
-  public void setUp() {
-    DbClient dbClient = new DbClient(db.database(), db.myBatis());
-
-    tester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileBackupAction(backuper, dbClient, new QProfileFactory(dbClient), LanguageTesting.newLanguages("xoo"))));
-  }
-
-  @Test
-  public void backup_profile() throws Exception {
-    String profileKey = "polop-palap-xoo-12345";
-
-    final String response = "<polop><palap/></polop>";
-    doAnswer(new Answer<Void>() {
-      @Override
-      public Void answer(InvocationOnMock invocation) throws Throwable {
-        Writer w = (Writer) invocation.getArguments()[1];
-        new PrintWriter(w).print(response);
-        w.close();
-        return null;
-      }
-    }).when(backuper).backup(eq(profileKey), any(Writer.class));
-
-    Result result = tester.newGetRequest("api/qualityprofiles", "backup").setParam("profileKey", profileKey).execute();
-    assertThat(result.outputAsString()).isEqualTo(response);
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_key() throws Exception {
-    tester.newGetRequest("api/qualityprofiles", "backup").execute();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentActionMediumTest.java
deleted file mode 100644 (file)
index 14beeb8..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import java.util.List;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.qualityprofile.db.ActiveRuleDto;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.qualityprofile.QProfileTesting;
-import org.sonar.server.qualityprofile.RuleActivator;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class QProfileChangeParentActionMediumTest {
-
-  // TODO Replace with DbTester + EsTester once DaoV2 is removed
-  @ClassRule
-  public static ServerTester tester = new ServerTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
-  QProfilesWs ws;
-  DbClient db;
-  DbSession session;
-  WsTester wsTester;
-
-  @Before
-  public void setUp() {
-    tester.clearDbAndIndexes();
-    db = tester.get(DbClient.class);
-    ws = tester.get(QProfilesWs.class);
-    wsTester = tester.get(WsTester.class);
-    session = db.openSession(false);
-    userSessionRule.login("gandalf").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-  }
-
-  @After
-  public void after() {
-    session.close();
-  }
-
-  @Test
-  public void change_parent_with_no_parent_before() throws Exception {
-    QualityProfileDto parent1 = createProfile("xoo", "Parent 1");
-    QualityProfileDto child = createProfile("xoo", "Child");
-
-    RuleDto rule1 = createRule("xoo", "rule1");
-    createActiveRule(rule1, parent1);
-    session.commit();
-
-    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
-
-    // Set parent
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey())
-      .setParam("parentKey", parent1.getKey().toString())
-      .execute();
-    session.clearCache();
-
-    // Check rule 1 enabled
-    List<ActiveRuleDto> activeRules1 = db.activeRuleDao().findByProfileKey(session, child.getKey());
-    assertThat(activeRules1).hasSize(1);
-    assertThat(activeRules1.get(0).getKey().ruleKey().rule()).isEqualTo("rule1");
-  }
-
-  @Test
-  public void replace_existing_parent() throws Exception {
-    QualityProfileDto parent1 = createProfile("xoo", "Parent 1");
-    QualityProfileDto parent2 = createProfile("xoo", "Parent 2");
-    QualityProfileDto child = createProfile("xoo", "Child");
-
-    RuleDto rule1 = createRule("xoo", "rule1");
-    RuleDto rule2 = createRule("xoo", "rule2");
-    createActiveRule(rule1, parent1);
-    createActiveRule(rule2, parent2);
-    session.commit();
-
-    // Set parent 1
-    tester.get(RuleActivator.class).setParent(child.getKey(), parent1.getKey());
-    session.clearCache();
-
-    // Set parent 2 through WS
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey())
-      .setParam("parentKey", parent2.getKey().toString())
-      .execute();
-    session.clearCache();
-
-    // Check rule 2 enabled
-    List<ActiveRuleDto> activeRules2 = db.activeRuleDao().findByProfileKey(session, child.getKey());
-    assertThat(activeRules2).hasSize(1);
-    assertThat(activeRules2.get(0).getKey().ruleKey().rule()).isEqualTo("rule2");
-  }
-
-  @Test
-  public void remove_parent() throws Exception {
-    QualityProfileDto parent = createProfile("xoo", "Parent 1");
-    QualityProfileDto child = createProfile("xoo", "Child");
-
-    RuleDto rule1 = createRule("xoo", "rule1");
-    createActiveRule(rule1, parent);
-    session.commit();
-
-    // Set parent
-    tester.get(RuleActivator.class).setParent(child.getKey(), parent.getKey());
-    session.clearCache();
-
-    // Remove parent through WS
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey())
-      .execute();
-    session.clearCache();
-
-    // Check no rule enabled
-    List<ActiveRuleDto> activeRules = db.activeRuleDao().findByProfileKey(session, child.getKey());
-    assertThat(activeRules).isEmpty();
-  }
-
-  @Test
-  public void change_parent_with_names() throws Exception {
-    QualityProfileDto parent1 = createProfile("xoo", "Parent 1");
-    QualityProfileDto parent2 = createProfile("xoo", "Parent 2");
-    QualityProfileDto child = createProfile("xoo", "Child");
-
-    RuleDto rule1 = createRule("xoo", "rule1");
-    RuleDto rule2 = createRule("xoo", "rule2");
-    createActiveRule(rule1, parent1);
-    createActiveRule(rule2, parent2);
-    session.commit();
-
-    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
-
-    // 1. Set parent 1
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
-      .setParam("parentName", parent1.getName())
-      .execute();
-    session.clearCache();
-
-    // 1. check rule 1 enabled
-    List<ActiveRuleDto> activeRules1 = db.activeRuleDao().findByProfileKey(session, child.getKey());
-    assertThat(activeRules1).hasSize(1);
-    assertThat(activeRules1.get(0).getKey().ruleKey().rule()).isEqualTo("rule1");
-
-    // 2. Set parent 2
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
-      .setParam("parentName", parent2.getName())
-      .execute();
-    session.clearCache();
-
-    // 2. check rule 2 enabled
-    List<ActiveRuleDto> activeRules2 = db.activeRuleDao().findByProfileKey(session, child.getKey());
-    assertThat(activeRules2).hasSize(1);
-    assertThat(activeRules2.get(0).getKey().ruleKey().rule()).isEqualTo("rule2");
-
-    // 3. Remove parent
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
-      .setParam("parentName", "")
-      .execute();
-    session.clearCache();
-
-    // 3. check no rule enabled
-    List<ActiveRuleDto> activeRules = db.activeRuleDao().findByProfileKey(session, child.getKey());
-    assertThat(activeRules).isEmpty();
-  }
-
-  @Test
-  public void remove_parent_with_empty_key() throws Exception {
-    QualityProfileDto parent = createProfile("xoo", "Parent 1");
-    QualityProfileDto child = createProfile("xoo", "Child");
-
-    RuleDto rule1 = createRule("xoo", "rule1");
-    createActiveRule(rule1, parent);
-    session.commit();
-
-    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
-
-    // Set parent
-    tester.get(RuleActivator.class).setParent(child.getKey(), parent.getKey());
-    session.clearCache();
-
-    // Remove parent
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey())
-      .setParam("parentKey", "")
-      .execute();
-    session.clearCache();
-
-    // Check no rule enabled
-    List<ActiveRuleDto> activeRules = db.activeRuleDao().findByProfileKey(session, child.getKey());
-    assertThat(activeRules).isEmpty();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_if_parent_key_and_name_both_set() throws Exception {
-    QualityProfileDto child = createProfile("xoo", "Child");
-    session.commit();
-
-    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
-
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKee())
-      .setParam("parentName", "polop")
-      .setParam("parentKey", "palap")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_if_profile_key_and_name_both_set() throws Exception {
-    QualityProfileDto child = createProfile("xoo", "Child");
-    session.commit();
-
-    assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
-
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKee())
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
-      .setParam("parentKey", "palap")
-      .execute();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_if_missing_permission() throws Exception {
-    userSessionRule.login("anakin");
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
-      .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, "polop")
-      .setParam("parentKey", "pulup")
-      .execute();
-  }
-
-  private QualityProfileDto createProfile(String lang, String name) {
-    QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), "p" + lang + "-" + name.toLowerCase());
-    db.qualityProfileDao().insert(session, profile);
-    return profile;
-  }
-
-  private RuleDto createRule(String lang, String id) {
-    RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id))
-      .setLanguage(lang)
-      .setSeverity(Severity.BLOCKER)
-      .setStatus(RuleStatus.READY);
-    db.ruleDao().insert(session, rule);
-    return rule;
-  }
-
-  private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) {
-    ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
-      .setSeverity(rule.getSeverityString());
-    db.activeRuleDao().insert(session, activeRule);
-    return activeRule;
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest.java
deleted file mode 100644 (file)
index 5a3aa53..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.collect.Maps;
-import org.joda.time.DateTime;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.config.Settings;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.Uuids;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.ActiveRuleKey;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.core.user.UserDto;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.index.ActivityDoc;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.activity.index.ActivityIndexDefinition;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.ActiveRuleChange;
-import org.sonar.server.qualityprofile.ActiveRuleChange.Type;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileTesting;
-import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.user.db.UserDao;
-import org.sonar.server.ws.WsTester;
-
-import java.util.Date;
-import java.util.Map;
-
-import static org.mockito.Mockito.mock;
-import static org.sonar.server.qualityprofile.QProfileTesting.XOO_P1_KEY;
-
-public class QProfileChangelogActionTest {
-
-  @ClassRule
-  public static DbTester dbTester = new DbTester();
-
-  @ClassRule
-  public static EsTester esTester = new EsTester().addDefinitions(new ActivityIndexDefinition(new Settings()));
-
-  private DbClient db;
-  private DbSession dbSession;
-  private WsTester wsTester;
-  private String login;
-
-  @Before
-  public void before() {
-    dbTester.truncateTables();
-    esTester.truncateIndices();
-
-    System2 system = mock(System2.class);
-
-    db = new DbClient(dbTester.database(), dbTester.myBatis(), new RuleDao(system), new QualityProfileDao(dbTester.myBatis(), system), new UserDao(dbTester.myBatis(), system));
-    dbSession = db.openSession(false);
-
-    // create pre-defined rules
-    RuleDto xooRule1 = RuleTesting.newXooX1().setSeverity("MINOR");
-    db.ruleDao().insert(dbSession, xooRule1);
-
-    // create pre-defined profiles P1 and P2
-    db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1(), QProfileTesting.newXooP2());
-
-    login = "david";
-    UserDto user = new UserDto().setLogin(login).setName("David").setEmail("dav@id.com").setCreatedAt(System.currentTimeMillis()).setUpdatedAt(System.currentTimeMillis());
-    db.userDao().insert(dbSession, user);
-
-    dbSession.commit();
-    dbSession.clearCache();
-
-    wsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
-      new QProfileChangelogAction(db, new ActivityIndex(esTester.client()), new QProfileFactory(db), LanguageTesting.newLanguages("xoo"))));
-  }
-
-  @After
-  public void after() {
-    dbSession.close();
-  }
-
-  @Test
-  public void changelog_empty() throws Exception {
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
-      .execute().assertJson(getClass(), "changelog_empty.json");
-  }
-
-  @Test
-  public void changelog_nominal() throws Exception {
-    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, new Date(), "max", "10");
-
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
-      .execute().assertJson(getClass(), "changelog_nominal.json");
-  }
-
-  @Test
-  public void changelog_no_param() throws Exception {
-    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, new Date());
-
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
-      .execute().assertJson(getClass(), "changelog_no_param.json");
-  }
-
-  @Test
-  public void changelog_system_user() throws Exception {
-    createActivity(null, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, new Date());
-
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
-      .execute().assertJson(getClass(), "changelog_no_login.json");
-  }
-
-  @Test
-  public void changelog_with_dates() throws Exception {
-    Date yesterday = DateTime.now().minusDays(1).toDate();
-    Date tomorrow = DateTime.now().plusDays(1).toDate();
-
-    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, new Date(), "max", "10");
-
-    // Tests with "since"
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("since",
-      DateUtils.formatDateTime(yesterday))
-      .execute().assertJson(getClass(), "changelog_nominal.json");
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("since",
-      DateUtils.formatDateTime(tomorrow))
-      .execute().assertJson(getClass(), "changelog_empty.json");
-
-    // Tests with "to"
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("to",
-      DateUtils.formatDateTime(yesterday))
-      .execute().assertJson(getClass(), "changelog_empty.json");
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("to",
-      DateUtils.formatDateTime(tomorrow))
-      .execute().assertJson(getClass(), "changelog_nominal.json");
-
-    // Test with both bounds set
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY)
-      .setParam("since", DateUtils.formatDateTime(yesterday))
-      .setParam("to", DateUtils.formatDateTime(tomorrow))
-      .execute().assertJson(getClass(), "changelog_nominal.json");
-  }
-
-  @Test
-  public void changelog_with_pagination() throws Exception {
-    Date farthest = new Date(1_500_000_000_000L);
-    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.MAJOR, farthest, "max", "10");
-    Date nearest = new Date(1_500_000_100_000L);
-    createActivity(login, ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.CRITICAL, nearest, "max", "20");
-
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("ps", "1")
-      .execute().assertJson(getClass(), "changelog_page1.json");
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("ps", "1").setParam("p", "2")
-      .execute().assertJson(getClass(), "changelog_page2.json");
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY).setParam("ps", "1").setParam("p", "3")
-      .execute().assertJson(getClass(), "changelog_page3.json");
-  }
-
-  @Test(expected = NotFoundException.class)
-  public void fail_on_unknown_profile() throws Exception {
-    wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", "unknown-profile").execute();
-  }
-
-  private void createActivity(String login, Type type, ActiveRuleKey activeRuleKey, String severity, Date createdAt, String... params) throws Exception {
-    Map<String, String> details = Maps.newHashMap();
-    details.put("key", activeRuleKey.toString());
-    details.put("ruleKey", activeRuleKey.ruleKey().toString());
-    details.put("profileKey", activeRuleKey.qProfile());
-    details.put("severity", severity);
-    for (int i = 0; i < params.length; i += 2) {
-      details.put("param_" + params[i], params[i + 1]);
-    }
-    ActivityDoc doc = new ActivityDoc(Maps.<String, Object>newHashMap());
-    doc.setAction(type.toString());
-    doc.setCreatedAt(createdAt);
-    doc.setDetails(details);
-    doc.setKey(Uuids.create());
-    doc.setLogin(login);
-    doc.setType(Activity.Type.QPROFILE.toString());
-
-    esTester.putDocuments(ActivityIndexDefinition.INDEX, ActivityIndexDefinition.TYPE, doc);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest.java
deleted file mode 100644 (file)
index 49447da..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.apache.commons.lang.StringUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.server.rule.RuleParamType;
-import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.qualityprofile.db.ActiveRuleDto;
-import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.core.rule.RuleParamDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.qualityprofile.QProfileTesting;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-public class QProfileCompareActionMediumTest {
-
-  @ClassRule
-  public static ServerTester tester = new ServerTester().addXoo()
-    .addComponents(new RulesDefinition() {
-      @Override
-      public void define(Context context) {
-        context.createRepository("blah", "xoo")
-          .setName("Blah")
-          .done();
-      }
-    });
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
-  private DbClient db;
-
-  private WsTester wsTester;
-
-  private DbSession session;
-
-  @Before
-  public void setUp() {
-    tester.clearDbAndIndexes();
-    db = tester.get(DbClient.class);
-    session = db.openSession(false);
-
-    wsTester = new WsTester(tester.get(QProfilesWs.class));
-  }
-
-  @After
-  public void tearDown() {
-    session.close();
-  }
-
-  @Test
-  public void compare_nominal() throws Exception {
-    RuleDto rule1 = createRule("xoo", "rule1");
-    RuleDto rule2 = createRule("xoo", "rule2");
-    RuleDto rule3 = createRule("xoo", "rule3");
-    RuleDto rule4 = createRuleWithParam("xoo", "rule4");
-    RuleDto rule5 = createRule("xoo", "rule5");
-
-    /*
-     * Profile 1:
-     * - rule 1 active (on both profiles) => "same"
-     * - rule 2 active (only in this profile) => "inLeft"
-     * - rule 4 active with different parameters => "modified"
-     * - rule 5 active with different severity => "modified"
-     */
-    QualityProfileDto profile1 = createProfile("xoo", "Profile 1", "xoo-profile-1-01234");
-    createActiveRule(rule1, profile1);
-    createActiveRule(rule2, profile1);
-    createActiveRuleWithParam(rule4, profile1, "polop");
-    createActiveRuleWithSeverity(rule5, profile1, Severity.MINOR);
-    session.commit();
-
-    /*
-     * Profile 1:
-     * - rule 1 active (on both profiles) => "same"
-     * - rule 3 active (only in this profile) => "inRight"
-     * - rule 4 active with different parameters => "modified"
-     */
-    QualityProfileDto profile2 = createProfile("xoo", "Profile 2", "xoo-profile-2-12345");
-    createActiveRule(rule1, profile2);
-    createActiveRule(rule3, profile2);
-    createActiveRuleWithParam(rule4, profile2, "palap");
-    createActiveRuleWithSeverity(rule5, profile2, Severity.MAJOR);
-    session.commit();
-
-    wsTester.newGetRequest("api/qualityprofiles", "compare")
-      .setParam("leftKey", profile1.getKey())
-      .setParam("rightKey", profile2.getKey())
-      .execute().assertJson(this.getClass(), "compare_nominal.json");
-  }
-
-  @Test
-  public void compare_param_on_left() throws Exception {
-    RuleDto rule1 = createRuleWithParam("xoo", "rule1");
-
-    QualityProfileDto profile1 = createProfile("xoo", "Profile 1", "xoo-profile-1-01234");
-    createActiveRuleWithParam(rule1, profile1, "polop");
-    session.commit();
-
-    QualityProfileDto profile2 = createProfile("xoo", "Profile 2", "xoo-profile-2-12345");
-    createActiveRule(rule1, profile2);
-    session.commit();
-
-    wsTester.newGetRequest("api/qualityprofiles", "compare")
-      .setParam("leftKey", profile1.getKey())
-      .setParam("rightKey", profile2.getKey())
-      .execute().assertJson(this.getClass(), "compare_param_on_left.json");
-  }
-
-  @Test
-  public void compare_param_on_right() throws Exception {
-    RuleDto rule1 = createRuleWithParam("xoo", "rule1");
-
-    QualityProfileDto profile1 = createProfile("xoo", "Profile 1", "xoo-profile-1-01234");
-    createActiveRule(rule1, profile1);
-    session.commit();
-
-    QualityProfileDto profile2 = createProfile("xoo", "Profile 2", "xoo-profile-2-12345");
-    createActiveRuleWithParam(rule1, profile2, "polop");
-    session.commit();
-
-    wsTester.newGetRequest("api/qualityprofiles", "compare")
-      .setParam("leftKey", profile1.getKey())
-      .setParam("rightKey", profile2.getKey())
-      .execute().assertJson(this.getClass(), "compare_param_on_right.json");
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_left_param() throws Exception {
-    wsTester.newGetRequest("api/qualityprofiles", "compare")
-      .setParam("rightKey", "polop")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_right_param() throws Exception {
-    wsTester.newGetRequest("api/qualityprofiles", "compare")
-      .setParam("leftKey", "polop")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_left_profile_not_found() throws Exception {
-    createProfile("xoo", "Right", "xoo-right-12345");
-    wsTester.newGetRequest("api/qualityprofiles", "compare")
-      .setParam("leftKey", "polop")
-      .setParam("rightKey", "xoo-right-12345")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_right_profile_not_found() throws Exception {
-    createProfile("xoo", "Left", "xoo-left-12345");
-    wsTester.newGetRequest("api/qualityprofiles", "compare")
-      .setParam("leftKey", "xoo-left-12345")
-      .setParam("rightKey", "polop")
-      .execute();
-  }
-
-  private QualityProfileDto createProfile(String lang, String name, String key) {
-    QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), key);
-    db.qualityProfileDao().insert(session, profile);
-    session.commit();
-    return profile;
-  }
-
-  private RuleDto createRule(String lang, String id) {
-    RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id))
-      .setName(StringUtils.capitalize(id))
-      .setLanguage(lang)
-      .setSeverity(Severity.BLOCKER)
-      .setStatus(RuleStatus.READY);
-    db.ruleDao().insert(session, rule);
-    RuleParamDto param = RuleParamDto.createFor(rule).setName("param_" + id).setType(RuleParamType.STRING.toString());
-    db.ruleDao().addRuleParam(session, rule, param);
-    return rule;
-  }
-
-  private RuleDto createRuleWithParam(String lang, String id) {
-    RuleDto rule = createRule(lang, id);
-    RuleParamDto param = RuleParamDto.createFor(rule).setName("param_" + id).setType(RuleParamType.STRING.toString());
-    db.ruleDao().addRuleParam(session, rule, param);
-    return rule;
-  }
-
-  private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) {
-    ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
-      .setSeverity(rule.getSeverityString());
-    db.activeRuleDao().insert(session, activeRule);
-    return activeRule;
-  }
-
-  private ActiveRuleDto createActiveRuleWithParam(RuleDto rule, QualityProfileDto profile, String value) {
-    ActiveRuleDto activeRule = createActiveRule(rule, profile);
-    RuleParamDto paramDto = db.ruleDao().findRuleParamsByRuleKey(session, rule.getKey()).get(0);
-    ActiveRuleParamDto activeRuleParam = ActiveRuleParamDto.createFor(paramDto).setValue(value);
-    db.activeRuleDao().addParam(session, activeRule, activeRuleParam);
-    return activeRule;
-  }
-
-  private ActiveRuleDto createActiveRuleWithSeverity(RuleDto rule, QualityProfileDto profile, String severity) {
-    ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
-      .setSeverity(severity);
-    db.activeRuleDao().insert(session, activeRule);
-    return activeRule;
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest.java
deleted file mode 100644 (file)
index bf14f09..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.QProfileCopier;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class QProfileCopyActionTest {
-
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private WsTester tester;
-
-  // TODO Replace with proper DbTester + EsTester medium test during removal of DaoV2
-  @Mock
-  private QProfileCopier qProfileCopier;
-
-  @Before
-  public void setUp() {
-    tester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileCopyAction(qProfileCopier, LanguageTesting.newLanguages("xoo"), userSessionRule)));
-  }
-
-  @Test
-  public void copy_nominal() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    String fromProfileKey = "xoo-sonar-way-23456";
-    String toName = "Other Sonar Way";
-
-    when(qProfileCopier.copyToName(fromProfileKey, toName)).thenReturn(
-      QualityProfileDto.createFor("xoo-other-sonar-way-12345")
-        .setName(toName)
-        .setLanguage("xoo"));
-
-    tester.newPostRequest("api/qualityprofiles", "copy")
-      .setParam("fromKey", fromProfileKey)
-      .setParam("toName", toName)
-      .execute().assertJson(getClass(), "copy_nominal.json");
-
-    verify(qProfileCopier).copyToName(fromProfileKey, toName);
-  }
-
-  @Test
-  public void copy_with_parent() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    String fromProfileKey = "xoo-sonar-way-23456";
-    String toName = "Other Sonar Way";
-
-    when(qProfileCopier.copyToName(fromProfileKey, toName)).thenReturn(
-      QualityProfileDto.createFor("xoo-other-sonar-way-12345")
-        .setName(toName)
-        .setLanguage("xoo")
-        .setParentKee("xoo-parent-profile-01324"));
-
-    tester.newPostRequest("api/qualityprofiles", "copy")
-      .setParam("fromKey", fromProfileKey)
-      .setParam("toName", toName)
-      .execute().assertJson(getClass(), "copy_with_parent.json");
-
-    verify(qProfileCopier).copyToName(fromProfileKey, toName);
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_key() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "copy")
-      .setParam("name", "Other Sonar Way")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_name() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "copy")
-      .setParam("key", "sonar-way-xoo1-13245")
-      .execute();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_on_missing_permission() throws Exception {
-    userSessionRule.login("obiwan");
-
-    tester.newPostRequest("api/qualityprofiles", "copy")
-      .setParam("key", "sonar-way-xoo1-13245")
-      .setParam("name", "Hey look I am not quality profile admin!")
-      .execute();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest.java
deleted file mode 100644 (file)
index d0c187d..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.qualityprofile.QProfileExporters;
-import org.sonar.server.qualityprofile.QProfileExportersTest.StandardExporter;
-import org.sonar.server.qualityprofile.QProfileExportersTest.XooExporter;
-import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileDefinition;
-import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporter;
-import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporterWithError;
-import org.sonar.server.qualityprofile.QProfileExportersTest.XooProfileImporterWithMessages;
-import org.sonar.server.qualityprofile.QProfileExportersTest.XooRulesDefinition;
-import org.sonar.server.qualityprofile.QProfileLoader;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-public class QProfileCreateActionMediumTest {
-
-  // TODO Replace with simpler test with DbTester / EsTester after removal of DaoV2
-  @ClassRule
-  public static ServerTester tester = new ServerTester().addXoo().addComponents(
-    XooRulesDefinition.class, XooProfileDefinition.class,
-    XooExporter.class, StandardExporter.class,
-    XooProfileImporter.class, XooProfileImporterWithMessages.class, XooProfileImporterWithError.class);
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
-  DbClient db;
-  DbSession dbSession;
-  QProfileExporters exporters;
-  QProfileLoader loader;
-  WsTester wsTester;
-
-  @Before
-  public void before() {
-    db = tester.get(DbClient.class);
-    dbSession = db.openSession(false);
-    exporters = tester.get(QProfileExporters.class);
-    loader = tester.get(QProfileLoader.class);
-    wsTester = new WsTester(tester.get(QProfilesWs.class));
-  }
-
-  @After
-  public void after() {
-    dbSession.close();
-  }
-
-  @Test
-  public void create_nominal() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    wsTester.newPostRequest("api/qualityprofiles", "create")
-      .setParam("backup_XooProfileImporter", "a value for xoo importer")
-      .setParam("language", "xoo")
-      .setParam("name", "My New Profile")
-      .execute().assertJson(this.getClass(), "create-nominal.json");
-  }
-
-  @Test
-  public void create_with_messages() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    wsTester.newPostRequest("api/qualityprofiles", "create")
-      .setParam("backup_XooProfileImporter", "a value for xoo importer")
-      .setParam("backup_XooProfileImporterWithMessages", "this will generate some messages")
-      .setParam("language", "xoo")
-      .setParam("name", "My Other Profile")
-      .execute().assertJson(this.getClass(), "create-with-messages.json");
-  }
-
-  @Test(expected = BadRequestException.class)
-  public void fail_on_error_from_importer() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    wsTester.newPostRequest("api/qualityprofiles", "create")
-      .setParam("backup_XooProfileImporter", "a value for xoo importer")
-      .setParam("backup_XooProfileImporterWithError", "this will fail")
-      .setParam("language", "xoo")
-      .setParam("name", "Error In Importer")
-      .execute();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCreateActionTest.java
deleted file mode 100644 (file)
index d308534..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.server.ws.WebService.Action;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class QProfileCreateActionTest {
-
-  @ClassRule
-  public static final DbTester db = new DbTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  @Test
-  public void should_not_fail_on_no_importers() throws Exception {
-    QualityProfileDao profileDao = new QualityProfileDao(db.myBatis(), mock(System2.class));
-    DbClient dbClient = new DbClient(db.database(), db.myBatis(), profileDao);
-
-    String xooKey = "xoo";
-    WsTester wsTester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
-      new QProfileCreateAction(dbClient, new QProfileFactory(dbClient), null, LanguageTesting.newLanguages(xooKey), userSessionRule)));
-
-    Action create = wsTester.controller("api/qualityprofiles").action("create");
-    assertThat(create.params()).hasSize(2);
-
-    userSessionRule.login("anakin").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    wsTester.newPostRequest("api/qualityprofiles", "create")
-      .setParam("language", xooKey).setParam("name", "Yeehaw!").execute().assertJson(getClass(), "create-no-importer.json");
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileDeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileDeleteActionTest.java
deleted file mode 100644 (file)
index c7ac268..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.utils.System2;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.db.ActiveRuleDao;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class QProfileDeleteActionTest {
-
-  @ClassRule
-  public static DbTester dbTester = new DbTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private DbClient dbClient;
-
-  private QualityProfileDao qualityProfileDao;
-
-  private ComponentDao componentDao;
-
-  private Language xoo1, xoo2;
-
-  private WsTester tester;
-
-  private DbSession session;
-
-  System2 system2 = mock(System2.class);
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-    qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
-    componentDao = new ComponentDao();
-
-    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao, new ActiveRuleDao(qualityProfileDao, new RuleDao(system2), system2));
-    session = dbClient.openSession(false);
-
-    xoo1 = LanguageTesting.newLanguage("xoo1");
-    xoo2 = LanguageTesting.newLanguage("xoo2");
-
-    tester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileDeleteAction(new Languages(xoo1, xoo2), new QProfileFactory(dbClient), dbClient, userSessionRule)));
-  }
-
-  @After
-  public void teadDown() {
-    session.close();
-  }
-
-  @Test
-  public void delete_nominal_with_key() throws Exception {
-    String profileKey = "sonar-way-xoo1-12345";
-
-    ComponentDto project = ComponentTesting.newProjectDto("polop");
-    componentDao.insert(session, project);
-    qualityProfileDao.insert(session, QualityProfileDto.createFor(profileKey).setLanguage(xoo1.getKey()).setName("Sonar way"));
-    qualityProfileDao.insertProjectProfileAssociation(project.uuid(), profileKey, session);
-    session.commit();
-
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileKey", "sonar-way-xoo1-12345").execute().assertNoContent();
-
-    assertThat(qualityProfileDao.getByKey(session, "sonar-way-xoo1-12345")).isNull();
-    assertThat(qualityProfileDao.selectProjects("Sonar way", xoo1.getName())).isEmpty();
-  }
-
-  @Test
-  public void delete_nominal_with_language_and_name() throws Exception {
-    String profileKey = "sonar-way-xoo1-12345";
-
-    ComponentDto project = ComponentTesting.newProjectDto("polop");
-    componentDao.insert(session, project);
-    qualityProfileDao.insert(session, QualityProfileDto.createFor(profileKey).setLanguage(xoo1.getKey()).setName("Sonar way"));
-    qualityProfileDao.insertProjectProfileAssociation(project.uuid(), profileKey, session);
-    session.commit();
-
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Sonar way").setParam("language", xoo1.getKey()).execute().assertNoContent();
-
-    assertThat(qualityProfileDao.getByKey(session, "sonar-way-xoo1-12345")).isNull();
-    assertThat(qualityProfileDao.selectProjects("Sonar way", xoo1.getName())).isEmpty();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_on_missing_permission() throws Exception {
-    userSessionRule.login("obiwan");
-    tester.newPostRequest("api/qualityprofiles", "delete").execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_arguments() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-    tester.newPostRequest("api/qualityprofiles", "delete").execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_language() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_name() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-    tester.newPostRequest("api/qualityprofiles", "delete").setParam("language", xoo1.getKey()).execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_too_many_arguments() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").setParam("language", xoo1.getKey()).setParam("profileKey", "polop").execute();
-  }
-
-  @Test(expected = NotFoundException.class)
-  public void fail_on_unexisting_profile() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-    tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").setParam("language", xoo1.getKey()).execute();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileExportActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileExportActionTest.java
deleted file mode 100644 (file)
index d145d0f..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.collect.Sets;
-import org.apache.commons.lang.StringUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.Matchers;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.profiles.ProfileExporter;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.server.ws.WebService.Action;
-import org.sonar.api.utils.System2;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.*;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-import org.sonar.server.ws.WsTester.Result;
-
-import java.io.IOException;
-import java.io.Writer;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class QProfileExportActionTest {
-
-  @ClassRule
-  public static final DbTester db = new DbTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  WsTester wsTester;
-
-  QualityProfileDao qualityProfileDao;
-
-  DbClient dbClient;
-
-  DbSession session;
-
-  QProfileBackuper backuper;
-
-  QProfileExporters exporters;
-
-  @Before
-  public void before() {
-    qualityProfileDao = new QualityProfileDao(db.myBatis(), mock(System2.class));
-    dbClient = new DbClient(db.database(), db.myBatis(), qualityProfileDao);
-    session = dbClient.openSession(false);
-    backuper = mock(QProfileBackuper.class);
-
-    db.truncateTables();
-
-    ProfileExporter exporter1 = newExporter("polop");
-    ProfileExporter exporter2 = newExporter("palap");
-
-    IndexClient indexClient = mock(IndexClient.class);
-    ActiveRuleIndex activeRuleIndex = mock(ActiveRuleIndex.class);
-    when(activeRuleIndex.findByProfile(Matchers.anyString())).thenReturn(Sets.<ActiveRule>newHashSet().iterator());
-
-    when(indexClient.get(ActiveRuleIndex.class)).thenReturn(activeRuleIndex);
-    exporters = new QProfileExporters(new QProfileLoader(dbClient, indexClient, userSessionRule), null, null, new ProfileExporter[] {exporter1, exporter2}, null);
-    wsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileExportAction(dbClient, new QProfileFactory(dbClient), backuper, exporters, LanguageTesting.newLanguages("xoo"))));
-  }
-
-  @After
-  public void after() {
-    session.close();
-  }
-
-  private ProfileExporter newExporter(final String key) {
-    return new ProfileExporter(key, StringUtils.capitalize(key)) {
-      @Override
-      public String getMimeType() {
-        return "text/plain+" + key;
-      }
-
-      @Override
-      public void exportProfile(RulesProfile profile, Writer writer) {
-        try {
-          writer.write(String.format("Profile %s exported by %s", profile.getName(), key));
-        } catch (IOException ioe) {
-          throw new RuntimeException(ioe);
-        }
-      }
-    };
-  }
-
-  @Test
-  public void export_without_format() throws Exception {
-    QualityProfileDto profile = QProfileTesting.newXooP1();
-    qualityProfileDao.insert(session, profile);
-    session.commit();
-
-    doAnswer(new Answer<Void>() {
-      @Override
-      public Void answer(InvocationOnMock invocation) throws Throwable {
-        invocation.getArgumentAt(1, Writer.class).write("As exported by SQ !");
-        return null;
-      }
-    }).when(backuper).backup(Matchers.eq(profile.getKey()), Matchers.any(Writer.class));
-
-    Result result = wsTester.newGetRequest("api/qualityprofiles", "export").setParam("language", profile.getLanguage()).setParam("name", profile.getName()).execute();
-
-    assertThat(result.outputAsString()).isEqualTo("As exported by SQ !");
-  }
-
-  @Test
-  public void export_with_format() throws Exception {
-    QualityProfileDto profile = QProfileTesting.newXooP1();
-    qualityProfileDao.insert(session, profile);
-    session.commit();
-
-    Result result = wsTester.newGetRequest("api/qualityprofiles", "export")
-      .setParam("language", profile.getLanguage()).setParam("name", profile.getName()).setParam("exporterKey", "polop").execute();
-
-    assertThat(result.outputAsString()).isEqualTo("Profile " + profile.getName() + " exported by polop");
-  }
-
-  @Test
-  public void export_default_profile() throws Exception {
-    QualityProfileDto profile1 = QProfileTesting.newXooP1();
-    QualityProfileDto profile2 = QProfileTesting.newXooP2().setDefault(true);
-    qualityProfileDao.insert(session, profile1, profile2);
-    session.commit();
-
-    Result result = wsTester.newGetRequest("api/qualityprofiles", "export")
-      .setParam("language", "xoo").setParam("exporterKey", "polop").execute();
-
-    assertThat(result.outputAsString()).isEqualTo("Profile " + profile2.getName() + " exported by polop");
-  }
-
-  @Test(expected = NotFoundException.class)
-  public void fail_on_unknown_profile() throws Exception {
-    wsTester.newGetRequest("api/qualityprofiles", "export")
-      .setParam("language", "xoo").setParam("exporterKey", "polop").execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_unknown_exporter() throws Exception {
-    QualityProfileDto profile = QProfileTesting.newXooP1();
-    qualityProfileDao.insert(session, profile);
-    session.commit();
-
-    wsTester.newGetRequest("api/qualityprofiles", "export")
-      .setParam("language", "xoo").setParam("exporterKey", "unknown").execute();
-  }
-
-  @Test
-  public void do_not_fail_when_no_exporters() throws Exception {
-    QProfileExporters myExporters = new QProfileExporters(null, null, null, new ProfileExporter[0], null);
-    WsTester myWsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileExportAction(dbClient, new QProfileFactory(dbClient), backuper, myExporters, LanguageTesting.newLanguages("xoo"))));
-
-    Action export = myWsTester.controller("api/qualityprofiles").action("export");
-    assertThat(export.params()).hasSize(2);
-
-    QualityProfileDto profile = QProfileTesting.newXooP1();
-    qualityProfileDao.insert(session, profile);
-    session.commit();
-
-    myWsTester.newGetRequest("api/qualityprofiles", "export").setParam("language", "xoo").setParam("name", profile.getName()).execute();
-
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileExportersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileExportersActionTest.java
deleted file mode 100644 (file)
index 9e3c4d3..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.Test;
-import org.sonar.api.profiles.ProfileExporter;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.server.ws.WsTester;
-
-import java.io.Writer;
-
-import static org.mockito.Mockito.mock;
-
-public class QProfileExportersActionTest {
-
-  @Test
-  public void importers_nominal() throws Exception {
-    WsTester wsTester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
-      new QProfileExportersAction(createExporters())));
-
-    wsTester.newGetRequest("api/qualityprofiles", "exporters").execute().assertJson(getClass(), "exporters.json");
-  }
-
-  private ProfileExporter[] createExporters() {
-    class NoopImporter extends ProfileExporter {
-      private NoopImporter(String key, String name, String... languages) {
-        super(key, name);
-        setSupportedLanguages(languages);
-      }
-
-      @Override
-      public void exportProfile(RulesProfile profile, Writer writer) {
-        // Nothing
-      }
-
-    }
-    return new ProfileExporter[] {
-      new NoopImporter("findbugs", "FindBugs", "java"),
-      new NoopImporter("jslint", "JS Lint", "js"),
-      new NoopImporter("vaadin", "Vaadin", "java", "js")
-    };
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileImportersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileImportersActionTest.java
deleted file mode 100644 (file)
index dfd16c7..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.Test;
-import org.sonar.api.profiles.ProfileImporter;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.utils.ValidationMessages;
-import org.sonar.server.ws.WsTester;
-
-import java.io.Reader;
-
-import static org.mockito.Mockito.mock;
-
-public class QProfileImportersActionTest {
-
-  @Test
-  public void importers_nominal() throws Exception {
-    WsTester wsTester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
-      new QProfileImportersAction(createImporters())));
-
-    wsTester.newGetRequest("api/qualityprofiles", "importers").execute().assertJson(getClass(), "importers.json");
-  }
-
-  private ProfileImporter[] createImporters() {
-    class NoopImporter extends ProfileImporter {
-      private NoopImporter(String key, String name, String... languages) {
-        super(key, name);
-        setSupportedLanguages(languages);
-      }
-
-      @Override
-      public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
-        return RulesProfile.create();
-      }
-
-    }
-    return new ProfileImporter[] {
-      new NoopImporter("findbugs", "FindBugs", "java"),
-      new NoopImporter("jslint", "JS Lint", "js"),
-      new NoopImporter("vaadin", "Vaadin", "java", "js")
-    };
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest.java
deleted file mode 100644 (file)
index 58dcf27..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.qualityprofile.db.ActiveRuleDto;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.qualityprofile.QProfileTesting;
-import org.sonar.server.qualityprofile.RuleActivation;
-import org.sonar.server.qualityprofile.RuleActivator;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-public class QProfileInheritanceActionMediumTest {
-
-  @ClassRule
-  public static final ServerTester tester = new ServerTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
-  private WsTester wsTester;
-
-  private DbClient db;
-
-  private DbSession session;
-
-  @Before
-  public void setUp() {
-    tester.clearDbAndIndexes();
-    db = tester.get(DbClient.class);
-    session = db.openSession(false);
-
-    wsTester = new WsTester(tester.get(QProfilesWs.class));
-  }
-
-  @After
-  public void tearDown() {
-    session.close();
-  }
-
-  @Test
-  public void inheritance_nominal() throws Exception {
-    RuleDto rule1 = createRule("xoo", "rule1");
-    RuleDto rule2 = createRule("xoo", "rule2");
-    RuleDto rule3 = createRule("xoo", "rule3");
-
-    /*
-     * groupWide (2) <- companyWide (2) <- buWide (2, 1 overriding) <- (forProject1 (2), forProject2 (2))
-     */
-    QualityProfileDto groupWide = createProfile("xoo", "My Group Profile", "xoo-my-group-profile-01234");
-    createActiveRule(rule1, groupWide);
-    createActiveRule(rule2, groupWide);
-    session.commit();
-
-    QualityProfileDto companyWide = createProfile("xoo", "My Company Profile", "xoo-my-company-profile-12345");
-    setParent(groupWide, companyWide);
-
-    QualityProfileDto buWide = createProfile("xoo", "My BU Profile", "xoo-my-bu-profile-23456");
-    setParent(companyWide, buWide);
-    overrideActiveRuleSeverity(rule1, buWide, Severity.CRITICAL);
-
-    QualityProfileDto forProject1 = createProfile("xoo", "For Project One", "xoo-for-project-one-34567");
-    setParent(buWide, forProject1);
-    createActiveRule(rule3, forProject1);
-    session.commit();
-
-    QualityProfileDto forProject2 = createProfile("xoo", "For Project Two", "xoo-for-project-two-45678");
-    setParent(buWide, forProject2);
-    overrideActiveRuleSeverity(rule2, forProject2, Severity.CRITICAL);
-
-    wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", buWide.getKee()).execute().assertJson(getClass(), "inheritance-buWide.json");
-  }
-
-  @Test
-  public void inheritance_no_family() throws Exception {
-    // Simple profile, no parent, no child
-    QualityProfileDto remi = createProfile("xoo", "Nobodys Boy", "xoo-nobody-s-boy-01234");
-
-    wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", remi.getKee()).execute().assertJson(getClass(), "inheritance-simple.json");
-  }
-
-  @Test(expected = NotFoundException.class)
-  public void fail_if_not_found() throws Exception {
-    wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", "polop").execute();
-  }
-
-  private QualityProfileDto createProfile(String lang, String name, String key) {
-    QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), key);
-    db.qualityProfileDao().insert(session, profile);
-    session.commit();
-    return profile;
-  }
-
-  private void setParent(QualityProfileDto profile, QualityProfileDto parent) {
-    tester.get(RuleActivator.class).setParent(parent.getKey(), profile.getKey());
-  }
-
-  private RuleDto createRule(String lang, String id) {
-    RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id))
-      .setLanguage(lang)
-      .setSeverity(Severity.BLOCKER)
-      .setStatus(RuleStatus.READY);
-    db.ruleDao().insert(session, rule);
-    return rule;
-  }
-
-  private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) {
-    ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
-      .setSeverity(rule.getSeverityString());
-    db.activeRuleDao().insert(session, activeRule);
-    return activeRule;
-  }
-
-  private void overrideActiveRuleSeverity(RuleDto rule, QualityProfileDto profile, String severity) {
-    tester.get(RuleActivator.class).activate(session, new RuleActivation(rule.getKey()).setSeverity(severity), profile.getKey());
-    session.commit();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest.java
deleted file mode 100644 (file)
index fd05411..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.core.user.AuthorizationDao;
-import org.sonar.core.user.GroupRoleDto;
-import org.sonar.core.user.RoleDao;
-import org.sonar.core.user.UserDto;
-import org.sonar.core.user.UserRoleDto;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfileTesting;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.user.db.UserDao;
-import org.sonar.server.ws.WsTester;
-import org.sonar.server.ws.WsTester.TestRequest;
-import org.sonar.test.DbTests;
-
-import static org.mockito.Mockito.mock;
-
-@Category(DbTests.class)
-public class QProfileProjectsActionTest {
-
-  @ClassRule
-  public static final DbTester dbTester = new DbTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private WsTester wsTester;
-
-  private DbClient dbClient;
-
-  private DbSession session;
-
-  private QualityProfileDto xooP1, xooP2;
-
-  private ComponentDto project1, project2, project3, project4;
-
-  private Long userId = 42L;
-
-  private RoleDao roleDao;
-
-  System2 system2 = mock(System2.class);
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(),
-      new QualityProfileDao(dbTester.myBatis(), system2),
-      new ComponentDao(),
-      new AuthorizationDao(dbTester.myBatis()));
-    roleDao = new RoleDao();
-    session = dbClient.openSession(false);
-
-    wsTester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileProjectsAction(dbClient, userSessionRule)));
-
-    userSessionRule.login("obiwan").setUserId(userId.intValue());
-    new UserDao(dbTester.myBatis(), mock(System2.class))
-      .insert(session, new UserDto()
-        .setActive(true)
-        .setId(userId)
-        .setLogin("obiwan"));
-
-    createProfiles();
-
-    session.commit();
-  }
-
-  @After
-  public void tearDown() {
-    session.close();
-  }
-
-  @Test
-  public void should_list_authorized_projects_only() throws Exception {
-    project1 = newProject("ABCD", "Project One");
-    project2 = newProject("BCDE", "Project Two");
-    dbClient.componentDao().insert(session, project1, project2);
-
-    // user only sees project1
-    roleDao.insertUserRole(new UserRoleDto().setUserId(userId).setResourceId(project1.getId()).setRole(UserRole.USER), session);
-
-    associateProjectsWithProfile(session, xooP1, project1, project2);
-
-    session.commit();
-
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").execute().assertJson(this.getClass(), "authorized_selected.json");
-  }
-
-  @Test
-  public void should_paginate() throws Exception {
-    project1 = newProject("ABCD", "Project One");
-    project2 = newProject("BCDE", "Project Two");
-    project3 = newProject("CDEF", "Project Three");
-    project4 = newProject("DEFA", "Project Four");
-    dbClient.componentDao().insert(session, project1, project2, project3, project4);
-
-    addBrowsePermissionToAnyone(session, project1, project2, project3, project4);
-
-    associateProjectsWithProfile(session, xooP1, project1, project2, project3, project4);
-
-    session.commit();
-
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "2")
-      .execute().assertJson(this.getClass(), "selected_page1.json");
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "2").setParam("page", "2")
-      .execute().assertJson(this.getClass(), "selected_page2.json");
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "2").setParam("page", "3")
-      .execute().assertJson(this.getClass(), "empty.json");
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "2").setParam("page", "4")
-      .execute().assertJson(this.getClass(), "empty.json");
-
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "3").setParam("page", "1")
-      .execute().assertJson(this.getClass(), "selected_ps3_page1.json");
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "3").setParam("page", "2")
-      .execute().assertJson(this.getClass(), "selected_ps3_page2.json");
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "selected").setParam("pageSize", "3").setParam("page", "3")
-      .execute().assertJson(this.getClass(), "empty.json");
-  }
-
-  @Test
-  public void should_show_unselected() throws Exception {
-    project1 = newProject("ABCD", "Project One");
-    project2 = newProject("BCDE", "Project Two");
-    project3 = newProject("CDEF", "Project Three");
-    project4 = newProject("DEFA", "Project Four");
-    dbClient.componentDao().insert(session, project1, project2, project3, project4);
-
-    addBrowsePermissionToAnyone(session, project1, project2, project3, project4);
-
-    associateProjectsWithProfile(session, xooP1, project1, project2);
-
-    session.commit();
-
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "deselected").execute().assertJson(this.getClass(), "deselected.json");
-  }
-
-  @Test
-  public void should_show_all() throws Exception {
-    project1 = newProject("ABCD", "Project One");
-    project2 = newProject("BCDE", "Project Two");
-    project3 = newProject("CDEF", "Project Three");
-    project4 = newProject("DEFA", "Project Four");
-    dbClient.componentDao().insert(session, project1, project2, project3, project4);
-
-    addBrowsePermissionToAnyone(session, project1, project2, project3, project4);
-
-    associateProjectsWithProfile(session, xooP1, project1, project2);
-    // project3 is associated with P2, must appear as not associated with xooP1
-    associateProjectsWithProfile(session, xooP2, project3);
-
-    session.commit();
-
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "all").execute().assertJson(this.getClass(), "all.json");
-  }
-
-  @Test
-  public void should_filter_on_name() throws Exception {
-    project1 = newProject("ABCD", "Project One");
-    project2 = newProject("BCDE", "Project Two");
-    project3 = newProject("CDEF", "Project Three");
-    project4 = newProject("DEFA", "Project Four");
-    dbClient.componentDao().insert(session, project1, project2, project3, project4);
-
-    addBrowsePermissionToAnyone(session, project1, project2, project3, project4);
-
-    associateProjectsWithProfile(session, xooP1, project1, project2);
-
-    session.commit();
-
-    newRequest().setParam("key", xooP1.getKey()).setParam("selected", "all").setParam("query", "project t").execute().assertJson(this.getClass(), "all_filtered.json");
-  }
-
-  @Test(expected = NotFoundException.class)
-  public void should_fail_on_nonexistent_profile() throws Exception {
-    newRequest().setParam("key", "unknown").setParam("selected", "all").execute();
-  }
-
-  private void createProfiles() {
-    xooP1 = QProfileTesting.newXooP1();
-    xooP2 = QProfileTesting.newXooP2();
-    dbClient.qualityProfileDao().insert(session, xooP1, xooP2);
-  }
-
-  private TestRequest newRequest() {
-    return wsTester.newGetRequest("api/qualityprofiles", "projects");
-  }
-
-  private ComponentDto newProject(String uuid, String name) {
-    return ComponentTesting.newProjectDto(uuid).setName(name);
-  }
-
-  private void addBrowsePermissionToAnyone(DbSession session, ComponentDto... projects) {
-    for (ComponentDto project : projects) {
-      roleDao.insertGroupRole(new GroupRoleDto().setGroupId(null).setResourceId(project.getId()).setRole(UserRole.USER), session);
-    }
-  }
-
-  private void associateProjectsWithProfile(DbSession session, QualityProfileDto profile, ComponentDto... projects) {
-    for (ComponentDto project : projects) {
-      dbClient.qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profile.getKey(), session);
-    }
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRenameActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRenameActionTest.java
deleted file mode 100644 (file)
index fc6a053..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class QProfileRenameActionTest {
-
-  @ClassRule
-  public static DbTester dbTester = new DbTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private DbClient dbClient;
-
-  private QualityProfileDao qualityProfileDao;
-
-  private String xoo1Key = "xoo1", xoo2Key = "xoo2";
-
-  private WsTester tester;
-
-  private DbSession session;
-
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-    qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
-    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao);
-    session = dbClient.openSession(false);
-
-    createProfiles();
-
-    tester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileRenameAction(new QProfileFactory(dbClient), userSessionRule)));
-  }
-
-  @After
-  public void tearDown() {
-    session.close();
-  }
-
-  @Test
-  public void rename_nominal() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "rename")
-      .setParam("key", "sonar-way-xoo2-23456")
-      .setParam("name", "Other Sonar Way")
-      .execute().assertNoContent();
-
-    assertThat(qualityProfileDao.getNonNullByKey(session, "sonar-way-xoo2-23456").getName()).isEqualTo("Other Sonar Way");
-  }
-
-  @Test(expected = BadRequestException.class)
-  public void do_nothing_on_conflict() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "rename")
-      .setParam("key", "sonar-way-xoo2-23456")
-      .setParam("name", "My Sonar way")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_key() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "rename")
-      .setParam("name", "Other Sonar Way")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_name() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "rename")
-      .setParam("key", "sonar-way-xoo1-13245")
-      .execute();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_on_missing_permission() throws Exception {
-    userSessionRule.login("obiwan");
-
-    tester.newPostRequest("api/qualityprofiles", "rename")
-      .setParam("key", "sonar-way-xoo1-13245")
-      .setParam("name", "Hey look I am not quality profile admin!")
-      .execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_unknown_profile() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "rename")
-      .setParam("key", "polop")
-      .setParam("name", "Uh oh, I don't know this profile")
-      .execute();
-  }
-
-  private void createProfiles() {
-    qualityProfileDao.insert(session,
-      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1Key).setName("Sonar way").setDefault(true),
-      QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2Key).setName("Sonar way"),
-      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2Key).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true)
-      );
-    session.commit();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreActionTest.java
deleted file mode 100644 (file)
index 4d53849..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import java.io.Reader;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.BulkChangeResult;
-import org.sonar.server.qualityprofile.QProfileBackuper;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class QProfileRestoreActionTest {
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  // TODO Replace with proper DbTester + EsTester medium test once DaoV2 is removed
-  @Mock
-  private QProfileBackuper backuper;
-
-  private WsTester tester;
-
-  @Before
-  public void setUp() {
-    tester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileRestoreAction(backuper, LanguageTesting.newLanguages("xoo"), userSessionRule)));
-  }
-
-  @Test
-  public void restore_profile() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    QualityProfileDto profile = QualityProfileDto.createFor("xoo-sonar-way-12345")
-      .setDefault(false).setLanguage("xoo").setName("Sonar way");
-    BulkChangeResult restoreResult = new BulkChangeResult(profile);
-    when(backuper.restore(any(Reader.class), (QProfileName) eq(null))).thenReturn(restoreResult);
-
-    tester.newPostRequest("api/qualityprofiles", "restore").setParam("backup", "<polop><palap/></polop>").execute()
-      .assertJson(getClass(), "restore_profile.json");
-    verify(backuper).restore(any(Reader.class), (QProfileName) eq(null));
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_missing_backup() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newGetRequest("api/qualityprofiles", "restore").execute();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_on_misssing_permission() throws Exception {
-    userSessionRule.login("obiwan");
-
-    tester.newPostRequest("api/qualityprofiles", "restore").setParam("backup", "<polop><palap/></polop>").execute();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRestoreBuiltInActionTest.java
deleted file mode 100644 (file)
index 043a8b3..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.qualityprofile.ws;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.i18n.I18n;
-import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.ws.WsTester;
-
-import static org.mockito.Mockito.mock;
-
-@RunWith(MockitoJUnitRunner.class)
-public class QProfileRestoreBuiltInActionTest {
-
-  @Mock
-  QProfileService profileService;
-
-  @Mock
-  I18n i18n;
-
-  WsTester tester;
-
-  @Before
-  public void setUp() {
-    tester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileRestoreBuiltInAction(profileService)));
-  }
-
-  @Test
-  public void return_empty_result_when_no_infos_or_warnings() throws Exception {
-    WsTester.TestRequest request = tester.newPostRequest("api/qualityprofiles", "restore_built_in").setParam("language", "java");
-    request.execute().assertNoContent();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest.java
deleted file mode 100644 (file)
index 4c13287..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import com.google.common.collect.ImmutableMap;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.utils.System2;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.QProfileLoader;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.ws.WsTester;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class QProfileSearchActionTest {
-
-  @ClassRule
-  public static DbTester dbTester = new DbTester();
-
-  private DbClient dbClient;
-
-  private QualityProfileDao qualityProfileDao;
-
-  private Language xoo1, xoo2;
-
-  private WsTester tester;
-
-  private DbSession session;
-
-  private QProfileLoader profileLoader;
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-    qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
-    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao);
-    session = dbClient.openSession(false);
-
-    // TODO Replace with actual implementation after removal of DaoV2...
-    profileLoader = mock(QProfileLoader.class);
-
-    xoo1 = LanguageTesting.newLanguage("xoo1");
-    xoo2 = LanguageTesting.newLanguage("xoo2");
-
-    tester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileSearchAction(new Languages(xoo1, xoo2), new QProfileLookup(dbClient), profileLoader, qualityProfileDao)));
-  }
-
-  @After
-  public void teadDown() {
-    session.close();
-  }
-
-  @Test
-  public void search_nominal() throws Exception {
-    when(profileLoader.countAllActiveRules()).thenReturn(ImmutableMap.of(
-      "sonar-way-xoo1-12345", 11L,
-      "my-sonar-way-xoo2-34567", 33L
-      ));
-
-    qualityProfileDao.insert(session,
-      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way").setDefault(true),
-      QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2.getKey()).setName("Sonar way"),
-      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2.getKey()).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456"),
-      QualityProfileDto.createFor("sonar-way-other-666").setLanguage("other").setName("Sonar way").setDefault(true)
-      );
-    new ComponentDao().insert(session,
-      ComponentTesting.newProjectDto("project-uuid1"),
-      ComponentTesting.newProjectDto("project-uuid2"));
-    qualityProfileDao.insertProjectProfileAssociation("project-uuid1", "sonar-way-xoo2-23456", session);
-    qualityProfileDao.insertProjectProfileAssociation("project-uuid2", "sonar-way-xoo2-23456", session);
-    session.commit();
-
-    tester.newGetRequest("api/qualityprofiles", "search").execute().assertJson(this.getClass(), "search.json");
-  }
-
-  @Test
-  public void search_with_fields() throws Exception {
-    qualityProfileDao.insert(session,
-      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way").setDefault(true),
-      QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2.getKey()).setName("Sonar way"),
-      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2.getKey()).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456")
-      );
-    session.commit();
-
-    tester.newGetRequest("api/qualityprofiles", "search").setParam("f", "key,language").execute().assertJson(this.getClass(), "search_fields.json");
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_on_unknown_fields() throws Exception {
-    tester.newGetRequest("api/qualityprofiles", "search").setParam("f", "polop").execute();
-  }
-
-  @Test
-  public void search_for_language() throws Exception {
-    qualityProfileDao.insert(session,
-      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way")
-      );
-    session.commit();
-
-    tester.newGetRequest("api/qualityprofiles", "search").setParam("language", xoo1.getKey()).execute().assertJson(this.getClass(), "search_xoo1.json");
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultActionTest.java
deleted file mode 100644 (file)
index e621bd0..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.qualityprofile.ws;
-
-import org.assertj.core.api.Fail;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class QProfileSetDefaultActionTest {
-
-  @ClassRule
-  public static DbTester dbTester = new DbTester();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private DbClient dbClient;
-
-  private QualityProfileDao qualityProfileDao;
-
-  private String xoo1Key = "xoo1", xoo2Key = "xoo2";
-
-  private WsTester tester;
-
-  private DbSession session;
-
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-    qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
-    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao);
-    session = dbClient.openSession(false);
-
-    createProfiles();
-
-    tester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class),
-      mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
-      new QProfileSetDefaultAction(LanguageTesting.newLanguages(xoo1Key, xoo2Key), new QProfileLookup(dbClient), new QProfileFactory(dbClient), userSessionRule)));
-  }
-
-  @After
-  public void tearDown() {
-    session.close();
-  }
-
-  @Test
-  public void set_default_profile_using_key() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-
-    checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
-    checkDefaultProfile(xoo2Key, "my-sonar-way-xoo2-34567");
-
-    tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
-
-    checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
-    checkDefaultProfile(xoo2Key, "sonar-way-xoo2-23456");
-    assertThat(dbClient.qualityProfileDao().getByKey(session, "sonar-way-xoo2-23456").isDefault()).isTrue();
-    assertThat(dbClient.qualityProfileDao().getByKey(session, "my-sonar-way-xoo2-34567").isDefault()).isFalse();
-
-    // One more time!
-    tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
-    checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
-    checkDefaultProfile(xoo2Key, "sonar-way-xoo2-23456");
-  }
-
-  @Test
-  public void set_default_profile_using_language_and_name() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    tester.newPostRequest("api/qualityprofiles", "set_default").setParam("language", xoo2Key).setParam("profileName", "Sonar way").execute().assertNoContent();
-
-    checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
-    checkDefaultProfile(xoo2Key, "sonar-way-xoo2-23456");
-  }
-
-  @Test
-  public void fail_to_set_default_profile_using_key() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    try {
-      tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "unknown-profile-666").execute();
-      Fail.failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
-    } catch(IllegalArgumentException nfe) {
-      assertThat(nfe).hasMessage("Quality profile not found: unknown-profile-666");
-      checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
-      checkDefaultProfile(xoo2Key, "my-sonar-way-xoo2-34567");
-    }
-  }
-
-
-  @Test
-  public void fail_to_set_default_profile_using_language_and_name() throws Exception {
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    try {
-      tester.newPostRequest("api/qualityprofiles", "set_default").setParam("language", xoo2Key).setParam("profileName", "Unknown").execute();
-      Fail.failBecauseExceptionWasNotThrown(NotFoundException.class);
-    } catch(NotFoundException nfe) {
-      assertThat(nfe).hasMessage("Unable to find a profile for language 'xoo2' with name 'Unknown'");
-      checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
-      checkDefaultProfile(xoo2Key, "my-sonar-way-xoo2-34567");
-    }
-  }
-
-  @Test
-  public void fail_on_missing_permission() throws Exception {
-    userSessionRule.login("obiwan");
-
-    try {
-      tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
-      Fail.failBecauseExceptionWasNotThrown(ForbiddenException.class);
-    } catch(ForbiddenException forbidden) {
-      checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
-      checkDefaultProfile(xoo2Key, "my-sonar-way-xoo2-34567");
-    }
-  }
-
-  private void createProfiles() {
-    qualityProfileDao.insert(session,
-      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1Key).setName("Sonar way").setDefault(true),
-      QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2Key).setName("Sonar way"),
-      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2Key).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true)
-      );
-    session.commit();
-  }
-
-  private void checkDefaultProfile(String language, String key) {
-    assertThat(dbClient.qualityProfileDao().getDefaultProfile(language).getKey()).isEqualTo(key);
-  }
-}
index 7f6dc975e6db0b444415aeac917f3eacab05262c..a27423428e0516c4c4157b9b4dfd5019243cf6a1 100644 (file)
@@ -63,23 +63,23 @@ public class QProfilesWsTest {
       new RuleActivationActions(profileService),
       new BulkRuleActivationActions(profileService, ruleService, i18n, userSessionRule),
       new ProjectAssociationActions(null, null, null, languages, userSessionRule),
-      new QProfileCreateAction(null, null, null, languages, importers, userSessionRule),
-      new QProfileImportersAction(importers),
-      new QProfileRestoreBuiltInAction(null),
-      new QProfileSearchAction(languages, null, null, null),
-      new QProfileSetDefaultAction(languages, null, null, userSessionRule),
-      new QProfileProjectsAction(null, userSessionRule),
-      new QProfileBackupAction(null, null, null, languages),
-      new QProfileRestoreAction(null, languages, userSessionRule),
-      new QProfileChangelogAction(null, null, null, languages),
-      new QProfileChangeParentAction(null, null, null, languages, userSessionRule),
-      new QProfileCompareAction(null, null, null, languages),
-      new QProfileCopyAction(null, languages, userSessionRule),
-      new QProfileDeleteAction(languages, null, null, userSessionRule),
-      new QProfileExportAction(null, null, null, mock(QProfileExporters.class), languages),
-      new QProfileExportersAction(),
-      new QProfileInheritanceAction(null, null, null, null, languages),
-      new QProfileRenameAction(null, userSessionRule)
+      new CreateAction(null, null, null, languages, importers, userSessionRule),
+      new ImportersAction(importers),
+      new RestoreBuiltInAction(null),
+      new SearchAction(languages, null, null, null),
+      new SetDefaultAction(languages, null, null, userSessionRule),
+      new ProjectsAction(null, userSessionRule),
+      new BackupAction(null, null, null, languages),
+      new RestoreAction(null, languages, userSessionRule),
+      new ChangelogAction(null, null, null, languages),
+      new ChangeParentAction(null, null, null, languages, userSessionRule),
+      new CompareAction(null, null, null, languages),
+      new CopyAction(null, languages, userSessionRule),
+      new DeleteAction(languages, null, null, userSessionRule),
+      new ExportAction(null, null, null, mock(QProfileExporters.class), languages),
+      new ExportersAction(),
+      new InheritanceAction(null, null, null, null, languages),
+      new RenameAction(null, userSessionRule)
     )).controller(QProfilesWs.API_ENDPOINT);
   }
 
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RenameActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RenameActionTest.java
new file mode 100644 (file)
index 0000000..d5d70d4
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class RenameActionTest {
+
+  @ClassRule
+  public static DbTester dbTester = new DbTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private DbClient dbClient;
+
+  private QualityProfileDao qualityProfileDao;
+
+  private String xoo1Key = "xoo1", xoo2Key = "xoo2";
+
+  private WsTester tester;
+
+  private DbSession session;
+
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao);
+    session = dbClient.openSession(false);
+
+    createProfiles();
+
+    tester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new RenameAction(new QProfileFactory(dbClient), userSessionRule)));
+  }
+
+  @After
+  public void tearDown() {
+    session.close();
+  }
+
+  @Test
+  public void rename_nominal() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "rename")
+      .setParam("key", "sonar-way-xoo2-23456")
+      .setParam("name", "Other Sonar Way")
+      .execute().assertNoContent();
+
+    assertThat(qualityProfileDao.getNonNullByKey(session, "sonar-way-xoo2-23456").getName()).isEqualTo("Other Sonar Way");
+  }
+
+  @Test(expected = BadRequestException.class)
+  public void do_nothing_on_conflict() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "rename")
+      .setParam("key", "sonar-way-xoo2-23456")
+      .setParam("name", "My Sonar way")
+      .execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_key() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "rename")
+      .setParam("name", "Other Sonar Way")
+      .execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_name() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "rename")
+      .setParam("key", "sonar-way-xoo1-13245")
+      .execute();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_on_missing_permission() throws Exception {
+    userSessionRule.login("obiwan");
+
+    tester.newPostRequest("api/qualityprofiles", "rename")
+      .setParam("key", "sonar-way-xoo1-13245")
+      .setParam("name", "Hey look I am not quality profile admin!")
+      .execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_unknown_profile() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "rename")
+      .setParam("key", "polop")
+      .setParam("name", "Uh oh, I don't know this profile")
+      .execute();
+  }
+
+  private void createProfiles() {
+    qualityProfileDao.insert(session,
+      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1Key).setName("Sonar way").setDefault(true),
+      QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2Key).setName("Sonar way"),
+      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2Key).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true)
+      );
+    session.commit();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java
new file mode 100644 (file)
index 0000000..7ad552f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import java.io.Reader;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.BulkChangeResult;
+import org.sonar.server.qualityprofile.QProfileBackuper;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RestoreActionTest {
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  // TODO Replace with proper DbTester + EsTester medium test once DaoV2 is removed
+  @Mock
+  private QProfileBackuper backuper;
+
+  private WsTester tester;
+
+  @Before
+  public void setUp() {
+    tester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new RestoreAction(backuper, LanguageTesting.newLanguages("xoo"), userSessionRule)));
+  }
+
+  @Test
+  public void restore_profile() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    QualityProfileDto profile = QualityProfileDto.createFor("xoo-sonar-way-12345")
+      .setDefault(false).setLanguage("xoo").setName("Sonar way");
+    BulkChangeResult restoreResult = new BulkChangeResult(profile);
+    when(backuper.restore(any(Reader.class), (QProfileName) eq(null))).thenReturn(restoreResult);
+
+    tester.newPostRequest("api/qualityprofiles", "restore").setParam("backup", "<polop><palap/></polop>").execute()
+      .assertJson(getClass(), "restore_profile.json");
+    verify(backuper).restore(any(Reader.class), (QProfileName) eq(null));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_missing_backup() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newGetRequest("api/qualityprofiles", "restore").execute();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_on_misssing_permission() throws Exception {
+    userSessionRule.login("obiwan");
+
+    tester.newPostRequest("api/qualityprofiles", "restore").setParam("backup", "<polop><palap/></polop>").execute();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java
new file mode 100644 (file)
index 0000000..1c433dd
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.i18n.I18n;
+import org.sonar.server.qualityprofile.QProfileService;
+import org.sonar.server.ws.WsTester;
+
+import static org.mockito.Mockito.mock;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RestoreBuiltInActionTest {
+
+  @Mock
+  QProfileService profileService;
+
+  @Mock
+  I18n i18n;
+
+  WsTester tester;
+
+  @Before
+  public void setUp() {
+    tester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new RestoreBuiltInAction(profileService)));
+  }
+
+  @Test
+  public void return_empty_result_when_no_infos_or_warnings() throws Exception {
+    WsTester.TestRequest request = tester.newPostRequest("api/qualityprofiles", "restore_built_in").setParam("language", "java");
+    request.execute().assertNoContent();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
new file mode 100644 (file)
index 0000000..28650ac
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileLoader;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.ws.WsTester;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SearchActionTest {
+
+  @ClassRule
+  public static DbTester dbTester = new DbTester();
+
+  private DbClient dbClient;
+
+  private QualityProfileDao qualityProfileDao;
+
+  private Language xoo1, xoo2;
+
+  private WsTester tester;
+
+  private DbSession session;
+
+  private QProfileLoader profileLoader;
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao);
+    session = dbClient.openSession(false);
+
+    // TODO Replace with actual implementation after removal of DaoV2...
+    profileLoader = mock(QProfileLoader.class);
+
+    xoo1 = LanguageTesting.newLanguage("xoo1");
+    xoo2 = LanguageTesting.newLanguage("xoo2");
+
+    tester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new SearchAction(new Languages(xoo1, xoo2), new QProfileLookup(dbClient), profileLoader, qualityProfileDao)));
+  }
+
+  @After
+  public void teadDown() {
+    session.close();
+  }
+
+  @Test
+  public void search_nominal() throws Exception {
+    when(profileLoader.countAllActiveRules()).thenReturn(ImmutableMap.of(
+      "sonar-way-xoo1-12345", 11L,
+      "my-sonar-way-xoo2-34567", 33L
+      ));
+
+    qualityProfileDao.insert(session,
+      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way").setDefault(true),
+      QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2.getKey()).setName("Sonar way"),
+      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2.getKey()).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456"),
+      QualityProfileDto.createFor("sonar-way-other-666").setLanguage("other").setName("Sonar way").setDefault(true)
+      );
+    new ComponentDao().insert(session,
+      ComponentTesting.newProjectDto("project-uuid1"),
+      ComponentTesting.newProjectDto("project-uuid2"));
+    qualityProfileDao.insertProjectProfileAssociation("project-uuid1", "sonar-way-xoo2-23456", session);
+    qualityProfileDao.insertProjectProfileAssociation("project-uuid2", "sonar-way-xoo2-23456", session);
+    session.commit();
+
+    tester.newGetRequest("api/qualityprofiles", "search").execute().assertJson(this.getClass(), "search.json");
+  }
+
+  @Test
+  public void search_with_fields() throws Exception {
+    qualityProfileDao.insert(session,
+      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way").setDefault(true),
+      QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2.getKey()).setName("Sonar way"),
+      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2.getKey()).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456")
+      );
+    session.commit();
+
+    tester.newGetRequest("api/qualityprofiles", "search").setParam("f", "key,language").execute().assertJson(this.getClass(), "search_fields.json");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_on_unknown_fields() throws Exception {
+    tester.newGetRequest("api/qualityprofiles", "search").setParam("f", "polop").execute();
+  }
+
+  @Test
+  public void search_for_language() throws Exception {
+    qualityProfileDao.insert(session,
+      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way")
+      );
+    session.commit();
+
+    tester.newGetRequest("api/qualityprofiles", "search").setParam("language", xoo1.getKey()).execute().assertJson(this.getClass(), "search_xoo1.json");
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SetDefaultActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SetDefaultActionTest.java
new file mode 100644 (file)
index 0000000..1c543a0
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.assertj.core.api.Fail;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class SetDefaultActionTest {
+
+  @ClassRule
+  public static DbTester dbTester = new DbTester();
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private DbClient dbClient;
+
+  private QualityProfileDao qualityProfileDao;
+
+  private String xoo1Key = "xoo1", xoo2Key = "xoo2";
+
+  private WsTester tester;
+
+  private DbSession session;
+
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao);
+    session = dbClient.openSession(false);
+
+    createProfiles();
+
+    tester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new SetDefaultAction(LanguageTesting.newLanguages(xoo1Key, xoo2Key), new QProfileLookup(dbClient), new QProfileFactory(dbClient), userSessionRule)));
+  }
+
+  @After
+  public void tearDown() {
+    session.close();
+  }
+
+  @Test
+  public void set_default_profile_using_key() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+
+    checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
+    checkDefaultProfile(xoo2Key, "my-sonar-way-xoo2-34567");
+
+    tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
+
+    checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
+    checkDefaultProfile(xoo2Key, "sonar-way-xoo2-23456");
+    assertThat(dbClient.qualityProfileDao().getByKey(session, "sonar-way-xoo2-23456").isDefault()).isTrue();
+    assertThat(dbClient.qualityProfileDao().getByKey(session, "my-sonar-way-xoo2-34567").isDefault()).isFalse();
+
+    // One more time!
+    tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
+    checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
+    checkDefaultProfile(xoo2Key, "sonar-way-xoo2-23456");
+  }
+
+  @Test
+  public void set_default_profile_using_language_and_name() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    tester.newPostRequest("api/qualityprofiles", "set_default").setParam("language", xoo2Key).setParam("profileName", "Sonar way").execute().assertNoContent();
+
+    checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
+    checkDefaultProfile(xoo2Key, "sonar-way-xoo2-23456");
+  }
+
+  @Test
+  public void fail_to_set_default_profile_using_key() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    try {
+      tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "unknown-profile-666").execute();
+      Fail.failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
+    } catch(IllegalArgumentException nfe) {
+      assertThat(nfe).hasMessage("Quality profile not found: unknown-profile-666");
+      checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
+      checkDefaultProfile(xoo2Key, "my-sonar-way-xoo2-34567");
+    }
+  }
+
+
+  @Test
+  public void fail_to_set_default_profile_using_language_and_name() throws Exception {
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    try {
+      tester.newPostRequest("api/qualityprofiles", "set_default").setParam("language", xoo2Key).setParam("profileName", "Unknown").execute();
+      Fail.failBecauseExceptionWasNotThrown(NotFoundException.class);
+    } catch(NotFoundException nfe) {
+      assertThat(nfe).hasMessage("Unable to find a profile for language 'xoo2' with name 'Unknown'");
+      checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
+      checkDefaultProfile(xoo2Key, "my-sonar-way-xoo2-34567");
+    }
+  }
+
+  @Test
+  public void fail_on_missing_permission() throws Exception {
+    userSessionRule.login("obiwan");
+
+    try {
+      tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
+      Fail.failBecauseExceptionWasNotThrown(ForbiddenException.class);
+    } catch(ForbiddenException forbidden) {
+      checkDefaultProfile(xoo1Key, "sonar-way-xoo1-12345");
+      checkDefaultProfile(xoo2Key, "my-sonar-way-xoo2-34567");
+    }
+  }
+
+  private void createProfiles() {
+    qualityProfileDao.insert(session,
+      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1Key).setName("Sonar way").setDefault(true),
+      QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2Key).setName("Sonar way"),
+      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2Key).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true)
+      );
+    session.commit();
+  }
+
+  private void checkDefaultProfile(String language, String key) {
+    assertThat(dbClient.qualityProfileDao().getDefaultProfile(language).getKey()).isEqualTo(key);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java
new file mode 100644 (file)
index 0000000..d0c68a0
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.test.ws;
+
+import java.util.Arrays;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.test.index.CoveredFileDoc;
+import org.sonar.server.test.index.TestIndex;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyList;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.server.component.ComponentTesting.newFileDto;
+import static org.sonar.server.component.ComponentTesting.newProjectDto;
+import static org.sonar.server.test.ws.CoveredFilesAction.TEST_UUID;
+
+public class CoveredFilesActionTest {
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  WsTester ws;
+  private DbClient dbClient;
+  private TestIndex testIndex;
+
+  @Before
+  public void setUp() {
+    dbClient = mock(DbClient.class, RETURNS_DEEP_STUBS);
+    testIndex = mock(TestIndex.class, RETURNS_DEEP_STUBS);
+    ws = new WsTester(new TestsWs(new CoveredFilesAction(dbClient, testIndex, userSessionRule)));
+  }
+
+  @Test
+  public void covered_files() throws Exception {
+    userSessionRule.addComponentUuidPermission(UserRole.CODEVIEWER, "SonarQube", "test-file-uuid");
+
+    when(testIndex.searchByTestUuid(anyString()).fileUuid()).thenReturn("test-file-uuid");
+    when(testIndex.coveredFiles("test-uuid")).thenReturn(Arrays.asList(
+      new CoveredFileDoc().setFileUuid("bar-uuid").setCoveredLines(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),
+      new CoveredFileDoc().setFileUuid("file-uuid").setCoveredLines(Arrays.asList(1, 2, 3))
+      ));
+    when(dbClient.componentDao().selectByUuids(any(DbSession.class), anyList())).thenReturn(
+      Arrays.asList(
+        newFileDto(newProjectDto(), "bar-uuid").setKey("org.foo.Bar.java").setLongName("src/main/java/org/foo/Bar.java"),
+        newFileDto(newProjectDto(), "file-uuid").setKey("org.foo.File.java").setLongName("src/main/java/org/foo/File.java")));
+
+    WsTester.TestRequest request = ws.newGetRequest("api/tests", "covered_files").setParam(TEST_UUID, "test-uuid");
+
+    request.execute().assertJson(getClass(), "tests-covered-files.json");
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java
new file mode 100644 (file)
index 0000000..753687d
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.test.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.config.Settings;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.test.index.CoveredFileDoc;
+import org.sonar.server.test.index.TestDoc;
+import org.sonar.server.test.index.TestIndex;
+import org.sonar.server.test.index.TestIndexDefinition;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.test.DbTests;
+
+import java.util.Arrays;
+import java.util.List;
+
+@Category(DbTests.class)
+public class ListActionTest {
+  DbClient dbClient;
+  DbSession dbSession;
+  TestIndex testIndex;
+
+  WsTester ws;
+
+  @ClassRule
+  public static DbTester db = new DbTester();
+  @ClassRule
+  public static EsTester es = new EsTester().addDefinitions(new TestIndexDefinition(new Settings()));
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  @Before
+  public void setUp() {
+    dbClient = new DbClient(db.database(), db.myBatis(), new ComponentDao());
+    dbSession = dbClient.openSession(false);
+    db.truncateTables();
+    es.truncateIndices();
+    testIndex = new TestIndex(es.client());
+
+    ws = new WsTester(new TestsWs(new ListAction(dbClient, testIndex, userSessionRule)));
+  }
+
+  @After
+  public void tearDown() {
+    dbSession.close();
+  }
+
+  @Test
+  public void list_based_on_test_uuid() throws Exception {
+    userSessionRule.addProjectUuidPermissions(UserRole.CODEVIEWER, TestFile1.PROJECT_UUID);
+
+    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
+    dbSession.commit();
+
+    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE,
+      new TestDoc()
+        .setUuid(TestFile1.UUID)
+        .setName(TestFile1.NAME)
+        .setFileUuid(TestFile1.FILE_UUID)
+        .setDurationInMs(TestFile1.DURATION_IN_MS)
+        .setStatus(TestFile1.STATUS)
+        .setMessage(TestFile1.MESSAGE)
+        .setCoveredFiles(TestFile1.COVERED_FILES)
+        .setStackTrace(TestFile1.STACKTRACE)
+      );
+
+    WsTester.TestRequest request = ws.newGetRequest("api/tests", "list").setParam(ListAction.TEST_UUID, TestFile1.UUID);
+
+    request.execute().assertJson(getClass(), "list-test-uuid.json");
+  }
+
+  @Test
+  public void list_based_on_test_file_uuid() throws Exception {
+    userSessionRule.addProjectUuidPermissions(UserRole.CODEVIEWER, TestFile1.PROJECT_UUID);
+    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
+    dbSession.commit();
+
+    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE,
+      new TestDoc()
+        .setUuid(TestFile1.UUID)
+        .setName(TestFile1.NAME)
+        .setFileUuid(TestFile1.FILE_UUID)
+        .setDurationInMs(TestFile1.DURATION_IN_MS)
+        .setCoveredFiles(TestFile1.COVERED_FILES)
+        .setStatus(TestFile1.STATUS)
+        .setMessage(TestFile1.MESSAGE)
+        .setStackTrace(TestFile1.STACKTRACE));
+
+    WsTester.TestRequest request = ws.newGetRequest("api/tests", "list").setParam(ListAction.TEST_FILE_UUID, TestFile1.FILE_UUID);
+
+    request.execute().assertJson(getClass(), "list-test-uuid.json");
+  }
+
+  @Test
+  public void list_based_on_test_file_key() throws Exception {
+    userSessionRule.addComponentPermission(UserRole.CODEVIEWER, TestFile1.PROJECT_UUID, TestFile1.KEY);
+    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
+    dbSession.commit();
+
+    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE,
+      new TestDoc()
+        .setUuid(TestFile1.UUID)
+        .setName(TestFile1.NAME)
+        .setFileUuid(TestFile1.FILE_UUID)
+        .setDurationInMs(TestFile1.DURATION_IN_MS)
+        .setCoveredFiles(TestFile1.COVERED_FILES)
+        .setStatus(TestFile1.STATUS)
+        .setMessage(TestFile1.MESSAGE)
+        .setStackTrace(TestFile1.STACKTRACE)
+      );
+
+    WsTester.TestRequest request = ws.newGetRequest("api/tests", "list").setParam(ListAction.TEST_FILE_KEY, TestFile1.KEY);
+
+    request.execute().assertJson(getClass(), "list-test-uuid.json");
+  }
+
+  @Test
+  public void list_based_on_main_file_and_line_number() throws Exception {
+    String mainFileUuid = "MAIN-FILE-UUID";
+    userSessionRule.addProjectUuidPermissions(UserRole.CODEVIEWER, TestFile1.PROJECT_UUID);
+    dbClient.componentDao().insert(dbSession,
+      new ComponentDto()
+        .setUuid(TestFile1.FILE_UUID)
+        .setLongName(TestFile1.LONG_NAME)
+        .setKey(TestFile1.KEY)
+        .setProjectUuid(TestFile1.PROJECT_UUID),
+      new ComponentDto()
+        .setUuid(TestFile2.FILE_UUID)
+        .setLongName(TestFile2.LONG_NAME)
+        .setProjectUuid(TestFile2.PROJECT_UUID)
+        .setKey(TestFile2.KEY),
+      new ComponentDto()
+        .setUuid(mainFileUuid)
+        .setProjectUuid(TestFile1.PROJECT_UUID)
+      );
+    dbSession.commit();
+
+    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE,
+      new TestDoc()
+        .setUuid(TestFile1.UUID)
+        .setName(TestFile1.NAME)
+        .setFileUuid(TestFile1.FILE_UUID)
+        .setDurationInMs(TestFile1.DURATION_IN_MS)
+        .setStatus(TestFile1.STATUS)
+        .setMessage(TestFile1.MESSAGE)
+        .setCoveredFiles(TestFile1.COVERED_FILES)
+        .setStackTrace(TestFile1.STACKTRACE),
+      new TestDoc()
+        .setUuid(TestFile2.UUID)
+        .setName(TestFile2.NAME)
+        .setFileUuid(TestFile2.FILE_UUID)
+        .setDurationInMs(TestFile2.DURATION_IN_MS)
+        .setStatus(TestFile2.STATUS)
+        .setStackTrace(TestFile2.STATUS)
+        .setMessage(TestFile2.MESSAGE)
+        .setCoveredFiles(TestFile2.COVERED_FILES)
+        .setStackTrace(TestFile2.STACKTRACE));
+
+    WsTester.TestRequest request = ws.newGetRequest("api/tests", "list")
+      .setParam(ListAction.SOURCE_FILE_UUID, mainFileUuid)
+      .setParam(ListAction.SOURCE_FILE_LINE_NUMBER, "10");
+
+    request.execute().assertJson(getClass(), "list-main-file.json");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_when_no_argument() throws Exception {
+    ws.newGetRequest("api/tests", "list").execute();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void fail_when_main_file_uuid_without_line_number() throws Exception {
+    ws.newGetRequest("api/tests", "list").setParam(ListAction.SOURCE_FILE_UUID, "ANY-UUID").execute();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_when_no_sufficent_privilege_on_file_uuid() throws Exception {
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, TestFile1.PROJECT_UUID);
+    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
+    dbSession.commit();
+    ws.newGetRequest("api/tests", "list").setParam(ListAction.TEST_FILE_UUID, TestFile1.FILE_UUID).execute();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_when_no_sufficent_privilege_on_test_uuid() throws Exception {
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, TestFile1.PROJECT_UUID);
+    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
+    dbSession.commit();
+    ws.newGetRequest("api/tests", "list").setParam(ListAction.TEST_FILE_UUID, TestFile1.FILE_UUID).execute();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_when_no_sufficent_privilege_on_file_key() throws Exception {
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, TestFile1.PROJECT_UUID);
+    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
+    dbSession.commit();
+    ws.newGetRequest("api/tests", "list").setParam(ListAction.TEST_FILE_KEY, TestFile1.KEY).execute();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_when_no_sufficient_privilege_on_main_file_uuid() throws Exception {
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, TestFile1.PROJECT_UUID);
+    String mainFileUuid = "MAIN-FILE-UUID";
+    dbClient.componentDao().insert(dbSession, new ComponentDto().setUuid(mainFileUuid).setProjectUuid(TestFile1.PROJECT_UUID));
+    dbSession.commit();
+
+    ws.newGetRequest("api/tests", "list")
+      .setParam(ListAction.SOURCE_FILE_UUID, mainFileUuid)
+      .setParam(ListAction.SOURCE_FILE_LINE_NUMBER, "10")
+      .execute();
+  }
+
+  private static final class TestFile1 {
+    public static final String UUID = "TEST-UUID-1";
+    public static final String FILE_UUID = "ABCD";
+    public static final String PROJECT_UUID = "PROJECT-UUID";
+    public static final String NAME = "test1";
+    public static final String STATUS = "OK";
+    public static final long DURATION_IN_MS = 10;
+    public static final String MESSAGE = "MESSAGE-1";
+    public static final String STACKTRACE = "STACKTRACE-1";
+    public static final String KEY = "org.foo.BarTest.java";
+    public static final String LONG_NAME = "src/test/java/org/foo/BarTest.java";
+    public static final List<CoveredFileDoc> COVERED_FILES = Arrays.asList(new CoveredFileDoc().setFileUuid("MAIN-FILE-UUID").setCoveredLines(Arrays.asList(1, 2, 3, 10)));
+
+    public static ComponentDto newDto() {
+      return new ComponentDto()
+        .setUuid(TestFile1.FILE_UUID)
+        .setLongName(TestFile1.LONG_NAME)
+        .setProjectUuid(TestFile1.PROJECT_UUID)
+        .setKey(TestFile1.KEY);
+    }
+
+    private TestFile1() {
+      // static stuff for test purposes
+    }
+  }
+
+  private static final class TestFile2 {
+    public static final String UUID = "TEST-UUID-2";
+    public static final String FILE_UUID = "BCDE";
+    public static final String PROJECT_UUID = "PROJECT-UUID";
+    public static final String NAME = "test2";
+    public static final String STATUS = "ERROR";
+    public static final long DURATION_IN_MS = 97;
+    public static final String MESSAGE = "MESSAGE-2";
+    public static final String STACKTRACE = "STACKTRACE-2";
+    public static final String KEY = "org.foo.FileTest.java";
+    public static final String LONG_NAME = "src/test/java/org/foo/FileTest.java";
+    public static final List<CoveredFileDoc> COVERED_FILES = Arrays.asList(new CoveredFileDoc().setFileUuid("MAIN-FILE-UUID").setCoveredLines(Arrays.asList(11, 12, 13, 10)));
+
+    private TestFile2() {
+      // static stuff for test purposes
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsCoveredFilesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsCoveredFilesActionTest.java
deleted file mode 100644 (file)
index a0156dc..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.test.ws;
-
-import java.util.Arrays;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.test.index.CoveredFileDoc;
-import org.sonar.server.test.index.TestIndex;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyList;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.component.ComponentTesting.newFileDto;
-import static org.sonar.server.component.ComponentTesting.newProjectDto;
-import static org.sonar.server.test.ws.TestsCoveredFilesAction.TEST_UUID;
-
-public class TestsCoveredFilesActionTest {
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  WsTester ws;
-  private DbClient dbClient;
-  private TestIndex testIndex;
-
-  @Before
-  public void setUp() {
-    dbClient = mock(DbClient.class, RETURNS_DEEP_STUBS);
-    testIndex = mock(TestIndex.class, RETURNS_DEEP_STUBS);
-    ws = new WsTester(new TestsWs(new TestsCoveredFilesAction(dbClient, testIndex, userSessionRule)));
-  }
-
-  @Test
-  public void covered_files() throws Exception {
-    userSessionRule.addComponentUuidPermission(UserRole.CODEVIEWER, "SonarQube", "test-file-uuid");
-
-    when(testIndex.searchByTestUuid(anyString()).fileUuid()).thenReturn("test-file-uuid");
-    when(testIndex.coveredFiles("test-uuid")).thenReturn(Arrays.asList(
-      new CoveredFileDoc().setFileUuid("bar-uuid").setCoveredLines(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),
-      new CoveredFileDoc().setFileUuid("file-uuid").setCoveredLines(Arrays.asList(1, 2, 3))
-      ));
-    when(dbClient.componentDao().selectByUuids(any(DbSession.class), anyList())).thenReturn(
-      Arrays.asList(
-        newFileDto(newProjectDto(), "bar-uuid").setKey("org.foo.Bar.java").setLongName("src/main/java/org/foo/Bar.java"),
-        newFileDto(newProjectDto(), "file-uuid").setKey("org.foo.File.java").setLongName("src/main/java/org/foo/File.java")));
-
-    WsTester.TestRequest request = ws.newGetRequest("api/tests", "covered_files").setParam(TEST_UUID, "test-uuid");
-
-    request.execute().assertJson(getClass(), "tests-covered-files.json");
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsListActionTest.java
deleted file mode 100644 (file)
index 3de460c..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.test.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.config.Settings;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.test.index.CoveredFileDoc;
-import org.sonar.server.test.index.TestDoc;
-import org.sonar.server.test.index.TestIndex;
-import org.sonar.server.test.index.TestIndexDefinition;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-import org.sonar.test.DbTests;
-
-import java.util.Arrays;
-import java.util.List;
-
-@Category(DbTests.class)
-public class TestsListActionTest {
-  DbClient dbClient;
-  DbSession dbSession;
-  TestIndex testIndex;
-
-  WsTester ws;
-
-  @ClassRule
-  public static DbTester db = new DbTester();
-  @ClassRule
-  public static EsTester es = new EsTester().addDefinitions(new TestIndexDefinition(new Settings()));
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  @Before
-  public void setUp() {
-    dbClient = new DbClient(db.database(), db.myBatis(), new ComponentDao());
-    dbSession = dbClient.openSession(false);
-    db.truncateTables();
-    es.truncateIndices();
-    testIndex = new TestIndex(es.client());
-
-    ws = new WsTester(new TestsWs(new TestsListAction(dbClient, testIndex, userSessionRule)));
-  }
-
-  @After
-  public void tearDown() {
-    dbSession.close();
-  }
-
-  @Test
-  public void list_based_on_test_uuid() throws Exception {
-    userSessionRule.addProjectUuidPermissions(UserRole.CODEVIEWER, TestFile1.PROJECT_UUID);
-
-    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
-    dbSession.commit();
-
-    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE,
-      new TestDoc()
-        .setUuid(TestFile1.UUID)
-        .setName(TestFile1.NAME)
-        .setFileUuid(TestFile1.FILE_UUID)
-        .setDurationInMs(TestFile1.DURATION_IN_MS)
-        .setStatus(TestFile1.STATUS)
-        .setMessage(TestFile1.MESSAGE)
-        .setCoveredFiles(TestFile1.COVERED_FILES)
-        .setStackTrace(TestFile1.STACKTRACE)
-      );
-
-    WsTester.TestRequest request = ws.newGetRequest("api/tests", "list").setParam(TestsListAction.TEST_UUID, TestFile1.UUID);
-
-    request.execute().assertJson(getClass(), "list-test-uuid.json");
-  }
-
-  @Test
-  public void list_based_on_test_file_uuid() throws Exception {
-    userSessionRule.addProjectUuidPermissions(UserRole.CODEVIEWER, TestFile1.PROJECT_UUID);
-    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
-    dbSession.commit();
-
-    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE,
-      new TestDoc()
-        .setUuid(TestFile1.UUID)
-        .setName(TestFile1.NAME)
-        .setFileUuid(TestFile1.FILE_UUID)
-        .setDurationInMs(TestFile1.DURATION_IN_MS)
-        .setCoveredFiles(TestFile1.COVERED_FILES)
-        .setStatus(TestFile1.STATUS)
-        .setMessage(TestFile1.MESSAGE)
-        .setStackTrace(TestFile1.STACKTRACE));
-
-    WsTester.TestRequest request = ws.newGetRequest("api/tests", "list").setParam(TestsListAction.TEST_FILE_UUID, TestFile1.FILE_UUID);
-
-    request.execute().assertJson(getClass(), "list-test-uuid.json");
-  }
-
-  @Test
-  public void list_based_on_test_file_key() throws Exception {
-    userSessionRule.addComponentPermission(UserRole.CODEVIEWER, TestFile1.PROJECT_UUID, TestFile1.KEY);
-    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
-    dbSession.commit();
-
-    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE,
-      new TestDoc()
-        .setUuid(TestFile1.UUID)
-        .setName(TestFile1.NAME)
-        .setFileUuid(TestFile1.FILE_UUID)
-        .setDurationInMs(TestFile1.DURATION_IN_MS)
-        .setCoveredFiles(TestFile1.COVERED_FILES)
-        .setStatus(TestFile1.STATUS)
-        .setMessage(TestFile1.MESSAGE)
-        .setStackTrace(TestFile1.STACKTRACE)
-      );
-
-    WsTester.TestRequest request = ws.newGetRequest("api/tests", "list").setParam(TestsListAction.TEST_FILE_KEY, TestFile1.KEY);
-
-    request.execute().assertJson(getClass(), "list-test-uuid.json");
-  }
-
-  @Test
-  public void list_based_on_main_file_and_line_number() throws Exception {
-    String mainFileUuid = "MAIN-FILE-UUID";
-    userSessionRule.addProjectUuidPermissions(UserRole.CODEVIEWER, TestFile1.PROJECT_UUID);
-    dbClient.componentDao().insert(dbSession,
-      new ComponentDto()
-        .setUuid(TestFile1.FILE_UUID)
-        .setLongName(TestFile1.LONG_NAME)
-        .setKey(TestFile1.KEY)
-        .setProjectUuid(TestFile1.PROJECT_UUID),
-      new ComponentDto()
-        .setUuid(TestFile2.FILE_UUID)
-        .setLongName(TestFile2.LONG_NAME)
-        .setProjectUuid(TestFile2.PROJECT_UUID)
-        .setKey(TestFile2.KEY),
-      new ComponentDto()
-        .setUuid(mainFileUuid)
-        .setProjectUuid(TestFile1.PROJECT_UUID)
-      );
-    dbSession.commit();
-
-    es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE,
-      new TestDoc()
-        .setUuid(TestFile1.UUID)
-        .setName(TestFile1.NAME)
-        .setFileUuid(TestFile1.FILE_UUID)
-        .setDurationInMs(TestFile1.DURATION_IN_MS)
-        .setStatus(TestFile1.STATUS)
-        .setMessage(TestFile1.MESSAGE)
-        .setCoveredFiles(TestFile1.COVERED_FILES)
-        .setStackTrace(TestFile1.STACKTRACE),
-      new TestDoc()
-        .setUuid(TestFile2.UUID)
-        .setName(TestFile2.NAME)
-        .setFileUuid(TestFile2.FILE_UUID)
-        .setDurationInMs(TestFile2.DURATION_IN_MS)
-        .setStatus(TestFile2.STATUS)
-        .setStackTrace(TestFile2.STATUS)
-        .setMessage(TestFile2.MESSAGE)
-        .setCoveredFiles(TestFile2.COVERED_FILES)
-        .setStackTrace(TestFile2.STACKTRACE));
-
-    WsTester.TestRequest request = ws.newGetRequest("api/tests", "list")
-      .setParam(TestsListAction.SOURCE_FILE_UUID, mainFileUuid)
-      .setParam(TestsListAction.SOURCE_FILE_LINE_NUMBER, "10");
-
-    request.execute().assertJson(getClass(), "list-main-file.json");
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_when_no_argument() throws Exception {
-    ws.newGetRequest("api/tests", "list").execute();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void fail_when_main_file_uuid_without_line_number() throws Exception {
-    ws.newGetRequest("api/tests", "list").setParam(TestsListAction.SOURCE_FILE_UUID, "ANY-UUID").execute();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_when_no_sufficent_privilege_on_file_uuid() throws Exception {
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, TestFile1.PROJECT_UUID);
-    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
-    dbSession.commit();
-    ws.newGetRequest("api/tests", "list").setParam(TestsListAction.TEST_FILE_UUID, TestFile1.FILE_UUID).execute();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_when_no_sufficent_privilege_on_test_uuid() throws Exception {
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, TestFile1.PROJECT_UUID);
-    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
-    dbSession.commit();
-    ws.newGetRequest("api/tests", "list").setParam(TestsListAction.TEST_FILE_UUID, TestFile1.FILE_UUID).execute();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_when_no_sufficent_privilege_on_file_key() throws Exception {
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, TestFile1.PROJECT_UUID);
-    dbClient.componentDao().insert(dbSession, TestFile1.newDto());
-    dbSession.commit();
-    ws.newGetRequest("api/tests", "list").setParam(TestsListAction.TEST_FILE_KEY, TestFile1.KEY).execute();
-  }
-
-  @Test(expected = ForbiddenException.class)
-  public void fail_when_no_sufficient_privilege_on_main_file_uuid() throws Exception {
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, TestFile1.PROJECT_UUID);
-    String mainFileUuid = "MAIN-FILE-UUID";
-    dbClient.componentDao().insert(dbSession, new ComponentDto().setUuid(mainFileUuid).setProjectUuid(TestFile1.PROJECT_UUID));
-    dbSession.commit();
-
-    ws.newGetRequest("api/tests", "list")
-      .setParam(TestsListAction.SOURCE_FILE_UUID, mainFileUuid)
-      .setParam(TestsListAction.SOURCE_FILE_LINE_NUMBER, "10")
-      .execute();
-  }
-
-  private static final class TestFile1 {
-    public static final String UUID = "TEST-UUID-1";
-    public static final String FILE_UUID = "ABCD";
-    public static final String PROJECT_UUID = "PROJECT-UUID";
-    public static final String NAME = "test1";
-    public static final String STATUS = "OK";
-    public static final long DURATION_IN_MS = 10;
-    public static final String MESSAGE = "MESSAGE-1";
-    public static final String STACKTRACE = "STACKTRACE-1";
-    public static final String KEY = "org.foo.BarTest.java";
-    public static final String LONG_NAME = "src/test/java/org/foo/BarTest.java";
-    public static final List<CoveredFileDoc> COVERED_FILES = Arrays.asList(new CoveredFileDoc().setFileUuid("MAIN-FILE-UUID").setCoveredLines(Arrays.asList(1, 2, 3, 10)));
-
-    public static ComponentDto newDto() {
-      return new ComponentDto()
-        .setUuid(TestFile1.FILE_UUID)
-        .setLongName(TestFile1.LONG_NAME)
-        .setProjectUuid(TestFile1.PROJECT_UUID)
-        .setKey(TestFile1.KEY);
-    }
-
-    private TestFile1() {
-      // static stuff for test purposes
-    }
-  }
-
-  private static final class TestFile2 {
-    public static final String UUID = "TEST-UUID-2";
-    public static final String FILE_UUID = "BCDE";
-    public static final String PROJECT_UUID = "PROJECT-UUID";
-    public static final String NAME = "test2";
-    public static final String STATUS = "ERROR";
-    public static final long DURATION_IN_MS = 97;
-    public static final String MESSAGE = "MESSAGE-2";
-    public static final String STACKTRACE = "STACKTRACE-2";
-    public static final String KEY = "org.foo.FileTest.java";
-    public static final String LONG_NAME = "src/test/java/org/foo/FileTest.java";
-    public static final List<CoveredFileDoc> COVERED_FILES = Arrays.asList(new CoveredFileDoc().setFileUuid("MAIN-FILE-UUID").setCoveredLines(Arrays.asList(11, 12, 13, 10)));
-
-    private TestFile2() {
-      // static stuff for test purposes
-    }
-  }
-
-}
index c052d9c03bd886ceb97d15532194092aef3a31f8..545c92fb4f7d387f04629c58fc057ae5452d5406 100644 (file)
@@ -41,8 +41,8 @@ public class TestsWsTest {
   @Before
   public void setUp() {
     WsTester tester = new WsTester(new TestsWs(
-      new TestsListAction(mock(DbClient.class), mock(TestIndex.class), userSessionRule),
-      new TestsCoveredFilesAction(mock(DbClient.class), mock(TestIndex.class), userSessionRule)));
+      new ListAction(mock(DbClient.class), mock(TestIndex.class), userSessionRule),
+      new CoveredFilesAction(mock(DbClient.class), mock(TestIndex.class), userSessionRule)));
     controller = tester.controller("api/tests");
   }
 
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java
new file mode 100644 (file)
index 0000000..7eba15e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.user.ws;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+
+public class CurrentActionTest {
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private WsTester tester;
+
+  @Before
+  public void before() {
+    tester = new WsTester(new UsersWs(new CurrentAction(userSessionRule)));
+  }
+
+  @Test
+  public void anonymous() throws Exception {
+    tester.newGetRequest("api/users", "current").execute().assertJson(getClass(), "anonymous.json");
+  }
+
+  @Test
+  public void authenticated() throws Exception {
+    userSessionRule.login("obiwan.kenobi").setName("Obiwan Kenobi")
+      .setGlobalPermissions(GlobalPermissions.ALL.toArray(new String[0]));
+    tester.newGetRequest("api/users", "current").execute().assertJson(getClass(), "authenticated.json");
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentUserActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentUserActionTest.java
deleted file mode 100644 (file)
index 3ee9168..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.user.ws;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-public class CurrentUserActionTest {
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private WsTester tester;
-
-  @Before
-  public void before() {
-    tester = new WsTester(new UsersWs(new CurrentUserAction(userSessionRule)));
-  }
-
-  @Test
-  public void anonymous() throws Exception {
-    tester.newGetRequest("api/users", "current").execute().assertJson(getClass(), "anonymous.json");
-  }
-
-  @Test
-  public void authenticated() throws Exception {
-    userSessionRule.login("obiwan.kenobi").setName("Obiwan Kenobi")
-      .setGlobalPermissions(GlobalPermissions.ALL.toArray(new String[0]));
-    tester.newGetRequest("api/users", "current").execute().assertJson(getClass(), "authenticated.json");
-  }
-}
index bb5fd484cc5f5cebc93e47fee91e549f95c1f750..ccbb54a383060d7efee62a886d16b592b3bbde7c 100644 (file)
@@ -43,7 +43,7 @@ public class UsersWsTest {
     WsTester tester = new WsTester(new UsersWs(
       new CreateAction(mock(UserIndex.class), mock(UserUpdater.class), mock(I18n.class), userSessionRule),
       new UpdateAction(mock(UserIndex.class), mock(UserUpdater.class), userSessionRule),
-      new CurrentUserAction(userSessionRule),
+      new CurrentAction(userSessionRule),
       new DeactivateAction(mock(UserIndex.class), mock(UserUpdater.class), userSessionRule),
       new ChangePasswordAction(mock(UserUpdater.class), userSessionRule),
       new SearchAction(mock(UserIndex.class))));
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_global_referentials.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_global_referentials.json
new file mode 100644 (file)
index 0000000..2e558ed
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "timestamp": 0,
+  "metrics": [
+    {
+      "id": 1,
+      "key": "coverage",
+      "valueType": "PERCENT",
+      "description": "Coverage by unit tests",
+      "direction": 1,
+      "name": "coverage",
+      "qualitative": true,
+      "userManaged": false,
+      "worstValue": 0.0,
+      "bestValue": 100.0,
+      "optimizedBestValue": false
+    }
+  ],
+  "globalSettings": {}
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_global_settings.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_global_settings.json
new file mode 100644 (file)
index 0000000..d6faa69
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "timestamp": 0,
+  "metrics": [],
+  "globalSettings": {
+    "foo" : "bar",
+    "foo.secured" : "1234",
+    "foo.license.secured" : "5678"
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_only_license_settings_without_scan_but_with_preview_permission.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalActionTest/return_only_license_settings_without_scan_but_with_preview_permission.json
new file mode 100644 (file)
index 0000000..b0af2f8
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "timestamp": 0,
+  "metrics": [],
+  "globalSettings": {
+    "foo" : "bar",
+    "foo.license.secured" : "5678"
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_referentials.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_referentials.json
deleted file mode 100644 (file)
index 2e558ed..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "timestamp": 0,
-  "metrics": [
-    {
-      "id": 1,
-      "key": "coverage",
-      "valueType": "PERCENT",
-      "description": "Coverage by unit tests",
-      "direction": 1,
-      "name": "coverage",
-      "qualitative": true,
-      "userManaged": false,
-      "worstValue": 0.0,
-      "bestValue": 100.0,
-      "optimizedBestValue": false
-    }
-  ],
-  "globalSettings": {}
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_settings.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_settings.json
deleted file mode 100644 (file)
index d6faa69..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "timestamp": 0,
-  "metrics": [],
-  "globalSettings": {
-    "foo" : "bar",
-    "foo.secured" : "1234",
-    "foo.license.secured" : "5678"
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_only_license_settings_without_scan_but_with_preview_permission.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_only_license_settings_without_scan_but_with_preview_permission.json
deleted file mode 100644 (file)
index b0af2f8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "timestamp": 0,
-  "metrics": [],
-  "globalSettings": {
-    "foo" : "bar",
-    "foo.license.secured" : "5678"
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectActionTest/project_referentials.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectActionTest/project_referentials.json
new file mode 100644 (file)
index 0000000..ff04061
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "timestamp": 0,
+  "qprofilesByLanguage": {
+    "java": {
+      "key": "abcd",
+      "name": "Default",
+      "language": "java",
+      "rulesUpdatedAt": "2014-01-14T13:00:00+0100"
+    }
+  },
+  "activeRules": [
+    {
+      "repositoryKey": "squid",
+      "ruleKey": "AvoidCycle",
+      "name": "Avoid Cycle",
+      "severity": "MINOR",
+      "internalKey": "squid-1",
+      "language": "java",
+      "params": {
+        "max" : "2"
+      }
+    }
+  ],
+  "settingsByModule": {
+    "org.codehaus.sonar:sonar": {
+      "sonar.jira.project.key": "SONAR",
+      "sonar.jira.login.secured": "john"
+    }
+  },
+  "fileDataByModuleAndPath": {}
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectRepositoryActionTest/project_referentials.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectRepositoryActionTest/project_referentials.json
deleted file mode 100644 (file)
index ff04061..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-  "timestamp": 0,
-  "qprofilesByLanguage": {
-    "java": {
-      "key": "abcd",
-      "name": "Default",
-      "language": "java",
-      "rulesUpdatedAt": "2014-01-14T13:00:00+0100"
-    }
-  },
-  "activeRules": [
-    {
-      "repositoryKey": "squid",
-      "ruleKey": "AvoidCycle",
-      "name": "Avoid Cycle",
-      "severity": "MINOR",
-      "internalKey": "squid-1",
-      "language": "java",
-      "params": {
-        "max" : "2"
-      }
-    }
-  ],
-  "settingsByModule": {
-    "org.codehaus.sonar:sonar": {
-      "sonar.jira.project.key": "SONAR",
-      "sonar.jira.login.secured": "john"
-    }
-  },
-  "fileDataByModuleAndPath": {}
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app.json
new file mode 100644 (file)
index 0000000..201fc70
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
+  "uuid": "ABCDE",
+  "path": "src/main/java/org/sonar/api/Plugin.java",
+  "name": "Plugin.java",
+  "longName": "src/main/java/org/sonar/api/Plugin.java",
+  "q": "FIL",
+  "subProject": "org.codehaus.sonar:sonar-plugin-api",
+  "subProjectName": "SonarQube :: Plugin API",
+  "project": "org.codehaus.sonar:sonar",
+  "projectName": "SonarQube",
+  "fav": true,
+  "canMarkAsFavourite": true,
+  "canCreateManualIssue": true,
+  "measures": {}
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_it_measure.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_it_measure.json
new file mode 100644 (file)
index 0000000..0b233ce
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
+  "uuid": "ABCDE",
+  "path": "src/main/java/org/sonar/api/Plugin.java",
+  "name": "Plugin.java",
+  "longName": "src/main/java/org/sonar/api/Plugin.java",
+  "q": "FIL",
+  "subProject": "org.codehaus.sonar:sonar-plugin-api",
+  "subProjectName": "SonarQube :: Plugin API",
+  "project": "org.codehaus.sonar:sonar",
+  "projectName": "SonarQube",
+  "fav": false,
+  "canMarkAsFavourite": false,
+  "canCreateManualIssue": false,
+  "measures": {"coverage": "85.2%"}
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_measures.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_measures.json
new file mode 100644 (file)
index 0000000..606f659
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
+  "uuid": "ABCDE",
+  "path": "src/main/java/org/sonar/api/Plugin.java",
+  "name": "Plugin.java",
+  "longName": "src/main/java/org/sonar/api/Plugin.java",
+  "q": "FIL",
+  "subProject": "org.codehaus.sonar:sonar-plugin-api",
+  "subProjectName": "SonarQube :: Plugin API",
+  "project": "org.codehaus.sonar:sonar",
+  "projectName": "SonarQube",
+  "fav": false,
+  "canMarkAsFavourite": false,
+  "canCreateManualIssue": false,
+  "measures": {
+    "lines": "200",
+    "coverage": "95.4%",
+    "duplicationDensity": "7.4%",
+    "debt": "3h 2min",
+    "sqaleRating": "C",
+    "debtRatio": "35.0%"
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_overall_measure.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_overall_measure.json
new file mode 100644 (file)
index 0000000..7cc5aed
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
+  "uuid": "ABCDE",
+  "path": "src/main/java/org/sonar/api/Plugin.java",
+  "name": "Plugin.java",
+  "longName": "src/main/java/org/sonar/api/Plugin.java",
+  "q": "FIL",
+  "subProject": "org.codehaus.sonar:sonar-plugin-api",
+  "subProjectName": "SonarQube :: Plugin API",
+  "project": "org.codehaus.sonar:sonar",
+  "projectName": "SonarQube",
+  "fav": false,
+  "canMarkAsFavourite": false,
+  "canCreateManualIssue": false,
+  "measures": {"coverage": "90.1%"}
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_ut_measure.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/AppActionTest/app_with_ut_measure.json
new file mode 100644 (file)
index 0000000..c6ef590
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
+  "uuid": "ABCDE",
+  "path": "src/main/java/org/sonar/api/Plugin.java",
+  "name": "Plugin.java",
+  "longName": "src/main/java/org/sonar/api/Plugin.java",
+  "q": "FIL",
+  "subProject": "org.codehaus.sonar:sonar-plugin-api",
+  "subProjectName": "SonarQube :: Plugin API",
+  "project": "org.codehaus.sonar:sonar",
+  "projectName": "SonarQube",
+  "fav": false,
+  "canMarkAsFavourite": false,
+  "canCreateManualIssue": false,
+  "measures": {"coverage": "95.4%"}
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app.json
deleted file mode 100644 (file)
index 201fc70..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
-  "uuid": "ABCDE",
-  "path": "src/main/java/org/sonar/api/Plugin.java",
-  "name": "Plugin.java",
-  "longName": "src/main/java/org/sonar/api/Plugin.java",
-  "q": "FIL",
-  "subProject": "org.codehaus.sonar:sonar-plugin-api",
-  "subProjectName": "SonarQube :: Plugin API",
-  "project": "org.codehaus.sonar:sonar",
-  "projectName": "SonarQube",
-  "fav": true,
-  "canMarkAsFavourite": true,
-  "canCreateManualIssue": true,
-  "measures": {}
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_it_measure.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_it_measure.json
deleted file mode 100644 (file)
index 0b233ce..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
-  "uuid": "ABCDE",
-  "path": "src/main/java/org/sonar/api/Plugin.java",
-  "name": "Plugin.java",
-  "longName": "src/main/java/org/sonar/api/Plugin.java",
-  "q": "FIL",
-  "subProject": "org.codehaus.sonar:sonar-plugin-api",
-  "subProjectName": "SonarQube :: Plugin API",
-  "project": "org.codehaus.sonar:sonar",
-  "projectName": "SonarQube",
-  "fav": false,
-  "canMarkAsFavourite": false,
-  "canCreateManualIssue": false,
-  "measures": {"coverage": "85.2%"}
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_measures.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_measures.json
deleted file mode 100644 (file)
index 606f659..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
-  "uuid": "ABCDE",
-  "path": "src/main/java/org/sonar/api/Plugin.java",
-  "name": "Plugin.java",
-  "longName": "src/main/java/org/sonar/api/Plugin.java",
-  "q": "FIL",
-  "subProject": "org.codehaus.sonar:sonar-plugin-api",
-  "subProjectName": "SonarQube :: Plugin API",
-  "project": "org.codehaus.sonar:sonar",
-  "projectName": "SonarQube",
-  "fav": false,
-  "canMarkAsFavourite": false,
-  "canCreateManualIssue": false,
-  "measures": {
-    "lines": "200",
-    "coverage": "95.4%",
-    "duplicationDensity": "7.4%",
-    "debt": "3h 2min",
-    "sqaleRating": "C",
-    "debtRatio": "35.0%"
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_overall_measure.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_overall_measure.json
deleted file mode 100644 (file)
index 7cc5aed..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
-  "uuid": "ABCDE",
-  "path": "src/main/java/org/sonar/api/Plugin.java",
-  "name": "Plugin.java",
-  "longName": "src/main/java/org/sonar/api/Plugin.java",
-  "q": "FIL",
-  "subProject": "org.codehaus.sonar:sonar-plugin-api",
-  "subProjectName": "SonarQube :: Plugin API",
-  "project": "org.codehaus.sonar:sonar",
-  "projectName": "SonarQube",
-  "fav": false,
-  "canMarkAsFavourite": false,
-  "canCreateManualIssue": false,
-  "measures": {"coverage": "90.1%"}
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_ut_measure.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_ut_measure.json
deleted file mode 100644 (file)
index c6ef590..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/Plugin.java",
-  "uuid": "ABCDE",
-  "path": "src/main/java/org/sonar/api/Plugin.java",
-  "name": "Plugin.java",
-  "longName": "src/main/java/org/sonar/api/Plugin.java",
-  "q": "FIL",
-  "subProject": "org.codehaus.sonar:sonar-plugin-api",
-  "subProjectName": "SonarQube :: Plugin API",
-  "project": "org.codehaus.sonar:sonar",
-  "projectName": "SonarQube",
-  "fav": false,
-  "canMarkAsFavourite": false,
-  "canCreateManualIssue": false,
-  "measures": {"coverage": "95.4%"}
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsGhostsActionTest/all-projects.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsGhostsActionTest/all-projects.json
deleted file mode 100644 (file)
index cd1aad1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "projects": [
-    {
-      "uuid": "ghost-uuid-1",
-      "key": "ghost-key-1",
-      "name": "ghost-name-1"
-    },
-    {
-      "uuid": "ghost-uuid-2",
-      "key": "ghost-key-2",
-      "name": "ghost-name-2"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsGhostsActionTest/pagination.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsGhostsActionTest/pagination.json
deleted file mode 100644 (file)
index 8967d5c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "p": 3,
-  "ps": 4,
-  "total": 10
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsProvisionedActionTest/all-projects.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProjectsProvisionedActionTest/all-projects.json
deleted file mode 100644 (file)
index 3fc3e56..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "projects":[
-    {
-      "uuid":"provisioned-uuid-1",
-      "key":"provisioned-key-1",
-      "name":"provisioned-name-1"
-    },
-    {
-      "uuid":"provisioned-uuid-2",
-      "key":"provisioned-key-2",
-      "name":"provisioned-name-2"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryActionMediumTest/list_history_reports.json b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryActionMediumTest/list_history_reports.json
new file mode 100644 (file)
index 0000000..caa1808
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "reports": [
+    {
+      "status": "SUCCESS",
+      "projectName": "POne",
+      "projectKey": "P1",
+      "projectUuid": "U1"
+    },
+    {
+      "status": "FAILED",
+      "projectName": "PTwo",
+      "projectKey": "P2",
+      "projectUuid": "U2"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryWsActionMediumTest/list_history_reports.json b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryWsActionMediumTest/list_history_reports.json
deleted file mode 100644 (file)
index caa1808..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "reports": [
-    {
-      "status": "SUCCESS",
-      "projectName": "POne",
-      "projectKey": "P1",
-      "projectUuid": "U1"
-    },
-    {
-      "status": "FAILED",
-      "projectName": "PTwo",
-      "projectKey": "P2",
-      "projectUuid": "U2"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueActionTest/list_queue_reports.json b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueActionTest/list_queue_reports.json
new file mode 100644 (file)
index 0000000..67f2234
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  "reports": [
+    {
+      "key": 1,
+      "status": "PENDING",
+      "projectName": "project-key",
+      "projectKey": "project-key",
+      "submittedAt": "2014-10-13T00:00:00+0200",
+      "startedAt": "2014-10-13T00:00:00+0200",
+      "finishedAt": "2014-10-13T00:00:00+0200"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueWsActionTest/list_queue_reports.json b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueWsActionTest/list_queue_reports.json
deleted file mode 100644 (file)
index 67f2234..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "reports": [
-    {
-      "key": 1,
-      "status": "PENDING",
-      "projectName": "project-key",
-      "projectKey": "project-key",
-      "submittedAt": "2014-10-13T00:00:00+0200",
-      "startedAt": "2014-10-13T00:00:00+0200",
-      "finishedAt": "2014-10-13T00:00:00+0200"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue.json
deleted file mode 100644 (file)
index e53e2b2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "line": 12,
-    "message": "Fix it",
-    "resolution": "FIXED",
-    "status": "CLOSED",
-    "severity": "MAJOR",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_component.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_component.json
deleted file mode 100644 (file)
index 33d376a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": false,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_action_plan.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_action_plan.json
deleted file mode 100644 (file)
index c03d5c8..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "actionPlan" : "AP-ABCD",
-    "actionPlanName" : "Version 4.2",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_actions.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_actions.json
deleted file mode 100644 (file)
index 8cf6348..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "status": "OPEN",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [
-       "comment", "assign", "set_tags", "assign_to_me", "plan"
-    ],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_changelog.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_changelog.json
deleted file mode 100644 (file)
index 4a1889d..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      },
-      {
-        "userName": "John",
-        "creationDate": "2014-02-22T19:10:03+0100",
-        "fCreationDate": "Fev 22, 2014 10:03 AM",
-        "diffs": ["Action plan updated to 1.0"]
-      },
-      {
-        "creationDate": "2014-02-23T19:10:03+0100",
-        "fCreationDate": "Fev 23, 2014 10:03 AM",
-        "diffs": ["Severity updated from Info to Blocker", "Status updated from Reopen to Resolved"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_characteristics.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_characteristics.json
deleted file mode 100644 (file)
index b227aba..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "characteristic": "Maintainability",
-    "subCharacteristic": "Readability",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_comments.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_comments.json
deleted file mode 100644 (file)
index 0827d1f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": ["comment", "assign", "set_tags", "assign_to_me", "plan"],
-    "comments": [
-      {
-        "key": "COMMENT-ABCD",
-        "userName": "John",
-        "raw": "*My comment*",
-        "html": "<em>My comment</em>",
-        "createdAt": "2014-02-22T19:10:03+0100",
-        "fCreatedAge": "9 days",
-        "updatable": false
-      },
-      {
-        "key": "COMMENT-ABCE",
-        "userName": "Arthur",
-        "raw": "Another comment",
-        "html": "Another comment",
-        "createdAt": "2014-02-23T19:10:03+0100",
-        "fCreatedAge": "10 days",
-        "updatable": true
-      }
-    ],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_dates.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_dates.json
deleted file mode 100644 (file)
index 5a7b591..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "updateDate": "2014-01-23T19:10:03+0100",
-    "fUpdateDate": "Jan 23, 2014 10:03 AM",
-    "fUpdateAge": "9 days",
-    "closeDate": "2014-01-24T19:10:03+0100",
-    "fCloseDate": "Jan 24, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_sub_project.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_sub_project.json
deleted file mode 100644 (file)
index 3222be9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "subProject": "org.sonar.server.Server",
-    "subProjectName": "SonarQube :: Server",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "line": 12,
-    "message": "Fix it",
-    "resolution": "FIXED",
-    "status": "CLOSED",
-    "severity": "MAJOR",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_technical_debt.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_technical_debt.json
deleted file mode 100644 (file)
index ff29d2d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "debt": "2h1min",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_transitions.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_transitions.json
deleted file mode 100644 (file)
index 9d06cd9..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "status": "RESOLVED",
-    "resolution": "FIXED",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": ["reopen"],
-    "actions": ["comment"],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_users.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_users.json
deleted file mode 100644 (file)
index eb96ea5..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "issue": {
-    "key": "ABCD",
-    "component": "org.sonar.server.issue.IssueClient",
-    "componentLongName": "SonarQube :: Issue Client",
-    "componentQualifier": "FIL",
-    "componentEnabled": true,
-    "project": "org.sonar.Sonar",
-    "projectName": "SonarQube",
-    "rule": "squid:AvoidCycle",
-    "ruleName": "Avoid cycle",
-    "assignee": "john",
-    "assigneeName": "John",
-    "reporter": "steven",
-    "reporterName": "Steven",
-    "author": "Henry",
-    "creationDate": "2014-01-22T19:10:03+0100",
-    "fCreationDate": "Jan 22, 2014 10:03 AM",
-    "transitions": [],
-    "actions": [],
-    "comments": [],
-    "changelog": [
-      {
-        "creationDate": "2014-01-22T19:10:03+0100",
-        "fCreationDate": "Jan 22, 2014 10:03 AM",
-        "diffs": ["Created"]
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue.json
new file mode 100644 (file)
index 0000000..e53e2b2
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "line": 12,
+    "message": "Fix it",
+    "resolution": "FIXED",
+    "status": "CLOSED",
+    "severity": "MAJOR",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_on_removed_component.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_on_removed_component.json
new file mode 100644 (file)
index 0000000..33d376a
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": false,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_action_plan.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_action_plan.json
new file mode 100644 (file)
index 0000000..c03d5c8
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "actionPlan" : "AP-ABCD",
+    "actionPlanName" : "Version 4.2",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_actions.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_actions.json
new file mode 100644 (file)
index 0000000..8cf6348
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "status": "OPEN",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [
+       "comment", "assign", "set_tags", "assign_to_me", "plan"
+    ],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_changelog.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_changelog.json
new file mode 100644 (file)
index 0000000..4a1889d
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      },
+      {
+        "userName": "John",
+        "creationDate": "2014-02-22T19:10:03+0100",
+        "fCreationDate": "Fev 22, 2014 10:03 AM",
+        "diffs": ["Action plan updated to 1.0"]
+      },
+      {
+        "creationDate": "2014-02-23T19:10:03+0100",
+        "fCreationDate": "Fev 23, 2014 10:03 AM",
+        "diffs": ["Severity updated from Info to Blocker", "Status updated from Reopen to Resolved"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_characteristics.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_characteristics.json
new file mode 100644 (file)
index 0000000..b227aba
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "characteristic": "Maintainability",
+    "subCharacteristic": "Readability",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_comments.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_comments.json
new file mode 100644 (file)
index 0000000..0827d1f
--- /dev/null
@@ -0,0 +1,44 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": ["comment", "assign", "set_tags", "assign_to_me", "plan"],
+    "comments": [
+      {
+        "key": "COMMENT-ABCD",
+        "userName": "John",
+        "raw": "*My comment*",
+        "html": "<em>My comment</em>",
+        "createdAt": "2014-02-22T19:10:03+0100",
+        "fCreatedAge": "9 days",
+        "updatable": false
+      },
+      {
+        "key": "COMMENT-ABCE",
+        "userName": "Arthur",
+        "raw": "Another comment",
+        "html": "Another comment",
+        "createdAt": "2014-02-23T19:10:03+0100",
+        "fCreatedAge": "10 days",
+        "updatable": true
+      }
+    ],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_dates.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_dates.json
new file mode 100644 (file)
index 0000000..5a7b591
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "updateDate": "2014-01-23T19:10:03+0100",
+    "fUpdateDate": "Jan 23, 2014 10:03 AM",
+    "fUpdateAge": "9 days",
+    "closeDate": "2014-01-24T19:10:03+0100",
+    "fCloseDate": "Jan 24, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_sub_project.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_sub_project.json
new file mode 100644 (file)
index 0000000..3222be9
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "subProject": "org.sonar.server.Server",
+    "subProjectName": "SonarQube :: Server",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "line": 12,
+    "message": "Fix it",
+    "resolution": "FIXED",
+    "status": "CLOSED",
+    "severity": "MAJOR",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_technical_debt.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_technical_debt.json
new file mode 100644 (file)
index 0000000..ff29d2d
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "debt": "2h1min",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_transitions.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_transitions.json
new file mode 100644 (file)
index 0000000..9d06cd9
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "status": "RESOLVED",
+    "resolution": "FIXED",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": ["reopen"],
+    "actions": ["comment"],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_users.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ShowActionTest/show_issue_with_users.json
new file mode 100644 (file)
index 0000000..eb96ea5
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "issue": {
+    "key": "ABCD",
+    "component": "org.sonar.server.issue.IssueClient",
+    "componentLongName": "SonarQube :: Issue Client",
+    "componentQualifier": "FIL",
+    "componentEnabled": true,
+    "project": "org.sonar.Sonar",
+    "projectName": "SonarQube",
+    "rule": "squid:AvoidCycle",
+    "ruleName": "Avoid cycle",
+    "assignee": "john",
+    "assigneeName": "John",
+    "reporter": "steven",
+    "reporterName": "Steven",
+    "author": "Henry",
+    "creationDate": "2014-01-22T19:10:03+0100",
+    "fCreationDate": "Jan 22, 2014 10:03 AM",
+    "transitions": [],
+    "actions": [],
+    "comments": [],
+    "changelog": [
+      {
+        "creationDate": "2014-01-22T19:10:03+0100",
+        "fCreationDate": "Jan 22, 2014 10:03 AM",
+        "diffs": ["Created"]
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/AvailableActionTest/properties_per_plugin.json b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/AvailableActionTest/properties_per_plugin.json
new file mode 100644 (file)
index 0000000..8c5ed3b
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  "plugins": [
+    {
+      "key": "p_key",
+      "name": "p_name",
+      "category": "p_category",
+      "description": "p_description",
+      "license": "p_license",
+      "organizationName": "p_orga_name",
+      "organizationUrl": "p_orga_url",
+      "termsAndConditionsUrl": "p_t_and_c_url",
+      "release": {
+        "version": "1.12.1",
+        "date": "2015-04-16"
+      },
+      "update": {
+        "status": "COMPATIBLE",
+        "requires": [
+          {
+            "key": "p_key_1",
+            "name": "p_name_1"
+          },
+          {
+            "key": "p_key_2",
+            "name": "p_name_2",
+            "description": "p_desc_2"
+          }
+        ]
+      }
+    }
+  ],
+  "updateCenterRefresh": "2015-04-24T16:08:36+0200"
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/AvailablePluginsWsActionTest/properties_per_plugin.json b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/AvailablePluginsWsActionTest/properties_per_plugin.json
deleted file mode 100644 (file)
index 8c5ed3b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  "plugins": [
-    {
-      "key": "p_key",
-      "name": "p_name",
-      "category": "p_category",
-      "description": "p_description",
-      "license": "p_license",
-      "organizationName": "p_orga_name",
-      "organizationUrl": "p_orga_url",
-      "termsAndConditionsUrl": "p_t_and_c_url",
-      "release": {
-        "version": "1.12.1",
-        "date": "2015-04-16"
-      },
-      "update": {
-        "status": "COMPATIBLE",
-        "requires": [
-          {
-            "key": "p_key_1",
-            "name": "p_name_1"
-          },
-          {
-            "key": "p_key_2",
-            "name": "p_name_2",
-            "description": "p_desc_2"
-          }
-        ]
-      }
-    }
-  ],
-  "updateCenterRefresh": "2015-04-24T16:08:36+0200"
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/InstalledActionTest/some.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/InstalledActionTest/some.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest/some.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest/some.jar
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/UpdatablePluginsWsActionTest/properties_per_plugin.json b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/UpdatablePluginsWsActionTest/properties_per_plugin.json
deleted file mode 100644 (file)
index 055feb3..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-  "plugins": [
-    {
-      "key": "p_key",
-      "name": "p_name",
-      "category": "p_category",
-      "description": "p_description",
-      "license": "p_license",
-      "organizationName": "p_orga_name",
-      "organizationUrl": "p_orga_url",
-      "termsAndConditionsUrl": "p_t_and_c_url",
-      "release": {
-        "version": "1.12.1",
-        "date": "2015-04-16",
-        "artifact": {
-          "name": "p_file.jar",
-          "url": "http://p_file.jar"
-        }
-      },
-      "update": {
-        "status": "COMPATIBLE",
-        "requires": [
-          {
-            "key": "p_key_1",
-            "name": "p_name_1"
-          },
-          {
-            "key": "p_key_2",
-            "name": "p_name_2",
-            "description": "p_desc_2"
-          }
-        ]
-      }
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/GhostsActionTest/all-projects.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/GhostsActionTest/all-projects.json
new file mode 100644 (file)
index 0000000..cd1aad1
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "projects": [
+    {
+      "uuid": "ghost-uuid-1",
+      "key": "ghost-key-1",
+      "name": "ghost-name-1"
+    },
+    {
+      "uuid": "ghost-uuid-2",
+      "key": "ghost-key-2",
+      "name": "ghost-name-2"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/GhostsActionTest/pagination.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/GhostsActionTest/pagination.json
new file mode 100644 (file)
index 0000000..8967d5c
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "p": 3,
+  "ps": 4,
+  "total": 10
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/ProvisionedActionTest/all-projects.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/ProvisionedActionTest/all-projects.json
new file mode 100644 (file)
index 0000000..3fc3e56
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "projects":[
+    {
+      "uuid":"provisioned-uuid-1",
+      "key":"provisioned-key-1",
+      "name":"provisioned-name-1"
+    },
+    {
+      "uuid":"provisioned-uuid-2",
+      "key":"provisioned-key-2",
+      "name":"provisioned-name-2"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_empty.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_empty.json
new file mode 100644 (file)
index 0000000..22d12b0
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "total": 0,
+  "p": 1,
+  "ps": 50,
+  "events": []
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_no_login.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_no_login.json
new file mode 100644 (file)
index 0000000..eb0fe99
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "total": 1,
+  "p": 1,
+  "ps": 50,
+  "events": [
+    {
+      "action" : "ACTIVATED",
+      "ruleKey" : "xoo:x1",
+      "ruleName" : "Rule x1",
+      "params" : {
+        "severity" : "MAJOR"
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_no_param.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_no_param.json
new file mode 100644 (file)
index 0000000..9ad8c7c
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "total": 1,
+  "p": 1,
+  "ps": 50,
+  "events": [
+    {
+      "action" : "ACTIVATED",
+      "authorLogin" : "david",
+      "authorName" : "David",
+      "ruleKey" : "xoo:x1",
+      "ruleName" : "Rule x1",
+      "params" : {
+        "severity" : "MAJOR"
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_nominal.json
new file mode 100644 (file)
index 0000000..b0262c2
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "total": 1,
+  "p": 1,
+  "ps": 50,
+  "events": [
+    {
+      "action" : "ACTIVATED",
+      "authorLogin" : "david",
+      "authorName" : "David",
+      "ruleKey" : "xoo:x1",
+      "ruleName" : "Rule x1",
+      "params" : {
+        "severity" : "MAJOR",
+        "max" : "10"
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page1.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page1.json
new file mode 100644 (file)
index 0000000..adc4088
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "total": 2,
+  "p": 1,
+  "ps": 1,
+  "events": [
+    {
+      "action" : "ACTIVATED",
+      "authorLogin" : "david",
+      "authorName" : "David",
+      "ruleKey" : "xoo:x1",
+      "ruleName" : "Rule x1",
+      "params" : {
+        "severity" : "CRITICAL",
+        "max" : "20"
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page2.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page2.json
new file mode 100644 (file)
index 0000000..728705a
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "total": 2,
+  "p": 2,
+  "ps": 1,
+  "events": [
+    {
+      "action" : "ACTIVATED",
+      "authorLogin" : "david",
+      "authorName" : "David",
+      "ruleKey" : "xoo:x1",
+      "ruleName" : "Rule x1",
+      "params" : {
+        "severity" : "MAJOR",
+        "max" : "10"
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page3.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ChangelogActionTest/changelog_page3.json
new file mode 100644 (file)
index 0000000..06536dd
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "total": 2,
+  "p": 3,
+  "ps": 1,
+  "events": []
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_nominal.json
new file mode 100644 (file)
index 0000000..1d0ef29
--- /dev/null
@@ -0,0 +1,79 @@
+{
+   "left" : {
+      "key" : "xoo-profile-1-01234",
+      "name" : "Profile 1"
+   },
+   "right" : {
+      "key" : "xoo-profile-2-12345",
+      "name" : "Profile 2"
+   },
+   "same" : [
+      {
+         "key" : "blah:rule1",
+         "pluginKey" : "blah",
+         "pluginName" : "Blah",
+         "languageKey": "xoo",
+         "languageName": "Xoo",
+         "name" : "Rule1",
+         "severity" : "BLOCKER"
+      }
+   ],
+   "inLeft" : [
+      {
+         "key" : "blah:rule2",
+         "pluginKey" : "blah",
+         "pluginName" : "Blah",
+         "languageKey": "xoo",
+         "languageName": "Xoo",
+         "name" : "Rule2",
+         "severity" : "BLOCKER"
+      }
+   ],
+   "inRight" : [
+      {
+         "key" : "blah:rule3",
+         "pluginKey" : "blah",
+         "pluginName" : "Blah",
+         "languageKey": "xoo",
+         "languageName": "Xoo",
+         "name" : "Rule3",
+         "severity" : "BLOCKER"
+      }
+   ],
+   "modified" : [
+      {
+         "key" : "blah:rule4",
+         "pluginKey" : "blah",
+         "pluginName" : "Blah",
+         "languageKey": "xoo",
+         "languageName": "Xoo",
+         "name" : "Rule4",
+         "left" : {
+            "severity" : "BLOCKER",
+            "params" : {
+               "param_rule4" : "polop"
+            }
+         },
+         "right" : {
+            "severity" : "BLOCKER",
+            "params" : {
+               "param_rule4" : "palap"
+            }
+         }
+      },
+      {
+         "key" : "blah:rule5",
+         "pluginKey" : "blah",
+         "pluginName" : "Blah",
+         "languageKey": "xoo",
+         "languageName": "Xoo",
+         "name" : "Rule5",
+         "left" : {
+            "severity" : "MINOR"
+         },
+         "right" : {
+            "severity" : "MAJOR"
+         }
+      }
+   ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_param_on_left.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_param_on_left.json
new file mode 100644 (file)
index 0000000..afe92f1
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "left" : {
+      "key" : "xoo-profile-1-01234",
+      "name" : "Profile 1"
+   },
+   "right" : {
+      "key" : "xoo-profile-2-12345",
+      "name" : "Profile 2"
+   },
+   "same" : [],
+   "inLeft" : [],
+   "inRight" : [],
+   "modified" : [
+      {
+         "key" : "blah:rule1",
+         "pluginKey" : "blah",
+         "pluginName" : "Blah",
+         "languageKey": "xoo",
+         "languageName": "Xoo",
+         "name" : "Rule1",
+         "left" : {
+            "severity" : "BLOCKER",
+            "params" : {
+               "param_rule1" : "polop"
+            }
+         },
+         "right" : {
+            "severity" : "BLOCKER"
+         }
+      }
+   ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_param_on_right.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CompareActionMediumTest/compare_param_on_right.json
new file mode 100644 (file)
index 0000000..ec90227
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "left" : {
+      "key" : "xoo-profile-1-01234",
+      "name" : "Profile 1"
+   },
+   "right" : {
+      "key" : "xoo-profile-2-12345",
+      "name" : "Profile 2"
+   },
+   "same" : [],
+   "inLeft" : [],
+   "inRight" : [],
+   "modified" : [
+      {
+         "key" : "blah:rule1",
+         "pluginKey" : "blah",
+         "pluginName" : "Blah",
+         "languageKey": "xoo",
+         "languageName": "Xoo",
+         "name" : "Rule1",
+         "left" : {
+            "severity" : "BLOCKER"
+         },
+         "right" : {
+            "severity" : "BLOCKER",
+            "params" : {
+               "param_rule1" : "polop"
+            }
+         }
+      }
+   ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CopyActionTest/copy_nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CopyActionTest/copy_nominal.json
new file mode 100644 (file)
index 0000000..bbf7ad6
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "key": "xoo-other-sonar-way-12345",
+  "name": "Other Sonar Way",
+  "language": "xoo",
+  "languageName": "Xoo",
+  "isDefault": false,
+  "isInherited": false
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CopyActionTest/copy_with_parent.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CopyActionTest/copy_with_parent.json
new file mode 100644 (file)
index 0000000..9fefdca
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "key": "xoo-other-sonar-way-12345",
+  "name": "Other Sonar Way",
+  "language": "xoo",
+  "languageName": "Xoo",
+  "isDefault": false,
+  "isInherited": true,
+  "parentKey": "xoo-parent-profile-01324"
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-nominal.json
new file mode 100644 (file)
index 0000000..a00e1eb
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "profile": {
+    "name": "My New Profile",
+    "language": "xoo",
+    "languageName": "Xoo",
+    "isDefault": false,
+    "isInherited": false
+  }
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-with-messages.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionMediumTest/create-with-messages.json
new file mode 100644 (file)
index 0000000..aec5817
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "profile": {
+    "name": "My Other Profile",
+    "language": "xoo",
+    "languageName": "Xoo",
+    "isDefault": false,
+    "isInherited": false
+  },
+  "infos": [
+    "an info"
+  ],
+  "warnings": [
+    "a warning"
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionTest/create-no-importer.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/CreateActionTest/create-no-importer.json
new file mode 100644 (file)
index 0000000..367abdd
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "profile": {
+    "name": "Yeehaw!",
+    "language": "xoo",
+    "languageName": "Xoo",
+    "isDefault": false,
+    "isInherited": false
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ExportersActionTest/exporters.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ExportersActionTest/exporters.json
new file mode 100644 (file)
index 0000000..cc0788d
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "exporters": [
+    {"key": "findbugs", "name": "FindBugs", "languages": ["java"]},
+    {"key": "jslint", "name": "JS Lint", "languages": ["js"]},
+    {"key": "vaadin", "name": "Vaadin", "languages": ["java", "js"]}
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ImportersActionTest/importers.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ImportersActionTest/importers.json
new file mode 100644 (file)
index 0000000..2c180ee
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "importers": [
+    {"key": "findbugs", "name": "FindBugs", "languages": ["java"]},
+    {"key": "jslint", "name": "JS Lint", "languages": ["js"]},
+    {"key": "vaadin", "name": "Vaadin", "languages": ["java", "js"]}
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest/inheritance-buWide.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest/inheritance-buWide.json
new file mode 100644 (file)
index 0000000..9e3707e
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "profile": {
+    "key": "xoo-my-bu-profile-23456", "name": "My BU Profile", "parent": "xoo-my-company-profile-12345",
+    "activeRuleCount": 2, "overridingRuleCount": 1
+  },
+  "ancestors": [
+    {"key": "xoo-my-company-profile-12345", "name": "My Company Profile", "parent": "xoo-my-group-profile-01234", "activeRuleCount": 2},
+    {"key": "xoo-my-group-profile-01234", "name": "My Group Profile", "activeRuleCount": 2}
+  ],
+  "children": [
+    {"key": "xoo-for-project-one-34567", "name": "For Project One", "activeRuleCount": 3},
+    {"key": "xoo-for-project-two-45678", "name": "For Project Two", "activeRuleCount": 2, "overridingRuleCount": 1}
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest/inheritance-simple.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/InheritanceActionMediumTest/inheritance-simple.json
new file mode 100644 (file)
index 0000000..b5168de
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "profile": {
+    "key": "xoo-nobody-s-boy-01234", "name": "Nobodys Boy", "activeRuleCount": 0
+  },
+  "ancestors": [],
+  "children": []
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/all.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/all.json
new file mode 100644 (file)
index 0000000..186208a
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "results":
+  [
+    {
+      "uuid": "DEFA",
+      "name": "Project Four",
+      "selected": false
+    },
+    {
+      "uuid": "ABCD",
+      "name": "Project One",
+      "selected": true
+    },
+    {
+      "uuid": "CDEF",
+      "name": "Project Three",
+      "selected": false
+    },
+    {
+      "uuid": "BCDE",
+      "name": "Project Two",
+      "selected": true
+    }
+  ],
+
+  "more": false
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/all_filtered.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/all_filtered.json
new file mode 100644 (file)
index 0000000..0687724
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "results":
+  [
+    {
+      "uuid": "CDEF",
+      "name": "Project Three",
+      "selected": false
+    },
+    {
+      "uuid": "BCDE",
+      "name": "Project Two",
+      "selected": true
+    }
+  ],
+
+  "more": false
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/authorized_selected.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/authorized_selected.json
new file mode 100644 (file)
index 0000000..f5b7377
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "results":
+  [
+    {
+      "uuid": "ABCD",
+      "name": "Project One",
+      "selected": true
+    }
+  ],
+
+  "more": false
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/deselected.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/deselected.json
new file mode 100644 (file)
index 0000000..2a0ecdb
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "results":
+  [
+    {
+      "uuid": "DEFA",
+      "name": "Project Four",
+      "selected": false
+    },
+    {
+      "uuid": "CDEF",
+      "name": "Project Three",
+      "selected": false
+    }
+  ],
+
+  "more": false
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/empty.json
new file mode 100644 (file)
index 0000000..cea4e2e
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "results":
+  [],
+
+  "more": false
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_page1.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_page1.json
new file mode 100644 (file)
index 0000000..70668d5
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "results":
+  [
+    {
+      "uuid": "DEFA",
+      "name": "Project Four",
+      "selected": true
+    },
+    {
+      "uuid": "ABCD",
+      "name": "Project One",
+      "selected": true
+    }
+  ],
+
+  "more": true
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_page2.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_page2.json
new file mode 100644 (file)
index 0000000..6b6fd49
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "results":
+  [
+    {
+      "uuid": "CDEF",
+      "name": "Project Three",
+      "selected": true
+    },
+    {
+      "uuid": "BCDE",
+      "name": "Project Two",
+      "selected": true
+    }
+  ],
+
+  "more": false
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_ps3_page1.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_ps3_page1.json
new file mode 100644 (file)
index 0000000..9c803fb
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "results":
+  [
+    {
+      "uuid": "DEFA",
+      "name": "Project Four",
+      "selected": true
+    },
+    {
+      "uuid": "ABCD",
+      "name": "Project One",
+      "selected": true
+    },
+    {
+      "uuid": "CDEF",
+      "name": "Project Three",
+      "selected": true
+    }
+  ],
+
+  "more": true
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_ps3_page2.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/ProjectsActionTest/selected_ps3_page2.json
new file mode 100644 (file)
index 0000000..28f8cd7
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "results":
+  [
+    {
+      "uuid": "BCDE",
+      "name": "Project Two",
+      "selected": true
+    }
+  ],
+
+  "more": false
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_empty.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_empty.json
deleted file mode 100644 (file)
index 22d12b0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "total": 0,
-  "p": 1,
-  "ps": 50,
-  "events": []
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_no_login.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_no_login.json
deleted file mode 100644 (file)
index eb0fe99..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "total": 1,
-  "p": 1,
-  "ps": 50,
-  "events": [
-    {
-      "action" : "ACTIVATED",
-      "ruleKey" : "xoo:x1",
-      "ruleName" : "Rule x1",
-      "params" : {
-        "severity" : "MAJOR"
-      }
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_no_param.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_no_param.json
deleted file mode 100644 (file)
index 9ad8c7c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "total": 1,
-  "p": 1,
-  "ps": 50,
-  "events": [
-    {
-      "action" : "ACTIVATED",
-      "authorLogin" : "david",
-      "authorName" : "David",
-      "ruleKey" : "xoo:x1",
-      "ruleName" : "Rule x1",
-      "params" : {
-        "severity" : "MAJOR"
-      }
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_nominal.json
deleted file mode 100644 (file)
index b0262c2..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "total": 1,
-  "p": 1,
-  "ps": 50,
-  "events": [
-    {
-      "action" : "ACTIVATED",
-      "authorLogin" : "david",
-      "authorName" : "David",
-      "ruleKey" : "xoo:x1",
-      "ruleName" : "Rule x1",
-      "params" : {
-        "severity" : "MAJOR",
-        "max" : "10"
-      }
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page1.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page1.json
deleted file mode 100644 (file)
index adc4088..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "total": 2,
-  "p": 1,
-  "ps": 1,
-  "events": [
-    {
-      "action" : "ACTIVATED",
-      "authorLogin" : "david",
-      "authorName" : "David",
-      "ruleKey" : "xoo:x1",
-      "ruleName" : "Rule x1",
-      "params" : {
-        "severity" : "CRITICAL",
-        "max" : "20"
-      }
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page2.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page2.json
deleted file mode 100644 (file)
index 728705a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "total": 2,
-  "p": 2,
-  "ps": 1,
-  "events": [
-    {
-      "action" : "ACTIVATED",
-      "authorLogin" : "david",
-      "authorName" : "David",
-      "ruleKey" : "xoo:x1",
-      "ruleName" : "Rule x1",
-      "params" : {
-        "severity" : "MAJOR",
-        "max" : "10"
-      }
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page3.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileChangelogActionTest/changelog_page3.json
deleted file mode 100644 (file)
index 06536dd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "total": 2,
-  "p": 3,
-  "ps": 1,
-  "events": []
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_nominal.json
deleted file mode 100644 (file)
index 1d0ef29..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-{
-   "left" : {
-      "key" : "xoo-profile-1-01234",
-      "name" : "Profile 1"
-   },
-   "right" : {
-      "key" : "xoo-profile-2-12345",
-      "name" : "Profile 2"
-   },
-   "same" : [
-      {
-         "key" : "blah:rule1",
-         "pluginKey" : "blah",
-         "pluginName" : "Blah",
-         "languageKey": "xoo",
-         "languageName": "Xoo",
-         "name" : "Rule1",
-         "severity" : "BLOCKER"
-      }
-   ],
-   "inLeft" : [
-      {
-         "key" : "blah:rule2",
-         "pluginKey" : "blah",
-         "pluginName" : "Blah",
-         "languageKey": "xoo",
-         "languageName": "Xoo",
-         "name" : "Rule2",
-         "severity" : "BLOCKER"
-      }
-   ],
-   "inRight" : [
-      {
-         "key" : "blah:rule3",
-         "pluginKey" : "blah",
-         "pluginName" : "Blah",
-         "languageKey": "xoo",
-         "languageName": "Xoo",
-         "name" : "Rule3",
-         "severity" : "BLOCKER"
-      }
-   ],
-   "modified" : [
-      {
-         "key" : "blah:rule4",
-         "pluginKey" : "blah",
-         "pluginName" : "Blah",
-         "languageKey": "xoo",
-         "languageName": "Xoo",
-         "name" : "Rule4",
-         "left" : {
-            "severity" : "BLOCKER",
-            "params" : {
-               "param_rule4" : "polop"
-            }
-         },
-         "right" : {
-            "severity" : "BLOCKER",
-            "params" : {
-               "param_rule4" : "palap"
-            }
-         }
-      },
-      {
-         "key" : "blah:rule5",
-         "pluginKey" : "blah",
-         "pluginName" : "Blah",
-         "languageKey": "xoo",
-         "languageName": "Xoo",
-         "name" : "Rule5",
-         "left" : {
-            "severity" : "MINOR"
-         },
-         "right" : {
-            "severity" : "MAJOR"
-         }
-      }
-   ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_param_on_left.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_param_on_left.json
deleted file mode 100644 (file)
index afe92f1..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-   "left" : {
-      "key" : "xoo-profile-1-01234",
-      "name" : "Profile 1"
-   },
-   "right" : {
-      "key" : "xoo-profile-2-12345",
-      "name" : "Profile 2"
-   },
-   "same" : [],
-   "inLeft" : [],
-   "inRight" : [],
-   "modified" : [
-      {
-         "key" : "blah:rule1",
-         "pluginKey" : "blah",
-         "pluginName" : "Blah",
-         "languageKey": "xoo",
-         "languageName": "Xoo",
-         "name" : "Rule1",
-         "left" : {
-            "severity" : "BLOCKER",
-            "params" : {
-               "param_rule1" : "polop"
-            }
-         },
-         "right" : {
-            "severity" : "BLOCKER"
-         }
-      }
-   ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_param_on_right.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_param_on_right.json
deleted file mode 100644 (file)
index ec90227..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-   "left" : {
-      "key" : "xoo-profile-1-01234",
-      "name" : "Profile 1"
-   },
-   "right" : {
-      "key" : "xoo-profile-2-12345",
-      "name" : "Profile 2"
-   },
-   "same" : [],
-   "inLeft" : [],
-   "inRight" : [],
-   "modified" : [
-      {
-         "key" : "blah:rule1",
-         "pluginKey" : "blah",
-         "pluginName" : "Blah",
-         "languageKey": "xoo",
-         "languageName": "Xoo",
-         "name" : "Rule1",
-         "left" : {
-            "severity" : "BLOCKER"
-         },
-         "right" : {
-            "severity" : "BLOCKER",
-            "params" : {
-               "param_rule1" : "polop"
-            }
-         }
-      }
-   ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest/copy_nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest/copy_nominal.json
deleted file mode 100644 (file)
index bbf7ad6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "key": "xoo-other-sonar-way-12345",
-  "name": "Other Sonar Way",
-  "language": "xoo",
-  "languageName": "Xoo",
-  "isDefault": false,
-  "isInherited": false
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest/copy_with_parent.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCopyActionTest/copy_with_parent.json
deleted file mode 100644 (file)
index 9fefdca..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "key": "xoo-other-sonar-way-12345",
-  "name": "Other Sonar Way",
-  "language": "xoo",
-  "languageName": "Xoo",
-  "isDefault": false,
-  "isInherited": true,
-  "parentKey": "xoo-parent-profile-01324"
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest/create-nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest/create-nominal.json
deleted file mode 100644 (file)
index a00e1eb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "profile": {
-    "name": "My New Profile",
-    "language": "xoo",
-    "languageName": "Xoo",
-    "isDefault": false,
-    "isInherited": false
-  }
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest/create-with-messages.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionMediumTest/create-with-messages.json
deleted file mode 100644 (file)
index aec5817..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "profile": {
-    "name": "My Other Profile",
-    "language": "xoo",
-    "languageName": "Xoo",
-    "isDefault": false,
-    "isInherited": false
-  },
-  "infos": [
-    "an info"
-  ],
-  "warnings": [
-    "a warning"
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionTest/create-no-importer.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCreateActionTest/create-no-importer.json
deleted file mode 100644 (file)
index 367abdd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "profile": {
-    "name": "Yeehaw!",
-    "language": "xoo",
-    "languageName": "Xoo",
-    "isDefault": false,
-    "isInherited": false
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileExportersActionTest/exporters.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileExportersActionTest/exporters.json
deleted file mode 100644 (file)
index cc0788d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "exporters": [
-    {"key": "findbugs", "name": "FindBugs", "languages": ["java"]},
-    {"key": "jslint", "name": "JS Lint", "languages": ["js"]},
-    {"key": "vaadin", "name": "Vaadin", "languages": ["java", "js"]}
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileImportersActionTest/importers.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileImportersActionTest/importers.json
deleted file mode 100644 (file)
index 2c180ee..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "importers": [
-    {"key": "findbugs", "name": "FindBugs", "languages": ["java"]},
-    {"key": "jslint", "name": "JS Lint", "languages": ["js"]},
-    {"key": "vaadin", "name": "Vaadin", "languages": ["java", "js"]}
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-buWide.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-buWide.json
deleted file mode 100644 (file)
index 9e3707e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "profile": {
-    "key": "xoo-my-bu-profile-23456", "name": "My BU Profile", "parent": "xoo-my-company-profile-12345",
-    "activeRuleCount": 2, "overridingRuleCount": 1
-  },
-  "ancestors": [
-    {"key": "xoo-my-company-profile-12345", "name": "My Company Profile", "parent": "xoo-my-group-profile-01234", "activeRuleCount": 2},
-    {"key": "xoo-my-group-profile-01234", "name": "My Group Profile", "activeRuleCount": 2}
-  ],
-  "children": [
-    {"key": "xoo-for-project-one-34567", "name": "For Project One", "activeRuleCount": 3},
-    {"key": "xoo-for-project-two-45678", "name": "For Project Two", "activeRuleCount": 2, "overridingRuleCount": 1}
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-simple.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-simple.json
deleted file mode 100644 (file)
index b5168de..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "profile": {
-    "key": "xoo-nobody-s-boy-01234", "name": "Nobodys Boy", "activeRuleCount": 0
-  },
-  "ancestors": [],
-  "children": []
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/all.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/all.json
deleted file mode 100644 (file)
index 186208a..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  "results":
-  [
-    {
-      "uuid": "DEFA",
-      "name": "Project Four",
-      "selected": false
-    },
-    {
-      "uuid": "ABCD",
-      "name": "Project One",
-      "selected": true
-    },
-    {
-      "uuid": "CDEF",
-      "name": "Project Three",
-      "selected": false
-    },
-    {
-      "uuid": "BCDE",
-      "name": "Project Two",
-      "selected": true
-    }
-  ],
-
-  "more": false
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/all_filtered.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/all_filtered.json
deleted file mode 100644 (file)
index 0687724..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "results":
-  [
-    {
-      "uuid": "CDEF",
-      "name": "Project Three",
-      "selected": false
-    },
-    {
-      "uuid": "BCDE",
-      "name": "Project Two",
-      "selected": true
-    }
-  ],
-
-  "more": false
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/authorized_selected.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/authorized_selected.json
deleted file mode 100644 (file)
index f5b7377..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "results":
-  [
-    {
-      "uuid": "ABCD",
-      "name": "Project One",
-      "selected": true
-    }
-  ],
-
-  "more": false
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/deselected.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/deselected.json
deleted file mode 100644 (file)
index 2a0ecdb..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "results":
-  [
-    {
-      "uuid": "DEFA",
-      "name": "Project Four",
-      "selected": false
-    },
-    {
-      "uuid": "CDEF",
-      "name": "Project Three",
-      "selected": false
-    }
-  ],
-
-  "more": false
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/empty.json
deleted file mode 100644 (file)
index cea4e2e..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "results":
-  [],
-
-  "more": false
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_page1.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_page1.json
deleted file mode 100644 (file)
index 70668d5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "results":
-  [
-    {
-      "uuid": "DEFA",
-      "name": "Project Four",
-      "selected": true
-    },
-    {
-      "uuid": "ABCD",
-      "name": "Project One",
-      "selected": true
-    }
-  ],
-
-  "more": true
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_page2.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_page2.json
deleted file mode 100644 (file)
index 6b6fd49..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "results":
-  [
-    {
-      "uuid": "CDEF",
-      "name": "Project Three",
-      "selected": true
-    },
-    {
-      "uuid": "BCDE",
-      "name": "Project Two",
-      "selected": true
-    }
-  ],
-
-  "more": false
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_ps3_page1.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_ps3_page1.json
deleted file mode 100644 (file)
index 9c803fb..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "results":
-  [
-    {
-      "uuid": "DEFA",
-      "name": "Project Four",
-      "selected": true
-    },
-    {
-      "uuid": "ABCD",
-      "name": "Project One",
-      "selected": true
-    },
-    {
-      "uuid": "CDEF",
-      "name": "Project Three",
-      "selected": true
-    }
-  ],
-
-  "more": true
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_ps3_page2.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileProjectsActionTest/selected_ps3_page2.json
deleted file mode 100644 (file)
index 28f8cd7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "results":
-  [
-    {
-      "uuid": "BCDE",
-      "name": "Project Two",
-      "selected": true
-    }
-  ],
-
-  "more": false
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileRestoreActionTest/restore_profile.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileRestoreActionTest/restore_profile.json
deleted file mode 100644 (file)
index 9375056..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "profile": {
-    "name": "Sonar way",
-    "language": "xoo",
-    "languageName": "Xoo",
-    "isDefault": false,
-    "isInherited": false
-  },
-  "ruleSuccesses": 0,
-  "ruleFailures": 0
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search.json
deleted file mode 100644 (file)
index 6c051e7..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "profiles": [
-    {
-      "key": "sonar-way-xoo1-12345",
-      "name": "Sonar way",
-      "language": "xoo1",
-      "languageName": "Xoo1",
-      "isInherited": false,
-      "isDefault": true,
-      "activeRuleCount": 11
-    },
-    {
-      "key": "my-sonar-way-xoo2-34567",
-      "name": "My Sonar way",
-      "language": "xoo2",
-      "languageName": "Xoo2",
-      "isInherited": true,
-      "isDefault": false,
-      "parentKey": "sonar-way-xoo2-23456",
-      "parentName": "Sonar way",
-      "activeRuleCount": 33,
-      "projectCount": 0
-    },
-    {
-      "key": "sonar-way-xoo2-23456",
-      "name": "Sonar way",
-      "language": "xoo2",
-      "languageName": "Xoo2",
-      "isInherited": false,
-      "isDefault": false,
-      "activeRuleCount": 0,
-      "projectCount": 2
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search_fields.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search_fields.json
deleted file mode 100644 (file)
index 143625c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "profiles": [
-    {
-      "key": "sonar-way-xoo1-12345",
-      "language": "xoo1"
-    },
-    {
-      "key": "my-sonar-way-xoo2-34567",
-      "language": "xoo2"
-    },
-    {
-      "key": "sonar-way-xoo2-23456",
-      "language": "xoo2"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search_xoo1.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileSearchActionTest/search_xoo1.json
deleted file mode 100644 (file)
index fcff99c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "profiles": [
-    {
-      "key": "sonar-way-xoo1-12345",
-      "name": "Sonar way",
-      "language": "xoo1",
-      "languageName": "Xoo1",
-      "isInherited": false
-    }
-  ]
-}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/RestoreActionTest/restore_profile.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/RestoreActionTest/restore_profile.json
new file mode 100644 (file)
index 0000000..9375056
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "profile": {
+    "name": "Sonar way",
+    "language": "xoo",
+    "languageName": "Xoo",
+    "isDefault": false,
+    "isInherited": false
+  },
+  "ruleSuccesses": 0,
+  "ruleFailures": 0
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search.json
new file mode 100644 (file)
index 0000000..6c051e7
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "profiles": [
+    {
+      "key": "sonar-way-xoo1-12345",
+      "name": "Sonar way",
+      "language": "xoo1",
+      "languageName": "Xoo1",
+      "isInherited": false,
+      "isDefault": true,
+      "activeRuleCount": 11
+    },
+    {
+      "key": "my-sonar-way-xoo2-34567",
+      "name": "My Sonar way",
+      "language": "xoo2",
+      "languageName": "Xoo2",
+      "isInherited": true,
+      "isDefault": false,
+      "parentKey": "sonar-way-xoo2-23456",
+      "parentName": "Sonar way",
+      "activeRuleCount": 33,
+      "projectCount": 0
+    },
+    {
+      "key": "sonar-way-xoo2-23456",
+      "name": "Sonar way",
+      "language": "xoo2",
+      "languageName": "Xoo2",
+      "isInherited": false,
+      "isDefault": false,
+      "activeRuleCount": 0,
+      "projectCount": 2
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search_fields.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search_fields.json
new file mode 100644 (file)
index 0000000..143625c
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "profiles": [
+    {
+      "key": "sonar-way-xoo1-12345",
+      "language": "xoo1"
+    },
+    {
+      "key": "my-sonar-way-xoo2-34567",
+      "language": "xoo2"
+    },
+    {
+      "key": "sonar-way-xoo2-23456",
+      "language": "xoo2"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search_xoo1.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/SearchActionTest/search_xoo1.json
new file mode 100644 (file)
index 0000000..fcff99c
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "profiles": [
+    {
+      "key": "sonar-way-xoo1-12345",
+      "name": "Sonar way",
+      "language": "xoo1",
+      "languageName": "Xoo1",
+      "isInherited": false
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/CoveredFilesActionTest/tests-covered-files.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/CoveredFilesActionTest/tests-covered-files.json
new file mode 100644 (file)
index 0000000..7b37f47
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "files": [
+    {
+      "key": "org.foo.Bar.java",
+      "longName": "src/main/java/org/foo/Bar.java",
+      "coveredLines": 10
+    },
+    {
+      "key": "org.foo.File.java",
+      "longName": "src/main/java/org/foo/File.java",
+      "coveredLines": 3
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-main-file.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-main-file.json
new file mode 100644 (file)
index 0000000..5a1e625
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "tests": [
+    {
+      "testUuid": "TEST-UUID-1",
+      "fileUuid": "ABCD",
+      "name": "test1",
+      "status": "OK",
+      "durationInMs": 10,
+      "coveredLines": 4,
+      "message": "MESSAGE-1",
+      "stacktrace": "STACKTRACE-1",
+      "fileKey": "org.foo.BarTest.java",
+      "fileLongName": "src/test/java/org/foo/BarTest.java"
+    },
+    {
+      "testUuid": "TEST-UUID-2",
+      "fileUuid": "BCDE",
+      "name": "test2",
+      "status": "ERROR",
+      "durationInMs": 97,
+      "coveredLines": 4,
+      "message": "MESSAGE-2",
+      "stacktrace": "STACKTRACE-2",
+      "fileKey": "org.foo.FileTest.java",
+      "fileLongName": "src/test/java/org/foo/FileTest.java"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-test-uuid.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-test-uuid.json
new file mode 100644 (file)
index 0000000..de6d8d8
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "tests": [
+    {
+      "testUuid": "TEST-UUID-1",
+      "fileUuid": "ABCD",
+      "name": "test1",
+      "status": "OK",
+      "durationInMs": 10,
+      "coveredLines": 4,
+      "message": "MESSAGE-1",
+      "stacktrace": "STACKTRACE-1",
+      "fileKey": "org.foo.BarTest.java",
+      "fileLongName": "src/test/java/org/foo/BarTest.java"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsCoveredFilesActionTest/tests-covered-files.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsCoveredFilesActionTest/tests-covered-files.json
deleted file mode 100644 (file)
index 7b37f47..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "files": [
-    {
-      "key": "org.foo.Bar.java",
-      "longName": "src/main/java/org/foo/Bar.java",
-      "coveredLines": 10
-    },
-    {
-      "key": "org.foo.File.java",
-      "longName": "src/main/java/org/foo/File.java",
-      "coveredLines": 3
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsListActionTest/list-main-file.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsListActionTest/list-main-file.json
deleted file mode 100644 (file)
index 5a1e625..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "tests": [
-    {
-      "testUuid": "TEST-UUID-1",
-      "fileUuid": "ABCD",
-      "name": "test1",
-      "status": "OK",
-      "durationInMs": 10,
-      "coveredLines": 4,
-      "message": "MESSAGE-1",
-      "stacktrace": "STACKTRACE-1",
-      "fileKey": "org.foo.BarTest.java",
-      "fileLongName": "src/test/java/org/foo/BarTest.java"
-    },
-    {
-      "testUuid": "TEST-UUID-2",
-      "fileUuid": "BCDE",
-      "name": "test2",
-      "status": "ERROR",
-      "durationInMs": 97,
-      "coveredLines": 4,
-      "message": "MESSAGE-2",
-      "stacktrace": "STACKTRACE-2",
-      "fileKey": "org.foo.FileTest.java",
-      "fileLongName": "src/test/java/org/foo/FileTest.java"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsListActionTest/list-test-uuid.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsListActionTest/list-test-uuid.json
deleted file mode 100644 (file)
index de6d8d8..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "tests": [
-    {
-      "testUuid": "TEST-UUID-1",
-      "fileUuid": "ABCD",
-      "name": "test1",
-      "status": "OK",
-      "durationInMs": 10,
-      "coveredLines": 4,
-      "message": "MESSAGE-1",
-      "stacktrace": "STACKTRACE-1",
-      "fileKey": "org.foo.BarTest.java",
-      "fileLongName": "src/test/java/org/foo/BarTest.java"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show.json
deleted file mode 100644 (file)
index f8832a0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-"tests": [
-    {
-      "name": "test1",
-      "status": "OK",
-      "durationInMs": 10,
-      "coveredLines": 32
-    },
-    {
-      "name": "test2",
-      "status": "ERROR",
-      "durationInMs": 97,
-      "coveredLines": 21,
-      "message": "expected:<true> but was:<false>",
-      "stackTrace" : "java.lang.AssertionError: expected:<true> but was:<false>\n\tat org.junit.Assert.fail(Assert.java:91)\n\tat org.junit.Assert.failNotEquals(Assert.java:645)\n\tat org.junit.Assert.assertEquals(Assert.java:126)\n\tat org.junit.Assert.assertEquals(Assert.java:145)\n"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show_from_test_data.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show_from_test_data.json
deleted file mode 100644 (file)
index 97a9239..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "tests": [
-    {
-      "name": "test1",
-      "status": "OK",
-      "durationInMs": 10
-    },
-    {
-      "name": "test2",
-      "status": "ERROR",
-      "durationInMs": 97,
-      "message": "expected:<true> but was:<false>",
-      "stackTrace": "java.lang.AssertionError: expected:<true> but was:<false>\n\tat org.junit.Assert.fail(Assert.java:91)\n\tat org.junit.Assert.failNotEquals(Assert.java:645)\n\tat org.junit.Assert.assertEquals(Assert.java:126)\n\tat org.junit.Assert.assertEquals(Assert.java:145)\n"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show_from_test_data_with_a_time_in_float.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/TestsShowActionTest/show_from_test_data_with_a_time_in_float.json
deleted file mode 100644 (file)
index 3f45bdb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "tests": [
-    {
-      "name": "test1",
-      "status": "OK",
-      "durationInMs": 12
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentActionTest/anonymous.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentActionTest/anonymous.json
new file mode 100644 (file)
index 0000000..ba25670
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "isLoggedIn": false,
+  "permissions": {
+    "global": []
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentActionTest/authenticated.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentActionTest/authenticated.json
new file mode 100644 (file)
index 0000000..ae2de7f
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "isLoggedIn": true,
+  "login": "obiwan.kenobi",
+  "name": "Obiwan Kenobi",
+  "permissions": {
+    "global": ["admin", "profileadmin", "shareDashboard", "scan", "dryRunScan", "provisioning"]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentUserActionTest/anonymous.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentUserActionTest/anonymous.json
deleted file mode 100644 (file)
index ba25670..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "isLoggedIn": false,
-  "permissions": {
-    "global": []
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentUserActionTest/authenticated.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/CurrentUserActionTest/authenticated.json
deleted file mode 100644 (file)
index ae2de7f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "isLoggedIn": true,
-  "login": "obiwan.kenobi",
-  "name": "Obiwan Kenobi",
-  "permissions": {
-    "global": ["admin", "profileadmin", "shareDashboard", "scan", "dryRunScan", "provisioning"]
-  }
-}